diff options
| author | Diego Nehab <diego@tecgraf.puc-rio.br> | 2004-02-11 03:31:53 +0000 |
|---|---|---|
| committer | Diego Nehab <diego@tecgraf.puc-rio.br> | 2004-02-11 03:31:53 +0000 |
| commit | 390846b640ee7013d51a766b4b2472bdcfbbdfcc (patch) | |
| tree | 3bedd023a0a84feb714615245b58eab5ffb4309b /src/ltn12.lua | |
| parent | 0b2542d1a61fc5425ff65ab3dbf7ba7de174763f (diff) | |
| download | luasocket-390846b640ee7013d51a766b4b2472bdcfbbdfcc.tar.gz luasocket-390846b640ee7013d51a766b4b2472bdcfbbdfcc.tar.bz2 luasocket-390846b640ee7013d51a766b4b2472bdcfbbdfcc.zip | |
Added ltn12 module. Modified mime to be stand alone.
Still crashes on invalid input. Dunno why.
Diffstat (limited to 'src/ltn12.lua')
| -rw-r--r-- | src/ltn12.lua | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/src/ltn12.lua b/src/ltn12.lua new file mode 100644 index 0000000..548588a --- /dev/null +++ b/src/ltn12.lua | |||
| @@ -0,0 +1,171 @@ | |||
| 1 | -- create code namespace inside LuaSocket namespace | ||
| 2 | ltn12 = ltn12 or {} | ||
| 3 | -- make all module globals fall into mime namespace | ||
| 4 | setmetatable(ltn12, { __index = _G }) | ||
| 5 | setfenv(1, ltn12) | ||
| 6 | |||
| 7 | -- sub namespaces | ||
| 8 | filter = {} | ||
| 9 | source = {} | ||
| 10 | sink = {} | ||
| 11 | |||
| 12 | -- 2048 seems to be better in windows... | ||
| 13 | BLOCKSIZE = 2048 | ||
| 14 | |||
| 15 | -- returns a high level filter that cycles a cycles a low-level filter | ||
| 16 | function filter.cycle(low, ctx, extra) | ||
| 17 | return function(chunk) | ||
| 18 | local ret | ||
| 19 | ret, ctx = low(ctx, chunk, extra) | ||
| 20 | return ret | ||
| 21 | end | ||
| 22 | end | ||
| 23 | |||
| 24 | -- chains two filters together | ||
| 25 | local function chain2(f1, f2) | ||
| 26 | return function(chunk) | ||
| 27 | local ret = f2(f1(chunk)) | ||
| 28 | if chunk then return ret | ||
| 29 | else return ret .. f2() end | ||
| 30 | end | ||
| 31 | end | ||
| 32 | |||
| 33 | -- chains a bunch of filters together | ||
| 34 | function filter.chain(...) | ||
| 35 | local f = arg[1] | ||
| 36 | for i = 2, table.getn(arg) do | ||
| 37 | f = chain2(f, arg[i]) | ||
| 38 | end | ||
| 39 | return f | ||
| 40 | end | ||
| 41 | |||
| 42 | -- create an empty source | ||
| 43 | function source.empty(err) | ||
| 44 | return function() | ||
| 45 | return nil, err | ||
| 46 | end | ||
| 47 | end | ||
| 48 | |||
| 49 | -- creates a file source | ||
| 50 | function source.file(handle, io_err) | ||
| 51 | if handle then | ||
| 52 | return function() | ||
| 53 | local chunk = handle:read(BLOCKSIZE) | ||
| 54 | if not chunk then handle:close() end | ||
| 55 | return chunk | ||
| 56 | end | ||
| 57 | else source.empty(io_err or "unable to open file") end | ||
| 58 | end | ||
| 59 | |||
| 60 | -- turns a fancy source into a simple source | ||
| 61 | function source.simplify(src) | ||
| 62 | return function() | ||
| 63 | local chunk, err_or_new = src() | ||
| 64 | src = err_or_new or src | ||
| 65 | if not chunk then return nil, err_or_new | ||
| 66 | else return chunk end | ||
| 67 | end | ||
| 68 | end | ||
| 69 | |||
| 70 | -- creates string source | ||
| 71 | function source.string(s) | ||
| 72 | if s then | ||
| 73 | local i = 1 | ||
| 74 | return function() | ||
| 75 | local chunk = string.sub(s, i, i+BLOCKSIZE-1) | ||
| 76 | i = i + BLOCKSIZE | ||
| 77 | if chunk ~= "" then return chunk | ||
| 78 | else return nil end | ||
| 79 | end | ||
| 80 | else source.empty() end | ||
| 81 | end | ||
| 82 | |||
| 83 | -- creates rewindable source | ||
| 84 | function source.rewind(src) | ||
| 85 | local t = {} | ||
| 86 | src = source.simplify(src) | ||
| 87 | return function(chunk) | ||
| 88 | if not chunk then | ||
| 89 | chunk = table.remove(t) | ||
| 90 | if not chunk then return src() | ||
| 91 | else return chunk end | ||
| 92 | else | ||
| 93 | table.insert(t, chunk) | ||
| 94 | end | ||
| 95 | end | ||
| 96 | end | ||
| 97 | |||
| 98 | -- chains a source with a filter | ||
| 99 | function source.chain(src, f) | ||
| 100 | src = source.simplify(src) | ||
| 101 | local chain = function() | ||
| 102 | local chunk, err = src() | ||
| 103 | if not chunk then return f(nil), source.empty(err) | ||
| 104 | else return f(chunk) end | ||
| 105 | end | ||
| 106 | return source.simplify(chain) | ||
| 107 | end | ||
| 108 | |||
| 109 | -- creates a sink that stores into a table | ||
| 110 | function sink.table(t) | ||
| 111 | t = t or {} | ||
| 112 | local f = function(chunk, err) | ||
| 113 | if chunk then table.insert(t, chunk) end | ||
| 114 | return 1 | ||
| 115 | end | ||
| 116 | return f, t | ||
| 117 | end | ||
| 118 | |||
| 119 | -- turns a fancy sink into a simple sink | ||
| 120 | function sink.simplify(snk) | ||
| 121 | return function(chunk, err) | ||
| 122 | local ret, err_or_new = snk(chunk, err) | ||
| 123 | if not ret then return nil, err_or_new end | ||
| 124 | snk = err_or_new or snk | ||
| 125 | return 1 | ||
| 126 | end | ||
| 127 | end | ||
| 128 | |||
| 129 | -- creates a file sink | ||
| 130 | function sink.file(handle, io_err) | ||
| 131 | if handle then | ||
| 132 | return function(chunk, err) | ||
| 133 | if not chunk then | ||
| 134 | handle:close() | ||
| 135 | return nil, err | ||
| 136 | end | ||
| 137 | return handle:write(chunk) | ||
| 138 | end | ||
| 139 | else sink.null() end | ||
| 140 | end | ||
| 141 | |||
| 142 | -- creates a sink that discards data | ||
| 143 | local function null() | ||
| 144 | return 1 | ||
| 145 | end | ||
| 146 | |||
| 147 | function sink.null() | ||
| 148 | return null | ||
| 149 | end | ||
| 150 | |||
| 151 | -- chains a sink with a filter | ||
| 152 | function sink.chain(f, snk) | ||
| 153 | snk = sink.simplify(snk) | ||
| 154 | return function(chunk, err) | ||
| 155 | local r, e = snk(f(chunk)) | ||
| 156 | if not r then return nil, e end | ||
| 157 | if not chunk then return snk(nil, err) end | ||
| 158 | return 1 | ||
| 159 | end | ||
| 160 | end | ||
| 161 | |||
| 162 | -- pumps all data from a source to a sink | ||
| 163 | function pump(src, snk) | ||
| 164 | snk = sink.simplify(snk) | ||
| 165 | for chunk, src_err in source.simplify(src) do | ||
| 166 | local ret, snk_err = snk(chunk, src_err) | ||
| 167 | if not chunk or not ret then | ||
| 168 | return not src_err and not snk_err, src_err or snk_err | ||
| 169 | end | ||
| 170 | end | ||
| 171 | end | ||
