You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
179 lines
3.7 KiB
Lua
179 lines
3.7 KiB
Lua
-- 嵌套表
|
|
local class = class
|
|
local select = select
|
|
local next = next
|
|
local setmetatable = setmetatable
|
|
local assert = assert
|
|
local type = type
|
|
local getmetatable = getmetatable
|
|
local pairs = pairs
|
|
local xpcall = xpcall
|
|
local tostring = tostring
|
|
local table_insert = table.insert
|
|
--------------------------------------------------
|
|
local NestingTable = class("NestingTable")
|
|
|
|
-- 断言类型
|
|
local function isKind(obj, strKind)
|
|
local mt
|
|
if type(obj) == "table" then
|
|
mt = getmetatable(obj)
|
|
end
|
|
|
|
while mt do
|
|
if mt.__cname == strKind then
|
|
return true
|
|
end
|
|
mt = mt.super
|
|
end
|
|
|
|
return false
|
|
end
|
|
|
|
local function exception(e)
|
|
-- Log.e(e)
|
|
return e
|
|
end
|
|
|
|
local function xxpcall(f, ...)
|
|
return xpcall(f, exception, ...)
|
|
end
|
|
|
|
--- 构造函数
|
|
-- @param deep 深度
|
|
-- @param bWeak 弱引用
|
|
function NestingTable:initialize(deep, bWeak)
|
|
self.m_deep = deep or 1
|
|
self.m_bWeak = bWeak == true
|
|
self.m_count = 0
|
|
self.m_items = {}
|
|
|
|
self:clear()
|
|
end
|
|
|
|
--- 新增对象
|
|
-- @param item 对象实例
|
|
-- @param k 键值
|
|
-- @param ... 多个键值
|
|
function NestingTable:add(item, k, ...)
|
|
if not item or not k or select("#", k, ...) ~= self.m_deep then
|
|
-- Log.w("NestingTable add nil!")
|
|
return
|
|
end
|
|
|
|
if ... then
|
|
local _item = self:get(k)
|
|
if not _item then
|
|
local deep = self.m_deep - 1
|
|
_item = NestingTable.new(deep, self.m_bWeak)
|
|
self.m_items[k] = _item
|
|
end
|
|
_item:add(item, ...)
|
|
else
|
|
self.m_items[k] = item
|
|
-- Log.d("NestingTable add", k, item)
|
|
end
|
|
end
|
|
|
|
--- 删除对象
|
|
-- @param k 键值
|
|
-- @param ... 多个键值
|
|
function NestingTable:remove(k, ...)
|
|
if not k or select("#", k, ...) ~= self.m_deep then
|
|
-- Log.w("NestingTable remove k nil!")
|
|
return
|
|
end
|
|
|
|
local _item = self:get(k)
|
|
if not ... then
|
|
-- Log.d("NestingTable remove", k, _item)
|
|
self.m_items[k] = nil
|
|
elseif _item then
|
|
_item:remove(...)
|
|
if not next(_item:getItems()) then
|
|
self.m_items[k] = nil
|
|
end
|
|
end
|
|
end
|
|
|
|
--- 取对象
|
|
-- @param k 键值
|
|
-- @param ... 多个键值
|
|
-- @return 被管理对象实例
|
|
function NestingTable:get(k, ...)
|
|
if not k then
|
|
-- Log.w("NestingTable get k nil!")
|
|
return
|
|
end
|
|
|
|
local item = self.m_items[k]
|
|
if not ... then
|
|
return item
|
|
end
|
|
|
|
if item then
|
|
return item:get(...)
|
|
end
|
|
end
|
|
|
|
--- 取所有对象
|
|
function NestingTable:getItems()
|
|
return self.m_items
|
|
end
|
|
|
|
function NestingTable:clear()
|
|
if self.m_deep <= 1 then
|
|
self.m_items = self.m_bWeak and setmetatable({}, {
|
|
__mode = "v",
|
|
}) or {}
|
|
else
|
|
self.m_items = {}
|
|
end
|
|
end
|
|
|
|
function NestingTable:traverse(closure)
|
|
assert(closure)
|
|
|
|
for _, item in pairs(self.m_items) do
|
|
if isKind(item, "NestingTable") then
|
|
item:traverse(closure)
|
|
else
|
|
xxpcall(closure, item)
|
|
end
|
|
end
|
|
end
|
|
|
|
function NestingTable:pack(packName, ...)
|
|
local ret = {}
|
|
|
|
for key, item in pairs(self.m_items) do
|
|
if isKind(item, "NestingTable") then
|
|
ret[tostring(key)] = item:pack(packName, ...)
|
|
elseif packName then
|
|
ret[tostring(key)] = item[packName](item, ...)
|
|
else
|
|
ret[tostring(key)] = item
|
|
end
|
|
end
|
|
|
|
return ret
|
|
end
|
|
|
|
function NestingTable:packKey(deep)
|
|
assert(deep, "packKey")
|
|
|
|
local ret = {}
|
|
|
|
for key, item in pairs(self.m_items) do
|
|
if deep <= self.m_deep then
|
|
ret[tostring(key)] = item:packKey(deep)
|
|
else
|
|
table_insert(ret, key)
|
|
end
|
|
end
|
|
|
|
return ret
|
|
end
|
|
|
|
return NestingTable
|