Serializer: Sauberer Umgang mit numerischen und zyklischen Tabellen
This commit is contained in:
parent
65c39c6cf7
commit
769cd77195
@ -1,34 +1,54 @@
|
|||||||
-- Tabelle in einen String umwandeln, rekursiv
|
-- Tabelle in einen String umwandeln, rekursiv
|
||||||
-- Funktionen als Lua-Werte werden ignoriert
|
-- Funktionen als Lua-Werte werden ignoriert
|
||||||
function __tostring(tab)
|
-- forbidden ist ein set von elterntabellen zum erkennen von kreisreferenzen
|
||||||
local t=type(tab)
|
function serialize(value, forbidden)
|
||||||
|
forbidden = forbidden or {}
|
||||||
|
local t=type(value)
|
||||||
if t=="table" then
|
if t=="table" then
|
||||||
|
-- Kreisreferenz -> als nil serialisieren
|
||||||
|
if forbidden[value] then return "nil" end
|
||||||
|
forbidden[value]=true
|
||||||
|
|
||||||
local r=""
|
local r=""
|
||||||
-- Tabellen-Keys sammeln und sortieren
|
local numeric_indexes={}
|
||||||
|
|
||||||
|
-- Schnellversion fuer numerische Tabellen
|
||||||
|
for k,v in ipairs(value) do
|
||||||
|
numeric_indexes[k]=true
|
||||||
|
r=r..(r=="" and "" or ",")..serialize(v, forbidden)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Tabellen-Keys fuer assoziative Tabellen sammeln
|
||||||
local tkeys={}
|
local tkeys={}
|
||||||
for k in pairs(tab) do table.insert(tkeys, k) end
|
for k in pairs(value) do
|
||||||
table.sort(tkeys, function(a,b) return tostring(a)<tostring(b) end)
|
-- Nur Keys, die nicht von ipairs() weiter oben schon verarbeitet wurden
|
||||||
-- Durch die Tabelle gehen
|
if numeric_indexes[k]==nil then
|
||||||
for _,k in ipairs(tkeys) do
|
table.insert(tkeys, k)
|
||||||
-- Uns selbst fuer Tabellen-Value aufrufen
|
|
||||||
local v = __tostring(tab[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.."["..__tostring(k).."]="..v
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Tabellen-Keys sortieren
|
||||||
|
table.sort(tkeys, function(a,b) return tostring(a)<tostring(b) end)
|
||||||
|
|
||||||
|
-- Durch die Tabelle gehen
|
||||||
|
for _,k in ipairs(tkeys) do
|
||||||
|
local v=serialize(value[k], forbidden)
|
||||||
|
if v ~= "nil" then
|
||||||
|
r=r
|
||||||
|
-- Komma, um von eventuellen vorherigen Daten abzugrenzen
|
||||||
|
..(r=="" and "" or ",")
|
||||||
|
-- Schluessel entweder direkt als string oder serialisiert in eckigen Klammern
|
||||||
|
..((type(k)=="string" and k:match("^[%l%u_][%w_]*$")) and k or "["..serialize(k).."]")
|
||||||
|
-- Die Zuweisung
|
||||||
|
.."="..v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
forbidden[value]=false
|
||||||
return "{"..r.."}"
|
return "{"..r.."}"
|
||||||
elseif t=="number" or t=="boolean" then
|
elseif t=="number" or t=="boolean" then
|
||||||
return tostring(tab)
|
return tostring(value)
|
||||||
elseif t=="string" then
|
elseif t=="string" then
|
||||||
return ("%q"):format(tab)
|
return string.format("%q",value)
|
||||||
else
|
else
|
||||||
return "nil"
|
return "nil"
|
||||||
end
|
end
|
||||||
@ -39,7 +59,7 @@ function dump(...)
|
|||||||
local args={...}
|
local args={...}
|
||||||
for i=1,#args do
|
for i=1,#args do
|
||||||
if type(args[i]) == "table" then
|
if type(args[i]) == "table" then
|
||||||
args[i]=__tostring(args[i])
|
args[i]=serialize(args[i])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
print(table.unpack(args))
|
print(table.unpack(args))
|
||||||
@ -50,7 +70,7 @@ end
|
|||||||
-- Formatierungszeichen werden URL-encoded, damit EEP mit ihren zurecht kommt
|
-- Formatierungszeichen werden URL-encoded, damit EEP mit ihren zurecht kommt
|
||||||
-- Speziell Hochkommas haben mir immer meine Daten abgeschnitten...
|
-- Speziell Hochkommas haben mir immer meine Daten abgeschnitten...
|
||||||
function speicherTabelle(Slotnummer, Tabelle)
|
function speicherTabelle(Slotnummer, Tabelle)
|
||||||
local s=__tostring(Tabelle):gsub("([%c%%\"])", function(c)
|
local s=serialize(Tabelle):gsub("([%c%%\"])", function(c)
|
||||||
return string.format("%%%02X", string.byte(c))
|
return string.format("%%%02X", string.byte(c))
|
||||||
end)
|
end)
|
||||||
EEPSaveData(Slotnummer, s)
|
EEPSaveData(Slotnummer, s)
|
||||||
|
Loading…
Reference in New Issue
Block a user