diff options
Diffstat (limited to 'src/FbTk/LResourceHelper.lua')
-rw-r--r-- | src/FbTk/LResourceHelper.lua | 135 |
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 @@ | |||
1 | read_resource, write_resource, res_magic = ...; | ||
2 | |||
3 | local cat_magic = {}; | ||
4 | |||
5 | local function myerror(table, msg) | ||
6 | error(getmetatable(table)._fullname .. ': ' .. msg); | ||
7 | end; | ||
8 | |||
9 | local 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); | ||
18 | end; | ||
19 | |||
20 | local new_cat; | ||
21 | local 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; | ||
44 | end; | ||
45 | |||
46 | local 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; | ||
54 | end; | ||
55 | |||
56 | new_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]; | ||
64 | end; | ||
65 | |||
66 | local 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); | ||
84 | end; | ||
85 | |||
86 | local 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; | ||
94 | end; | ||
95 | |||
96 | local 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; | ||
119 | end; | ||
120 | |||
121 | local function dump(root, file) | ||
122 | local fd = io.open(file, 'w'); | ||
123 | dump_(root, fd); | ||
124 | fd:close(); | ||
125 | end; | ||
126 | |||
127 | local 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); | ||
133 | end; | ||
134 | |||
135 | return make_root, register_resource, dump; | ||