util-tbs.lua /size: 3995 b    last modification: 2024-01-16 10:22
1if not modules then modules = { } end modules ['util-tbs'] = {
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 tonumber, type, rawget = tonumber, type, rawget
10
11utilities            = utilities or {}
12local tablestore     = { }
13utilities.tablestore = tablestore
14
15local loaded  = { }
16local current = nil
17
18function tablestore.load(namespace,filename)
19    local data = loaded[namespace]
20    if not data then
21        if type(filename) == "table" then
22            data = filename
23        else
24            local fullname = resolvers.findfile(filename)
25            if fullname and fullname ~= "" then
26                if file.suffix(fullname,"json") and utilities.json then
27                    data = io.loaddata(fullname)
28                    if data then
29                        data = utilities.json.tolua(data)
30                    else
31                        -- error
32                    end
33                else
34                    data = table.load(fullname)
35                end
36            end
37        end
38        if not data then
39            data = { }
40        end
41        loaded[namespace] = data
42        if metapost then
43            metapost.setparameterset(namespace,data)
44        end
45    end
46    current = data
47    return data
48end
49
50function tablestore.loaded(namespace)
51    return (namespace and loaded[namespace]) or current or { }
52end
53
54function tablestore.known(namespace)
55    return namespace and rawget(loaded,namespace) or false
56end
57
58do
59
60    local find, gmatch, formatters = string.find, string.gmatch, string.formatters
61
62    local P, C, Ct, Cc, R = lpeg.P, lpeg.C, lpeg.Ct, lpeg.Cc, lpeg.R
63
64    local separator = P(".")
65    local equal     = P("=")
66    local digit     = R("09")
67    local lbracket  = P("[")
68    local rbracket  = P("]")
69    local index     = Ct(Cc("index") * lbracket * (digit^1 / tonumber) * rbracket)
70    local test      = Ct(Cc("test")  * lbracket * C((1-equal)^1) * equal * C((1-rbracket)^1) * rbracket)
71    local entry     = Ct(Cc("entry") * C((1-lbracket-separator)^1))
72
73    local specifier = Ct ((entry + (separator + index + test))^1)
74
75    local function field(namespace,name,default)
76        local data = loaded[namespace] or current
77        if data then
78    --         if find(name,"%[") then
79                local t = lpeg.match(specifier,name)
80                for i=1,#t do
81                    local ti = t[i]
82                    local t1 = ti[1]
83                    local k  = ti[2]
84                    if t1 == "test" then
85                        local v = ti[3]
86                        for j=1,#data do
87                            local dj = data[j]
88                            if dj[k] == v then
89                                data = dj
90                                goto OKAY
91                            end
92                        end
93                        return
94                    else
95                        data = data[k]
96                        if not data then
97                            return
98                        end
99                    end
100                  ::OKAY::
101                end
102    --         else
103    --             for s in gmatch(name,"[^%.]+") do
104    --                 data = data[s] or data[tonumber(s) or 0]
105    --                 if not data then
106    --                     return
107    --                 end
108    --             end
109    --         end
110            return data
111        end
112    end
113
114
115    function length(namespace,name,default)
116        local data = field(namespace,name)
117        return type(data) == "table" and #data or 0
118    end
119
120    function formatted(namespace,name,fmt)
121        local data = field(namespace,name)
122        if data then
123            return formatters[fmt](data)
124        end
125    end
126
127    tablestore.field     = field
128    tablestore.length    = length
129    tablestore.formatted = formatted
130
131end
132