util-sto.lua /size: 6661 b    last modification: 2020-07-01 14:35
1if not modules then modules = { } end modules ['util-sto'] = {
2    version   = 1.001,
3    comment   = "companion to luat-lib.mkiv",
4    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5    copyright = "PRAGMA ADE / ConTeXt Development Team",
6    license   = "see context related readme files"
7}
8
9local setmetatable, getmetatable, rawset, type = setmetatable, getmetatable, rawset, type
10
11utilities         = utilities or { }
12utilities.storage = utilities.storage or { }
13local storage     = utilities.storage
14
15function storage.mark(t)
16    if not t then
17        print("\nfatal error: storage cannot be marked\n")
18        os.exit()
19        return
20    end
21    local m = getmetatable(t)
22    if not m then
23        m = { }
24        setmetatable(t,m)
25    end
26    m.__storage__ = true
27    return t
28end
29
30function storage.allocate(t)
31    t = t or { }
32    local m = getmetatable(t)
33    if not m then
34        m = { }
35        setmetatable(t,m)
36    end
37    m.__storage__ = true
38    return t
39end
40
41function storage.marked(t)
42    local m = getmetatable(t)
43    return m and m.__storage__
44end
45
46function storage.checked(t)
47    if not t then
48        report("\nfatal error: storage has not been allocated\n")
49        os.exit()
50        return
51    end
52    return t
53end
54
55-- function utilities.storage.delay(parent,name,filename)
56--     local m = getmetatable(parent)
57--     m.__list[name] = filename
58-- end
59--
60-- function utilities.storage.predefine(parent)
61--     local list = { }
62--     local m = getmetatable(parent) or {
63--         __list = list,
64--         __index = function(t,k)
65--             local l = require(list[k])
66--             t[k] = l
67--             return l
68--         end
69--     }
70--     setmetatable(parent,m)
71-- end
72--
73-- bla = { }
74-- utilities.storage.predefine(bla)
75-- utilities.storage.delay(bla,"test","oepsoeps")
76-- local t = bla.test
77-- table.print(t)
78-- print(t.a)
79
80function storage.setinitializer(data,initialize)
81    local m = getmetatable(data) or { }
82    m.__index = function(data,k)
83        m.__index = nil -- so that we can access the entries during initializing
84        initialize()
85        return data[k]
86    end
87    setmetatable(data, m)
88end
89
90local keyisvalue = { __index = function(t,k)
91    t[k] = k
92    return k
93end }
94
95function storage.sparse(t)
96    t = t or { }
97    setmetatable(t,keyisvalue)
98    return t
99end
100
101-- table namespace ?
102
103local function f_empty ()                           return "" end -- t,k
104local function f_self  (t,k) t[k] = k               return k  end
105local function f_table (t,k) local v = { } t[k] = v return v  end
106local function f_number(t,k) t[k] = 0               return 0  end -- t,k,v
107local function f_ignore()                                     end -- t,k,v
108
109local f_index = {
110    ["empty"]  = f_empty,
111    ["self"]   = f_self,
112    ["table"]  = f_table,
113    ["number"] = f_number,
114}
115
116function table.setmetatableindex(t,f)
117    if type(t) ~= "table" then
118        f, t = t, { }
119    end
120    local m = getmetatable(t)
121    local i = f_index[f] or f
122    if m then
123        m.__index = i
124    else
125        setmetatable(t,{ __index = i })
126    end
127    return t
128end
129
130local f_index = {
131    ["ignore"] = f_ignore,
132}
133
134function table.setmetatablenewindex(t,f)
135    if type(t) ~= "table" then
136        f, t = t, { }
137    end
138    local m = getmetatable(t)
139    local i = f_index[f] or f
140    if m then
141        m.__newindex = i
142    else
143        setmetatable(t,{ __newindex = i })
144    end
145    return t
146end
147
148function table.setmetatablecall(t,f)
149    if type(t) ~= "table" then
150        f, t = t, { }
151    end
152    local m = getmetatable(t)
153    if m then
154        m.__call = f
155    else
156        setmetatable(t,{ __call = f })
157    end
158    return t
159end
160
161-- the manual is somewhat fuzzy about this but suggests that one can best
162-- set all fields before assigning a metatable
163
164function table.setmetatableindices(t,f,n,c)
165    if type(t) ~= "table" then
166        f, t = t, { }
167    end
168    local m = getmetatable(t)
169    local i = f_index[f] or f
170    if m then
171        m.__index    = i
172        m.__newindex = n
173        m.__call     = c
174    else
175        setmetatable(t,{
176            __index    = i,
177            __newindex = n,
178            __call     = c,
179        })
180    end
181    return t
182end
183
184function table.setmetatablekey(t,key,value)
185    local m = getmetatable(t)
186    if not m then
187        m = { }
188        setmetatable(t,m)
189    end
190    m[key] = value
191    return t
192end
193
194function table.getmetatablekey(t,key,value)
195    local m = getmetatable(t)
196    return m and m[key]
197end
198
199function table.makeweak(t)
200    if not t then
201        t = { }
202    end
203    local m = getmetatable(t)
204    if m then
205        m.__mode = "v"
206    else
207        setmetatable(t,{ __mode = "v" })
208    end
209    return t
210end
211
212-- Problem: we have no __next (which is ok as it would probably slow down lua) so
213-- we cannot loop over the keys.
214
215-- local parametersets = table.autokeys()
216--
217-- parametersets.foo.bar = function(t,k) return "OEPS" end
218-- parametersets.foo.foo = "SPEO"
219-- parametersets.crap = { a = "a", b = table.autokey { function() return "b" end } }
220--
221-- print(parametersets.foo.bar)
222-- print(parametersets.foo.foo)
223-- print(parametersets.crap.b)
224-- print(parametersets.crap.b[1])
225
226-- function table.autotables(t)
227--     local t = t or { }
228--     local m = getmetatable(t)
229--     if not m then
230--         m = { }
231--         setmetatable(t,m)
232--     end
233--     m.__newindex = function(t,k,p)
234--         local v = { }
235--         local m = {
236--             __index = function(t,k)
237--                 local v = p[k]
238--                 if type(v) == "function" then
239--                     return v(t,k) -- so we can have multiple arguments
240--                 else
241--                     return v
242--                 end
243--             end,
244--             __newindex = function(t,k,v)
245--                 p[k] = v
246--             end,
247--             __len = function(t)
248--                 return #p
249--             end,
250--         }
251--         setmetatable(v,m)
252--         rawset(t,k,v)
253--         return v
254--     end
255--     m.__index = function(t,k)
256--         local v = { }
257--         t[k] = v -- calls newindex
258--         return v
259--     end
260--     return t
261-- end
262--
263-- function table.autokeys(p)
264--     local t = { }
265--     setmetatable(t, {
266--         __newindex = function(t,k,v)
267--             p[k] = v
268--         end,
269--         __index = function(t,k)
270--             local v = p[k]
271--             if type(v) == "function" then
272--                 return v(t,k) -- so we can have multiple arguments
273--             else
274--                 return v
275--             end
276--         end,
277--         __len = function(t)
278--             return #p
279--         end,
280--     })
281--     return t
282-- end
283