2020-06-05 22:54:51 +10:00
|
|
|
local lz = require "lzss"
|
|
|
|
local buffer = require "buffer"
|
|
|
|
|
|
|
|
lz16 = {}
|
|
|
|
|
|
|
|
local function readBuffer(fi)
|
|
|
|
local stream = {}
|
|
|
|
if fi:read(4) ~= "lz16" then
|
|
|
|
return false, "not an lz16 archive"
|
|
|
|
end
|
|
|
|
function stream.read()
|
2021-05-26 16:15:24 +10:00
|
|
|
local len = string.unpack(">I2", fi:read(2) or "\0\0")
|
2020-06-05 22:54:51 +10:00
|
|
|
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)
|
2021-05-26 16:15:24 +10:00
|
|
|
fo:write(string.pack(">I2", cblock:len()) .. cblock)
|
2020-06-05 22:54:51 +10:00
|
|
|
return cblock:len()+2
|
|
|
|
end
|
|
|
|
function stream.close()
|
|
|
|
fo:close()
|
|
|
|
end
|
|
|
|
fo:write("lz16") -- write header
|
|
|
|
return buffer.new("wb",stream)
|
|
|
|
end
|
|
|
|
|
2020-06-05 23:07:06 +10:00
|
|
|
function lz16.buffer(stream) -- table -- table -- Wrap a stream to read or write LZ16.
|
2020-06-05 22:54:51 +10:00
|
|
|
if stream.mode.w then
|
|
|
|
return writeBuffer(stream)
|
|
|
|
end
|
|
|
|
return readBuffer(stream)
|
|
|
|
end
|
|
|
|
|
2020-06-05 23:07:06 +10:00
|
|
|
function lz16.open(fname, mode) -- string string -- table -- Open file *fname* to read or write LZ16-compressed data depending on *mode*
|
2020-06-05 22:54:51 +10:00
|
|
|
local f = io.open(fname, mode)
|
|
|
|
if not f then return false end
|
|
|
|
f.mode.b = true
|
|
|
|
return lz16.buffer(f)
|
|
|
|
end
|
|
|
|
|
|
|
|
return lz16
|