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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
|
if not modules then modules = { } end modules ['data-con'] = {
version = 1.100,
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 setmetatable = setmetatable
local format, lower, gsub = string.format, string.lower, string.gsub
local trace_cache = false trackers.register("resolvers.cache", function(v) trace_cache = v end)
local trace_containers = false trackers.register("resolvers.containers", function(v) trace_containers = v end)
local trace_storage = false trackers.register("resolvers.storage", function(v) trace_storage = v end)
--[[ldx--
<p>Once we found ourselves defining similar cache constructs several times,
containers were introduced. Containers are used to collect tables in memory and
reuse them when possible based on (unique) hashes (to be provided by the calling
function).</p>
<p>Caching to disk is disabled by default. Version numbers are stored in the
saved table which makes it possible to change the table structures without
bothering about the disk cache.</p>
<p>Examples of usage can be found in the font related code. This code is not
ideal but we need it in generic too so we compromise.</p>
--ldx]]--
containers = containers or { }
local containers = containers
containers.usecache = true
local getwritablepath = caches.getwritablepath
local getreadablepaths = caches.getreadablepaths
local cacheiswritable = caches.is_writable
local loaddatafromcache = caches.loaddata
local savedataincache = caches.savedata
local report_containers = logs.reporter("resolvers","containers")
local allocated = { }
local mt = {
__index = function(t,k)
if k == "writable" then
local writable = getwritablepath(t.category,t.subcategory) or { "." }
t.writable = writable
return writable
elseif k == "readables" then
local readables = getreadablepaths(t.category,t.subcategory) or { "." }
t.readables = readables
return readables
end
end,
__storage__ = true
}
function containers.define(category, subcategory, version, enabled)
if category and subcategory then
local c = allocated[category]
if not c then
c = { }
allocated[category] = c
end
local s = c[subcategory]
if not s then
s = {
category = category,
subcategory = subcategory,
storage = { },
enabled = enabled,
version = version or math.pi, -- after all, this is TeX
trace = false,
-- writable = getwritablepath and getwritablepath (category,subcategory) or { "." },
-- readables = getreadablepaths and getreadablepaths(category,subcategory) or { "." },
}
setmetatable(s,mt)
c[subcategory] = s
end
return s
end
end
function containers.is_usable(container,name)
return container.enabled and caches and cacheiswritable(container.writable, name)
end
function containers.is_valid(container,name)
if name and name ~= "" then
local storage = container.storage[name]
return storage and storage.cache_version == container.version
else
return false
end
end
function containers.read(container,name)
local storage = container.storage
local stored = storage[name]
if not stored and container.enabled and caches and containers.usecache then
stored = loaddatafromcache(container.readables,name,container.writable)
if stored and stored.cache_version == container.version then
if trace_cache or trace_containers then
report_containers("action %a, category %a, name %a","load",container.subcategory,name)
end
else
stored = nil
end
storage[name] = stored
elseif stored then
if trace_cache or trace_containers then
report_containers("action %a, category %a, name %a","reuse",container.subcategory,name)
end
end
return stored
end
function containers.write(container, name, data, fast)
if data then
data.cache_version = container.version
if container.enabled and caches then
local unique = data.unique
local shared = data.shared
data.unique = nil
data.shared = nil
savedataincache(container.writable, name, data, fast)
if trace_cache or trace_containers then
report_containers("action %a, category %a, name %a","save",container.subcategory,name)
end
data.unique = unique
data.shared = shared
end
if trace_cache or trace_containers then
report_containers("action %a, category %a, name %a","store",container.subcategory,name)
end
container.storage[name] = data
end
return data
end
function containers.content(container,name)
return container.storage[name]
end
function containers.cleanname(name)
-- return (gsub(lower(name),"[^%w]+","-"))
return (gsub(lower(name),"[^%w\128-\255]+","-")) -- more utf friendly
end
|