619 lines
14 KiB
Lua
619 lines
14 KiB
Lua
--[[
|
||
|
||
Copyright (c) 2014-2017 Chukong Technologies Inc.
|
||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||
of this software and associated documentation files (the "Software"), to deal
|
||
in the Software without restriction, including without limitation the rights
|
||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||
copies of the Software, and to permit persons to whom the Software is
|
||
furnished to do so, subject to the following conditions:
|
||
|
||
The above copyright notice and this permission notice shall be included in
|
||
all copies or substantial portions of the Software.
|
||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||
THE SOFTWARE.
|
||
|
||
]]
|
||
|
||
function checknumber(value, base)
|
||
return tonumber(value, base) or 0
|
||
end
|
||
|
||
function checkint(value)
|
||
return math.round(checknumber(value))
|
||
end
|
||
|
||
function checkbool(value)
|
||
return (value ~= nil and value ~= false)
|
||
end
|
||
|
||
function checktable(value)
|
||
if type(value) ~= "table" then value = {} end
|
||
return value
|
||
end
|
||
|
||
function clone(object)
|
||
local lookup_table = {}
|
||
local function _copy(object)
|
||
if type(object) ~= "table" then
|
||
return object
|
||
elseif lookup_table[object] then
|
||
return lookup_table[object]
|
||
end
|
||
local newObject = {}
|
||
lookup_table[object] = newObject
|
||
for key, value in pairs(object) do
|
||
newObject[_copy(key)] = _copy(value)
|
||
end
|
||
return setmetatable(newObject, getmetatable(object))
|
||
end
|
||
return _copy(object)
|
||
end
|
||
|
||
local function emptyFunction()
|
||
end
|
||
|
||
function class(classname, super)
|
||
local cls = {__cname = classname}
|
||
|
||
if super then
|
||
local superType = type(super)
|
||
assert(superType == "table",
|
||
string.format("class() - create class \"%s\" with invalid super class type \"%s\"",
|
||
classname, superType))
|
||
cls.super = super
|
||
setmetatable(cls, {__index = super})
|
||
end
|
||
|
||
cls.ctor = emptyFunction
|
||
cls.new = function(_, ...)
|
||
local instance = {}
|
||
setmetatable(instance, {__index = cls})
|
||
instance.class = cls
|
||
if instance.super then
|
||
local _constructor
|
||
_constructor = function(c, ...)
|
||
if c.super then
|
||
_constructor(c.super, ...)
|
||
end
|
||
c.ctor(instance, ...)
|
||
end
|
||
_constructor(instance.super, ...)
|
||
end
|
||
instance:ctor(...)
|
||
return instance
|
||
end
|
||
cls.create = cls.new
|
||
return cls
|
||
end
|
||
|
||
function iskindof(obj, classname)
|
||
local t = type(obj)
|
||
if t ~= "table" then return false end
|
||
|
||
local mt = getmetatable(obj)
|
||
if mt then
|
||
local __index = rawget(mt, "__index")
|
||
if type(__index) == "table" and rawget(__index, "__cname") == classname then return true end
|
||
end
|
||
|
||
if rawget(obj, "__cname") == classname then return true end
|
||
|
||
local super = obj.super
|
||
while super do
|
||
if rawget(super, "__cname") == classname then return true end
|
||
super = super.super
|
||
end
|
||
return false
|
||
end
|
||
|
||
function handler(obj, method)
|
||
return function(...)
|
||
return method(obj, ...)
|
||
end
|
||
end
|
||
|
||
function math.newrandomseed()
|
||
local ok, socket = pcall(function()
|
||
return require("socket")
|
||
end)
|
||
|
||
if ok then
|
||
math.randomseed(socket.gettime() * 1000)
|
||
else
|
||
math.randomseed(os.time())
|
||
end
|
||
math.random()
|
||
math.random()
|
||
math.random()
|
||
math.random()
|
||
end
|
||
|
||
function math.round(value)
|
||
value = checknumber(value)
|
||
return math.floor(value + 0.5)
|
||
end
|
||
|
||
function math.clamp(value, min, max)
|
||
if value < min then
|
||
return min
|
||
end
|
||
if value > max then
|
||
return max
|
||
end
|
||
return value
|
||
end
|
||
|
||
local pi_div_180 = math.pi / 180
|
||
function math.angle2radian(angle)
|
||
return angle * pi_div_180
|
||
end
|
||
|
||
function math.radian2angle(radian)
|
||
return radian * 180 / math.pi
|
||
end
|
||
|
||
function io.exists(path)
|
||
local file = io.open(path, "r")
|
||
if file then
|
||
io.close(file)
|
||
return true
|
||
end
|
||
return false
|
||
end
|
||
|
||
function io.readfile(path)
|
||
local file = io.open(path, "r")
|
||
if file then
|
||
local content = file:read("*a")
|
||
io.close(file)
|
||
return content
|
||
end
|
||
return nil
|
||
end
|
||
|
||
function io.writefile(path, content, mode)
|
||
mode = mode or "w+b"
|
||
local file = io.open(path, mode)
|
||
if file then
|
||
if file:write(content) == nil then return false end
|
||
io.close(file)
|
||
return true
|
||
else
|
||
return false
|
||
end
|
||
end
|
||
|
||
function io.pathinfo(path)
|
||
local pos = string.len(path)
|
||
local extpos = pos + 1
|
||
while pos > 0 do
|
||
local b = string.byte(path, pos)
|
||
if b == 46 then -- 46 = char "."
|
||
extpos = pos
|
||
elseif b == 47 then -- 47 = char "/"
|
||
break
|
||
end
|
||
pos = pos - 1
|
||
end
|
||
|
||
local dirname = string.sub(path, 1, pos)
|
||
local filename = string.sub(path, pos + 1)
|
||
extpos = extpos - pos
|
||
local basename = string.sub(filename, 1, extpos - 1)
|
||
local extname = string.sub(filename, extpos)
|
||
return {
|
||
dirname = dirname,
|
||
filename = filename,
|
||
basename = basename,
|
||
extname = extname
|
||
}
|
||
end
|
||
|
||
function io.filesize(path)
|
||
local size = false
|
||
local file = io.open(path, "r")
|
||
if file then
|
||
local current = file:seek()
|
||
size = file:seek("end")
|
||
file:seek("set", current)
|
||
io.close(file)
|
||
end
|
||
return size
|
||
end
|
||
|
||
function table.nums(t)
|
||
local count = 0
|
||
for k, v in pairs(t) do
|
||
count = count + 1
|
||
end
|
||
return count
|
||
end
|
||
|
||
function table.keys(hashtable)
|
||
local keys = {}
|
||
for k, v in pairs(hashtable) do
|
||
keys[#keys + 1] = k
|
||
end
|
||
return keys
|
||
end
|
||
|
||
function table.values(hashtable)
|
||
local values = {}
|
||
for k, v in pairs(hashtable) do
|
||
values[#values + 1] = v
|
||
end
|
||
return values
|
||
end
|
||
|
||
function table.merge(dest, src)
|
||
for k, v in pairs(src) do
|
||
dest[k] = v
|
||
end
|
||
end
|
||
|
||
function table.insertto(dest, src, begin)
|
||
begin = checkint(begin)
|
||
if begin <= 0 then
|
||
begin = #dest + 1
|
||
end
|
||
|
||
local len = #src
|
||
for i = 0, len - 1 do
|
||
dest[i + begin] = src[i + 1]
|
||
end
|
||
end
|
||
|
||
function table.indexof(array, value, begin)
|
||
for i = begin or 1, #array do
|
||
if array[i] == value then return i end
|
||
end
|
||
return false
|
||
end
|
||
|
||
function table.keyof(hashtable, value)
|
||
for k, v in pairs(hashtable) do
|
||
if v == value then return k end
|
||
end
|
||
return nil
|
||
end
|
||
|
||
function table.removebyvalue(array, value, removeall)
|
||
local c, i, max = 0, 1, #array
|
||
while i <= max do
|
||
if array[i] == value then
|
||
table.remove(array, i)
|
||
c = c + 1
|
||
i = i - 1
|
||
max = max - 1
|
||
if not removeall then break end
|
||
end
|
||
i = i + 1
|
||
end
|
||
return c
|
||
end
|
||
|
||
function table.map(t, fn)
|
||
for k, v in pairs(t) do
|
||
t[k] = fn(v, k)
|
||
end
|
||
end
|
||
|
||
function table.walk(t, fn)
|
||
for k,v in pairs(t) do
|
||
fn(v, k)
|
||
end
|
||
end
|
||
|
||
function table.filter(t, fn)
|
||
for k, v in pairs(t) do
|
||
if not fn(v, k) then t[k] = nil end
|
||
end
|
||
end
|
||
|
||
function table.unique(t, bArray)
|
||
local check = {}
|
||
local n = {}
|
||
local idx = 1
|
||
for k, v in pairs(t) do
|
||
if not check[v] then
|
||
if bArray then
|
||
n[idx] = v
|
||
idx = idx + 1
|
||
else
|
||
n[k] = v
|
||
end
|
||
check[v] = true
|
||
end
|
||
end
|
||
return n
|
||
end
|
||
|
||
function table.containValue(t, value)
|
||
for k, v in pairs(t) do
|
||
if v == value then
|
||
return true
|
||
end
|
||
end
|
||
return false
|
||
end
|
||
|
||
function table.shuffle(t)
|
||
if type(t)~="table" then
|
||
return
|
||
end
|
||
local tab = {}
|
||
local index = 1
|
||
while #t ~= 0 do
|
||
local n = math.random(1, #t)
|
||
if t[n] ~= nil then
|
||
tab[index] = t[n]
|
||
table.remove(t,n)
|
||
index = index + 1
|
||
end
|
||
end
|
||
return tab
|
||
end
|
||
|
||
function table.shuffleBySeed(t, seed)
|
||
if type(t)~="table" then
|
||
return
|
||
end
|
||
local tab = {}
|
||
local index = 1
|
||
while #t ~= 0 do
|
||
local n = GFunc.getRandomIndexBySeed(seed, 1, #t)
|
||
if t[n] ~= nil then
|
||
tab[index] = t[n]
|
||
table.remove(t,n)
|
||
index = index + 1
|
||
end
|
||
end
|
||
return tab
|
||
end
|
||
|
||
function table.clear(t)
|
||
if not t then
|
||
return
|
||
end
|
||
if type(t) ~= "table" then
|
||
return
|
||
end
|
||
for key, v in pairs(t) do
|
||
t[key] = nil
|
||
end
|
||
end
|
||
|
||
function table.clearOrCreate(t)
|
||
if not t then
|
||
return {}
|
||
end
|
||
if type(t) ~= "table" then
|
||
return {}
|
||
end
|
||
table.clear(t)
|
||
return t
|
||
end
|
||
|
||
---查找一个满足条件的元素
|
||
function table.find(t, predict)
|
||
for k, v in pairs(t) do
|
||
if predict(v) then
|
||
return v, k
|
||
end
|
||
end
|
||
end
|
||
|
||
---浅拷贝
|
||
function table.refCopy(t)
|
||
if not t then return nil end
|
||
local copy = {}
|
||
for i,v in pairs(t) do
|
||
copy[i] = v
|
||
end
|
||
return copy
|
||
end
|
||
|
||
---将array'from' insert到to
|
||
function table.addArray(to, from)
|
||
if not to or not from then return end
|
||
for _, v in ipairs(from) do
|
||
table.insert(to, v)
|
||
end
|
||
return to
|
||
end
|
||
|
||
---将array'from' insert到to
|
||
function table.addDic(to, from)
|
||
if not to or not from then return end
|
||
for _, v in pairs(from) do
|
||
to[_] = v
|
||
end
|
||
return to
|
||
end
|
||
|
||
--tbl需要删除对象的表, func用于判断是否是需要删除的对象的函数,
|
||
--func返回两个参数,1、是否remove 2、是否继续
|
||
---该函数会copy一次table
|
||
function table.removeEx(tbl, func)
|
||
if tbl == nil or func == nil then
|
||
return tbl
|
||
end
|
||
local newTbl = {}
|
||
for k, v in pairs(tbl) do
|
||
local needRemove, continue = func(k, v)
|
||
|
||
if not needRemove and v then
|
||
newTbl[#newTbl + 1] = v
|
||
end
|
||
|
||
if not continue then
|
||
break
|
||
end
|
||
end
|
||
return newTbl
|
||
end
|
||
|
||
--- 反转阵列
|
||
function table.revert(tableArray)
|
||
local length = #tableArray
|
||
local half = length / 2
|
||
local temp
|
||
for i = 1, half do
|
||
temp = tableArray[i]
|
||
tableArray[i] = tableArray[length - i + 1]
|
||
tableArray[length - i + 1] = temp
|
||
end
|
||
return tableArray
|
||
end
|
||
|
||
---满足任意条件
|
||
function table.any(tbl, func)
|
||
for _, v in pairs(tbl) do
|
||
if func(v) then
|
||
return true
|
||
end
|
||
end
|
||
return false
|
||
end
|
||
|
||
--- 遍历
|
||
function table.foreach(tbl, func)
|
||
for k, v in pairs(tbl) do
|
||
func(k, v)
|
||
end
|
||
end
|
||
|
||
--- 计算每一个val的满足条件的count
|
||
function table.count(tbl, func)
|
||
local result = 0
|
||
for _, v in pairs(tbl) do
|
||
result = result + func(v)
|
||
end
|
||
return result
|
||
end
|
||
|
||
|
||
string._htmlspecialchars_set = {}
|
||
string._htmlspecialchars_set["&"] = "&"
|
||
string._htmlspecialchars_set["\""] = """
|
||
string._htmlspecialchars_set["'"] = "'"
|
||
string._htmlspecialchars_set["<"] = "<"
|
||
string._htmlspecialchars_set[">"] = ">"
|
||
|
||
function string.htmlspecialchars(input)
|
||
for k, v in pairs(string._htmlspecialchars_set) do
|
||
input = string.gsub(input, k, v)
|
||
end
|
||
return input
|
||
end
|
||
|
||
function string.restorehtmlspecialchars(input)
|
||
for k, v in pairs(string._htmlspecialchars_set) do
|
||
input = string.gsub(input, v, k)
|
||
end
|
||
return input
|
||
end
|
||
|
||
function string.nl2br(input)
|
||
return string.gsub(input, "\n", "<br />")
|
||
end
|
||
|
||
function string.text2html(input)
|
||
input = string.gsub(input, "\t", " ")
|
||
input = string.htmlspecialchars(input)
|
||
input = string.gsub(input, " ", " ")
|
||
input = string.nl2br(input)
|
||
return input
|
||
end
|
||
|
||
function string.split(input, delimiter)
|
||
input = tostring(input)
|
||
delimiter = tostring(delimiter)
|
||
if (delimiter=='') then return false end
|
||
local pos,arr = 0, {}
|
||
-- for each divider found
|
||
for st,sp in function() return string.find(input, delimiter, pos, true) end do
|
||
table.insert(arr, string.sub(input, pos, st - 1))
|
||
pos = sp + 1
|
||
end
|
||
table.insert(arr, string.sub(input, pos))
|
||
return arr
|
||
end
|
||
|
||
function string.ltrim(input)
|
||
return string.gsub(input, "^[ \t\n\r]+", "")
|
||
end
|
||
|
||
function string.rtrim(input)
|
||
return string.gsub(input, "[ \t\n\r]+$", "")
|
||
end
|
||
|
||
function string.trim(input)
|
||
input = string.gsub(input, "^[ \t\n\r]+", "")
|
||
return string.gsub(input, "[ \t\n\r]+$", "")
|
||
end
|
||
|
||
function string.ucfirst(input)
|
||
return string.upper(string.sub(input, 1, 1)) .. string.sub(input, 2)
|
||
end
|
||
|
||
local function urlencodechar(char)
|
||
return "%" .. string.format("%02X", string.byte(char))
|
||
end
|
||
function string.urlencode(input)
|
||
-- convert line endings
|
||
input = string.gsub(tostring(input), "\n", "\r\n")
|
||
-- escape all characters but alphanumeric, '.' and '-'
|
||
input = string.gsub(input, "([^%w%.%- ])", urlencodechar)
|
||
-- convert spaces to "+" symbols
|
||
return string.gsub(input, " ", "+")
|
||
end
|
||
|
||
function string.urldecode(input)
|
||
input = string.gsub (input, "+", " ")
|
||
input = string.gsub (input, "%%(%x%x)", function(h) return string.char(checknumber(h,16)) end)
|
||
input = string.gsub (input, "\r\n", "\n")
|
||
return input
|
||
end
|
||
|
||
function string.utf8len(input)
|
||
local len = string.len(input)
|
||
local left = len
|
||
local cnt = 0
|
||
local arr = {0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc}
|
||
while left ~= 0 do
|
||
local tmp = string.byte(input, -left)
|
||
local i = #arr
|
||
while arr[i] do
|
||
if tmp >= arr[i] then
|
||
left = left - i
|
||
break
|
||
end
|
||
i = i - 1
|
||
end
|
||
cnt = cnt + 1
|
||
end
|
||
return cnt
|
||
end
|
||
|
||
function string.formatnumberthousands(num)
|
||
local formatted = tostring(checknumber(num))
|
||
local k
|
||
while true do
|
||
formatted, k = string.gsub(formatted, "^(-?%d+)(%d%d%d)", '%1,%2')
|
||
if k == 0 then break end
|
||
end
|
||
return formatted
|
||
end
|
||
|
||
function string.isEmptyOrNil(str)
|
||
return not str or #str == 0
|
||
end |