local string = require("string")
local table = require("table")
local base = _G
local ltn12 = {}
ltn12.filter = {}
ltn12.source = {}
ltn12.sink = {}
ltn12.pump = {}
BLOCKSIZE = 2048
_VERSION = "LTN12 1.0.1"
function ltn12.filter.cycle(low, ctx, extra)
base.assert(low)
return function(chunk)
local ret
ret, ctx = low(ctx, chunk, extra)
return ret
end
end
function ltn12.filter.chain(_)
local n = #arg
local top, index = 1, 1
local retry = ""
return function(chunk)
retry = chunk and retry
while true do
if index == top then
chunk = arg[index](chunk)
if chunk == "" or top == n then
return chunk
elseif chunk then
index = index + 1
else
top = top + 1
index = top
end
else
chunk = arg[index](chunk or "")
if chunk == "" then
index = index - 1
chunk = retry
elseif chunk then
if index == n then
return chunk
else
index = index + 1
end
else
base.error("filter returned inappropriate nil")
end
end
end
end
end
local function empty()
return nil
end
function ltn12.source.empty()
return empty
end
function ltn12.source.error(err)
return function()
return nil, err
end
end
function ltn12.source.file(handle, io_err)
if handle then
return function()
local chunk = handle:read(BLOCKSIZE)
if not chunk then handle:close() end
return chunk
end
else
return ltn12.source.error(io_err or "unable to open file")
end
end
function ltn12.source.simplify(src)
base.assert(src)
return function()
local chunk, err_or_new = src()
src = err_or_new or src
if not chunk then
return nil, err_or_new
else
return chunk
end
end
end
function ltn12.source.string(s)
if s then
local i = 1
return function()
local chunk = string.sub(s, i, i + BLOCKSIZE - 1)
i = i + BLOCKSIZE
if chunk ~= "" then
return chunk
else
return nil
end
end
else
return ltn12.source.empty()
end
end
function ltn12.source.rewind(src)
base.assert(src)
local t = {}
return function(chunk)
if not chunk then
chunk = table.remove(t)
if not chunk then
return src()
else
return chunk
end
else
table.insert(t, chunk)
end
end
end
function ltn12.source.chain(src, f)
base.assert(src and f)
local last_in, last_out = "", ""
local state = "feeding"
local err
return function()
if not last_out then
base.error('source is empty!', 2)
end
while true do
if state == "feeding" then
last_in, err = src()
if err then return nil, err end
last_out = f(last_in)
if not last_out then
if last_in then
base.error('filter returned inappropriate nil')
else
return nil
end
elseif last_out ~= "" then
state = "eating"
if last_in then last_in = "" end
return last_out
end
else
last_out = f(last_in)
if last_out == "" then
if last_in == "" then
state = "feeding"
else
base.error('filter returned ""')
end
elseif not last_out then
if last_in then
base.error('filter returned inappropriate nil')
else
return nil
end
else
return last_out
end
end
end
end
end
function ltn12.source.cat(_)
local src = table.remove(arg, 1)
return function()
while src do
local chunk, err = src()
if chunk then return chunk end
if err then return nil, err end
src = table.remove(arg, 1)
end
end
end
function ltn12.sink.table(t)
t = t or {}
local f = function(chunk, _)
if chunk then table.insert(t, chunk) end
return 1
end
return f, t
end
function ltn12.sink.simplify(snk)
base.assert(snk)
return function(chunk, err)
local ret, err_or_new = snk(chunk, err)
if not ret then return nil, err_or_new end
snk = err_or_new or snk
return 1
end
end
function ltn12.sink.file(handle, io_err)
if handle then
return function(chunk, _)
if not chunk then
handle:close()
return 1
else
return handle:write(chunk)
end
end
else
return ltn12.sink.error(io_err or "unable to open file")
end
end
local function null()
return 1
end
function ltn12.sink.null()
return null
end
function ltn12.sink.error(err)
return function()
return nil, err
end
end
function ltn12.sink.chain(f, snk)
base.assert(f and snk)
return function(chunk, err)
if chunk ~= "" then
local filtered = f(chunk)
local done = chunk and ""
while true do
local ret, snkerr = snk(filtered, err)
if not ret then return nil, snkerr end
if filtered == done then return 1 end
filtered = f(done)
end
else
return 1
end
end
end
function ltn12.pump.step(src, snk)
local chunk, src_err = src()
local ret, snk_err = snk(chunk, src_err)
if chunk and ret then
return 1
else
return nil, src_err or snk_err
end
end
function ltn12.pump.all(src, snk, step)
base.assert(src and snk)
step = step or ltn12.pump.step
while true do
local ret, err = step(src, snk)
if not ret then
if err then
return nil, err
else
return 1
end
end
end
end
return ltn12