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.

127 lines
2.8 KiB
Lua

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

-- enum.lua
--[[提供枚举机制
示例:
local enum = require(enum)
用法1
local TEST1 = enum("TEST1", 0, "ONE", "THREE", "TWO")
print(TEST1.TWO)
用法2
local TEST2 = enum("TEST2", 1, "ONE", "THREE", "TWO")
TEST2.FOUR = TEST2()
print(TEST2.TWO, TEST2.FOUR)
用法3
local TEST3 = enum("TEST3", 2)
TEST3("ONE")
TEST3("TWO")
TEST3("FOUR", 4)
local five = TEST3("FIVE")
print(TEST3.TWO, TEST3.FOUR, TEST3.FIVE, five)
--]]
local skynet = require "skynet"
local ipairs = ipairs
local rawget = rawget
local rawset = rawset
local tconcat = table.concat
local sformat = string.format
local dgetinfo = debug.getinfo
local setmetatable = setmetatable
local enum_tpls = {}
local function enum_tostring(eo)
return sformat("enum:%s(max:%s, elems: {%s})", eo.__name, eo.__vmax, tconcat(eo.__vlist, ","))
end
local function enum_new(emobj, field, value)
value = value or emobj.__vmax
if field then
emobj.__vlist[field] = value
if value >= emobj.__vmax then
emobj.__vmax = value + 1
end
end
return value
end
local function enum_index(emobj, field)
return emobj.__vlist[field]
end
local function enum_newindex(emobj, field, value)
local vlist = emobj.__vlist
if vlist[field] then
skynet.error("enum %s redefine field %s!", emobj.__name, field)
end
vlist[field] = value
if value >= emobj.__vmax then
emobj.__vmax = value + 1
end
end
local enumMT = {
__call = enum_new,
__index = enum_index,
__newindex = enum_newindex,
__tostring = enum_tostring,
}
local function enum_init(emobj, base, ...)
emobj.__vlist = {}
emobj.__vmax = base
for _, field in ipairs({...}) do
emobj.__vlist[field] = emobj.__vmax
emobj.__vmax = emobj.__vmax + 1
end
end
local function enum_list(ems)
local elist = rawget(ems, "__list")
if not elist then
elist = {}
rawset(ems, "__list", elist)
end
return elist
end
local function new(ems, name, base, ...)
local info = dgetinfo(2, "S")
local moudle = info.short_src
local lists = enum_list(ems)
local eobj = lists[name]
if eobj then
if eobj.__moudle ~= moudle then
skynet.error("enum %s redefined! moudle:%s", name, moudle)
end
else
eobj = {
__name = name,
__moudle = moudle,
}
end
enum_init(eobj, base, ...)
setmetatable(eobj, enumMT)
lists[name] = eobj
return eobj
end
local function index(ems, field)
local lists = enum_list(ems)
return lists[field]
end
local MT = {
__call = new,
__index = index,
}
setmetatable(enum_tpls, MT)
function Enum(name, base, ...)
if base then
return enum_tpls(name, base, ...)
end
-- 没有传base参数表示查询
return enum_tpls[name]
end