home *** CD-ROM | disk | FTP | other *** search
/ Clickx 115 / Clickx 115.iso / software / tools / windows / tails-i386-0.16.iso / live / filesystem.squashfs / usr / share / lua / 5.1 / ltn12.lua next >
Encoding:
Text File  |  2009-07-20  |  8.0 KB  |  293 lines

  1. -----------------------------------------------------------------------------
  2. -- LTN12 - Filters, sources, sinks and pumps.
  3. -- LuaSocket toolkit.
  4. -- Author: Diego Nehab
  5. -- RCS ID: $Id: ltn12.lua,v 1.31 2006/04/03 04:45:42 diego Exp $
  6. -----------------------------------------------------------------------------
  7.  
  8. -----------------------------------------------------------------------------
  9. -- Declare module
  10. -----------------------------------------------------------------------------
  11. local string = require("string")
  12. local table = require("table")
  13. local base = _G
  14. module("ltn12")
  15.  
  16. filter = {}
  17. source = {}
  18. sink = {}
  19. pump = {}
  20.  
  21. -- 2048 seems to be better in windows...
  22. BLOCKSIZE = 2048
  23. _VERSION = "LTN12 1.0.1"
  24.  
  25. -----------------------------------------------------------------------------
  26. -- Filter stuff
  27. -----------------------------------------------------------------------------
  28. -- returns a high level filter that cycles a low-level filter
  29. function filter.cycle(low, ctx, extra)
  30.     base.assert(low)
  31.     return function(chunk)
  32.         local ret
  33.         ret, ctx = low(ctx, chunk, extra)
  34.         return ret
  35.     end
  36. end
  37.  
  38. -- chains a bunch of filters together
  39. -- (thanks to Wim Couwenberg)
  40. function filter.chain(...)
  41.     local n = table.getn(arg)
  42.     local top, index = 1, 1
  43.     local retry = ""
  44.     return function(chunk)
  45.         retry = chunk and retry
  46.         while true do
  47.             if index == top then
  48.                 chunk = arg[index](chunk)
  49.                 if chunk == "" or top == n then return chunk
  50.                 elseif chunk then index = index + 1
  51.                 else
  52.                     top = top+1
  53.                     index = top
  54.                 end
  55.             else
  56.                 chunk = arg[index](chunk or "")
  57.                 if chunk == "" then
  58.                     index = index - 1
  59.                     chunk = retry
  60.                 elseif chunk then
  61.                     if index == n then return chunk
  62.                     else index = index + 1 end
  63.                 else base.error("filter returned inappropriate nil") end
  64.             end
  65.         end
  66.     end
  67. end
  68.  
  69. -----------------------------------------------------------------------------
  70. -- Source stuff
  71. -----------------------------------------------------------------------------
  72. -- create an empty source
  73. local function empty()
  74.     return nil
  75. end
  76.  
  77. function source.empty()
  78.     return empty
  79. end
  80.  
  81. -- returns a source that just outputs an error
  82. function source.error(err)
  83.     return function()
  84.         return nil, err
  85.     end
  86. end
  87.  
  88. -- creates a file source
  89. function source.file(handle, io_err)
  90.     if handle then
  91.         return function()
  92.             local chunk = handle:read(BLOCKSIZE)
  93.             if not chunk then handle:close() end
  94.             return chunk
  95.         end
  96.     else return source.error(io_err or "unable to open file") end
  97. end
  98.  
  99. -- turns a fancy source into a simple source
  100. function source.simplify(src)
  101.     base.assert(src)
  102.     return function()
  103.         local chunk, err_or_new = src()
  104.         src = err_or_new or src
  105.         if not chunk then return nil, err_or_new
  106.         else return chunk end
  107.     end
  108. end
  109.  
  110. -- creates string source
  111. function source.string(s)
  112.     if s then
  113.         local i = 1
  114.         return function()
  115.             local chunk = string.sub(s, i, i+BLOCKSIZE-1)
  116.             i = i + BLOCKSIZE
  117.             if chunk ~= "" then return chunk
  118.             else return nil end
  119.         end
  120.     else return source.empty() end
  121. end
  122.  
  123. -- creates rewindable source
  124. function source.rewind(src)
  125.     base.assert(src)
  126.     local t = {}
  127.     return function(chunk)
  128.         if not chunk then
  129.             chunk = table.remove(t)
  130.             if not chunk then return src()
  131.             else return chunk end
  132.         else
  133.             table.insert(t, chunk)
  134.         end
  135.     end
  136. end
  137.  
  138. function source.chain(src, f)
  139.     base.assert(src and f)
  140.     local last_in, last_out = "", ""
  141.     local state = "feeding"
  142.     local err
  143.     return function()
  144.         if not last_out then
  145.             base.error('source is empty!', 2)
  146.         end
  147.         while true do
  148.             if state == "feeding" then
  149.                 last_in, err = src()
  150.                 if err then return nil, err end
  151.                 last_out = f(last_in)
  152.                 if not last_out then
  153.                     if last_in then
  154.                         base.error('filter returned inappropriate nil')
  155.                     else
  156.                         return nil
  157.                     end
  158.                 elseif last_out ~= "" then
  159.                     state = "eating"
  160.                     if last_in then last_in = "" end
  161.                     return last_out
  162.                 end
  163.             else
  164.                 last_out = f(last_in)
  165.                 if last_out == "" then
  166.                     if last_in == "" then
  167.                         state = "feeding"
  168.                     else
  169.                         base.error('filter returned ""')
  170.                     end
  171.                 elseif not last_out then
  172.                     if last_in then
  173.                         base.error('filter returned inappropriate nil')
  174.                     else
  175.                         return nil
  176.                     end
  177.                 else
  178.                     return last_out
  179.                 end
  180.             end
  181.         end
  182.     end
  183. end
  184.  
  185. -- creates a source that produces contents of several sources, one after the
  186. -- other, as if they were concatenated
  187. -- (thanks to Wim Couwenberg)
  188. function source.cat(...)
  189.     local src = table.remove(arg, 1)
  190.     return function()
  191.         while src do
  192.             local chunk, err = src()
  193.             if chunk then return chunk end
  194.             if err then return nil, err end
  195.             src = table.remove(arg, 1)
  196.         end
  197.     end
  198. end
  199.  
  200. -----------------------------------------------------------------------------
  201. -- Sink stuff
  202. -----------------------------------------------------------------------------
  203. -- creates a sink that stores into a table
  204. function sink.table(t)
  205.     t = t or {}
  206.     local f = function(chunk, err)
  207.         if chunk then table.insert(t, chunk) end
  208.         return 1
  209.     end
  210.     return f, t
  211. end
  212.  
  213. -- turns a fancy sink into a simple sink
  214. function sink.simplify(snk)
  215.     base.assert(snk)
  216.     return function(chunk, err)
  217.         local ret, err_or_new = snk(chunk, err)
  218.         if not ret then return nil, err_or_new end
  219.         snk = err_or_new or snk
  220.         return 1
  221.     end
  222. end
  223.  
  224. -- creates a file sink
  225. function sink.file(handle, io_err)
  226.     if handle then
  227.         return function(chunk, err)
  228.             if not chunk then
  229.                 handle:close()
  230.                 return 1
  231.             else return handle:write(chunk) end
  232.         end
  233.     else return sink.error(io_err or "unable to open file") end
  234. end
  235.  
  236. -- creates a sink that discards data
  237. local function null()
  238.     return 1
  239. end
  240.  
  241. function sink.null()
  242.     return null
  243. end
  244.  
  245. -- creates a sink that just returns an error
  246. function sink.error(err)
  247.     return function()
  248.         return nil, err
  249.     end
  250. end
  251.  
  252. -- chains a sink with a filter
  253. function sink.chain(f, snk)
  254.     base.assert(f and snk)
  255.     return function(chunk, err)
  256.         if chunk ~= "" then
  257.             local filtered = f(chunk)
  258.             local done = chunk and ""
  259.             while true do
  260.                 local ret, snkerr = snk(filtered, err)
  261.                 if not ret then return nil, snkerr end
  262.                 if filtered == done then return 1 end
  263.                 filtered = f(done)
  264.             end
  265.         else return 1 end
  266.     end
  267. end
  268.  
  269. -----------------------------------------------------------------------------
  270. -- Pump stuff
  271. -----------------------------------------------------------------------------
  272. -- pumps one chunk from the source to the sink
  273. function pump.step(src, snk)
  274.     local chunk, src_err = src()
  275.     local ret, snk_err = snk(chunk, src_err)
  276.     if chunk and ret then return 1
  277.     else return nil, src_err or snk_err end
  278. end
  279.  
  280. -- pumps all data from a source to a sink, using a step function
  281. function pump.all(src, snk, step)
  282.     base.assert(src and snk)
  283.     step = step or pump.step
  284.     while true do
  285.         local ret, err = step(src, snk)
  286.         if not ret then
  287.             if err then return nil, err
  288.             else return 1 end
  289.         end
  290.     end
  291. end
  292.  
  293.