data-con.lua /size: 5388 b    last modification: 2020-07-01 14:35
1if not modules then modules = { } end modules ['data-con'] = {
2    version   = 1.100,
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 = setmetatable
10local format, lower, gsub = string.format, string.lower, string.gsub
11
12local trace_cache      = false  trackers.register("resolvers.cache",      function(v) trace_cache      = v end)
13local trace_containers = false  trackers.register("resolvers.containers", function(v) trace_containers = v end)
14local trace_storage    = false  trackers.register("resolvers.storage",    function(v) trace_storage    = v end)
15
16--[[ldx--
17<p>Once we found ourselves defining similar cache constructs several times,
18containers were introduced. Containers are used to collect tables in memory and
19reuse them when possible based on (unique) hashes (to be provided by the calling
20function).</p>
21
22<p>Caching to disk is disabled by default. Version numbers are stored in the
23saved table which makes it possible to change the table structures without
24bothering about the disk cache.</p>
25
26<p>Examples of usage can be found in the font related code. This code is not
27ideal but we need it in generic too so we compromise.</p>
28--ldx]]--
29
30containers              = containers or { }
31local containers        = containers
32containers.usecache     = true
33
34local getwritablepath   = caches.getwritablepath
35local getreadablepaths  = caches.getreadablepaths
36local cacheiswritable   = caches.is_writable
37local loaddatafromcache = caches.loaddata
38local savedataincache   = caches.savedata
39
40local report_containers = logs.reporter("resolvers","containers")
41
42local allocated = { }
43
44local mt = {
45    __index = function(t,k)
46        if k == "writable" then
47            local writable = getwritablepath(t.category,t.subcategory) or { "." }
48            t.writable = writable
49            return writable
50        elseif k == "readables" then
51            local readables = getreadablepaths(t.category,t.subcategory) or { "." }
52            t.readables = readables
53            return readables
54        end
55    end,
56    __storage__ = true
57}
58
59function containers.define(category, subcategory, version, enabled)
60    if category and subcategory then
61        local c = allocated[category]
62        if not c then
63            c  = { }
64            allocated[category] = c
65        end
66        local s = c[subcategory]
67        if not s then
68            s = {
69                category    = category,
70                subcategory = subcategory,
71                storage     = { },
72                enabled     = enabled,
73                version     = version or math.pi, -- after all, this is TeX
74                trace       = false,
75             -- writable    = getwritablepath  and getwritablepath (category,subcategory) or { "." },
76             -- readables   = getreadablepaths and getreadablepaths(category,subcategory) or { "." },
77            }
78            setmetatable(s,mt)
79            c[subcategory] = s
80        end
81        return s
82    end
83end
84
85function containers.is_usable(container,name)
86    return container.enabled and caches and cacheiswritable(container.writable, name)
87end
88
89function containers.is_valid(container,name)
90    if name and name ~= "" then
91        local storage = container.storage[name]
92        return storage and storage.cache_version == container.version
93    else
94        return false
95    end
96end
97
98function containers.read(container,name)
99    local storage = container.storage
100    local stored = storage[name]
101    if not stored and container.enabled and caches and containers.usecache then
102        stored = loaddatafromcache(container.readables,name,container.writable)
103        if stored and stored.cache_version == container.version then
104            if trace_cache or trace_containers then
105                report_containers("action %a, category %a, name %a","load",container.subcategory,name)
106            end
107        else
108            stored = nil
109        end
110        storage[name] = stored
111    elseif stored then
112        if trace_cache or trace_containers then
113            report_containers("action %a, category %a, name %a","reuse",container.subcategory,name)
114        end
115    end
116    return stored
117end
118
119function containers.write(container, name, data, fast)
120    if data then
121        data.cache_version = container.version
122        if container.enabled and caches then
123            local unique = data.unique
124            local shared = data.shared
125            data.unique  = nil
126            data.shared  = nil
127            savedataincache(container.writable, name, data, fast)
128            if trace_cache or trace_containers then
129                report_containers("action %a, category %a, name %a","save",container.subcategory,name)
130            end
131            data.unique = unique
132            data.shared = shared
133        end
134        if trace_cache or trace_containers then
135            report_containers("action %a, category %a, name %a","store",container.subcategory,name)
136        end
137        container.storage[name] = data
138    end
139    return data
140end
141
142function containers.content(container,name)
143    return container.storage[name]
144end
145
146function containers.cleanname(name)
147 -- return (gsub(lower(name),"[^%w]+","-"))
148    return (gsub(lower(name),"[^%w\128-\255]+","-")) -- more utf friendly
149end
150