aboutsummaryrefslogtreecommitdiff
path: root/src/FbTk/LResourceHelper.lua
diff options
context:
space:
mode:
Diffstat (limited to 'src/FbTk/LResourceHelper.lua')
-rw-r--r--src/FbTk/LResourceHelper.lua135
1 files changed, 135 insertions, 0 deletions
diff --git a/src/FbTk/LResourceHelper.lua b/src/FbTk/LResourceHelper.lua
new file mode 100644
index 0000000..f336e05
--- /dev/null
+++ b/src/FbTk/LResourceHelper.lua
@@ -0,0 +1,135 @@
1read_resource, write_resource, res_magic = ...;
2
3local cat_magic = {};
4
5local function myerror(table, msg)
6 error(getmetatable(table)._fullname .. ': ' .. msg);
7end;
8
9local function check_arg(table, key)
10 if type(key) ~= 'string' then
11 myerror(table, 'expecting strings as keys.');
12 end;
13 if string.match(key, "^_") then
14 myerror(table, 'resource names must not begin with "_".');
15 end;
16 local t = getmetatable(table)[key];
17 return t, getmetatable(t);
18end;
19
20local new_cat;
21local function newindex(table, key, value)
22 local meta = getmetatable(table);
23 local t, mt = check_arg(table, key);
24
25 if type(value) == 'table' then
26 if mt == res_magic then
27 myerror(table, '"' .. key .. '" is a resource.');
28 end;
29 if mt == nil or mt._magic ~= cat_magic then
30 t = new_cat(table, key);
31 end;
32 for k,v in pairs(value) do
33 t[k] = v;
34 end;
35 else
36 if mt ~= nil and mt._magic == cat_magic and mt._state == 1 then
37 myerror(table, '"' .. key .. '" is a category.');
38 elseif mt == res_magic then
39 write_resource(t, value);
40 else
41 meta[key] = value;
42 end;
43 end;
44end;
45
46local function index(table, key)
47 local t, mt = check_arg(table, key);
48
49 if mt == res_magic then
50 return read_resource(t);
51 end;
52
53 return t;
54end;
55
56new_cat = function(table, key)
57 local meta = getmetatable(table);
58 local mt = {
59 __newindex = newindex, __index = index,
60 _magic = cat_magic, _fullname = meta._fullname .. '.' .. key, _state = 0
61 };
62 meta[key] = setmetatable({}, mt);
63 return meta[key];
64end;
65
66local function register_resource(root, name, object)
67 local meta = getmetatable(root);
68 meta._state = 1;
69
70 local head, tail = string.match(name, '^(%a+)%.?(.*)');
71 local t = meta[head];
72 if tail == '' then
73 meta[head] = object;
74 if getmetatable(object) == res_magic then
75 write_resource(object, t);
76 end;
77 return t;
78 end;
79
80 if t == nil then
81 t = new_cat(root, head);
82 end;
83 return register_resource(t, tail, object);
84end;
85
86local function dump_value(val)
87 if type(val) == "string" then
88 return string.format('%q', val);
89 elseif type(val) == "number" then
90 return string.format('%g', val);
91 else
92 error('Unsupported value type: ' .. type(val));
93 end;
94end;
95
96local function dump_(root, fd)
97 local meta = getmetatable(root);
98 if not string.match(meta._fullname, "^[%a.]+$") then
99 error("Someone has been messing with metatables.");
100 end;
101
102 for k, v in pairs(meta) do
103 if type(k) == "string" and string.match(k, "^%a+$") then
104 local mt = getmetatable(v);
105
106 fd:write(meta._fullname, '.', k, ' = ');
107 if mt ~= nil and mt._magic == cat_magic then
108 fd:write('{}\n');
109 dump(v);
110 fd:write('\n');
111 else
112 if mt == res_magic then
113 v = read_resource(v);
114 end;
115 fd:write(dump_value(v), '\n');
116 end;
117 end;
118 end;
119end;
120
121local function dump(root, file)
122 local fd = io.open(file, 'w');
123 dump_(root, fd);
124 fd:close();
125end;
126
127local function make_root(name)
128 local t = {
129 __newindex = newindex, __index = index,
130 _magic = cat_magic, _fullname = name, _state = 0
131 };
132 getfenv()[name] = setmetatable({}, t);
133end;
134
135return make_root, register_resource, dump;