2022-06-16 23:10:45 +02:00
|
|
|
Prototype={}
|
|
|
|
|
|
|
|
function Prototype:init() end -- dummy constructor
|
|
|
|
|
|
|
|
-- function for injecting our functionality into an table
|
|
|
|
function Prototype:__set_parent(newparent)
|
|
|
|
setmetatable(self, {
|
|
|
|
-- non-overwritten keys are to be fetched from parent
|
|
|
|
__index=newparent,
|
|
|
|
-- construct a child when called directly
|
|
|
|
__call=function(parent, ...)
|
|
|
|
local newchild = {}
|
|
|
|
self.__set_parent(newchild, parent)
|
|
|
|
newchild:init(...)
|
|
|
|
return newchild
|
|
|
|
end
|
|
|
|
})
|
|
|
|
end
|
|
|
|
|
|
|
|
-- serialize our object into a string
|
|
|
|
function Prototype:__tostring()
|
|
|
|
local t=type(self)
|
|
|
|
if t=="table" then
|
|
|
|
local r=""
|
|
|
|
-- load and sort table keys
|
|
|
|
local tkeys={}
|
|
|
|
for k in pairs(self) do table.insert(tkeys, k) end
|
2022-06-18 01:40:50 +02:00
|
|
|
table.sort(tkeys, function(a,b) return tostring(a)<tostring(b) end)
|
2022-06-16 23:10:45 +02:00
|
|
|
-- iterate over our table
|
|
|
|
for _,k in ipairs(tkeys) do
|
|
|
|
local v = Prototype.__tostring(self[k])
|
|
|
|
-- ignore nil values, they unset the key anyways
|
|
|
|
if v~= nil and v ~= "nil" then
|
|
|
|
if r~="" then r=r.."," end
|
|
|
|
-- short format: foo="bar", saves bytes
|
|
|
|
if type(k)=="string" and k:match("^[%l%u_][%w_]*$") then
|
|
|
|
r=r..k.."="..v
|
|
|
|
-- long format: ["foo"]="bar", allows weird keys
|
|
|
|
else
|
|
|
|
r=r.."["..Prototype.__tostring(k).."]="..v
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return "{"..r.."}"
|
2022-06-18 01:41:07 +02:00
|
|
|
elseif t=="number" or t=="boolean" then
|
2022-06-16 23:10:45 +02:00
|
|
|
return tostring(self)
|
|
|
|
elseif t=="string" then
|
2022-06-19 18:20:59 +02:00
|
|
|
return ("%q"):format(self)
|
2022-06-16 23:10:45 +02:00
|
|
|
else
|
|
|
|
return "nil"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
Prototype:__set_parent(nil) -- enable __call
|