28 local os_remove = os.remove; |
28 local os_remove = os.remove; |
29 local tostring, tonumber = tostring, tonumber; |
29 local tostring, tonumber = tostring, tonumber; |
30 local error = error; |
30 local error = error; |
31 local next = next; |
31 local next = next; |
32 local t_insert = table.insert; |
32 local t_insert = table.insert; |
33 |
33 local append = require "util.serialization".append; |
34 local indent = function(f, i) |
|
35 for n = 1, i do |
|
36 f:write("\t"); |
|
37 end |
|
38 end |
|
39 |
|
40 local data_path = "data"; |
|
41 |
34 |
42 module "datamanager" |
35 module "datamanager" |
43 |
36 |
44 |
|
45 ---- utils ----- |
37 ---- utils ----- |
46 local encode, decode; |
38 local encode, decode; |
47 |
|
48 do |
39 do |
49 local urlcodes = setmetatable({}, { __index = function (t, k) t[k] = char(tonumber("0x"..k)); return t[k]; end }); |
40 local urlcodes = setmetatable({}, { __index = function (t, k) t[k] = char(tonumber("0x"..k)); return t[k]; end }); |
50 |
41 |
51 decode = function (s) |
42 decode = function (s) |
52 return s and (s:gsub("+", " "):gsub("%%([a-fA-F0-9][a-fA-F0-9])", urlcodes)); |
43 return s and (s:gsub("+", " "):gsub("%%([a-fA-F0-9][a-fA-F0-9])", urlcodes)); |
55 encode = function (s) |
46 encode = function (s) |
56 return s and (s:gsub("%W", function (c) return format("%%%x", c:byte()); end)); |
47 return s and (s:gsub("%W", function (c) return format("%%%x", c:byte()); end)); |
57 end |
48 end |
58 end |
49 end |
59 |
50 |
60 local function basicSerialize (o) |
|
61 if type(o) == "number" or type(o) == "boolean" then |
|
62 return tostring(o); |
|
63 else -- assume it is a string -- FIXME make sure it's a string. throw an error otherwise. |
|
64 return (format("%q", tostring(o)):gsub("\\\n", "\\n")); |
|
65 end |
|
66 end |
|
67 |
|
68 |
|
69 local function simplesave (f, o, ind) |
|
70 if type(o) == "number" then |
|
71 f:write(o) |
|
72 elseif type(o) == "string" then |
|
73 f:write((format("%q", o):gsub("\\\n", "\\n"))) |
|
74 elseif type(o) == "table" then |
|
75 f:write("{\n") |
|
76 for k,v in pairs(o) do |
|
77 indent(f, ind); |
|
78 f:write("[", basicSerialize(k), "] = ") |
|
79 simplesave(f, v, ind+1) |
|
80 f:write(",\n") |
|
81 end |
|
82 indent(f, ind-1); |
|
83 f:write("}") |
|
84 elseif type(o) == "boolean" then |
|
85 f:write(o and "true" or "false"); |
|
86 else |
|
87 error("cannot serialize a " .. type(o)) |
|
88 end |
|
89 end |
|
90 |
|
91 ------- API ------------- |
51 ------- API ------------- |
92 |
52 |
|
53 local data_path = "data"; |
93 function set_data_path(path) |
54 function set_data_path(path) |
94 data_path = path; |
55 data_path = path; |
95 end |
56 end |
96 |
57 |
97 function getpath(username, host, datastore, ext) |
58 function getpath(username, host, datastore, ext) |
129 if not f then |
90 if not f then |
130 log("error", "Unable to write to "..datastore.." storage ('"..msg.."') for user: "..(username or "nil").."@"..(host or "nil")); |
91 log("error", "Unable to write to "..datastore.." storage ('"..msg.."') for user: "..(username or "nil").."@"..(host or "nil")); |
131 return; |
92 return; |
132 end |
93 end |
133 f:write("return "); |
94 f:write("return "); |
134 simplesave(f, data, 1); |
95 append(f, data); |
135 f:close(); |
96 f:close(); |
136 if not next(data) then -- try to delete empty datastore |
97 if not next(data) then -- try to delete empty datastore |
137 os_remove(getpath(username, host, datastore)); |
98 os_remove(getpath(username, host, datastore)); |
138 end |
99 end |
139 -- we write data even when we are deleting because lua doesn't have a |
100 -- we write data even when we are deleting because lua doesn't have a |
166 log("error", "Unable to write to "..datastore.." storage ('"..msg.."') for user: "..(username or "nil").."@"..(host or "nil")); |
127 log("error", "Unable to write to "..datastore.." storage ('"..msg.."') for user: "..(username or "nil").."@"..(host or "nil")); |
167 return; |
128 return; |
168 end |
129 end |
169 for _, d in ipairs(data) do |
130 for _, d in ipairs(data) do |
170 f:write("item("); |
131 f:write("item("); |
171 simplesave(f, d, 1); |
132 append(f, d); |
172 f:write(");\n"); |
133 f:write(");\n"); |
173 end |
134 end |
174 f:close(); |
135 f:close(); |
175 if not next(data) then -- try to delete empty datastore |
136 if not next(data) then -- try to delete empty datastore |
176 os_remove(getpath(username, host, datastore, "list")); |
137 os_remove(getpath(username, host, datastore, "list")); |