0
|
1 local format = string.format;
|
|
2 local setmetatable, type = setmetatable, type;
|
|
3 local pairs = pairs;
|
|
4 local char = string.char;
|
|
5 local loadfile, setfenv, pcall = loadfile, setfenv, pcall;
|
|
6 local log = log;
|
|
7 local io_open = io.open;
|
|
8
|
|
9 module "datamanager"
|
|
10
|
|
11
|
|
12 ---- utils -----
|
|
13 local encode, decode;
|
|
14
|
|
15 local log = function (type, msg) return log(type, "datamanager", msg); end
|
|
16
|
|
17 do
|
|
18 local urlcodes = setmetatable({}, { __index = function (t, k) t[k] = char(tonumber("0x"..k)); return t[k]; end });
|
|
19
|
|
20 decode = function (s)
|
|
21 return s and (s:gsub("+", " "):gsub("%%([a-fA-F0-9][a-fA-F0-9])", urlcodes));
|
|
22 end
|
|
23
|
|
24 encode = function (s)
|
|
25 return s and (s:gsub("%W", function (c) return format("%%%x", c:byte()); end));
|
|
26 end
|
|
27 end
|
|
28
|
|
29 local function basicSerialize (o)
|
|
30 if type(o) == "number" or type(o) == "boolean" then
|
|
31 return tostring(o)
|
|
32 else -- assume it is a string
|
|
33 return string.format("%q", tostring(o))
|
|
34 end
|
|
35 end
|
|
36
|
|
37
|
|
38 local function simplesave (f, o)
|
|
39 if type(o) == "number" then
|
|
40 f:write(o)
|
|
41 elseif type(o) == "string" then
|
|
42 f:write(format("%q", o))
|
|
43 elseif type(o) == "table" then
|
|
44 f:write("{\n")
|
|
45 for k,v in pairs(o) do
|
|
46 f:write(" [", format("%q", k), "] = ")
|
|
47 simplesave(f, v)
|
|
48 f:write(",\n")
|
|
49 end
|
|
50 f:write("}\n")
|
|
51 else
|
|
52 error("cannot serialize a " .. type(o))
|
|
53 end
|
|
54 end
|
|
55
|
|
56 ------- API -------------
|
|
57
|
|
58 function getpath(username, host, datastore)
|
|
59 return format("data/%s/%s/%s.dat", encode(host), datastore, encode(username));
|
|
60 end
|
|
61
|
|
62 function load(username, host, datastore)
|
|
63 local data, ret = loadfile(getpath(username, host, datastore));
|
|
64 if not data then log("warn", "Failed to load "..datastore.." storage ('"..ret.."') for user: "..username.."@"..host); return nil; end
|
|
65 setfenv(data, {});
|
|
66 local success, ret = pcall(data);
|
|
67 if not success then log("error", "Unable to load "..datastore.." storage ('"..ret.."') for user: "..username.."@"..host); return nil; end
|
|
68 return ret;
|
|
69 end
|
|
70
|
|
71 function store(username, host, datastore, data)
|
|
72 local f, msg = io_open(getpath(username, host, datastore), "w+");
|
|
73 if not f then log("error", "Unable to write to "..datastore.." storage ('"..msg.."') for user: "..username.."@"..host); return nil; end
|
|
74 f:write("return ");
|
|
75 simplesave(f, data);
|
|
76 f:close();
|
|
77 return true;
|
|
78 end
|
|
79
|