summaryrefslogtreecommitdiff
path: root/tex/context/base/mkiv/util-tbs.lua
blob: 339abcfccd8d8454005fc074494267bd8850e87d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
if not modules then modules = { } end modules ['util-tbs'] = {
    version   = 1.001,
    comment   = "companion to luat-lib.mkiv",
    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
    copyright = "PRAGMA ADE / ConTeXt Development Team",
    license   = "see context related readme files"
}

local tonumber, type, rawget = tonumber, type, rawget

utilities            = utilities or {}
local tablestore     = { }
utilities.tablestore = tablestore

local loaded  = { }
local current = nil

function tablestore.load(namespace,filename)
    local data = loaded[namespace]
    if not data then
        if type(filename) == "table" then
            data = filename
        else
            local fullname = resolvers.findfile(filename)
            if fullname and fullname ~= "" then
                if file.suffix(fullname,"json") and utilities.json then
                    data = io.loaddata(fullname)
                    if data then
                        data = utilities.json.tolua(data)
                    else
                        -- error
                    end
                else
                    data = table.load(fullname)
                end
            end
        end
        if not data then
            data = { }
        end
        loaded[namespace] = data
        if metapost then
            metapost.setparameterset(namespace,data)
        end
    end
    current = data
    return data
end

function tablestore.loaded(namespace)
    return (namespace and loaded[namespace]) or current or { }
end

function tablestore.known(namespace)
    return namespace and rawget(loaded,namespace) or false
end

do

    local find, gmatch, formatters = string.find, string.gmatch, string.formatters

    local P, C, Ct, Cc, R = lpeg.P, lpeg.C, lpeg.Ct, lpeg.Cc, lpeg.R

    local separator = P(".")
    local equal     = P("=")
    local digit     = R("09")
    local lbracket  = P("[")
    local rbracket  = P("]")
    local index     = Ct(Cc("index") * lbracket * (digit^1 / tonumber) * rbracket)
    local test      = Ct(Cc("test")  * lbracket * C((1-equal)^1) * equal * C((1-rbracket)^1) * rbracket)
    local entry     = Ct(Cc("entry") * C((1-lbracket-separator)^1))

    local specifier = Ct ((entry + (separator + index + test))^1)

    local function field(namespace,name,default)
        local data = loaded[namespace] or current
        if data then
    --         if find(name,"%[") then
                local t = lpeg.match(specifier,name)
                for i=1,#t do
                    local ti = t[i]
                    local t1 = ti[1]
                    local k  = ti[2]
                    if t1 == "test" then
                        local v = ti[3]
                        for j=1,#data do
                            local dj = data[j]
                            if dj[k] == v then
                                data = dj
                                goto OKAY
                            end
                        end
                        return
                    else
                        data = data[k]
                        if not data then
                            return
                        end
                    end
                  ::OKAY::
                end
    --         else
    --             for s in gmatch(name,"[^%.]+") do
    --                 data = data[s] or data[tonumber(s) or 0]
    --                 if not data then
    --                     return
    --                 end
    --             end
    --         end
            return data
        end
    end


    function length(namespace,name,default)
        local data = field(namespace,name)
        return type(data) == "table" and #data or 0
    end

    function formatted(namespace,name,fmt)
        local data = field(namespace,name)
        if data then
            return formatters[fmt](data)
        end
    end

    tablestore.field     = field
    tablestore.length    = length
    tablestore.formatted = formatted

end