kskit/Serializer.lua

82 lines
2.5 KiB
Lua

-- Tabelle in einen String umwandeln, rekursiv
-- Funktionen als Lua-Werte werden ignoriert
-- forbidden ist ein set von elterntabellen zum erkennen von kreisreferenzen
function serialize(value, forbidden)
forbidden = forbidden or {}
local t=type(value)
if t=="table" then
-- Kreisreferenz -> als nil serialisieren
if forbidden[value] then return "nil" end
forbidden[value]=true
local r=""
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={}
for k in pairs(value) do
-- Nur Keys, die nicht von ipairs() weiter oben schon verarbeitet wurden
if numeric_indexes[k]==nil then
table.insert(tkeys, k)
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.."}"
elseif t=="boolean" then
return tostring(value)
elseif t=="number" then
return tostring(math.tointeger(value) or value)
elseif t=="string" then
return string.format("%q",value)
else
return "nil"
end
end
-- Tabelle in beliebigen Slot speichern
-- Im Slot steht dann eine Lua-Tabelle als String
-- Formatierungszeichen werden URL-encoded, damit EEP mit ihren zurecht kommt
-- Speziell Hochkommas haben mir immer meine Daten abgeschnitten...
function speicherTabelle(Slotnummer, Tabelle)
local s=serialize(Tabelle):gsub("([%c%%\"])", function(c)
return string.format("%%%02X", string.byte(c))
end)
EEPSaveData(Slotnummer, s)
end
-- Tabelle aus beliebigen Slot laden
-- Sind die Daten nicht lesbar, wird eine leere Tabelle zurueckgegeben
function ladeTabelle(Slotnummer)
local ok, raw = EEPLoadData(Slotnummer)
if not ok then
print("WARNUNG: Daten im Slot ",Slotnummer," unleserlich")
return {}
end
return load("return "..raw:gsub("%%(%x%x)", function(x)
return string.char(tonumber(x, 16))
end))()
end