1if not modules then modules = { } end modules ['core-dat'] = {
2 version = 1.001,
3 comment = "companion to core-dat.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
9
10
11
12local tonumber, tostring, type = tonumber, tostring, type
13
14local context = context
15
16local trace_datasets = false trackers.register("job.datasets" , function(v) trace_datasets = v end)
17
18local report_dataset = logs.reporter("dataset")
19
20local allocate = utilities.storage.allocate
21local settings_to_hash = utilities.parsers.settings_to_hash
22
23local texgetcount = tex.getcount
24local texsetcount = tex.setcount
25
26local v_yes = interfaces.variables.yes
27
28local new_latelua = nodes.pool.latelua
29
30local implement = interfaces.implement
31
32local c_realpageno = tex.iscount("realpageno")
33
34local collected = allocate()
35local tobesaved = allocate()
36
37local datasets = {
38 collected = collected,
39 tobesaved = tobesaved,
40}
41
42job.datasets = datasets
43
44local function initializer()
45 collected = datasets.collected
46 tobesaved = datasets.tobesaved
47end
48
49job.register('job.datasets.collected', tobesaved, initializer, nil)
50
51local sets = { }
52
53table.setmetatableindex(tobesaved, function(t,k)
54 local v = { }
55 t[k] = v
56 return v
57end)
58
59table.setmetatableindex(sets, function(t,k)
60 local v = {
61 index = 0,
62 order = 0,
63 }
64 t[k] = v
65 return v
66end)
67
68local function setdata(settings)
69 local name = settings.name
70 local tag = settings.tag
71 local data = settings.data
72 local list = tobesaved[name]
73 if settings.convert and type(data) == "string" then
74 data = settings_to_hash(data)
75 end
76 if type(data) ~= "table" then
77 data = { data = data }
78 end
79 if not tag then
80 tag = #list + 1
81 else
82 tag = tonumber(tag) or tag
83 end
84 list[tag] = data
85 if settings.delay == v_yes then
86 local set = sets[name]
87 local index = set.index + 1
88 set.index = index
89 data.index = index
90 data.order = index
91 data.realpage = texgetcount(c_realpageno)
92 if trace_datasets then
93 report_dataset("action %a, name %a, tag %a, index %a","assign delayed",name,tag,index)
94 end
95 elseif trace_datasets then
96 report_dataset("action %a, name %a, tag %a","assign immediate",name,tag)
97 end
98 return name, tag, data
99end
100
101datasets.setdata = setdata
102
103function datasets.extend(name,tag)
104 if type(name) == "table" then
105 name, tag = name.name, name.tag
106 end
107 local set = sets[name]
108 local order = set.order + 1
109 local realpage = texgetcount(c_realpageno)
110 set.order = order
111 local t = tobesaved[name][tag]
112 t.realpage = realpage
113 t.order = order
114 if trace_datasets then
115 report_dataset("action %a, name %a, tag %a, page %a, index %a","flush by order",name,tag,t.index or 0,order,realpage)
116 end
117end
118
119function datasets.getdata(name,tag,key,default)
120 local t = collected[name]
121 if t == nil then
122 if trace_datasets then
123 report_dataset("error: unknown dataset, name %a",name)
124 end
125 elseif type(t) ~= "table" then
126 return t
127 else
128 t = t[tag] or t[tonumber(tag)]
129 if not t then
130 if trace_datasets then
131 report_dataset("error: unknown dataset, name %a, tag %a",name,tag)
132 end
133 elseif key then
134 return t[key] or default
135 else
136 return t
137 end
138 end
139 return default
140end
141
142local function setdataset(settings)
143 settings.convert = true
144 local name, tag = setdata(settings)
145 if settings.delay ~= v_yes then
146
147 else
148 context(new_latelua { action = job.datasets.extend, name = name, tag = tag })
149 end
150end
151
152local cache = table.setmetatableindex(function(t,k)
153 local v = table.load(k..".tuc")
154 if v then
155 v = v.job
156 if v then
157 v = v.datasets
158 if v then
159 v = v.collected
160 end
161 end
162 end
163 if not v then
164 v = { }
165 if trace_datasets then
166 report_dataset("error: unknown dataset job %a",k)
167 end
168 end
169 t[k] = v
170 return v
171end)
172
173local function datasetvariable(jobname,name,tag,key)
174 local t = (jobname ~= "" and cache[jobname] or collected)[name]
175 if t == nil then
176 if trace_datasets then
177 report_dataset("error: unknown dataset, name %a, tag %a, not passed to tex",name)
178 end
179 elseif type(t) ~= "table" then
180 context(tostring(t))
181 else
182 t = t and (t[tag] or t[tonumber(tag)])
183 if not t then
184 if trace_datasets then
185 report_dataset("error: unknown dataset, name %a, tag %a, not passed to tex",name,tag)
186 end
187 elseif type(t) == "table" then
188 local s = t[key]
189 if type(s) ~= "table" then
190 context(tostring(s))
191 elseif trace_datasets then
192 report_dataset("error: unknown dataset, name %a, tag %a, not passed to tex",name,tag)
193 end
194 end
195 end
196end
197
198local function datasetsize(jobname,name)
199 local t = (jobname ~= "" and cache[jobname] or collected)[name]
200 context(t and type(t) == "table" and #t or 0)
201end
202
203implement {
204 name = "setdataset",
205 actions = setdataset,
206 arguments = {
207 {
208 { "name" },
209 { "tag" },
210 { "delay" },
211 { "data" },
212 }
213 }
214}
215
216implement {
217 name = "datasetvariable",
218 actions = datasetvariable,
219 arguments = "4 strings",
220}
221
222
223implement {
224 name = "datasetsize",
225 arguments = "2 strings",
226 actions = datasetsize,
227}
228 |