2019-11-09 16:00:49 +11:00
|
|
|
local serial = {}
|
|
|
|
local local_pairs=function(tbl)
|
|
|
|
local mt=getmetatable(tbl)
|
|
|
|
return (mt and mt.__pairs or pairs)(tbl)
|
2019-01-12 20:48:03 +11:00
|
|
|
end
|
2019-12-16 14:35:11 +11:00
|
|
|
function serial.serialize(value,af) -- serialize *value* into a string. If *af* is true, allow functions. This breaks unserialization.
|
2019-11-09 16:00:49 +11:00
|
|
|
local kw={["and"]=true,["break"]=true,["do"]=true,["else"]=true,["elseif"]=true,["end"]=true,["false"]=true,["for"]=true,["function"]=true,["goto"]=true,["if"]=true,["in"]=true,["local"]=true,["nil"]=true,["not"]=true,["or"]=true,["repeat"]=true,["return"]=true,["then"]=true,["true"]=true,["until"]=true,["while"]=true}
|
|
|
|
local id="^[%a_][%w_]*$"
|
|
|
|
local ts={}
|
|
|
|
local function s(v,l)
|
|
|
|
local t=type(v)
|
|
|
|
if t=="nil" then return "nil"
|
|
|
|
elseif t=="boolean" then return v and "true" or "false"
|
|
|
|
elseif t=="number" then
|
|
|
|
if v~=v then return "0/0"
|
|
|
|
elseif v==math.huge then return "math.huge"
|
|
|
|
elseif v==-math.huge then return "-math.huge"
|
|
|
|
else return tostring(v) end
|
|
|
|
elseif t=="string" then return string.format("%q",v):gsub("\\\n","\\n")
|
|
|
|
elseif t=="table" then
|
|
|
|
if ts[v] then error("tcyc") end
|
|
|
|
ts[v]=true
|
|
|
|
local i,r=1, nil
|
|
|
|
local f=table.pack(local_pairs(v))
|
|
|
|
for k,v in table.unpack(f) do
|
|
|
|
if r then r=r..","..(("\n"..string.rep(" ",l)) or "")
|
|
|
|
else r="{" end
|
|
|
|
local tk=type(k)
|
|
|
|
if tk=="number" and k==i then
|
|
|
|
i=i+1
|
|
|
|
r=r..s(v,l+1)
|
2019-01-12 20:48:03 +11:00
|
|
|
else
|
2019-11-09 16:00:49 +11:00
|
|
|
if tk == "string" and not kw[k] and string.match(k,id) then r=r..k
|
|
|
|
else r=r.."["..s(k,l+1).."]" end
|
|
|
|
r=r.."="..s(v,l+1) end end
|
|
|
|
ts[v]=nil
|
|
|
|
return (r or "{").."}"
|
2019-12-16 14:35:11 +11:00
|
|
|
elseif t=="function" and af then
|
|
|
|
return tostring(v)
|
2019-11-09 16:00:49 +11:00
|
|
|
else error("ut "..t) end end
|
|
|
|
return s(value, 1)
|
2019-01-12 20:48:03 +11:00
|
|
|
end
|
2019-12-16 14:35:11 +11:00
|
|
|
function serial.unserialize(data) -- return *data*, but unserialized
|
2019-11-09 16:00:49 +11:00
|
|
|
checkArg(1, data, "string")
|
|
|
|
local result, reason = load("return " .. data, "=data", _, {math={huge=math.huge}})
|
|
|
|
if not result then return nil, reason end
|
|
|
|
local ok, output = pcall(result)
|
|
|
|
if not ok then return nil, output end
|
|
|
|
return output
|
2019-01-12 20:48:03 +11:00
|
|
|
end
|
2019-11-09 16:00:49 +11:00
|
|
|
return serial
|