1
2
3
4local select , unpack = select , unpack
5local insert , remove = table . insert , table . remove
6local sub = string . sub
7
8local 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
20end
21
22local filter = { }
23local source = { }
24local sink = { }
25local pump = { }
26
27local 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
43
44function filter . cycle ( low , ctx , extra )
45 if low then
46 return function ( chunk )
47 return ( low ( ctx , chunk , extra ) )
48 end
49 end
50end
51
52
53
54function 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
92end
93
94
95
96local function empty ( )
97 return nil
98end
99
100function source . empty ( )
101 return empty
102end
103
104
105
106local function sourceerror ( err )
107 return function ( )
108 return nil , err
109 end
110end
111
112source . error = sourceerror
113
114
115
116function 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
129end
130
131
132
133function 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
145end
146
147
148
149function 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
164end
165
166
167
168function 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
182end
183
184
185
186function 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
238end
239
240
241
242
243function 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
258end
259
260
261
262function 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
273end
274
275
276
277function 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
288end
289
290
291
292local function null ( )
293 return 1
294end
295
296function sink . null ( )
297 return null
298end
299
300
301
302local function sinkerror ( err )
303 return function ( )
304 return nil , err
305 end
306end
307
308sink . error = sinkerror
309
310
311
312function 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
325end
326
327
328
329function 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
353end
354
355
356
357function 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
365end
366
367
368
369function 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
383end
384
385package . loaded [ " ltn12 " ] = ltn12
386
387return ltn12
388 |