l-io.lua /size: 11 Kb    last modification: 2020-07-01 14:35
1
if
not
modules
then
modules
=
{
}
end
modules
[
'
l-io
'
]
=
{
2
version
=
1
.
001
,
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 9
local
io
=
io
10
local
open
,
flush
,
write
,
read
=
io
.
open
,
io
.
flush
,
io
.
write
,
io
.
read
11
local
byte
,
find
,
gsub
,
format
=
string
.
byte
,
string
.
find
,
string
.
gsub
,
string
.
format
12
local
concat
=
table
.
concat
13
----- floor = math.floor
14
local
type
=
type
15 16
if
string
.
find
(
os
.
getenv
(
"
PATH
"
)
or
"
"
,
"
;
"
,
1
,
true
)
then
17
io
.
fileseparator
,
io
.
pathseparator
=
"
\\
"
,
"
;
"
18
else
19
io
.
fileseparator
,
io
.
pathseparator
=
"
/
"
,
"
:
"
20
end
21 22
-- local function readall(f)
23
-- return f:read("*all")
24
-- end
25 26
-- The next one is upto 50% faster on large files and less memory consumption due
27
-- to less intermediate large allocations. This phenomena was discussed on the
28
-- luatex dev list.
29 30
local
large
=
0x01000000
-- 2^24 16.777.216
31
local
medium
=
0x00100000
-- 2^20 1.048.576
32
local
small
=
0x00020000
-- 2^17 131.072
33 34
-- local function readall(f)
35
-- local size = f:seek("end")
36
-- if size == 0 then
37
-- return ""
38
-- end
39
-- f:seek("set",0)
40
-- if size < medium then
41
-- return f:read('*all')
42
-- else
43
-- local step = (size > large) and large or (floor(size/(medium)) * small)
44
-- local data = { }
45
-- while true do
46
-- local r = f:read(step)
47
-- if not r then
48
-- return concat(data)
49
-- else
50
-- data[#data+1] = r
51
-- end
52
-- end
53
-- end
54
-- end
55 56
local
function
readall
(
f
)
57
-- return f:read("*all")
58
local
size
=
f
:
seek
(
"
end
"
)
59
if
size
>
0
then
60
f
:
seek
(
"
set
"
,
0
)
61
return
f
:
read
(
size
)
62
else
63
return
"
"
64
end
65
end
66 67
io
.
readall
=
readall
68 69
function
io
.
loaddata
(
filename
,
textmode
)
-- return nil if empty
70
local
f
=
open
(
filename
,
(
textmode
and
'
r
'
)
or
'
rb
'
)
71
if
f
then
72
local
size
=
f
:
seek
(
"
end
"
)
73
local
data
=
nil
74
if
size
>
0
then
75
-- data = f:read("*all")
76
f
:
seek
(
"
set
"
,
0
)
77
data
=
f
:
read
(
size
)
78
end
79
f
:
close
(
)
80
return
data
81
end
82
end
83 84
-- function io.copydata(source,target,action)
85
-- local f = open(source,"rb")
86
-- if f then
87
-- local g = open(target,"wb")
88
-- if g then
89
-- local size = f:seek("end")
90
-- if size == 0 then
91
-- -- empty
92
-- else
93
-- f:seek("set",0)
94
-- if size < medium then
95
-- local data = f:read('*all')
96
-- if action then
97
-- data = action(data)
98
-- end
99
-- if data then
100
-- g:write(data)
101
-- end
102
-- else
103
-- local step = (size > large) and large or (floor(size/(medium)) * small)
104
-- while true do
105
-- local data = f:read(step)
106
-- if data then
107
-- if action then
108
-- data = action(data)
109
-- end
110
-- if data then
111
-- g:write(data)
112
-- end
113
-- else
114
-- break
115
-- end
116
-- end
117
-- end
118
-- end
119
-- g:close()
120
-- end
121
-- f:close()
122
-- flush()
123
-- end
124
-- end
125 126
function
io
.
copydata
(
source
,
target
,
action
)
127
local
f
=
open
(
source
,
"
rb
"
)
128
if
f
then
129
local
g
=
open
(
target
,
"
wb
"
)
130
if
g
then
131
local
size
=
f
:
seek
(
"
end
"
)
132
if
size
>
0
then
133
-- local data = f:read('*all')
134
f
:
seek
(
"
set
"
,
0
)
135
local
data
=
f
:
read
(
size
)
136
if
action
then
137
data
=
action
(
data
)
138
end
139
if
data
then
140
g
:
write
(
data
)
141
end
142
end
143
g
:
close
(
)
144
end
145
f
:
close
(
)
146
flush
(
)
147
end
148
end
149 150
function
io
.
savedata
(
filename
,
data
,
joiner
)
151
local
f
=
open
(
filename
,
"
wb
"
)
152
if
f
then
153
if
type
(
data
)
=
=
"
table
"
then
154
f
:
write
(
concat
(
data
,
joiner
or
"
"
)
)
155
elseif
type
(
data
)
=
=
"
function
"
then
156
data
(
f
)
157
else
158
f
:
write
(
data
or
"
"
)
159
end
160
f
:
close
(
)
161
flush
(
)
162
return
true
163
else
164
return
false
165
end
166
end
167 168
-- we can also chunk this one if needed: io.lines(filename,chunksize,"*l")
169 170
-- ffi.readline
171 172
if
fio
and
fio
.
readline
then
173 174
local
readline
=
fio
.
readline
175 176
function
io
.
loadlines
(
filename
,
n
)
-- return nil if empty
177
local
f
=
open
(
filename
,
'
r
'
)
178
if
not
f
then
179
-- no file
180
elseif
n
then
181
local
lines
=
{
}
182
for
i
=
1
,
n
do
183
local
line
=
readline
(
f
)
184
if
line
then
185
lines
[
i
]
=
line
186
else
187
break
188
end
189
end
190
f
:
close
(
)
191
lines
=
concat
(
lines
,
"
\n
"
)
192
if
#
lines
>
0
then
193
return
lines
194
end
195
else
196
local
line
=
readline
(
f
)
197
f
:
close
(
)
198
if
line
and
#
line
>
0
then
199
return
line
200
end
201
end
202
end
203 204
else
205 206
function
io
.
loadlines
(
filename
,
n
)
-- return nil if empty
207
local
f
=
open
(
filename
,
'
r
'
)
208
if
not
f
then
209
-- no file
210
elseif
n
then
211
local
lines
=
{
}
212
for
i
=
1
,
n
do
213
local
line
=
f
:
read
(
"
*lines
"
)
214
if
line
then
215
lines
[
i
]
=
line
216
else
217
break
218
end
219
end
220
f
:
close
(
)
221
lines
=
concat
(
lines
,
"
\n
"
)
222
if
#
lines
>
0
then
223
return
lines
224
end
225
else
226
local
line
=
f
:
read
(
"
*line
"
)
or
"
"
227
f
:
close
(
)
228
if
#
line
>
0
then
229
return
line
230
end
231
end
232
end
233 234
end
235 236
function
io
.
loadchunk
(
filename
,
n
)
237
local
f
=
open
(
filename
,
'
rb
'
)
238
if
f
then
239
local
data
=
f
:
read
(
n
or
1024
)
240
f
:
close
(
)
241
if
#
data
>
0
then
242
return
data
243
end
244
end
245
end
246 247
function
io
.
exists
(
filename
)
248
local
f
=
open
(
filename
)
249
if
f
=
=
nil
then
250
return
false
251
else
252
f
:
close
(
)
253
return
true
254
end
255
end
256 257
function
io
.
size
(
filename
)
258
local
f
=
open
(
filename
)
259
if
f
=
=
nil
then
260
return
0
261
else
262
local
s
=
f
:
seek
(
"
end
"
)
263
f
:
close
(
)
264
return
s
265
end
266
end
267 268
local
function
noflines
(
f
)
269
if
type
(
f
)
=
=
"
string
"
then
270
local
f
=
open
(
filename
)
271
if
f
then
272
local
n
=
f
and
noflines
(
f
)
or
0
273
f
:
close
(
)
274
return
n
275
else
276
return
0
277
end
278
else
279
-- todo: load and lpeg
280
local
n
=
0
281
for
_
in
f
:
lines
(
)
do
282
n
=
n
+
1
283
end
284
f
:
seek
(
'
set
'
,
0
)
285
return
n
286
end
287
end
288 289
io
.
noflines
=
noflines
290 291
-- inlined is faster ... beware, better use util-fil
292 293
local
nextchar
=
{
294
[
4
]
=
function
(
f
)
295
return
f
:
read
(
1
,
1
,
1
,
1
)
296
end
,
297
[
2
]
=
function
(
f
)
298
return
f
:
read
(
1
,
1
)
299
end
,
300
[
1
]
=
function
(
f
)
301
return
f
:
read
(
1
)
302
end
,
303
[
-2
]
=
function
(
f
)
304
local
a
,
b
=
f
:
read
(
1
,
1
)
305
return
b
,
a
306
end
,
307
[
-4
]
=
function
(
f
)
308
local
a
,
b
,
c
,
d
=
f
:
read
(
1
,
1
,
1
,
1
)
309
return
d
,
c
,
b
,
a
310
end
311
}
312 313
function
io
.
characters
(
f
,
n
)
314
if
f
then
315
return
nextchar
[
n
or
1
]
,
f
316
end
317
end
318 319
local
nextbyte
=
{
320
[
4
]
=
function
(
f
)
321
local
a
,
b
,
c
,
d
=
f
:
read
(
1
,
1
,
1
,
1
)
322
if
d
then
323
return
byte
(
a
)
,
byte
(
b
)
,
byte
(
c
)
,
byte
(
d
)
324
end
325
end
,
326
[
3
]
=
function
(
f
)
327
local
a
,
b
,
c
=
f
:
read
(
1
,
1
,
1
)
328
if
b
then
329
return
byte
(
a
)
,
byte
(
b
)
,
byte
(
c
)
330
end
331
end
,
332
[
2
]
=
function
(
f
)
333
local
a
,
b
=
f
:
read
(
1
,
1
)
334
if
b
then
335
return
byte
(
a
)
,
byte
(
b
)
336
end
337
end
,
338
[
1
]
=
function
(
f
)
339
local
a
=
f
:
read
(
1
)
340
if
a
then
341
return
byte
(
a
)
342
end
343
end
,
344
[
-2
]
=
function
(
f
)
345
local
a
,
b
=
f
:
read
(
1
,
1
)
346
if
b
then
347
return
byte
(
b
)
,
byte
(
a
)
348
end
349
end
,
350
[
-3
]
=
function
(
f
)
351
local
a
,
b
,
c
=
f
:
read
(
1
,
1
,
1
)
352
if
b
then
353
return
byte
(
c
)
,
byte
(
b
)
,
byte
(
a
)
354
end
355
end
,
356
[
-4
]
=
function
(
f
)
357
local
a
,
b
,
c
,
d
=
f
:
read
(
1
,
1
,
1
,
1
)
358
if
d
then
359
return
byte
(
d
)
,
byte
(
c
)
,
byte
(
b
)
,
byte
(
a
)
360
end
361
end
362
}
363 364
function
io
.
bytes
(
f
,
n
)
365
if
f
then
366
return
nextbyte
[
n
or
1
]
,
f
367
else
368
return
nil
,
nil
369
end
370
end
371 372
function
io
.
ask
(
question
,
default
,
options
)
373
while
true
do
374
write
(
question
)
375
if
options
then
376
write
(
format
(
"
[%s]
"
,
concat
(
options
,
"
|
"
)
)
)
377
end
378
if
default
then
379
write
(
format
(
"
[%s]
"
,
default
)
)
380
end
381
write
(
format
(
"
"
)
)
382
flush
(
)
383
local
answer
=
read
(
)
384
answer
=
gsub
(
answer
,
"
^%s*(.*)%s*$
"
,
"
%1
"
)
385
if
answer
=
=
"
"
and
default
then
386
return
default
387
elseif
not
options
then
388
return
answer
389
else
390
for
k
=
1
,
#
options
do
391
if
options
[
k
]
=
=
answer
then
392
return
answer
393
end
394
end
395
local
pattern
=
"
^
"
.
.
answer
396
for
k
=
1
,
#
options
do
397
local
v
=
options
[
k
]
398
if
find
(
v
,
pattern
)
then
399
return
v
400
end
401
end
402
end
403
end
404
end
405 406
local
function
readnumber
(
f
,
n
,
m
)
-- to be replaced
407
if
m
then
408
f
:
seek
(
"
set
"
,
n
)
409
n
=
m
410
end
411
if
n
=
=
1
then
412
return
byte
(
f
:
read
(
1
)
)
413
elseif
n
=
=
2
then
414
local
a
,
b
=
byte
(
f
:
read
(
2
)
,
1
,
2
)
415
return
0x100
*
a
+
b
416
elseif
n
=
=
3
then
417
local
a
,
b
,
c
=
byte
(
f
:
read
(
3
)
,
1
,
3
)
418
return
0x10000
*
a
+
0x100
*
b
+
c
419
elseif
n
=
=
4
then
420
local
a
,
b
,
c
,
d
=
byte
(
f
:
read
(
4
)
,
1
,
4
)
421
return
0x1000000
*
a
+
0x10000
*
b
+
0x100
*
c
+
d
422
elseif
n
=
=
8
then
423
local
a
,
b
=
readnumber
(
f
,
4
)
,
readnumber
(
f
,
4
)
424
return
0x100
*
a
+
b
425
elseif
n
=
=
12
then
426
local
a
,
b
,
c
=
readnumber
(
f
,
4
)
,
readnumber
(
f
,
4
)
,
readnumber
(
f
,
4
)
427
return
0x10000
*
a
+
0x100
*
b
+
c
428
elseif
n
=
=
-2
then
429
local
b
,
a
=
byte
(
f
:
read
(
2
)
,
1
,
2
)
430
return
0x100
*
a
+
b
431
elseif
n
=
=
-3
then
432
local
c
,
b
,
a
=
byte
(
f
:
read
(
3
)
,
1
,
3
)
433
return
0x10000
*
a
+
0x100
*
b
+
c
434
elseif
n
=
=
-4
then
435
local
d
,
c
,
b
,
a
=
byte
(
f
:
read
(
4
)
,
1
,
4
)
436
return
0x1000000
*
a
+
0x10000
*
b
+
0x100
*
c
+
d
437
elseif
n
=
=
-8
then
438
local
h
,
g
,
f
,
e
,
d
,
c
,
b
,
a
=
byte
(
f
:
read
(
8
)
,
1
,
8
)
439
return
0x100000000000000
*
a
+
0x1000000000000
*
b
+
0x10000000000
*
c
+
0x100000000
*
d
+
440
0x1000000
*
e
+
0x10000
*
f
+
0x100
*
g
+
h
441
else
442
return
0
443
end
444
end
445 446
io
.
readnumber
=
readnumber
447 448
function
io
.
readstring
(
f
,
n
,
m
)
449
if
m
then
450
f
:
seek
(
"
set
"
,
n
)
451
n
=
m
452
end
453
local
str
=
gsub
(
f
:
read
(
n
)
,
"
\000
"
,
"
"
)
454
return
str
455
end
456 457
-- This works quite ok:
458
--
459
-- function io.piped(command,writer)
460
-- local pipe = io.popen(command)
461
-- -- for line in pipe:lines() do
462
-- -- print(line)
463
-- -- end
464
-- while true do
465
-- local line = pipe:read(1)
466
-- if not line then
467
-- break
468
-- elseif line ~= "\n" then
469
-- writer(line)
470
-- end
471
-- end
472
-- return pipe:close() -- ok, status, (error)code
473
-- end
474