local lz = require "lzss" local buffer = require "buffer" lz16 = {} local function cint(n,l) local t={} for i = 0, 7 do t[i+1] = (n >> (i * 8)) & 0xFF end return string.reverse(string.char(table.unpack(t)):sub(1,l)) end local function toint(s) local n = 0 local i = 1 for p in s:gmatch(".") do n = n << 8 n = n | string.byte(p) i=i+1 end return n end local function readBuffer(fi) local stream = {} if fi:read(4) ~= "lz16" then return false, "not an lz16 archive" end function stream.read() local len = toint(fi:read(2) or "\0\0") if len < 1 then return nil end coroutine.yield() return lz.decompress(fi:read(len)) end function stream.close() fi:close() end return buffer.new("rb",stream) end local function writeBuffer(fo) local stream = {} function stream:write(data) local cblock = lz.compress(data) fo:write(cint(cblock:len(),2)..cblock) return cblock:len()+2 end function stream.close() fo:close() end fo:write("lz16") -- write header return buffer.new("wb",stream) end function lz16.buffer(stream) if stream.mode.w then return writeBuffer(stream) end return readBuffer(stream) end function lz16.open(fname, mode) local f = io.open(fname, mode) if not f then return false end f.mode.b = true return lz16.buffer(f) end return lz16