1if not modules then modules = { } end modules ['util-sac'] = {
2 version = 1.001,
3 optimize = true,
4 comment = "companion to luat-lib.mkiv",
5 author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
6 copyright = "PRAGMA ADE / ConTeXt Development Team",
7 license = "see context related readme files"
8}
9
10
11
12
13local byte, sub = string.byte, string.sub
14local tonumber = tonumber
15
16utilities = utilities or { }
17local streams = { }
18utilities.streams = streams
19
20function streams.open(filename,zerobased)
21 local f = filename and io.loaddata(filename)
22 if f then
23 return { f, 1, #f, zerobased or false }
24 end
25end
26
27function streams.openstring(f,zerobased)
28 if f then
29 return { f, 1, #f, zerobased or false }
30 end
31end
32
33function streams.getstring(f)
34 if f then
35 return f[1]
36 end
37end
38
39function streams.close()
40
41end
42
43function streams.size(f)
44 return f and f[3] or 0
45end
46
47streams.getsize = streams.size
48
49function streams.setposition(f,i)
50 if f[4] then
51
52 if i <= 0 then
53 f[2] = 1
54 else
55 f[2] = i + 1
56 end
57 else
58 if i <= 1 then
59 f[2] = 1
60 else
61 f[2] = i
62 end
63 end
64end
65
66function streams.getposition(f)
67 if f[4] then
68
69 return f[2] - 1
70 else
71 return f[2]
72 end
73end
74
75function streams.look(f,n,chars)
76 local b = f[2]
77 local e = b + n - 1
78 if chars then
79 return sub(f[1],b,e)
80 else
81 return byte(f[1],b,e)
82 end
83end
84
85function streams.skip(f,n)
86 f[2] = f[2] + n
87end
88
89function streams.readbyte(f)
90 local i = f[2]
91 f[2] = i + 1
92 return byte(f[1],i)
93end
94
95function streams.readbytes(f,n)
96 local i = f[2]
97 local j = i + n
98 f[2] = j
99 return byte(f[1],i,j-1)
100end
101
102function streams.readbytetable(f,n)
103 local i = f[2]
104 local j = i + n
105 f[2] = j
106 return { byte(f[1],i,j-1) }
107end
108
109function streams.skipbytes(f,n)
110 f[2] = f[2] + n
111end
112
113function streams.readchar(f)
114 local i = f[2]
115 f[2] = i + 1
116 return sub(f[1],i,i)
117end
118
119function streams.readstring(f,n)
120 local i = f[2]
121 local j = i + n
122 f[2] = j
123 return sub(f[1],i,j-1)
124end
125
126function streams.readinteger1(f)
127 local i = f[2]
128 f[2] = i + 1
129 local n = byte(f[1],i)
130 if n >= 0x80 then
131 return n - 0x100
132 else
133 return n
134 end
135end
136
137streams.readcardinal1 = streams.readbyte
138streams.readcardinal = streams.readcardinal1
139streams.readinteger = streams.readinteger1
140
141function streams.readcardinal2(f)
142 local i = f[2]
143 local j = i + 1
144 f[2] = j + 1
145 local a, b = byte(f[1],i,j)
146 return 0x100 * a + b
147end
148
149function streams.readcardinal2le(f)
150 local i = f[2]
151 local j = i + 1
152 f[2] = j + 1
153 local b, a = byte(f[1],i,j)
154 return 0x100 * a + b
155end
156
157function streams.readinteger2(f)
158 local i = f[2]
159 local j = i + 1
160 f[2] = j + 1
161 local a, b = byte(f[1],i,j)
162 if a >= 0x80 then
163 return 0x100 * a + b - 0x10000
164 else
165 return 0x100 * a + b
166 end
167end
168
169function streams.readinteger2le(f)
170 local i = f[2]
171 local j = i + 1
172 f[2] = j + 1
173 local b, a = byte(f[1],i,j)
174 if a >= 0x80 then
175 return 0x100 * a + b - 0x10000
176 else
177 return 0x100 * a + b
178 end
179end
180
181function streams.readcardinal3(f)
182 local i = f[2]
183 local j = i + 2
184 f[2] = j + 1
185 local a, b, c = byte(f[1],i,j)
186 return 0x10000 * a + 0x100 * b + c
187end
188
189function streams.readcardinal3le(f)
190 local i = f[2]
191 local j = i + 2
192 f[2] = j + 1
193 local c, b, a = byte(f[1],i,j)
194 return 0x10000 * a + 0x100 * b + c
195end
196
197function streams.readinteger3(f)
198 local i = f[2]
199 local j = i + 3
200 f[2] = j + 1
201 local a, b, c = byte(f[1],i,j)
202 if a >= 0x80 then
203 return 0x10000 * a + 0x100 * b + c - 0x1000000
204 else
205 return 0x10000 * a + 0x100 * b + c
206 end
207end
208
209function streams.readinteger3le(f)
210 local i = f[2]
211 local j = i + 3
212 f[2] = j + 1
213 local c, b, a = byte(f[1],i,j)
214 if a >= 0x80 then
215 return 0x10000 * a + 0x100 * b + c - 0x1000000
216 else
217 return 0x10000 * a + 0x100 * b + c
218 end
219end
220
221function streams.readcardinal4(f)
222 local i = f[2]
223 local j = i + 3
224 f[2] = j + 1
225 local a, b, c, d = byte(f[1],i,j)
226 return 0x1000000 * a + 0x10000 * b + 0x100 * c + d
227end
228
229function streams.readcardinal4le(f)
230 local i = f[2]
231 local j = i + 3
232 f[2] = j + 1
233 local d, c, b, a = byte(f[1],i,j)
234 return 0x1000000 * a + 0x10000 * b + 0x100 * c + d
235end
236
237function streams.readinteger4(f)
238 local i = f[2]
239 local j = i + 3
240 f[2] = j + 1
241 local a, b, c, d = byte(f[1],i,j)
242 if a >= 0x80 then
243 return 0x1000000 * a + 0x10000 * b + 0x100 * c + d - 0x100000000
244 else
245 return 0x1000000 * a + 0x10000 * b + 0x100 * c + d
246 end
247end
248
249function streams.readinteger4le(f)
250 local i = f[2]
251 local j = i + 3
252 f[2] = j + 1
253 local d, c, b, a = byte(f[1],i,j)
254 if a >= 0x80 then
255 return 0x1000000 * a + 0x10000 * b + 0x100 * c + d - 0x100000000
256 else
257 return 0x1000000 * a + 0x10000 * b + 0x100 * c + d
258 end
259end
260
261function streams.readfixed2(f)
262 local i = f[2]
263 local j = i + 1
264 f[2] = j + 1
265 local n1, n2 = byte(f[1],i,j)
266 if n1 >= 0x80 then
267 n1 = n1 - 0x100
268 end
269 return n1 + n2/0xFF
270end
271
272function streams.readfixed4(f)
273 local i = f[2]
274 local j = i + 3
275 f[2] = j + 1
276 local a, b, c, d = byte(f[1],i,j)
277 local n1 = 0x100 * a + b
278 local n2 = 0x100 * c + d
279 if n1 >= 0x8000 then
280 n1 = n1 - 0x10000
281 end
282 return n1 + n2/0xFFFF
283end
284
285if bit32 then
286
287 local extract = bit32.extract
288 local band = bit32.band
289
290 function streams.read2dot14(f)
291 local i = f[2]
292 local j = i + 1
293 f[2] = j + 1
294 local a, b = byte(f[1],i,j)
295 if a >= 0x80 then
296 local n = -(0x100 * a + b)
297 return - (extract(n,14,2) + (band(n,0x3FFF) / 16384.0))
298 else
299 local n = 0x100 * a + b
300 return (extract(n,14,2) + (band(n,0x3FFF) / 16384.0))
301 end
302 end
303
304end
305
306function streams.skipshort(f,n)
307 f[2] = f[2] + 2*(n or 1)
308end
309
310function streams.skiplong(f,n)
311 f[2] = f[2] + 4*(n or 1)
312end
313
314if sio and sio.readcardinal2 then
315
316 local readcardinal1 = sio.readcardinal1
317 local readcardinal2 = sio.readcardinal2
318 local readcardinal3 = sio.readcardinal3
319 local readcardinal4 = sio.readcardinal4
320 local readinteger1 = sio.readinteger1
321 local readinteger2 = sio.readinteger2
322 local readinteger3 = sio.readinteger3
323 local readinteger4 = sio.readinteger4
324 local readfixed2 = sio.readfixed2
325 local readfixed4 = sio.readfixed4
326 local read2dot14 = sio.read2dot14
327 local readbytes = sio.readbytes
328 local readbytetable = sio.readbytetable
329
330 function streams.readcardinal1(f)
331 local i = f[2]
332 f[2] = i + 1
333 return readcardinal1(f[1],i)
334 end
335 function streams.readcardinal2(f)
336 local i = f[2]
337 f[2] = i + 2
338 return readcardinal2(f[1],i)
339 end
340 function streams.readcardinal3(f)
341 local i = f[2]
342 f[2] = i + 3
343 return readcardinal3(f[1],i)
344 end
345 function streams.readcardinal4(f)
346 local i = f[2]
347 f[2] = i + 4
348 return readcardinal4(f[1],i)
349 end
350 function streams.readinteger1(f)
351 local i = f[2]
352 f[2] = i + 1
353 return readinteger1(f[1],i)
354 end
355 function streams.readinteger2(f)
356 local i = f[2]
357 f[2] = i + 2
358 return readinteger2(f[1],i)
359 end
360 function streams.readinteger3(f)
361 local i = f[2]
362 f[2] = i + 3
363 return readinteger3(f[1],i)
364 end
365 function streams.readinteger4(f)
366 local i = f[2]
367 f[2] = i + 4
368 return readinteger4(f[1],i)
369 end
370 function streams.readfixed2(f)
371 local i = f[2]
372 f[2] = i + 2
373 return readfixed2(f[1],i)
374 end
375 function streams.readfixed4(f)
376 local i = f[2]
377 f[2] = i + 4
378 return readfixed4(f[1],i)
379 end
380 function streams.read2dot14(f)
381 local i = f[2]
382 f[2] = i + 2
383 return read2dot14(f[1],i)
384 end
385 function streams.readbytes(f,n)
386 local i = f[2]
387 local s = f[3]
388 local p = i + n
389 if p > s then
390 f[2] = s + 1
391 else
392 f[2] = p
393 end
394 return readbytes(f[1],i,n)
395 end
396 function streams.readbytetable(f,n)
397 local i = f[2]
398 local s = f[3]
399 local p = i + n
400 if p > s then
401 f[2] = s + 1
402 else
403 f[2] = p
404 end
405 return readbytetable(f[1],i,n)
406 end
407
408 streams.readbyte = streams.readcardinal1
409 streams.readsignedbyte = streams.readinteger1
410 streams.readcardinal = streams.readcardinal1
411 streams.readinteger = streams.readinteger1
412
413end
414
415if sio and sio.readcardinaltable then
416
417 local readcardinaltable = sio.readcardinaltable
418 local readintegertable = sio.readintegertable
419
420 function utilities.streams.readcardinaltable(f,n,b)
421 local i = f[2]
422 local s = f[3]
423 local p = i + n * b
424 if p > s then
425 f[2] = s + 1
426 else
427 f[2] = p
428 end
429 return readcardinaltable(f[1],i,n,b)
430 end
431
432 function utilities.streams.readintegertable(f,n,b)
433 local i = f[2]
434 local s = f[3]
435 local p = i + n * b
436 if p > s then
437 f[2] = s + 1
438 else
439 f[2] = p
440 end
441 return readintegertable(f[1],i,n,b)
442 end
443
444else
445
446 local readcardinal1 = streams.readcardinal1
447 local readcardinal2 = streams.readcardinal2
448 local readcardinal3 = streams.readcardinal3
449 local readcardinal4 = streams.readcardinal4
450
451 function streams.readcardinaltable(f,n,b)
452 local i = f[2]
453 local s = f[3]
454 local p = i + n * b
455 if p > s then
456 f[2] = s + 1
457 else
458 f[2] = p
459 end
460 local t = { }
461 if b == 1 then for i=1,n do t[i] = readcardinal1(f[1],i) end
462 elseif b == 2 then for i=1,n do t[i] = readcardinal2(f[1],i) end
463 elseif b == 3 then for i=1,n do t[i] = readcardinal3(f[1],i) end
464 elseif b == 4 then for i=1,n do t[i] = readcardinal4(f[1],i) end end
465 return t
466 end
467
468 local readinteger1 = streams.readinteger1
469 local readinteger2 = streams.readinteger2
470 local readinteger3 = streams.readinteger3
471 local readinteger4 = streams.readinteger4
472
473 function streams.readintegertable(f,n,b)
474 local i = f[2]
475 local s = f[3]
476 local p = i + n * b
477 if p > s then
478 f[2] = s + 1
479 else
480 f[2] = p
481 end
482 local t = { }
483 if b == 1 then for i=1,n do t[i] = readinteger1(f[1],i) end
484 elseif b == 2 then for i=1,n do t[i] = readinteger2(f[1],i) end
485 elseif b == 3 then for i=1,n do t[i] = readinteger3(f[1],i) end
486 elseif b == 4 then for i=1,n do t[i] = readinteger4(f[1],i) end end
487 return t
488 end
489
490end
491
492
493
494
495do
496
497 local files = utilities.files
498
499 if files then
500
501 local openfile = files.open
502 local openstream = streams.open
503 local openstring = streams.openstring
504
505 local setmetatable = setmetatable
506
507 function io.newreader(str,method)
508 local f, m
509 if method == "string" then
510 f = openstring(str,true)
511 m = streams
512 elseif method == "stream" then
513 f = openstream(str,true)
514 m = streams
515 else
516 f = openfile(str,"rb")
517 m = files
518 end
519 if f then
520 local t = { }
521 setmetatable(t, {
522 __index = function(t,k)
523 local r = m[k]
524 if k == "close" then
525
526 if f then
527 m.close(f)
528 f = nil
529 end
530 return function() end
531 elseif r then
532 local v = function(_,a,b) return r(f,a,b) end
533 t[k] = v
534 return v
535 else
536 print("unknown key",k)
537 end
538 end
539 } )
540 return t
541 end
542 end
543
544 end
545
546end
547
548if bit32 and not streams.tocardinal1 then
549
550 local extract = bit32.extract
551 local char = string.char
552
553 streams.tocardinal1 = char
554 function streams.tocardinal2(n) return char(extract(n, 8,8),extract(n, 0,8)) end
555 function streams.tocardinal3(n) return char(extract(n,16,8),extract(n, 8,8),extract(n,0,8)) end
556 function streams.tocardinal4(n) return char(extract(n,24,8),extract(n,16,8),extract(n,8,8),extract(n,0,8)) end
557
558 streams.tocardinal1le = char
559 function streams.tocardinal2le(n) return char(extract(n,0,8),extract(n,8,8)) end
560 function streams.tocardinal3le(n) return char(extract(n,0,8),extract(n,8,8),extract(n,16,8)) end
561 function streams.tocardinal4le(n) return char(extract(n,0,8),extract(n,8,8),extract(n,16,8),extract(n,24,8)) end
562
563end
564
565if not streams.readcstring then
566
567 local readchar = streams.readchar
568 local concat = table.concat
569
570 function streams.readcstring(f)
571 local t = { }
572 while true do
573 local c = readchar(f)
574 if c and c ~= "\0" then
575 t[#t+1] = c
576 else
577 return concat(t)
578 end
579 end
580 end
581
582end
583 |