1if 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
9local io = io
10local open, flush, write, read = io.open, io.flush, io.write, io.read
11local byte, find, gsub, format = string.byte, string.find, string.gsub, string.format
12local concat = table.concat
13
14local type = type
15
16if string.find(os.getenv("PATH") or "",";",1,true) then
17 io.fileseparator, io.pathseparator = "\\", ";"
18else
19 io.fileseparator, io.pathseparator = "/" , ":"
20end
21
22
23
24
25
26
27
28
29
30local large = 0x01000000
31local medium = 0x00100000
32local small = 0x00020000
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56local function readall(f)
57
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
65end
66
67io.readall = readall
68
69function io.loaddata(filename,textmode)
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
76 f:seek("set",0)
77 data = f:read(size)
78 end
79 f:close()
80 return data
81 end
82end
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
126function 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
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
148end
149
150function io.savedata(filename,data,joiner,append)
151 local f = open(filename,append and "ab" or "wb")
152 if f then
153 if append and joiner and f:seek("end") > 0 then
154 f:write(joiner)
155 end
156 if type(data) == "table" then
157 f:write(concat(data,joiner or ""))
158 elseif type(data) == "function" then
159 data(f)
160 else
161 f:write(data or "")
162 end
163 f:close()
164 flush()
165 return true
166 else
167 return false
168 end
169end
170
171
172
173
174
175if fio and fio.readline then
176
177 local readline = fio.readline
178
179 function io.loadlines(filename,n)
180 local f = open(filename,'r')
181 if not f then
182
183 elseif n then
184 local lines = { }
185 for i=1,n do
186 local line = readline(f)
187 if line then
188 lines[i] = line
189 else
190 break
191 end
192 end
193 f:close()
194 lines = concat(lines,"\n")
195 if #lines > 0 then
196 return lines
197 end
198 else
199 local line = readline(f)
200 f:close()
201 if line and #line > 0 then
202 return line
203 end
204 end
205 end
206
207else
208
209 function io.loadlines(filename,n)
210 local f = open(filename,'r')
211 if not f then
212
213 elseif n then
214 local lines = { }
215 for i=1,n do
216 local line = f:read("*lines")
217 if line then
218 lines[i] = line
219 else
220 break
221 end
222 end
223 f:close()
224 lines = concat(lines,"\n")
225 if #lines > 0 then
226 return lines
227 end
228 else
229 local line = f:read("*line") or ""
230 f:close()
231 if #line > 0 then
232 return line
233 end
234 end
235 end
236
237end
238
239function io.loadchunk(filename,n)
240 local f = open(filename,'rb')
241 if f then
242 local data = f:read(n or 1024)
243 f:close()
244 if #data > 0 then
245 return data
246 end
247 end
248end
249
250function io.exists(filename)
251 local f = open(filename)
252 if f == nil then
253 return false
254 else
255 f:close()
256 return true
257 end
258end
259
260function io.size(filename)
261 local f = open(filename)
262 if f == nil then
263 return 0
264 else
265 local s = f:seek("end")
266 f:close()
267 return s
268 end
269end
270
271local function noflines(f)
272 if type(f) == "string" then
273 local f = open(filename)
274 if f then
275 local n = f and noflines(f) or 0
276 f:close()
277 return n
278 else
279 return 0
280 end
281 else
282
283 local n = 0
284 for _ in f:lines() do
285 n = n + 1
286 end
287 f:seek('set',0)
288 return n
289 end
290end
291
292io.noflines = noflines
293
294
295
296
297local nextchar = {
298 [ 4] = function(f)
299 return f:read(1,1,1,1)
300 end,
301 [ 2] = function(f)
302 return f:read(1,1)
303 end,
304 [ 1] = function(f)
305 return f:read(1)
306 end,
307 [-2] = function(f)
308 local a, b = f:read(1,1)
309 return b, a
310 end,
311 [-4] = function(f)
312 local a, b, c, d = f:read(1,1,1,1)
313 return d, c, b, a
314 end
315}
316
317function io.characters(f,n)
318 if f then
319 return nextchar[n or 1], f
320 end
321end
322
323local nextbyte = {
324 [4] = function(f)
325 local a, b, c, d = f:read(1,1,1,1)
326 if d then
327 return byte(a), byte(b), byte(c), byte(d)
328 end
329 end,
330 [3] = function(f)
331 local a, b, c = f:read(1,1,1)
332 if b then
333 return byte(a), byte(b), byte(c)
334 end
335 end,
336 [2] = function(f)
337 local a, b = f:read(1,1)
338 if b then
339 return byte(a), byte(b)
340 end
341 end,
342 [1] = function (f)
343 local a = f:read(1)
344 if a then
345 return byte(a)
346 end
347 end,
348 [-2] = function (f)
349 local a, b = f:read(1,1)
350 if b then
351 return byte(b), byte(a)
352 end
353 end,
354 [-3] = function(f)
355 local a, b, c = f:read(1,1,1)
356 if b then
357 return byte(c), byte(b), byte(a)
358 end
359 end,
360 [-4] = function(f)
361 local a, b, c, d = f:read(1,1,1,1)
362 if d then
363 return byte(d), byte(c), byte(b), byte(a)
364 end
365 end
366}
367
368function io.bytes(f,n)
369 if f then
370 return nextbyte[n or 1], f
371 else
372 return nil, nil
373 end
374end
375
376function io.ask(question,default,options)
377 while true do
378 write(question)
379 if options then
380 write(format(" [%s]",concat(options,"|")))
381 end
382 if default then
383 write(format(" [%s]",default))
384 end
385 write(format(" "))
386 flush()
387 local answer = read()
388 answer = gsub(answer,"^%s*(.*)%s*$","%1")
389 if answer == "" and default then
390 return default
391 elseif not options then
392 return answer
393 else
394 for k=1,#options do
395 if options[k] == answer then
396 return answer
397 end
398 end
399 local pattern = "^" .. answer
400 for k=1,#options do
401 local v = options[k]
402 if find(v,pattern) then
403 return v
404 end
405 end
406 end
407 end
408end
409
410local function readnumber(f,n,m)
411 if m then
412 f:seek("set",n)
413 n = m
414 end
415 if n == 1 then
416 return byte(f:read(1))
417 elseif n == 2 then
418 local a, b = byte(f:read(2),1,2)
419 return 0x100 * a + b
420 elseif n == 3 then
421 local a, b, c = byte(f:read(3),1,3)
422 return 0x10000 * a + 0x100 * b + c
423 elseif n == 4 then
424 local a, b, c, d = byte(f:read(4),1,4)
425 return 0x1000000 * a + 0x10000 * b + 0x100 * c + d
426 elseif n == 8 then
427 local a, b = readnumber(f,4), readnumber(f,4)
428 return 0x100 * a + b
429 elseif n == 12 then
430 local a, b, c = readnumber(f,4), readnumber(f,4), readnumber(f,4)
431 return 0x10000 * a + 0x100 * b + c
432 elseif n == -2 then
433 local b, a = byte(f:read(2),1,2)
434 return 0x100 * a + b
435 elseif n == -3 then
436 local c, b, a = byte(f:read(3),1,3)
437 return 0x10000 * a + 0x100 * b + c
438 elseif n == -4 then
439 local d, c, b, a = byte(f:read(4),1,4)
440 return 0x1000000 * a + 0x10000 * b + 0x100*c + d
441 elseif n == -8 then
442 local h, g, f, e, d, c, b, a = byte(f:read(8),1,8)
443 return 0x100000000000000 * a + 0x1000000000000 * b + 0x10000000000 * c + 0x100000000 * d +
444 0x1000000 * e + 0x10000 * f + 0x100 * g + h
445 else
446 return 0
447 end
448end
449
450io.readnumber = readnumber
451
452function io.readstring(f,n,m)
453 if m then
454 f:seek("set",n)
455 n = m
456 end
457 local str = gsub(f:read(n),"\000","")
458 return str
459end
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478 |