this is going to be magnificent if I can manage it
[QuestHelper.git] / persistence.lua
blob0cc1a43e5df1a9933db3eb023cb1bcefc0ecd6aa
1 persistence =
3 store = function (f, item)
4 if f then
5 persistence.write(f, item, 0);
6 f:write("\n");
7 else
8 error(e);
9 end;
10 end;
12 load = function (path)
13 local f, e = loadfile(path);
14 if f then
15 return f();
16 else
17 return nil, e;
18 --error(e);
19 end;
20 end;
22 write = function (f, item, level)
23 local t = type(item);
24 persistence.writers[t](f, item, level);
25 end;
27 writeIndent = function (f, level)
28 for i = 1, level do
29 f:write("\t");
30 end;
31 end;
33 writers = {
34 ["nil"] = function (f, item, level)
35 f:write("nil");
36 end;
37 ["number"] = function (f, item, level)
38 f:write(tostring(item));
39 end;
40 ["string"] = function (f, item, level)
41 f:write(string.format("%q", item));
42 end;
43 ["boolean"] = function (f, item, level)
44 if item then
45 f:write("true");
46 else
47 f:write("false");
48 end
49 end;
50 ["table"] = function (f, item, level)
51 f:write("{\n");
53 -- First we test to see if it's a trivial flat layout
54 local isflat = true
56 local idx = 1
57 for k, v in ipairs(item) do
58 if k ~= idx then isflat = false break end
59 idx = idx + 1
60 end
61 end
63 local order = {}
64 for k, v in pairs(item) do
65 if type(k) ~= "number" or k < 1 or k > #item then isflat = false end
66 table.insert(order, k)
67 end
69 if #order ~= #item then isflat = false end
71 if isflat then
72 -- We're flat! Special case.
73 --f:write("--[[isflat]]")
74 persistence.writeIndent(f, level+1);
76 for k, v in ipairs(item) do
77 if k ~= 1 then
78 f:write(", ")
79 end
81 persistence.write(f, v, level+1)
82 end
83 else
84 --f:write(string.format("--[[notflat %d/%d]]", #order, #item))
85 table.sort(order, function (a, b)
86 if type(a) == type(b) then return a < b end
87 return type(a) < type(b)
88 end)
90 local first = true
91 for _, v in pairs(order) do
92 if not first then f:write(",\n") end
93 first = false
94 persistence.writeIndent(f, level+1);
96 if type(v) == "string" and v:match("[a-z]+") then
97 f:write(v)
98 else
99 f:write("[");
100 persistence.write(f, v, level+1);
101 f:write("]");
103 f:write(" = ");
105 persistence.write(f, item[v], level+1);
107 f:write("\n")
108 persistence.writeIndent(f, level);
110 f:write("}");
111 end;
112 ["function"] = function (f, item, level)
113 -- Does only work for "normal" functions, not those
114 -- with upvalues or c functions
115 local dInfo = debug.getinfo(item, "uS");
116 if dInfo.nups > 0 then
117 f:write("nil -- functions with upvalue not supported\n");
118 elseif dInfo.what ~= "Lua" then
119 f:write("nil -- function is not a lua function\n");
120 else
121 local r, s = pcall(string.dump,item);
122 if r then
123 f:write(string.format("loadstring(%q)", s));
124 else
125 f:write("nil -- function could not be dumped\n");
128 end;
129 ["thread"] = function (f, item, level)
130 f:write("nil --thread\n");
131 end;
132 ["userdata"] = function (f, item, level)
133 f:write("nil --userdata\n");
134 end;