diff options
author | Diego Nehab <diego@tecgraf.puc-rio.br> | 2004-03-16 06:42:53 +0000 |
---|---|---|
committer | Diego Nehab <diego@tecgraf.puc-rio.br> | 2004-03-16 06:42:53 +0000 |
commit | bcc0c2a9f0be2ca796ef5206a78e283fe15e6186 (patch) | |
tree | 65c269d4854aa5ff4a0b2c8eede5cdb18d716033 /src/ltn12.lua | |
parent | b6edaac2841137cf0ef5105f75358bbab4570d87 (diff) | |
download | luasocket-bcc0c2a9f0be2ca796ef5206a78e283fe15e6186.tar.gz luasocket-bcc0c2a9f0be2ca796ef5206a78e283fe15e6186.tar.bz2 luasocket-bcc0c2a9f0be2ca796ef5206a78e283fe15e6186.zip |
New filter scheme.
ltn12 and mime updated.
smtp/ftp broken.
Diffstat (limited to 'src/ltn12.lua')
-rw-r--r-- | src/ltn12.lua | 75 |
1 files changed, 54 insertions, 21 deletions
diff --git a/src/ltn12.lua b/src/ltn12.lua index 548588a..de7103d 100644 --- a/src/ltn12.lua +++ b/src/ltn12.lua | |||
@@ -1,6 +1,6 @@ | |||
1 | -- create code namespace inside LuaSocket namespace | 1 | -- create module namespace |
2 | ltn12 = ltn12 or {} | 2 | ltn12 = ltn12 or {} |
3 | -- make all module globals fall into mime namespace | 3 | -- make all globals fall into ltn12 namespace |
4 | setmetatable(ltn12, { __index = _G }) | 4 | setmetatable(ltn12, { __index = _G }) |
5 | setfenv(1, ltn12) | 5 | setfenv(1, ltn12) |
6 | 6 | ||
@@ -12,6 +12,14 @@ sink = {} | |||
12 | -- 2048 seems to be better in windows... | 12 | -- 2048 seems to be better in windows... |
13 | BLOCKSIZE = 2048 | 13 | BLOCKSIZE = 2048 |
14 | 14 | ||
15 | local function second(a, b) | ||
16 | return b | ||
17 | end | ||
18 | |||
19 | local function skip(a, b, c) | ||
20 | return b, c | ||
21 | end | ||
22 | |||
15 | -- returns a high level filter that cycles a cycles a low-level filter | 23 | -- returns a high level filter that cycles a cycles a low-level filter |
16 | function filter.cycle(low, ctx, extra) | 24 | function filter.cycle(low, ctx, extra) |
17 | return function(chunk) | 25 | return function(chunk) |
@@ -24,9 +32,7 @@ end | |||
24 | -- chains two filters together | 32 | -- chains two filters together |
25 | local function chain2(f1, f2) | 33 | local function chain2(f1, f2) |
26 | return function(chunk) | 34 | return function(chunk) |
27 | local ret = f2(f1(chunk)) | 35 | return f2(f1(chunk)) |
28 | if chunk then return ret | ||
29 | else return ret .. f2() end | ||
30 | end | 36 | end |
31 | end | 37 | end |
32 | 38 | ||
@@ -83,7 +89,6 @@ end | |||
83 | -- creates rewindable source | 89 | -- creates rewindable source |
84 | function source.rewind(src) | 90 | function source.rewind(src) |
85 | local t = {} | 91 | local t = {} |
86 | src = source.simplify(src) | ||
87 | return function(chunk) | 92 | return function(chunk) |
88 | if not chunk then | 93 | if not chunk then |
89 | chunk = table.remove(t) | 94 | chunk = table.remove(t) |
@@ -97,13 +102,38 @@ end | |||
97 | 102 | ||
98 | -- chains a source with a filter | 103 | -- chains a source with a filter |
99 | function source.chain(src, f) | 104 | function source.chain(src, f) |
100 | src = source.simplify(src) | 105 | local co = coroutine.create(function() |
101 | local chain = function() | 106 | while true do |
102 | local chunk, err = src() | 107 | local chunk, err = src() |
103 | if not chunk then return f(nil), source.empty(err) | 108 | local filtered = f(chunk) |
104 | else return f(chunk) end | 109 | local done = chunk and "" |
110 | while true do | ||
111 | coroutine.yield(filtered) | ||
112 | if filtered == done then break end | ||
113 | filtered = f(done) | ||
114 | end | ||
115 | if not chunk then return nil, err end | ||
116 | end | ||
117 | end) | ||
118 | return function() | ||
119 | return skip(coroutine.resume(co)) | ||
105 | end | 120 | end |
106 | return source.simplify(chain) | 121 | end |
122 | |||
123 | -- creates a source that produces contents of several files one after the | ||
124 | -- other, as if they were concatenated | ||
125 | function source.cat(...) | ||
126 | local co = coroutine.create(function() | ||
127 | local i = 1 | ||
128 | while i <= table.getn(arg) do | ||
129 | local chunk = arg[i]:read(2048) | ||
130 | if chunk then coroutine.yield(chunk) | ||
131 | else i = i + 1 end | ||
132 | end | ||
133 | end) | ||
134 | return source.simplify(function() | ||
135 | return second(coroutine.resume(co)) | ||
136 | end) | ||
107 | end | 137 | end |
108 | 138 | ||
109 | -- creates a sink that stores into a table | 139 | -- creates a sink that stores into a table |
@@ -150,22 +180,25 @@ end | |||
150 | 180 | ||
151 | -- chains a sink with a filter | 181 | -- chains a sink with a filter |
152 | function sink.chain(f, snk) | 182 | function sink.chain(f, snk) |
153 | snk = sink.simplify(snk) | ||
154 | return function(chunk, err) | 183 | return function(chunk, err) |
155 | local r, e = snk(f(chunk)) | 184 | local filtered = f(chunk) |
156 | if not r then return nil, e end | 185 | local done = chunk and "" |
157 | if not chunk then return snk(nil, err) end | 186 | while true do |
158 | return 1 | 187 | local ret, snkerr = snk(filtered, err) |
188 | if not ret then return nil, snkerr end | ||
189 | if filtered == done then return 1 end | ||
190 | filtered = f(done) | ||
191 | end | ||
159 | end | 192 | end |
160 | end | 193 | end |
161 | 194 | ||
162 | -- pumps all data from a source to a sink | 195 | -- pumps all data from a source to a sink |
163 | function pump(src, snk) | 196 | function pump(src, snk) |
164 | snk = sink.simplify(snk) | 197 | while true do |
165 | for chunk, src_err in source.simplify(src) do | 198 | local chunk, src_err = src() |
166 | local ret, snk_err = snk(chunk, src_err) | 199 | local ret, snk_err = snk(chunk, src_err) |
167 | if not chunk or not ret then | 200 | if not chunk or not ret then |
168 | return not src_err and not snk_err, src_err or snk_err | 201 | return not src_err and not snk_err, src_err or snk_err |
169 | end | 202 | end |
170 | end | 203 | end |
171 | end | 204 | end |