阿里云服务器免费领卷啦。

捡代码论坛-最全的游戏源码下载技术网站!

 找回密码
 立 即 注 册

QQ登录

只需一步,快速开始

搜索
关于源码区的附件失效或欺骗帖, 处理办法
查看: 2183|回复: 0

lua的functions.lua源码

[复制链接]

4212

主题

210

回帖

12万

积分

管理员

管理员

Rank: 9Rank: 9Rank: 9

积分
126801
QQ
发表于 2017-2-16 11:25:48 | 显示全部楼层 |阅读模式
  1. --[[

  2. Copyright (c) 2011-2014 chukong-inc.com

  3. Permission is hereby granted, free of charge, to any person obtaining a copy
  4. of this software and associated documentation files (the "Software"), to deal
  5. in the Software without restriction, including without limitation the rights
  6. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. copies of the Software, and to permit persons to whom the Software is
  8. furnished to do so, subject to the following conditions:

  9. The above copyright notice and this permission notice shall be included in
  10. all copies or substantial portions of the Software.

  11. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  12. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  13. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  14. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  15. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  16. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  17. THE SOFTWARE.

  18. ]]

  19. --------------------------------
  20. -- @module functions

  21. --[[--

  22. 提供一组常用函数,以及对 Lua 标准库的扩展

  23. ]]

  24. --[[--

  25. 输出格式化字符串

  26. ~~~ lua

  27. printf("The value = %d", 100)

  28. ~~~

  29. @param string fmt 输出格式
  30. @param [mixed ...] 更多参数

  31. ]]
  32. function printf(fmt, ...)
  33.     print(string.format(tostring(fmt), ...))
  34. end

  35. --[[--

  36. 检查并尝试转换为数值,如果无法转换则返回 0

  37. @param mixed value 要检查的值
  38. @param [integer base] 进制,默认为十进制

  39. @return number

  40. ]]
  41. function checknumber(value, base)
  42.     return tonumber(value, base) or 0
  43. end

  44. --[[--

  45. 检查并尝试转换为整数,如果无法转换则返回 0

  46. @param mixed value 要检查的值

  47. @return integer

  48. ]]
  49. function checkint(value)
  50.     return math.round(checknumber(value))
  51. end

  52. --[[--

  53. 检查并尝试转换为布尔值,除了 nil 和 false,其他任何值都会返回 true

  54. @param mixed value 要检查的值

  55. @return boolean

  56. ]]
  57. function checkbool(value)
  58.     return (value ~= nil and value ~= false)
  59. end

  60. --[[--

  61. 检查值是否是一个表格,如果不是则返回一个空表格

  62. @param mixed value 要检查的值

  63. @return table

  64. ]]
  65. function checktable(value)
  66.     if type(value) ~= "table" then value = {} end
  67.     return value
  68. end

  69. --[[--

  70. 如果表格中指定 key 的值为 nil,或者输入值不是表格,返回 false,否则返回 true

  71. @param table hashtable 要检查的表格
  72. @param mixed key 要检查的键名

  73. @return boolean

  74. ]]
  75. function isset(hashtable, key)
  76.     local t = type(hashtable)
  77.     return (t == "table" or t == "userdata") and hashtable[key] ~= nil
  78. end

  79. --[[--

  80. 深度克隆一个值

  81. ~~~ lua

  82. -- 下面的代码,t2 是 t1 的引用,修改 t2 的属性时,t1 的内容也会发生变化
  83. local t1 = {a = 1, b = 2}
  84. local t2 = t1
  85. t2.b = 3    -- t1 = {a = 1, b = 3} <-- t1.b 发生变化

  86. -- clone() 返回 t1 的副本,修改 t2 不会影响 t1
  87. local t1 = {a = 1, b = 2}
  88. local t2 = clone(t1)
  89. t2.b = 3    -- t1 = {a = 1, b = 2} <-- t1.b 不受影响

  90. ~~~

  91. @param mixed object 要克隆的值

  92. @return mixed

  93. ]]
  94. function clone(object)
  95.     local lookup_table = {}
  96.     local function _copy(object)
  97.         if type(object) ~= "table" then
  98.             return object
  99.         elseif lookup_table[object] then
  100.             return lookup_table[object]
  101.         end
  102.         local new_table = {}
  103.         lookup_table[object] = new_table
  104.         for key, value in pairs(object) do
  105.             new_table[_copy(key)] = _copy(value)
  106.         end
  107.         return setmetatable(new_table, getmetatable(object))
  108.     end
  109.     return _copy(object)
  110. end

  111. --[[--

  112. 创建一个类

  113. ~~~ lua

  114. -- 定义名为 Shape 的基础类
  115. local Shape = class("Shape")

  116. -- ctor() 是类的构造函数,在调用 Shape.new() 创建 Shape 对象实例时会自动执行
  117. function Shape:ctor(shapeName)
  118.     self.shapeName = shapeName
  119.     printf("Shape:ctor(%s)", self.shapeName)
  120. end

  121. -- 为 Shape 定义个名为 draw() 的方法
  122. function Shape:draw()
  123.     printf("draw %s", self.shapeName)
  124. end

  125. --

  126. -- Circle 是 Shape 的继承类
  127. local Circle = class("Circle", Shape)

  128. function Circle:ctor()
  129.     -- 如果继承类覆盖了 ctor() 构造函数,那么必须手动调用父类构造函数
  130.     -- 类名.super 可以访问指定类的父类
  131.     Circle.super.ctor(self, "circle")
  132.     self.radius = 100
  133. end

  134. function Circle:setRadius(radius)
  135.     self.radius = radius
  136. end

  137. -- 覆盖父类的同名方法
  138. function Circle:draw()
  139.     printf("draw %s, raidus = %0.2f", self.shapeName, self.raidus)
  140. end

  141. --

  142. local Rectangle = class("Rectangle", Shape)

  143. function Rectangle:ctor()
  144.     Rectangle.super.ctor(self, "rectangle")
  145. end

  146. --

  147. local circle = Circle.new()             -- 输出: Shape:ctor(circle)
  148. circle:setRaidus(200)
  149. circle:draw()                           -- 输出: draw circle, radius = 200.00

  150. local rectangle = Rectangle.new()       -- 输出: Shape:ctor(rectangle)
  151. rectangle:draw()                        -- 输出: draw rectangle

  152. ~~~

  153. ### 高级用法

  154. class() 除了定义纯 Lua 类之外,还可以从 C++ 对象继承类。

  155. 比如需要创建一个工具栏,并在添加按钮时自动排列已有的按钮,那么我们可以使用如下的代码:

  156. ~~~ lua

  157. -- 从 cc.Node 对象派生 Toolbar 类,该类具有 cc.Node 的所有属性和行为
  158. local Toolbar = class("Toolbar", function()
  159.     return display.newNode() -- 返回一个 cc.Node 对象
  160. end)

  161. -- 构造函数
  162. function Toolbar:ctor()
  163.     self.buttons = {} -- 用一个 table 来记录所有的按钮
  164. end

  165. -- 添加一个按钮,并且自动设置按钮位置
  166. function Toolbar:addButton(button)
  167.     -- 将按钮对象加入 table
  168.     self.buttons[#self.buttons + 1] = button

  169.     -- 添加按钮对象到 cc.Node 中,以便显示该按钮
  170.     -- 因为 Toolbar 是从 cc.Node 继承的,所以可以使用 addChild() 方法
  171.     self:addChild(button)

  172.     -- 按照按钮数量,调整所有按钮的位置
  173.     local x = 0
  174.     for _, button in ipairs(self.buttons) do
  175.         button:setPosition(x, 0)
  176.         -- 依次排列按钮,每个按钮之间间隔 10 点
  177.         x = x + button:getContentSize().width + 10
  178.     end
  179. end

  180. ~~~

  181. class() 的这种用法让我们可以在 C++ 对象基础上任意扩展行为。

  182. 既然是继承,自然就可以覆盖 C++ 对象的方法:

  183. ~~~ lua

  184. function Toolbar:setPosition(x, y)
  185.     -- 由于在 Toolbar 继承类中覆盖了 cc.Node 对象的 setPosition() 方法
  186.     -- 所以我们要用以下形式才能调用到 cc.Node 原本的 setPosition() 方法
  187.     getmetatable(self).setPosition(self, x, y)

  188.     printf("x = %0.2f, y = %0.2f", x, y)
  189. end

  190. ~~~

  191. **注意:** Lua 继承类覆盖的方法并不能从 C++ 调用到。也就是说通过 C++ 代码调用这个 cc.Node 对象的 setPosition() 方法时,并不会执行我们在 Lua 中定义的 Toolbar:setPosition() 方法。

  192. @param string classname 类名
  193. @param [mixed super] 父类或者创建对象实例的函数

  194. @return table

  195. ]]
  196. function class(classname, super)
  197.     local superType = type(super)
  198.     local cls

  199.     if superType ~= "function" and superType ~= "table" then
  200.         superType = nil
  201.         super = nil
  202.     end

  203.     if superType == "function" or (super and super.__ctype == 1) then
  204.         -- inherited from native C++ Object
  205.         cls = {}

  206.         if superType == "table" then
  207.             -- copy fields from super
  208.             for k,v in pairs(super) do cls[k] = v end
  209.             cls.__create = super.__create
  210.             cls.super    = super
  211.         else
  212.             cls.__create = super
  213.             cls.ctor = function() end
  214.         end

  215.         cls.__cname = classname
  216.         cls.__ctype = 1

  217.         function cls.new(...)
  218.             local instance = cls.__create(...)
  219.             -- copy fields from class to native object
  220.             for k,v in pairs(cls) do instance[k] = v end
  221.             instance.class = cls
  222.             instance:ctor(...)
  223.             return instance
  224.         end

  225.     else
  226.         -- inherited from Lua Object
  227.         if super then
  228.             cls = {}
  229.             setmetatable(cls, {__index = super})
  230.             cls.super = super
  231.         else
  232.             cls = {ctor = function() end}
  233.         end

  234.         cls.__cname = classname
  235.         cls.__ctype = 2 -- lua
  236.         cls.__index = cls

  237.         function cls.new(...)
  238.             local instance = setmetatable({}, cls)
  239.             instance.class = cls
  240.             instance:ctor(...)
  241.             return instance
  242.         end
  243.     end

  244.     return cls
  245. end

  246. --[[--

  247. 如果对象是指定类或其子类的实例,返回 true,否则返回 false

  248. ~~~ lua

  249. local Animal = class("Animal")
  250. local Duck = class("Duck", Animal)

  251. print(iskindof(Duck.new(), "Animal")) -- 输出 true

  252. ~~~

  253. @param mixed obj 要检查的对象
  254. @param string classname 类名

  255. @return boolean

  256. ]]
  257. function iskindof(obj, classname)
  258.     local t = type(obj)
  259.     local mt
  260.     if t == "table" then
  261.         mt = getmetatable(obj)
  262.     elseif t == "userdata" then
  263.         mt = tolua.getpeer(obj)
  264.     end

  265.     while mt do
  266.         if mt.__cname == classname then
  267.             return true
  268.         end
  269.         mt = mt.super
  270.     end

  271.     return false
  272. end

  273. --[[--

  274. 载入一个模块

  275. import() 与 require() 功能相同,但具有一定程度的自动化特性。

  276. 假设我们有如下的目录结构:

  277. ~~~

  278. app/
  279. app/classes/
  280. app/classes/MyClass.lua
  281. app/classes/MyClassBase.lua
  282. app/classes/data/Data1.lua
  283. app/classes/data/Data2.lua

  284. ~~~

  285. MyClass 中需要载入 MyClassBase 和 MyClassData。如果用 require(),MyClass 内的代码如下:

  286. ~~~ lua

  287. local MyClassBase = require("app.classes.MyClassBase")
  288. local MyClass = class("MyClass", MyClassBase)

  289. local Data1 = require("app.classes.data.Data1")
  290. local Data2 = require("app.classes.data.Data2")

  291. ~~~

  292. 假如我们将 MyClass 及其相关文件换一个目录存放,那么就必须修改 MyClass 中的 require() 命令,否则将找不到模块文件。

  293. 而使用 import(),我们只需要如下写:

  294. ~~~ lua

  295. local MyClassBase = import(".MyClassBase")
  296. local MyClass = class("MyClass", MyClassBase)

  297. local Data1 = import(".data.Data1")
  298. local Data2 = import(".data.Data2")

  299. ~~~

  300. 当在模块名前面有一个"." 时,import() 会从当前模块所在目录中查找其他模块。因此 MyClass 及其相关文件不管存放到什么目录里,我们都不再需要修改 MyClass 中的 import() 命令。这在开发一些重复使用的功能组件时,会非常方便。

  301. 我们可以在模块名前添加多个"." ,这样 import() 会从更上层的目录开始查找模块。

  302. ~

  303. 不过 import() 只有在模块级别调用(也就是没有将 import() 写在任何函数中)时,才能够自动得到当前模块名。如果需要在函数中调用 import(),那么就需要指定当前模块名:

  304. ~~~ lua

  305. # MyClass.lua

  306. # 这里的 ... 是隐藏参数,包含了当前模块的名字,所以最好将这行代码写在模块的第一行
  307. local CURRENT_MODULE_NAME = ...

  308. local function testLoad()
  309.     local MyClassBase = import(".MyClassBase", CURRENT_MODULE_NAME)
  310.     # 更多代码
  311. end

  312. ~~~

  313. @param string moduleName 要载入的模块的名字
  314. @param [string currentModuleName] 当前模块名

  315. @return module

  316. ]]
  317. function import(moduleName, currentModuleName)
  318.     local currentModuleNameParts
  319.     local moduleFullName = moduleName
  320.     local offset = 1

  321.     while true do
  322.         if string.byte(moduleName, offset) ~= 46 then -- .
  323.             moduleFullName = string.sub(moduleName, offset)
  324.             if currentModuleNameParts and #currentModuleNameParts > 0 then
  325.                 moduleFullName = table.concat(currentModuleNameParts, ".") .. "." .. moduleFullName
  326.             end
  327.             break
  328.         end
  329.         offset = offset + 1

  330.         if not currentModuleNameParts then
  331.             if not currentModuleName then
  332.                 local n,v = debug.getlocal(3, 1)
  333.                 currentModuleName = v
  334.             end

  335.             currentModuleNameParts = string.split(currentModuleName, ".")
  336.         end
  337.         table.remove(currentModuleNameParts, #currentModuleNameParts)
  338.     end

  339.     return require(moduleFullName)
  340. end

  341. --[[--

  342. 将 Lua 对象及其方法包装为一个匿名函数

  343. 在 quick-cocos2d-x 中,许多功能需要传入一个 Lua 函数做参数,然后在特定事件发生时就会调用传入的函数。例如触摸事件、帧事件等等。

  344. ~~~ lua

  345. local MyScene = class("MyScene", function()
  346.     return display.newScene("MyScene")
  347. end)

  348. function MyScene:ctor()
  349.     self.frameTimeCount = 0
  350.     -- 注册帧事件
  351.     self:addNodeEventListener(cc.NODE_ENTER_FRAME_EVENT, self.onEnterFrame)
  352.     self:scheduleUpdate()
  353. end

  354. function MyScene:onEnterFrame(dt)
  355.     self.frameTimeCount = self.frameTimeCount + dt
  356. end

  357. ~~~

  358. 上述代码执行时将出错,报告"Invalid self" ,这就是因为 C++ 无法识别 Lua 对象方法。因此在调用我们传入的 self.onEnterFrame 方法时没有提供正确的参数。

  359. 要让上述的代码正常工作,就需要使用 handler() 进行一下包装:

  360. ~~~ lua

  361. function MyScene:ctor()
  362.     self.frameTimeCount = 0
  363.     -- 注册帧事件
  364.     self:addNodeEventListener(cc.ENTER_FRAME_EVENT, handler(self, self.onEnterFrame))
  365.     self:scheduleUpdate()
  366. end

  367. ~~~

  368. 实际上,除了 C++ 回调 Lua 函数之外,在其他所有需要回调的地方都可以使用 handler()。

  369. @param mixed obj Lua 对象
  370. @param function method 对象方法

  371. @return function

  372. ]]
  373. function handler(obj, method)
  374.     return function(...)
  375.         return method(obj, ...)
  376.     end
  377. end


  378. --------------------------------
  379. -- @module math

  380. -- start --

  381. --------------------------------
  382. -- 根据系统时间初始化随机数种子,让后续的 math.random() 返回更随机的值
  383. -- @function [parent=#math] newrandomseed

  384. -- end --

  385. function math.newrandomseed()
  386.     local ok, socket = pcall(function()
  387.         return require("socket")
  388.     end)

  389.     if ok then
  390.         -- 如果集成了 socket 模块,则使用 socket.gettime() 获取随机数种子
  391.         math.randomseed(socket.gettime())
  392.     else
  393.         math.randomseed(os.time())
  394.     end
  395.     math.random()
  396.     math.random()
  397.     math.random()
  398.     math.random()
  399. end

  400. -- start --

  401. --------------------------------
  402. -- 对数值进行四舍五入,如果不是数值则返回 0
  403. -- @function [parent=#math] round
  404. -- @param number value 输入值
  405. -- @return number#number

  406. -- end --

  407. function math.round(value)
  408.     value = checknumber(value)
  409.     return math.floor(value + 0.5)
  410. end

  411. -- start --

  412. --------------------------------
  413. -- 角度转弧度
  414. -- @function [parent=#math] angle2radian

  415. -- end --

  416. function math.angle2radian(angle)
  417.         return angle*math.pi/180
  418. end

  419. -- start --

  420. --------------------------------
  421. -- 弧度转角度
  422. -- @function [parent=#math] radian2angle

  423. -- end --

  424. function math.radian2angle(radian)
  425.         return radian/math.pi*180
  426. end



  427. --------------------------------
  428. -- @module io

  429. -- start --

  430. --------------------------------
  431. -- 检查指定的文件或目录是否存在,如果存在返回 true,否则返回 false
  432. -- @function [parent=#io] exists
  433. -- @param string path 要检查的文件或目录的完全路径
  434. -- @return boolean#boolean

  435. --[[--

  436. 检查指定的文件或目录是否存在,如果存在返回 true,否则返回 false

  437. 可以使用 cc.FileUtils:fullPathForFilename() 函数查找特定文件的完整路径,例如:

  438. ~~~ lua

  439. local path = cc.FileUtils:getInstance():fullPathForFilename("gamedata.txt")
  440. if io.exists(path) then
  441.     ....
  442. end

  443. ~~~

  444. ]]

  445. -- end --

  446. function io.exists(path)
  447.     local file = io.open(path, "r")
  448.     if file then
  449.         io.close(file)
  450.         return true
  451.     end
  452.     return false
  453. end

  454. -- start --

  455. --------------------------------
  456. -- 读取文件内容,返回包含文件内容的字符串,如果失败返回 nil
  457. -- @function [parent=#io] readfile
  458. -- @param string path 文件完全路径
  459. -- @return string#string

  460. --[[--

  461. 读取文件内容,返回包含文件内容的字符串,如果失败返回 nil

  462. io.readfile() 会一次性读取整个文件的内容,并返回一个字符串,因此该函数不适宜读取太大的文件。

  463. ]]

  464. -- end --

  465. function io.readfile(path)
  466.     local file = io.open(path, "rb")
  467.     if file then
  468.         local content = file:read("*a")
  469.         io.close(file)
  470.         return content
  471.     end
  472.     return nil
  473. end

  474. -- start --

  475. --------------------------------
  476. -- 以字符串内容写入文件,成功返回 true,失败返回 false
  477. -- @function [parent=#io] writefile
  478. -- @param string path 文件完全路径
  479. -- @param string content 要写入的内容
  480. -- @param string mode 写入模式,默认值为 "w+b"
  481. -- @return boolean#boolean

  482. --[[--

  483. 以字符串内容写入文件,成功返回 true,失败返回 false

  484. "mode 写入模式" 参数决定 io.writefile() 如何写入内容,可用的值如下:

  485. -   "w+" : 覆盖文件已有内容,如果文件不存在则创建新文件
  486. -   "a+" : 追加内容到文件尾部,如果文件不存在则创建文件

  487. 此外,还可以在 "写入模式" 参数最后追加字符 "b" ,表示以二进制方式写入数据,这样可以避免内容写入不完整。

  488. **Android 特别提示:** 在 Android 平台上,文件只能写入存储卡所在路径,assets 和 data 等目录都是无法写入的。

  489. ]]

  490. -- end --

  491. function io.writefile(path, content, mode)
  492.     mode = mode or "w+b"
  493.     local file = io.open(path, mode)
  494.     if file then
  495.         if file:write(content) == nil then return false end
  496.         io.close(file)
  497.         return true
  498.     else
  499.         return false
  500.     end
  501. end

  502. -- start --

  503. --------------------------------
  504. -- 拆分一个路径字符串,返回组成路径的各个部分
  505. -- @function [parent=#io] pathinfo
  506. -- @param string path 要分拆的路径字符串
  507. -- @return table#table

  508. --[[--

  509. 拆分一个路径字符串,返回组成路径的各个部分

  510. ~~~ lua

  511. local pathinfo  = io.pathinfo("/var/app/test/abc.png")

  512. -- 结果:
  513. -- pathinfo.dirname  = "/var/app/test/"
  514. -- pathinfo.filename = "abc.png"
  515. -- pathinfo.basename = "abc"
  516. -- pathinfo.extname  = ".png"

  517. ~~~

  518. ]]

  519. -- end --

  520. function io.pathinfo(path)
  521.     local pos = string.len(path)
  522.     local extpos = pos + 1
  523.     while pos > 0 do
  524.         local b = string.byte(path, pos)
  525.         if b == 46 then -- 46 = char "."
  526.             extpos = pos
  527.         elseif b == 47 then -- 47 = char "/"
  528.             break
  529.         end
  530.         pos = pos - 1
  531.     end

  532.     local dirname = string.sub(path, 1, pos)
  533.     local filename = string.sub(path, pos + 1)
  534.     extpos = extpos - pos
  535.     local basename = string.sub(filename, 1, extpos - 1)
  536.     local extname = string.sub(filename, extpos)
  537.     return {
  538.         dirname = dirname,
  539.         filename = filename,
  540.         basename = basename,
  541.         extname = extname
  542.     }
  543. end

  544. -- start --

  545. --------------------------------
  546. -- 返回指定文件的大小,如果失败返回 false
  547. -- @function [parent=#io] filesize
  548. -- @param string path 文件完全路径
  549. -- @return integer#integer

  550. -- end --

  551. function io.filesize(path)
  552.     local size = false
  553.     local file = io.open(path, "r")
  554.     if file then
  555.         local current = file:seek()
  556.         size = file:seek("end")
  557.         file:seek("set", current)
  558.         io.close(file)
  559.     end
  560.     return size
  561. end


  562. --------------------------------
  563. -- @module table

  564. -- start --

  565. --------------------------------
  566. -- 计算表格包含的字段数量
  567. -- @function [parent=#table] nums
  568. -- @param table t 要检查的表格
  569. -- @return integer#integer

  570. --[[--

  571. 计算表格包含的字段数量

  572. Lua table 的 "#" 操作只对依次排序的数值下标数组有效,table.nums() 则计算 table 中所有不为 nil 的值的个数。

  573. ]]

  574. -- end --

  575. function table.nums(t)
  576.     local count = 0
  577.     for k, v in pairs(t) do
  578.         count = count + 1
  579.     end
  580.     return count
  581. end

  582. -- start --

  583. --------------------------------
  584. -- 返回指定表格中的所有键
  585. -- @function [parent=#table] keys
  586. -- @param table hashtable 要检查的表格
  587. -- @return table#table

  588. --[[--

  589. 返回指定表格中的所有键

  590. ~~~ lua

  591. local hashtable = {a = 1, b = 2, c = 3}
  592. local keys = table.keys(hashtable)
  593. -- keys = {"a", "b", "c"}

  594. ~~~

  595. ]]

  596. -- end --

  597. function table.keys(hashtable)
  598.     local keys = {}
  599.     for k, v in pairs(hashtable) do
  600.         keys[#keys + 1] = k
  601.     end
  602.     return keys
  603. end

  604. -- start --

  605. --------------------------------
  606. -- 返回指定表格中的所有值
  607. -- @function [parent=#table] values
  608. -- @param table hashtable 要检查的表格
  609. -- @return table#table

  610. --[[--

  611. 返回指定表格中的所有值

  612. ~~~ lua

  613. local hashtable = {a = 1, b = 2, c = 3}
  614. local values = table.values(hashtable)
  615. -- values = {1, 2, 3}

  616. ~~~

  617. ]]

  618. -- end --

  619. function table.values(hashtable)
  620.     local values = {}
  621.     for k, v in pairs(hashtable) do
  622.         values[#values + 1] = v
  623.     end
  624.     return values
  625. end

  626. -- start --

  627. --------------------------------
  628. -- 将来源表格中所有键及其值复制到目标表格对象中,如果存在同名键,则覆盖其值
  629. -- @function [parent=#table] merge
  630. -- @param table dest 目标表格
  631. -- @param table src 来源表格

  632. --[[--

  633. 将来源表格中所有键及其值复制到目标表格对象中,如果存在同名键,则覆盖其值

  634. ~~~ lua

  635. local dest = {a = 1, b = 2}
  636. local src  = {c = 3, d = 4}
  637. table.merge(dest, src)
  638. -- dest = {a = 1, b = 2, c = 3, d = 4}

  639. ~~~

  640. ]]

  641. -- end --

  642. function table.merge(dest, src)
  643.     for k, v in pairs(src) do
  644.         dest[k] = v
  645.     end
  646. end

  647. -- start --

  648. --------------------------------
  649. -- 在目标表格的指定位置插入来源表格,如果没有指定位置则连接两个表格
  650. -- @function [parent=#table] insertto
  651. -- @param table dest 目标表格
  652. -- @param table src 来源表格
  653. -- @param integer begin 插入位置,默认最后

  654. --[[--

  655. 在目标表格的指定位置插入来源表格,如果没有指定位置则连接两个表格

  656. ~~~ lua

  657. local dest = {1, 2, 3}
  658. local src  = {4, 5, 6}
  659. table.insertto(dest, src)
  660. -- dest = {1, 2, 3, 4, 5, 6}

  661. dest = {1, 2, 3}
  662. table.insertto(dest, src, 5)
  663. -- dest = {1, 2, 3, nil, 4, 5, 6}

  664. ~~~

  665. ]]

  666. -- end --

  667. function table.insertto(dest, src, begin)
  668.         begin = checkint(begin)
  669.         if begin <= 0 then
  670.                 begin = #dest + 1
  671.         end

  672.         local len = #src
  673.         for i = 0, len - 1 do
  674.                 dest[i + begin] = src[i + 1]
  675.         end
  676. end

  677. -- start --

  678. --------------------------------
  679. -- 从表格中查找指定值,返回其索引,如果没找到返回 false
  680. -- @function [parent=#table] indexof
  681. -- @param table array 表格
  682. -- @param mixed value 要查找的值
  683. -- @param integer begin 起始索引值
  684. -- @return integer#integer

  685. --[[--

  686. 从表格中查找指定值,返回其索引,如果没找到返回 false

  687. ~~~ lua

  688. local array = {"a", "b", "c"}
  689. print(table.indexof(array, "b")) -- 输出 2

  690. ~~~

  691. ]]

  692. -- end --

  693. function table.indexof(array, value, begin)
  694.     for i = begin or 1, #array do
  695.         if array[i] == value then return i end
  696.     end
  697.         return false
  698. end

  699. -- start --

  700. --------------------------------
  701. -- 从表格中查找指定值,返回其 key,如果没找到返回 nil
  702. -- @function [parent=#table] keyof
  703. -- @param table hashtable 表格
  704. -- @param mixed value 要查找的值
  705. -- @return string#string  该值对应的 key

  706. --[[--

  707. 从表格中查找指定值,返回其 key,如果没找到返回 nil

  708. ~~~ lua

  709. local hashtable = {name = "dualface", comp = "chukong"}
  710. print(table.keyof(hashtable, "chukong")) -- 输出 comp

  711. ~~~

  712. ]]

  713. -- end --

  714. function table.keyof(hashtable, value)
  715.     for k, v in pairs(hashtable) do
  716.         if v == value then return k end
  717.     end
  718.     return nil
  719. end

  720. -- start --

  721. --------------------------------
  722. -- 从表格中删除指定值,返回删除的值的个数
  723. -- @function [parent=#table] removebyvalue
  724. -- @param table array 表格
  725. -- @param mixed value 要删除的值
  726. -- @param boolean removeall 是否删除所有相同的值
  727. -- @return integer#integer

  728. --[[--

  729. 从表格中删除指定值,返回删除的值的个数

  730. ~~~ lua

  731. local array = {"a", "b", "c", "c"}
  732. print(table.removebyvalue(array, "c", true)) -- 输出 2

  733. ~~~

  734. ]]

  735. -- end --

  736. function table.removebyvalue(array, value, removeall)
  737.     local c, i, max = 0, 1, #array
  738.     while i <= max do
  739.         if array[i] == value then
  740.             table.remove(array, i)
  741.             c = c + 1
  742.             i = i - 1
  743.             max = max - 1
  744.             if not removeall then break end
  745.         end
  746.         i = i + 1
  747.     end
  748.     return c
  749. end

  750. -- start --

  751. --------------------------------
  752. -- 对表格中每一个值执行一次指定的函数,并用函数返回值更新表格内容
  753. -- @function [parent=#table] map
  754. -- @param table t 表格
  755. -- @param function fn 函数

  756. --[[--

  757. 对表格中每一个值执行一次指定的函数,并用函数返回值更新表格内容

  758. ~~~ lua

  759. local t = {name = "dualface", comp = "chukong"}
  760. table.map(t, function(v, k)
  761.     -- 在每一个值前后添加括号
  762.     return "[" .. v .. "]"
  763. end)

  764. -- 输出修改后的表格内容
  765. for k, v in pairs(t) do
  766.     print(k, v)
  767. end

  768. -- 输出
  769. -- name [dualface]
  770. -- comp [chukong]

  771. ~~~

  772. fn 参数指定的函数具有两个参数,并且返回一个值。原型如下:

  773. ~~~ lua

  774. function map_function(value, key)
  775.     return value
  776. end

  777. ~~~

  778. ]]

  779. -- end --

  780. function table.map(t, fn)
  781.     for k, v in pairs(t) do
  782.         t[k] = fn(v, k)
  783.     end
  784. end

  785. -- start --

  786. --------------------------------
  787. -- 对表格中每一个值执行一次指定的函数,但不改变表格内容
  788. -- @function [parent=#table] walk
  789. -- @param table t 表格
  790. -- @param function fn 函数

  791. --[[--

  792. 对表格中每一个值执行一次指定的函数,但不改变表格内容

  793. ~~~ lua

  794. local t = {name = "dualface", comp = "chukong"}
  795. table.walk(t, function(v, k)
  796.     -- 输出每一个值
  797.     print(v)
  798. end)

  799. ~~~

  800. fn 参数指定的函数具有两个参数,没有返回值。原型如下:

  801. ~~~ lua

  802. function map_function(value, key)

  803. end

  804. ~~~

  805. ]]

  806. -- end --

  807. function table.walk(t, fn)
  808.     for k,v in pairs(t) do
  809.         fn(v, k)
  810.     end
  811. end

  812. -- start --

  813. --------------------------------
  814. -- 对表格中每一个值执行一次指定的函数,如果该函数返回 false,则对应的值会从表格中删除
  815. -- @function [parent=#table] filter
  816. -- @param table t 表格
  817. -- @param function fn 函数

  818. --[[--

  819. 对表格中每一个值执行一次指定的函数,如果该函数返回 false,则对应的值会从表格中删除

  820. ~~~ lua

  821. local t = {name = "dualface", comp = "chukong"}
  822. table.filter(t, function(v, k)
  823.     return v ~= "dualface" -- 当值等于 dualface 时过滤掉该值
  824. end)

  825. -- 输出修改后的表格内容
  826. for k, v in pairs(t) do
  827.     print(k, v)
  828. end

  829. -- 输出
  830. -- comp chukong

  831. ~~~

  832. fn 参数指定的函数具有两个参数,并且返回一个 boolean 值。原型如下:

  833. ~~~ lua

  834. function map_function(value, key)
  835.     return true or false
  836. end

  837. ~~~

  838. ]]

  839. -- end --

  840. function table.filter(t, fn)
  841.     for k, v in pairs(t) do
  842.         if not fn(v, k) then t[k] = nil end
  843.     end
  844. end

  845. -- start --

  846. --------------------------------
  847. -- 遍历表格,确保其中的值唯一
  848. -- @function [parent=#table] unique
  849. -- @param table t 表格
  850. -- @param boolean bArray t是否是数组,是数组,t中重复的项被移除后,后续的项会前移
  851. -- @return table#table  包含所有唯一值的新表格

  852. --[[--

  853. 遍历表格,确保其中的值唯一

  854. ~~~ lua

  855. local t = {"a", "a", "b", "c"} -- 重复的 a 会被过滤掉
  856. local n = table.unique(t)

  857. for k, v in pairs(n) do
  858.     print(v)
  859. end

  860. -- 输出
  861. -- a
  862. -- b
  863. -- c

  864. ~~~

  865. ]]

  866. -- end --

  867. function table.unique(t, bArray)
  868.     local check = {}
  869.     local n = {}
  870.     local idx = 1
  871.     for k, v in pairs(t) do
  872.         if not check[v] then
  873.             if bArray then
  874.                 n[idx] = v
  875.                 idx = idx + 1
  876.             else
  877.                 n[k] = v
  878.             end
  879.             check[v] = true
  880.         end
  881.     end
  882.     return n
  883. end


  884. --------------------------------
  885. -- @module string


  886. string._htmlspecialchars_set = {}
  887. string._htmlspecialchars_set["&"] = "&"
  888. string._htmlspecialchars_set["""] = """
  889. string._htmlspecialchars_set["'"] = "'"
  890. string._htmlspecialchars_set["<"] = "<"
  891. string._htmlspecialchars_set[">"] = ">"

  892. -- start --

  893. --------------------------------
  894. -- 将特殊字符转为 HTML 转义符
  895. -- @function [parent=#string] htmlspecialchars
  896. -- @param string input 输入字符串
  897. -- @return string#string  转换结果

  898. --[[--

  899. 将特殊字符转为 HTML 转义符

  900. ~~~ lua

  901. print(string.htmlspecialchars("<ABC>"))
  902. -- 输出 <ABC>

  903. ~~~

  904. ]]

  905. -- end --

  906. function string.htmlspecialchars(input)
  907.     for k, v in pairs(string._htmlspecialchars_set) do
  908.         input = string.gsub(input, k, v)
  909.     end
  910.     return input
  911. end

  912. -- start --

  913. --------------------------------
  914. -- 将 HTML 转义符还原为特殊字符,功能与 string.htmlspecialchars() 正好相反
  915. -- @function [parent=#string] restorehtmlspecialchars
  916. -- @param string input 输入字符串
  917. -- @return string#string  转换结果

  918. --[[--

  919. 将 HTML 转义符还原为特殊字符,功能与 string.htmlspecialchars() 正好相反

  920. ~~~ lua

  921. print(string.restorehtmlspecialchars("<ABC>"))
  922. -- 输出 <ABC>

  923. ~~~

  924. ]]

  925. -- end --

  926. function string.restorehtmlspecialchars(input)
  927.     for k, v in pairs(string._htmlspecialchars_set) do
  928.         input = string.gsub(input, v, k)
  929.     end
  930.     return input
  931. end

  932. -- start --

  933. --------------------------------
  934. -- 将字符串中的 \n 换行符转换为 HTML 标记
  935. -- @function [parent=#string] nl2br
  936. -- @param string input 输入字符串
  937. -- @return string#string  转换结果

  938. --[[--

  939. 将字符串中的 \n 换行符转换为 HTML 标记

  940. ~~~ lua

  941. print(string.nl2br("Hello\nWorld"))
  942. -- 输出
  943. -- Hello<br />World

  944. ~~~

  945. ]]

  946. -- end --

  947. function string.nl2br(input)
  948.     return string.gsub(input, "\n", "<br />")
  949. end

  950. -- start --

  951. --------------------------------
  952. -- 将字符串中的特殊字符和 \n 换行符转换为 HTML 转移符和标记
  953. -- @function [parent=#string] text2html
  954. -- @param string input 输入字符串
  955. -- @return string#string  转换结果

  956. --[[--

  957. 将字符串中的特殊字符和 \n 换行符转换为 HTML 转移符和标记

  958. ~~~ lua

  959. print(string.text2html("<Hello>\nWorld"))
  960. -- 输出
  961. -- <Hello><br />World

  962. ~~~

  963. ]]

  964. -- end --

  965. function string.text2html(input)
  966.     input = string.gsub(input, "\t", "    ")
  967.     input = string.htmlspecialchars(input)
  968.     input = string.gsub(input, " ", " ")
  969.     input = string.nl2br(input)
  970.     return input
  971. end

  972. -- start --

  973. --------------------------------
  974. -- 用指定字符或字符串分割输入字符串,返回包含分割结果的数组
  975. -- @function [parent=#string] split
  976. -- @param string input 输入字符串
  977. -- @param string delimiter 分割标记字符或字符串
  978. -- @return array#array  包含分割结果的数组

  979. --[[--

  980. 用指定字符或字符串分割输入字符串,返回包含分割结果的数组

  981. ~~~ lua

  982. local input = "Hello,World"
  983. local res = string.split(input, ",")
  984. -- res = {"Hello", "World"}

  985. local input = "Hello-+-World-+-Quick"
  986. local res = string.split(input, "-+-")
  987. -- res = {"Hello", "World", "Quick"}

  988. ~~~

  989. ]]

  990. -- end --

  991. function string.split(input, delimiter)
  992.     input = tostring(input)
  993.     delimiter = tostring(delimiter)
  994.     if (delimiter=='') then return false end
  995.     local pos,arr = 0, {}
  996.     -- for each divider found
  997.     for st,sp in function() return string.find(input, delimiter, pos, true) end do
  998.         table.insert(arr, string.sub(input, pos, st - 1))
  999.         pos = sp + 1
  1000.     end
  1001.     table.insert(arr, string.sub(input, pos))
  1002.     return arr
  1003. end

  1004. -- start --

  1005. --------------------------------
  1006. -- 去除输入字符串头部的空白字符,返回结果
  1007. -- @function [parent=#string] ltrim
  1008. -- @param string input 输入字符串
  1009. -- @return string#string  结果
  1010. -- @see string.rtrim, string.trim

  1011. --[[--

  1012. 去除输入字符串头部的空白字符,返回结果

  1013. ~~~ lua

  1014. local input = "  ABC"
  1015. print(string.ltrim(input))
  1016. -- 输出 ABC,输入字符串前面的两个空格被去掉了

  1017. ~~~

  1018. 空白字符包括:

  1019. -   空格
  1020. -   制表符 \t
  1021. -   换行符 \n
  1022. -   回到行首符 \r

  1023. ]]

  1024. -- end --

  1025. function string.ltrim(input)
  1026.     return string.gsub(input, "^[ \t\n\r]+", "")
  1027. end

  1028. -- start --

  1029. --------------------------------
  1030. -- 去除输入字符串尾部的空白字符,返回结果
  1031. -- @function [parent=#string] rtrim
  1032. -- @param string input 输入字符串
  1033. -- @return string#string  结果
  1034. -- @see string.ltrim, string.trim

  1035. --[[--

  1036. 去除输入字符串尾部的空白字符,返回结果

  1037. ~~~ lua

  1038. local input = "ABC  "
  1039. print(string.rtrim(input))
  1040. -- 输出 ABC,输入字符串最后的两个空格被去掉了

  1041. ~~~

  1042. ]]

  1043. -- end --

  1044. function string.rtrim(input)
  1045.     return string.gsub(input, "[ \t\n\r]+[        DISCUZ_CODE_0        ]quot;, "")
  1046. end

  1047. -- start --

  1048. --------------------------------
  1049. -- 去掉字符串首尾的空白字符,返回结果
  1050. -- @function [parent=#string] trim
  1051. -- @param string input 输入字符串
  1052. -- @return string#string  结果
  1053. -- @see string.ltrim, string.rtrim

  1054. --[[--

  1055. 去掉字符串首尾的空白字符,返回结果

  1056. ]]

  1057. -- end --

  1058. function string.trim(input)
  1059.     input = string.gsub(input, "^[ \t\n\r]+", "")
  1060.     return string.gsub(input, "[ \t\n\r]+[        DISCUZ_CODE_0        ]quot;, "")
  1061. end

  1062. -- start --

  1063. --------------------------------
  1064. -- 将字符串的第一个字符转为大写,返回结果
  1065. -- @function [parent=#string] ucfirst
  1066. -- @param string input 输入字符串
  1067. -- @return string#string  结果

  1068. --[[--

  1069. 将字符串的第一个字符转为大写,返回结果

  1070. ~~~ lua

  1071. local input = "hello"
  1072. print(string.ucfirst(input))
  1073. -- 输出 Hello

  1074. ~~~

  1075. ]]

  1076. -- end --

  1077. function string.ucfirst(input)
  1078.     return string.upper(string.sub(input, 1, 1)) .. string.sub(input, 2)
  1079. end

  1080. local function urlencodechar(char)
  1081.     return "%" .. string.format("%02X", string.byte(char))
  1082. end

  1083. -- start --

  1084. --------------------------------
  1085. -- 将字符串转换为符合 URL 传递要求的格式,并返回转换结果
  1086. -- @function [parent=#string] urlencode
  1087. -- @param string input 输入字符串
  1088. -- @return string#string  转换后的结果
  1089. -- @see string.urldecode

  1090. --[[--

  1091. 将字符串转换为符合 URL 传递要求的格式,并返回转换结果

  1092. ~~~ lua

  1093. local input = "hello world"
  1094. print(string.urlencode(input))
  1095. -- 输出
  1096. -- hello%20world

  1097. ~~~

  1098. ]]

  1099. -- end --

  1100. function string.urlencode(input)
  1101.     -- convert line endings
  1102.     input = string.gsub(tostring(input), "\n", "\r\n")
  1103.     -- escape all characters but alphanumeric, '.' and '-'
  1104.     input = string.gsub(input, "([^%w%.%- ])", urlencodechar)
  1105.     -- convert spaces to "+" symbols
  1106.     return string.gsub(input, " ", "+")
  1107. end

  1108. -- start --

  1109. --------------------------------
  1110. -- 将 URL 中的特殊字符还原,并返回结果
  1111. -- @function [parent=#string] urldecode
  1112. -- @param string input 输入字符串
  1113. -- @return string#string  转换后的结果
  1114. -- @see string.urlencode

  1115. --[[--

  1116. 将 URL 中的特殊字符还原,并返回结果

  1117. ~~~ lua

  1118. local input = "hello%20world"
  1119. print(string.urldecode(input))
  1120. -- 输出
  1121. -- hello world

  1122. ~~~

  1123. ]]

  1124. -- end --

  1125. function string.urldecode(input)
  1126.     input = string.gsub (input, "+", " ")
  1127.     input = string.gsub (input, "%%(%x%x)", function(h) return string.char(checknumber(h,16)) end)
  1128.     input = string.gsub (input, "\r\n", "\n")
  1129.     return input
  1130. end

  1131. -- start --

  1132. --------------------------------
  1133. -- 计算 UTF8 字符串的长度,每一个中文算一个字符
  1134. -- @function [parent=#string] utf8len
  1135. -- @param string input 输入字符串
  1136. -- @return integer#integer  长度

  1137. --[[--

  1138. 计算 UTF8 字符串的长度,每一个中文算一个字符

  1139. ~~~ lua

  1140. local input = "你好World"
  1141. print(string.utf8len(input))
  1142. -- 输出 7

  1143. ~~~

  1144. ]]

  1145. -- end --

  1146. function string.utf8len(input)
  1147.     local len  = string.len(input)
  1148.     local left = len
  1149.     local cnt  = 0
  1150.     local arr  = {0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc}
  1151.     while left ~= 0 do
  1152.         local tmp = string.byte(input, -left)
  1153.         local i   = #arr
  1154.         while arr[i] do
  1155.             if tmp >= arr[i] then
  1156.                 left = left - i
  1157.                 break
  1158.             end
  1159.             i = i - 1
  1160.         end
  1161.         cnt = cnt + 1
  1162.     end
  1163.     return cnt
  1164. end

  1165. -- start --

  1166. --------------------------------
  1167. -- 将数值格式化为包含千分位分隔符的字符串
  1168. -- @function [parent=#string] formatnumberthousands
  1169. -- @param number num 数值
  1170. -- @return string#string  格式化结果

  1171. --[[--

  1172. 将数值格式化为包含千分位分隔符的字符串

  1173. ~~~ lua

  1174. print(string.formatnumberthousands(1924235))
  1175. -- 输出 1,924,235

  1176. ~~~

  1177. ]]

  1178. -- end --

  1179. function string.formatnumberthousands(num)
  1180.     local formatted = tostring(checknumber(num))
  1181.     local k
  1182.     while true do
  1183.         formatted, k = string.gsub(formatted, "^(-?%d+)(%d%d%d)", '%1,%2')
  1184.         if k == 0 then break end
  1185.     end
  1186.     return formatted
  1187. end


  1188. math.__randseed = 1

  1189. function math.rand(l,u)
  1190.     math.__randseed =  math.__randseed* 214013 + 2531011
  1191.     local r = bit.band(bit.rshift(math.__randseed,16),0x7fff)
  1192.     if l and  u then
  1193.         r = r/0x7fff
  1194.         r =math.floor(r*(u-l+1))+l
  1195.     elseif l and u == nil then
  1196.         r = r/0x7fff
  1197.         r = math.floor(r*l)+1
  1198.     end
  1199.     return r
  1200. end

  1201. function math.srand(r)
  1202.     math.__randseed  = r
  1203. end


  1204. local lfs = require("lfs")

  1205. function os.exists(path)
  1206.     if lfs.attributes(path)~=nil then return true end
  1207.     return false
  1208. end

  1209. -- 删除非空目录
  1210. function os.rmdir(path)
  1211.     if os.exists(path) then
  1212.         local function _rmdir(path)
  1213.             local iter, dir_obj = lfs.dir(path)
  1214.             while true do
  1215.                 local dir = iter(dir_obj)
  1216.                 if dir == nil then break end
  1217.                 if dir ~= "." and dir ~= ".." then
  1218.                     local curDir = path..'/'..dir
  1219.                     print ('curDir',curDir)
  1220.                     local mode = lfs.attributes(curDir, "mode")
  1221.                     if mode == "directory" then
  1222.                         _rmdir(curDir)
  1223.                     elseif mode == "file" then
  1224.                         os.remove(curDir)
  1225.                     end
  1226.                 end
  1227.             end
  1228.             local succ, des = lfs.rmdir(path)
  1229.             -- if des then print(des) end
  1230.             -- print('succ',succ)
  1231.             return succ
  1232.         end
  1233.         _rmdir(path)
  1234.     end
  1235.     return true
  1236. end

  1237. function os.mkdir_ex(path)
  1238.     path = string.gsub(path, '\\', '/')
  1239.     local parts = string.split(path, '/')
  1240.     local s = parts[1]
  1241.     for i=2,#parts-1,1 do
  1242.         s = s..'/'..parts[i]
  1243.         if not os.exists(s) then
  1244.             lfs.mkdir(s)
  1245.         end
  1246.     end
  1247. end

  1248. function io.copyfile(src,dst)
  1249.     fsrc = io.open(src,'rb')
  1250.     if not fsrc then return false end
  1251.     fdst = io.open(dst,'wb')
  1252.     if not fsrc then return false end

  1253.     data = fsrc:read(1024*64)
  1254.     while data and #data > 0 do
  1255.         fdst:write(data)
  1256.         data = fsrc:read(1024*64)
  1257.     end
  1258.     fsrc:close()
  1259.     fdst:close()
  1260. end
复制代码

源码文件:
游客,如果您要查看本帖隐藏内容请回复


捡代码论坛-最全的游戏源码下载技术网站! - 论坛版权郑重声明:
1、本主题所有言论和图片纯属会员个人意见,与本论坛立场无关
2、本站所有主题由该帖子作者发表,该帖子作者与捡代码论坛-最全的游戏源码下载技术网站!享有帖子相关版权
3、捡代码论坛版权,详细了解请点击。
4、本站所有内容均由互联网收集整理、网友上传,并且以计算机技术研究交流为目的,仅供大家参考、学习,不存在任何商业目的与商业用途。
5、若您需要商业运营或用于其他商业活动,请您购买正版授权并合法使用。 我们不承担任何技术及版权问题,且不对任何资源负法律责任。
6、如无法链接失效或侵犯版权,请给我们来信:jiandaima@foxmail.com

回复

使用道具 举报

*滑块验证:
您需要登录后才可以回帖 登录 | 立 即 注 册

本版积分规则

技术支持
在线咨询
QQ咨询
3351529868

QQ|手机版|小黑屋|捡代码论坛-专业源码分享下载 ( 陕ICP备15015195号-1|网站地图

GMT+8, 2024-9-28 19:40

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表