2014-12-27 11:59:14 +08:00
|
|
|
--[[
|
|
|
|
|
|
|
|
Copyright (c) 2011-2014 chukong-inc.com
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
|
|
]]
|
|
|
|
|
|
|
|
local function dump_value_(v)
|
|
|
|
if type(v) == "string" then
|
|
|
|
v = "\"" .. v .. "\""
|
|
|
|
end
|
|
|
|
return tostring(v)
|
|
|
|
end
|
|
|
|
|
|
|
|
function dump(value, desciption, nesting)
|
|
|
|
if type(nesting) ~= "number" then nesting = 3 end
|
|
|
|
|
|
|
|
local lookupTable = {}
|
|
|
|
local result = {}
|
|
|
|
|
|
|
|
local traceback = string.split(debug.traceback("", 2), "\n")
|
|
|
|
print("dump from: " .. string.trim(traceback[3]))
|
|
|
|
|
|
|
|
local function dump_(value, desciption, indent, nest, keylen)
|
|
|
|
desciption = desciption or "<var>"
|
|
|
|
local spc = ""
|
|
|
|
if type(keylen) == "number" then
|
|
|
|
spc = string.rep(" ", keylen - string.len(dump_value_(desciption)))
|
|
|
|
end
|
|
|
|
if type(value) ~= "table" then
|
|
|
|
result[#result +1 ] = string.format("%s%s%s = %s", indent, dump_value_(desciption), spc, dump_value_(value))
|
|
|
|
elseif lookupTable[tostring(value)] then
|
|
|
|
result[#result +1 ] = string.format("%s%s%s = *REF*", indent, dump_value_(desciption), spc)
|
|
|
|
else
|
|
|
|
lookupTable[tostring(value)] = true
|
|
|
|
if nest > nesting then
|
|
|
|
result[#result +1 ] = string.format("%s%s = *MAX NESTING*", indent, dump_value_(desciption))
|
|
|
|
else
|
|
|
|
result[#result +1 ] = string.format("%s%s = {", indent, dump_value_(desciption))
|
|
|
|
local indent2 = indent.." "
|
|
|
|
local keys = {}
|
|
|
|
local keylen = 0
|
|
|
|
local values = {}
|
|
|
|
for k, v in pairs(value) do
|
|
|
|
keys[#keys + 1] = k
|
|
|
|
local vk = dump_value_(k)
|
|
|
|
local vkl = string.len(vk)
|
|
|
|
if vkl > keylen then keylen = vkl end
|
|
|
|
values[k] = v
|
|
|
|
end
|
|
|
|
table.sort(keys, function(a, b)
|
|
|
|
if type(a) == "number" and type(b) == "number" then
|
|
|
|
return a < b
|
|
|
|
else
|
|
|
|
return tostring(a) < tostring(b)
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
for i, k in ipairs(keys) do
|
|
|
|
dump_(values[k], k, indent2, nest + 1, keylen)
|
|
|
|
end
|
|
|
|
result[#result +1] = string.format("%s}", indent)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
dump_(value, desciption, "- ", 1)
|
|
|
|
|
|
|
|
for i, line in ipairs(result) do
|
|
|
|
print(line)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function printf(fmt, ...)
|
|
|
|
print(string.format(tostring(fmt), ...))
|
|
|
|
end
|
|
|
|
|
|
|
|
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 isset(hashtable, key)
|
|
|
|
local t = type(hashtable)
|
|
|
|
return (t == "table" or t == "userdata") and hashtable[key] ~= nil
|
|
|
|
end
|
|
|
|
|
|
|
|
local setmetatableindex_
|
|
|
|
setmetatableindex_ = function(t, index)
|
|
|
|
if type(t) == "userdata" then
|
|
|
|
local peer = tolua.getpeer(t)
|
|
|
|
if not peer then
|
|
|
|
tolua.setpeer(t, index)
|
|
|
|
else
|
|
|
|
setmetatableindex_(peer, index)
|
|
|
|
end
|
|
|
|
else
|
|
|
|
local mt = getmetatable(t)
|
|
|
|
if not mt then mt = {} end
|
|
|
|
if not mt.__index then
|
|
|
|
mt.__index = index
|
|
|
|
setmetatable(t, mt)
|
|
|
|
elseif mt.__index ~= index then
|
|
|
|
setmetatableindex_(mt, index)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
setmetatableindex = setmetatableindex_
|
2014-10-11 01:27:12 +08:00
|
|
|
|
2014-03-10 14:04:58 +08:00
|
|
|
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
|
2014-12-27 11:59:14 +08:00
|
|
|
local newObject = {}
|
|
|
|
lookup_table[object] = newObject
|
2014-03-10 14:04:58 +08:00
|
|
|
for key, value in pairs(object) do
|
2014-12-27 11:59:14 +08:00
|
|
|
newObject[_copy(key)] = _copy(value)
|
2014-03-10 14:04:58 +08:00
|
|
|
end
|
2014-12-27 11:59:14 +08:00
|
|
|
return setmetatable(newObject, getmetatable(object))
|
2014-03-10 14:04:58 +08:00
|
|
|
end
|
|
|
|
return _copy(object)
|
|
|
|
end
|
|
|
|
|
2014-12-27 11:59:14 +08:00
|
|
|
function class(classname, ...)
|
|
|
|
local cls = {__cname = classname}
|
2014-03-10 14:04:58 +08:00
|
|
|
|
2014-12-27 11:59:14 +08:00
|
|
|
local supers = {...}
|
|
|
|
for _, super in ipairs(supers) do
|
|
|
|
local superType = type(super)
|
|
|
|
assert(superType == "nil" or superType == "table" or superType == "function",
|
|
|
|
string.format("class() - create class \"%s\" with invalid super class type \"%s\"",
|
|
|
|
classname, superType))
|
|
|
|
|
|
|
|
if superType == "function" then
|
|
|
|
assert(cls.__create == nil,
|
|
|
|
string.format("class() - create class \"%s\" with more than one creating function",
|
|
|
|
classname));
|
|
|
|
-- if super is function, set it to __create
|
|
|
|
cls.__create = super
|
|
|
|
elseif superType == "table" then
|
|
|
|
if super[".isclass"] then
|
|
|
|
-- super is native class
|
|
|
|
assert(cls.__create == nil,
|
|
|
|
string.format("class() - create class \"%s\" with more than one creating function or native class",
|
|
|
|
classname));
|
|
|
|
cls.__create = function() return super:create() end
|
|
|
|
else
|
|
|
|
-- super is pure lua class
|
|
|
|
cls.__supers = cls.__supers or {}
|
|
|
|
cls.__supers[#cls.__supers + 1] = super
|
|
|
|
if not cls.super then
|
|
|
|
-- set first super pure lua class as class.super
|
|
|
|
cls.super = super
|
|
|
|
end
|
|
|
|
end
|
|
|
|
else
|
|
|
|
error(string.format("class() - create class \"%s\" with invalid super type",
|
|
|
|
classname), 0)
|
|
|
|
end
|
2014-03-10 14:04:58 +08:00
|
|
|
end
|
|
|
|
|
2014-12-27 11:59:14 +08:00
|
|
|
cls.__index = cls
|
|
|
|
if not cls.__supers or #cls.__supers == 1 then
|
|
|
|
setmetatable(cls, {__index = cls.super})
|
|
|
|
else
|
|
|
|
setmetatable(cls, {__index = function(_, key)
|
|
|
|
local supers = cls.__supers
|
|
|
|
for i = 1, #supers do
|
|
|
|
local super = supers[i]
|
|
|
|
if super[key] then return super[key] end
|
|
|
|
end
|
|
|
|
end})
|
|
|
|
end
|
2014-03-10 14:04:58 +08:00
|
|
|
|
2014-12-27 11:59:14 +08:00
|
|
|
if not cls.ctor then
|
|
|
|
-- add default constructor
|
|
|
|
cls.ctor = function() end
|
|
|
|
end
|
|
|
|
cls.new = function(...)
|
|
|
|
local instance
|
|
|
|
if cls.__create then
|
|
|
|
instance = cls.__create(...)
|
2014-03-10 14:04:58 +08:00
|
|
|
else
|
2014-12-27 11:59:14 +08:00
|
|
|
instance = {}
|
2014-03-10 14:04:58 +08:00
|
|
|
end
|
2014-12-27 11:59:14 +08:00
|
|
|
setmetatableindex(instance, cls)
|
|
|
|
instance.class = cls
|
|
|
|
instance:ctor(...)
|
|
|
|
return instance
|
|
|
|
end
|
|
|
|
cls.create = function(_, ...)
|
|
|
|
return cls.new(...)
|
|
|
|
end
|
2014-03-10 14:04:58 +08:00
|
|
|
|
2014-12-27 11:59:14 +08:00
|
|
|
return cls
|
|
|
|
end
|
2014-03-10 14:04:58 +08:00
|
|
|
|
2014-12-27 11:59:14 +08:00
|
|
|
local iskindof_
|
|
|
|
iskindof_ = function(cls, name)
|
|
|
|
if cls.__cname == name then return true end
|
|
|
|
if not cls.__supers then return false end
|
|
|
|
for _, super in ipairs(cls.__supers) do
|
|
|
|
if iskindof_(super, name) then return true end
|
|
|
|
end
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
|
|
|
|
function iskindof(obj, classname)
|
|
|
|
local t = type(obj)
|
|
|
|
assert(t == "table" or t == "userdata", "iskindof() - invalid object")
|
|
|
|
local mt = getmetatable(obj)
|
|
|
|
if mt then
|
|
|
|
return iskindof_(mt, classname)
|
|
|
|
end
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
|
|
|
|
function import(moduleName, currentModuleName)
|
|
|
|
local currentModuleNameParts
|
|
|
|
local moduleFullName = moduleName
|
|
|
|
local offset = 1
|
|
|
|
|
|
|
|
while true do
|
|
|
|
if string.byte(moduleName, offset) ~= 46 then -- .
|
|
|
|
moduleFullName = string.sub(moduleName, offset)
|
|
|
|
if currentModuleNameParts and #currentModuleNameParts > 0 then
|
|
|
|
moduleFullName = table.concat(currentModuleNameParts, ".") .. "." .. moduleFullName
|
|
|
|
end
|
|
|
|
break
|
2014-03-10 14:04:58 +08:00
|
|
|
end
|
2014-12-27 11:59:14 +08:00
|
|
|
offset = offset + 1
|
2014-03-10 14:04:58 +08:00
|
|
|
|
2014-12-27 11:59:14 +08:00
|
|
|
if not currentModuleNameParts then
|
|
|
|
if not currentModuleName then
|
|
|
|
local n,v = debug.getlocal(3, 1)
|
|
|
|
currentModuleName = v
|
|
|
|
end
|
2014-03-10 14:04:58 +08:00
|
|
|
|
2014-12-27 11:59:14 +08:00
|
|
|
currentModuleNameParts = string.split(currentModuleName, ".")
|
2014-03-10 14:04:58 +08:00
|
|
|
end
|
2014-12-27 11:59:14 +08:00
|
|
|
table.remove(currentModuleNameParts, #currentModuleNameParts)
|
2014-03-10 14:04:58 +08:00
|
|
|
end
|
|
|
|
|
2014-12-27 11:59:14 +08:00
|
|
|
return require(moduleFullName)
|
2014-03-10 14:04:58 +08:00
|
|
|
end
|
|
|
|
|
2014-12-27 11:59:14 +08:00
|
|
|
function handler(obj, method)
|
|
|
|
return function(...)
|
|
|
|
return method(obj, ...)
|
|
|
|
end
|
2014-03-10 14:04:58 +08:00
|
|
|
end
|
|
|
|
|
2014-12-27 11:59:14 +08:00
|
|
|
local c = cc or {}
|
|
|
|
|
|
|
|
c.loaded_packages = {}
|
|
|
|
local loaded_packages = c.loaded_packages
|
|
|
|
|
|
|
|
local function load_(...)
|
|
|
|
local names = {...}
|
|
|
|
assert(#names > 0, "cc.load() - invalid package names")
|
|
|
|
|
|
|
|
local packages = {}
|
|
|
|
for _, name in ipairs(names) do
|
|
|
|
if not loaded_packages[name] then
|
|
|
|
local packageName = string.format("packages.%s.init", name)
|
|
|
|
local cls = require(packageName)
|
|
|
|
assert(cls, string.format("cc.load() - package class \"%s\" load failed", packageName))
|
|
|
|
loaded_packages[name] = cls
|
|
|
|
end
|
|
|
|
packages[#packages + 1] = loaded_packages[name]
|
|
|
|
end
|
|
|
|
return unpack(packages)
|
2014-03-10 14:04:58 +08:00
|
|
|
end
|
2014-12-27 11:59:14 +08:00
|
|
|
c.load = load_
|
|
|
|
|
|
|
|
local function bind_(target, ...)
|
|
|
|
local names = {...}
|
|
|
|
assert(#names > 0, "cc.bind() - invalid package names")
|
|
|
|
|
|
|
|
load_(...)
|
|
|
|
target.components_ = target.components_ or {}
|
|
|
|
for _, name in ipairs(names) do
|
|
|
|
if not target.components_[name] then
|
|
|
|
local cls = loaded_packages[name]
|
|
|
|
for __, depend in ipairs(cls.depends or {}) do
|
|
|
|
if not target.components_[depend] then
|
|
|
|
bind_(target, depend)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
local component = cls:create()
|
|
|
|
target.components_[name] = component
|
|
|
|
component:bind(target)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
return target
|
|
|
|
end
|
|
|
|
c.bind = bind_
|
|
|
|
|
|
|
|
local function unbind_(target, ...)
|
|
|
|
local names = {...}
|
|
|
|
assert(#names > 0, "cc.unbind() - invalid package names")
|
|
|
|
assert(type(target.components_) == "table", "cc.unbind() - target not binding components")
|
|
|
|
|
|
|
|
for _, name in ipairs(names) do
|
|
|
|
local component = target.components_[name]
|
|
|
|
assert(component, string.format("cc.unbind() - component \"%s\" not found", tostring(name)))
|
|
|
|
component:unbind(target)
|
|
|
|
target.components_[name] = nil
|
|
|
|
end
|
|
|
|
|
|
|
|
return target
|
|
|
|
end
|
|
|
|
c.unbind = unbind_
|
|
|
|
|