util-soc-imp-ltn12.lua /size: 8709 b    last modification: 2020-07-01 14:35
1
-- original file : ltn12.lua
2
-- for more into : see util-soc.lua
3 4
local
select
,
unpack
=
select
,
unpack
5
local
insert
,
remove
=
table
.
insert
,
table
.
remove
6
local
sub
=
string
.
sub
7 8
local
function
report
(
fmt
,
first
,
...
)
9
if
logs
then
10
report
=
logs
and
logs
.
reporter
(
"
ltn12
"
)
11
report
(
fmt
,
first
,
...
)
12
elseif
fmt
then
13
fmt
=
"
ltn12:
"
.
.
fmt
14
if
first
then
15
print
(
format
(
fmt
,
first
,
...
)
)
16
else
17
print
(
fmt
)
18
end
19
end
20
end
21 22
local
filter
=
{
}
23
local
source
=
{
}
24
local
sink
=
{
}
25
local
pump
=
{
}
26 27
local
ltn12
=
{
28 29
_VERSION
=
"
LTN12 1.0.3
"
,
30 31
BLOCKSIZE
=
2048
,
32 33
filter
=
filter
,
34
source
=
source
,
35
sink
=
sink
,
36
pump
=
pump
,
37 38
report
=
report
,
39 40
}
41 42
-- returns a high level filter that cycles a low-level filter
43 44
function
filter
.
cycle
(
low
,
ctx
,
extra
)
45
if
low
then
46
return
function
(
chunk
)
47
return
(
low
(
ctx
,
chunk
,
extra
)
)
48
end
49
end
50
end
51 52
-- chains a bunch of filters together
53 54
function
filter
.
chain
(
...
)
55
local
arg
=
{
...
}
56
local
n
=
select
(
'
#
'
,
...
)
57
local
top
=
1
58
local
index
=
1
59
local
retry
=
"
"
60
return
function
(
chunk
)
61
retry
=
chunk
and
retry
62
while
true
do
63
local
action
=
arg
[
index
]
64
if
index
=
=
top
then
65
chunk
=
action
(
chunk
)
66
if
chunk
=
=
"
"
or
top
=
=
n
then
67
return
chunk
68
elseif
chunk
then
69
index
=
index
+
1
70
else
71
top
=
top
+
1
72
index
=
top
73
end
74
else
75
chunk
=
action
(
chunk
or
"
"
)
76
if
chunk
=
=
"
"
then
77
index
=
index
-
1
78
chunk
=
retry
79
elseif
chunk
then
80
if
index
=
=
n
then
81
return
chunk
82
else
83
index
=
index
+
1
84
end
85
else
86
report
(
"
error: filter returned inappropriate 'nil'
"
)
87
return
88
end
89
end
90
end
91
end
92
end
93 94
-- create an empty source
95 96
local
function
empty
(
)
97
return
nil
98
end
99 100
function
source
.
empty
(
)
101
return
empty
102
end
103 104
-- returns a source that just outputs an error
105 106
local
function
sourceerror
(
err
)
107
return
function
(
)
108
return
nil
,
err
109
end
110
end
111 112
source
.
error
=
sourceerror
113 114
-- creates a file source
115 116
function
source
.
file
(
handle
,
io_err
)
117
if
handle
then
118
local
blocksize
=
ltn12
.
BLOCKSIZE
119
return
function
(
)
120
local
chunk
=
handle
:
read
(
blocksize
)
121
if
not
chunk
then
122
handle
:
close
(
)
123
end
124
return
chunk
125
end
126
else
127
return
sourceerror
(
io_err
or
"
unable to open file
"
)
128
end
129
end
130 131
-- turns a fancy source into a simple source
132 133
function
source
.
simplify
(
src
)
134
return
function
(
)
135
local
chunk
,
err_or_new
=
src
(
)
136
if
err_or_new
then
137
src
=
err_or_new
138
end
139
if
chunk
then
140
return
chunk
141
else
142
return
nil
,
err_or_new
143
end
144
end
145
end
146 147
-- creates string source
148 149
function
source
.
string
(
s
)
150
if
s
then
151
local
blocksize
=
ltn12
.
BLOCKSIZE
152
local
i
=
1
153
return
function
(
)
154
local
nexti
=
i
+
blocksize
155
local
chunk
=
sub
(
s
,
i
,
nexti
-
1
)
156
i
=
nexti
157
if
chunk
~
=
"
"
then
158
return
chunk
159
else
160
return
nil
161
end
162
end
163
else
return
source
.
empty
(
)
end
164
end
165 166
-- creates rewindable source
167 168
function
source
.
rewind
(
src
)
169
local
t
=
{
}
170
return
function
(
chunk
)
171
if
chunk
then
172
insert
(
t
,
chunk
)
173
else
174
chunk
=
remove
(
t
)
175
if
chunk
then
176
return
chunk
177
else
178
return
src
(
)
179
end
180
end
181
end
182
end
183 184
-- chains a source with one or several filter(s)
185 186
function
source
.
chain
(
src
,
f
,
...
)
187
if
...
then
188
f
=
filter
.
chain
(
f
,
...
)
189
end
190
local
last_in
=
"
"
191
local
last_out
=
"
"
192
local
state
=
"
feeding
"
193
local
err
194
return
function
(
)
195
if
not
last_out
then
196
report
(
"
error: source is empty
"
)
197
return
198
end
199
while
true
do
200
if
state
=
=
"
feeding
"
then
201
last_in
,
err
=
src
(
)
202
if
err
then
203
return
nil
,
err
204
end
205
last_out
=
f
(
last_in
)
206
if
not
last_out
then
207
if
last_in
then
208
report
(
"
error: filter returned inappropriate 'nil'
"
)
209
end
210
return
nil
211
elseif
last_out
~
=
"
"
then
212
state
=
"
eating
"
213
if
last_in
then
214
last_in
=
"
"
215
end
216
return
last_out
217
end
218
else
219
last_out
=
f
(
last_in
)
220
if
last_out
=
=
"
"
then
221
if
last_in
=
=
"
"
then
222
state
=
"
feeding
"
223
else
224
report
(
"
error: filter returned nothing
"
)
225
return
226
end
227
elseif
not
last_out
then
228
if
last_in
then
229
report
(
"
filter returned inappropriate 'nil'
"
)
230
end
231
return
nil
232
else
233
return
last_out
234
end
235
end
236
end
237
end
238
end
239 240
-- creates a source that produces contents of several sources, one after the
241
-- other, as if they were concatenated
242 243
function
source
.
cat
(
...
)
244
local
arg
=
{
...
}
245
local
src
=
remove
(
arg
,
1
)
246
return
function
(
)
247
while
src
do
248
local
chunk
,
err
=
src
(
)
249
if
chunk
then
250
return
chunk
251
end
252
if
err
then
253
return
nil
,
err
254
end
255
src
=
remove
(
arg
,
1
)
256
end
257
end
258
end
259 260
-- creates a sink that stores into a table
261 262
function
sink
.
table
(
t
)
263
if
not
t
then
264
t
=
{
}
265
end
266
local
f
=
function
(
chunk
,
err
)
267
if
chunk
then
268
insert
(
t
,
chunk
)
269
end
270
return
1
271
end
272
return
f
,
t
273
end
274 275
-- turns a fancy sink into a simple sink
276 277
function
sink
.
simplify
(
snk
)
278
return
function
(
chunk
,
err
)
279
local
ret
,
err_or_new
=
snk
(
chunk
,
err
)
280
if
not
ret
then
281
return
nil
,
err_or_new
282
end
283
if
err_or_new
then
284
snk
=
err_or_new
285
end
286
return
1
287
end
288
end
289 290
-- creates a sink that discards data
291 292
local
function
null
(
)
293
return
1
294
end
295 296
function
sink
.
null
(
)
297
return
null
298
end
299 300
-- creates a sink that just returns an error
301 302
local
function
sinkerror
(
err
)
303
return
function
(
)
304
return
nil
,
err
305
end
306
end
307 308
sink
.
error
=
sinkerror
309 310
-- creates a file sink
311 312
function
sink
.
file
(
handle
,
io_err
)
313
if
handle
then
314
return
function
(
chunk
,
err
)
315
if
not
chunk
then
316
handle
:
close
(
)
317
return
1
318
else
319
return
handle
:
write
(
chunk
)
320
end
321
end
322
else
323
return
sinkerror
(
io_err
or
"
unable to open file
"
)
324
end
325
end
326 327
-- chains a sink with one or several filter(s)
328 329
function
sink
.
chain
(
f
,
snk
,
...
)
330
if
...
then
331
local
args
=
{
f
,
snk
,
...
}
332
snk
=
remove
(
args
,
#
args
)
333
f
=
filter
.
chain
(
unpack
(
args
)
)
334
end
335
return
function
(
chunk
,
err
)
336
if
chunk
~
=
"
"
then
337
local
filtered
=
f
(
chunk
)
338
local
done
=
chunk
and
"
"
339
while
true
do
340
local
ret
,
snkerr
=
snk
(
filtered
,
err
)
341
if
not
ret
then
342
return
nil
,
snkerr
343
end
344
if
filtered
=
=
done
then
345
return
1
346
end
347
filtered
=
f
(
done
)
348
end
349
else
350
return
1
351
end
352
end
353
end
354 355
-- pumps one chunk from the source to the sink
356 357
function
pump
.
step
(
src
,
snk
)
358
local
chunk
,
src_err
=
src
(
)
359
local
ret
,
snk_err
=
snk
(
chunk
,
src_err
)
360
if
chunk
and
ret
then
361
return
1
362
else
363
return
nil
,
src_err
or
snk_err
364
end
365
end
366 367
-- pumps all data from a source to a sink, using a step function
368 369
function
pump
.
all
(
src
,
snk
,
step
)
370
if
not
step
then
371
step
=
pump
.
step
372
end
373
while
true
do
374
local
ret
,
err
=
step
(
src
,
snk
)
375
if
not
ret
then
376
if
err
then
377
return
nil
,
err
378
else
379
return
1
380
end
381
end
382
end
383
end
384 385
package
.
loaded
[
"
ltn12
"
]
=
ltn12
386 387
return
ltn12
388