-- zzlib-bit32 - zlib decompression in Lua - version using bit/bit32 libraries -- Copyright (c) 2016-2020 Francois Galea -- 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