Coroutine-free filter.chain.

This commit is contained in:
Diego Nehab 2004-07-29 05:11:21 +00:00
parent 30ec722a3b
commit ecb8db95a4
2 changed files with 37 additions and 20 deletions

View File

@ -26,28 +26,45 @@ function filter.cycle(low, ctx, extra)
end end
end end
-- given the return of a filter, can it have pending data?
local function pending(s)
return s ~= "" and s
end
-- chains two filters together -- chains two filters together
local function chain2(f1, f2) local function chain2(f1, f2)
assert(f1 and f2) local cf1, cf2
local co = coroutine.create(function(chunk)
while true do
local filtered1 = f1(chunk)
local filtered2 = f2(filtered1)
local done2 = filtered1 and ""
while true do
if filtered2 == "" or filtered2 == nil then break end
coroutine.yield(filtered2)
filtered2 = f2(done2)
end
if filtered1 == "" then chunk = coroutine.yield(filtered1)
elseif filtered1 == nil then return nil
else chunk = chunk and "" end
end
end)
return function(chunk) return function(chunk)
local ret, a, b = coroutine.resume(co, chunk) -- if f2 has pending data, service it first, always
if ret then return a, b if pending(cf2) then
else return nil, a end cf2 = f2(cf1)
if pending(cf2) then return cf2 end
end
-- here either f2 was already empty or we just found out it is
-- we get filtered data from f1
cf1 = f1(chunk)
-- make sure next time we call f1 to get pending data,
-- we don't pass the same chunk again
if chunk then chunk = "" end
-- while there is data in f1
while pending(cf1) do
-- pass the new data to f2
cf2 = f2(cf1)
-- if f2 produced something, return it
if pending(cf2) then
-- make sure next time we call f2 to get pending data,
-- we don't pass the same chunk again
if cf1 then cf1 = "" end
return cf2
end
-- here f2 is still not satisfied with the amount of data
-- f1 produced. we keep trying.
cf1 = f1(chunk)
end
-- here f1 was empty or it became empty without managing
-- to produce enough data for f2 to produce something
cf2 = f2(cf1)
return cf2
end end
end end

View File

@ -8,7 +8,7 @@ local qptest = "qptest.bin"
local eqptest = "qptest.bin2" local eqptest = "qptest.bin2"
local dqptest = "qptest.bin3" local dqptest = "qptest.bin3"
local b64test = "luasocket.so" local b64test = "luasocket.dylib"
local eb64test = "b64test.bin" local eb64test = "b64test.bin"
local db64test = "b64test.bin2" local db64test = "b64test.bin2"