| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280 |
- -- zzlib-bit32 - zlib decompression in Lua - version using bit/bit32 libraries
- -- Copyright (c) 2016-2020 Francois Galea <fgalea at free.fr>
- -- This program is free software. It comes without any warranty, to
- -- the extent permitted by applicable law. You can redistribute it
- -- and/or modify it under the terms of the Do What The Fuck You Want
- -- To Public License, Version 2, as published by Sam Hocevar. See
- -- the COPYING file or http://www.wtfpl.net/ for more details.
- local inflate = {}
- local bit = bit32 or bit
- inflate.band = bit.band
- inflate.rshift = bit.rshift
- function inflate.bitstream_init(file)
- local bs = {
- file = file, -- the open file handle
- buf = nil, -- character buffer
- len = nil, -- length of character buffer
- pos = 1, -- position in char buffer
- b = 0, -- bit buffer
- n = 0, -- number of bits in buffer
- }
- -- get rid of n first bits
- function bs:flushb(n)
- self.n = self.n - n
- self.b = bit.rshift(self.b,n)
- end
- -- peek a number of n bits from stream
- function bs:peekb(n)
- while self.n < n do
- if self.pos > self.len then
- self.buf = self.file:read(4096)
- self.len = self.buf:len()
- self.pos = 1
- end
- self.b = self.b + bit.lshift(self.buf:byte(self.pos),self.n)
- self.pos = self.pos + 1
- self.n = self.n + 8
- end
- return bit.band(self.b,bit.lshift(1,n)-1)
- end
- -- get a number of n bits from stream
- function bs:getb(n)
- local ret = bs:peekb(n)
- self.n = self.n - n
- self.b = bit.rshift(self.b,n)
- return ret
- end
- -- get next variable-size of maximum size=n element from stream, according to Huffman table
- function bs:getv(hufftable,n)
- local e = hufftable[bs:peekb(n)]
- local len = bit.band(e,15)
- local ret = bit.rshift(e,4)
- self.n = self.n - len
- self.b = bit.rshift(self.b,len)
- return ret
- end
- function bs:close()
- if self.file then
- self.file:close()
- end
- end
- if type(file) == "string" then
- bs.file = nil
- bs.buf = file
- else
- bs.buf = file:read(4096)
- end
- bs.len = bs.buf:len()
- return bs
- end
- local function hufftable_create(depths)
- local nvalues = #depths
- local nbits = 1
- local bl_count = {}
- local next_code = {}
- for i=1,nvalues do
- local d = depths[i]
- if d > nbits then
- nbits = d
- end
- bl_count[d] = (bl_count[d] or 0) + 1
- end
- local table = {}
- local code = 0
- bl_count[0] = 0
- for i=1,nbits do
- code = (code + (bl_count[i-1] or 0)) * 2
- next_code[i] = code
- end
- for i=1,nvalues do
- local len = depths[i] or 0
- if len > 0 then
- local e = (i-1)*16 + len
- local code = next_code[len]
- local rcode = 0
- for j=1,len do
- rcode = rcode + bit.lshift(bit.band(1,bit.rshift(code,j-1)),len-j)
- end
- for j=0,2^nbits-1,2^len do
- table[j+rcode] = e
- end
- next_code[len] = next_code[len] + 1
- end
- end
- return table,nbits
- end
- local function block_loop(out,bs,nlit,ndist,littable,disttable)
- local lit
- repeat
- lit = bs:getv(littable,nlit)
- if lit < 256 then
- table.insert(out,lit)
- elseif lit > 256 then
- local nbits = 0
- local size = 3
- local dist = 1
- if lit < 265 then
- size = size + lit - 257
- elseif lit < 285 then
- nbits = bit.rshift(lit-261,2)
- size = size + bit.lshift(bit.band(lit-261,3)+4,nbits)
- else
- size = 258
- end
- if nbits > 0 then
- size = size + bs:getb(nbits)
- end
- local v = bs:getv(disttable,ndist)
- if v < 4 then
- dist = dist + v
- else
- nbits = bit.rshift(v-2,1)
- dist = dist + bit.lshift(bit.band(v,1)+2,nbits)
- dist = dist + bs:getb(nbits)
- end
- local p = #out-dist+1
- while size > 0 do
- table.insert(out,out[p])
- p = p + 1
- size = size - 1
- end
- end
- until lit == 256
- end
- local function block_dynamic(out,bs)
- local order = { 17, 18, 19, 1, 9, 8, 10, 7, 11, 6, 12, 5, 13, 4, 14, 3, 15, 2, 16 }
- local hlit = 257 + bs:getb(5)
- local hdist = 1 + bs:getb(5)
- local hclen = 4 + bs:getb(4)
- local depths = {}
- for i=1,hclen do
- local v = bs:getb(3)
- depths[order[i]] = v
- end
- for i=hclen+1,19 do
- depths[order[i]] = 0
- end
- local lengthtable,nlen = hufftable_create(depths)
- local i=1
- while i<=hlit+hdist do
- local v = bs:getv(lengthtable,nlen)
- if v < 16 then
- depths[i] = v
- i = i + 1
- elseif v < 19 then
- local nbt = {2,3,7}
- local nb = nbt[v-15]
- local c = 0
- local n = 3 + bs:getb(nb)
- if v == 16 then
- c = depths[i-1]
- elseif v == 18 then
- n = n + 8
- end
- for j=1,n do
- depths[i] = c
- i = i + 1
- end
- else
- error("wrong entry in depth table for literal/length alphabet: "..v);
- end
- end
- local litdepths = {} for i=1,hlit do table.insert(litdepths,depths[i]) end
- local littable,nlit = hufftable_create(litdepths)
- local distdepths = {} for i=hlit+1,#depths do table.insert(distdepths,depths[i]) end
- local disttable,ndist = hufftable_create(distdepths)
- block_loop(out,bs,nlit,ndist,littable,disttable)
- end
- local function block_static(out,bs)
- local cnt = { 144, 112, 24, 8 }
- local dpt = { 8, 9, 7, 8 }
- local depths = {}
- for i=1,4 do
- local d = dpt[i]
- for j=1,cnt[i] do
- table.insert(depths,d)
- end
- end
- local littable,nlit = hufftable_create(depths)
- depths = {}
- for i=1,32 do
- depths[i] = 5
- end
- local disttable,ndist = hufftable_create(depths)
- block_loop(out,bs,nlit,ndist,littable,disttable)
- end
- local function block_uncompressed(out,bs)
- bs:flushb(bit.band(bs.n,7))
- local len = bs:getb(16)
- if bs.n > 0 then
- error("Unexpected.. should be zero remaining bits in buffer.")
- end
- local nlen = bs:getb(16)
- if bit.bxor(len,nlen) ~= 65535 then
- error("LEN and NLEN don't match")
- end
- for i=bs.pos,bs.pos+len-1 do
- table.insert(out,bs.buf:byte(i,i))
- end
- bs.pos = bs.pos + len
- end
- function inflate.main(bs)
- local last,type
- local output = {}
- repeat
- local block
- last = bs:getb(1)
- type = bs:getb(2)
- if type == 0 then
- block_uncompressed(output,bs)
- elseif type == 1 then
- block_static(output,bs)
- elseif type == 2 then
- block_dynamic(output,bs)
- else
- error("unsupported block type")
- end
- until last == 1
- bs:flushb(bit.band(bs.n,7))
- return output
- end
- local crc32_table
- function inflate.crc32(s,crc)
- if not crc32_table then
- crc32_table = {}
- for i=0,255 do
- local r=i
- for j=1,8 do
- r = bit.bxor(bit.rshift(r,1),bit.band(0xedb88320,bit.bnot(bit.band(r,1)-1)))
- end
- crc32_table[i] = r
- end
- end
- crc = bit.bnot(crc or 0)
- for i=1,#s do
- local c = s:byte(i)
- crc = bit.bxor(crc32_table[bit.bxor(c,bit.band(crc,0xff))],bit.rshift(crc,8))
- end
- crc = bit.bnot(crc)
- if crc<0 then
- -- in Lua < 5.2, sign extension was performed
- crc = crc + 4294967296
- end
- return crc
- end
- return inflate
|