UNPKG

@soapbox.pub/wasmboy

Version:

Soapbox fork of Wasmboy.

1,210 lines (1,128 loc) 33 kB
// Taken/Modified From: https://github.com/photopea/UZIP.js let UZIP = {}; // Make it a hacky es module const uzip = UZIP; export default uzip; UZIP['parse'] = function( buf // ArrayBuffer ) { let rUs = UZIP.bin.readUshort, rUi = UZIP.bin.readUint, o = 0, out = {}; let data = new Uint8Array(buf); let eocd = data.length - 4; while (rUi(data, eocd) != 0x06054b50) eocd--; o = eocd; o += 4; // sign = 0x06054b50 o += 4; // disks = 0; let cnu = rUs(data, o); o += 2; let cnt = rUs(data, o); o += 2; let csize = rUi(data, o); o += 4; let coffs = rUi(data, o); o += 4; o = coffs; for (let i = 0; i < cnu; i++) { let sign = rUi(data, o); o += 4; o += 4; // versions; o += 4; // flag + compr o += 4; // time let crc32 = rUi(data, o); o += 4; let csize = rUi(data, o); o += 4; let usize = rUi(data, o); o += 4; let nl = rUs(data, o), el = rUs(data, o + 2), cl = rUs(data, o + 4); o += 6; // name, extra, comment o += 8; // disk, attribs let roff = rUi(data, o); o += 4; o += nl + el + cl; UZIP._readLocal(data, roff, out, csize, usize); } //console.log(out); return out; }; UZIP._readLocal = function(data, o, out, csize, usize) { let rUs = UZIP.bin.readUshort, rUi = UZIP.bin.readUint; let sign = rUi(data, o); o += 4; let ver = rUs(data, o); o += 2; let gpflg = rUs(data, o); o += 2; //if((gpflg&8)!=0) throw "unknown sizes"; let cmpr = rUs(data, o); o += 2; let time = rUi(data, o); o += 4; let crc32 = rUi(data, o); o += 4; //let csize = rUi(data, o); o+=4; //let usize = rUi(data, o); o+=4; o += 8; let nlen = rUs(data, o); o += 2; let elen = rUs(data, o); o += 2; let name = UZIP.bin.readUTF8(data, o, nlen); o += nlen; o += elen; //console.log(sign.toString(16), ver, gpflg, cmpr, crc32.toString(16), "csize, usize", csize, usize, nlen, elen, name, o); let file = new Uint8Array(data.buffer, o); if (false) { } else if (cmpr == 0) out[name] = new Uint8Array(file.buffer.slice(o, o + csize)); else if (cmpr == 8) { let buf = new Uint8Array(usize); UZIP.inflateRaw(file, buf); //let nbuf = pako["inflateRaw"](file); //for(let i=0; i<buf.length; i++) if(buf[i]!=nbuf[i]) { console.log(buf.length, nbuf.length, usize, i); throw "e"; } out[name] = buf; } else throw 'unknown compression method: ' + cmpr; }; UZIP.inflateRaw = function(file, buf) { return UZIP.F.inflate(file, buf); }; UZIP.inflate = function(file, buf) { let CMF = file[0], FLG = file[1]; let CM = CMF & 15, CINFO = CMF >>> 4; //console.log(CM, CINFO,CMF,FLG); return UZIP.inflateRaw(new Uint8Array(file.buffer, file.byteOffset + 2, file.length - 6), buf); }; UZIP.deflate = function(data, opts /*, buf, off*/) { if (opts == null) opts = { level: 6 }; let off = 0, buf = new Uint8Array(50 + Math.floor(data.length * 1.1)); buf[off] = 120; buf[off + 1] = 156; off += 2; off = UZIP.F.deflateRaw(data, buf, off, opts.level); let crc = UZIP.adler(data, 0, data.length); buf[off + 0] = (crc >>> 24) & 255; buf[off + 1] = (crc >>> 16) & 255; buf[off + 2] = (crc >>> 8) & 255; buf[off + 3] = (crc >>> 0) & 255; return new Uint8Array(buf.buffer, 0, off + 4); }; UZIP.deflateRaw = function(data, opts) { if (opts == null) opts = { level: 6 }; let buf = new Uint8Array(50 + Math.floor(data.length * 1.1)); let off; off = UZIP.F.deflateRaw(data, buf, off, opts.level); return new Uint8Array(buf.buffer, 0, off); }; UZIP.encode = function(obj) { let tot = 0, wUi = UZIP.bin.writeUint, wUs = UZIP.bin.writeUshort; let zpd = {}; for (let p in obj) { let cpr = !UZIP._noNeed(p), buf = obj[p], crc = UZIP.crc.crc(buf, 0, buf.length); zpd[p] = { cpr: cpr, usize: buf.length, crc: crc, file: cpr ? UZIP.deflateRaw(buf) : buf }; } for (let p in zpd) tot += zpd[p].file.length + 30 + 46 + 2 * UZIP.bin.sizeUTF8(p); tot += 22; let data = new Uint8Array(tot), o = 0; let fof = []; for (let p in zpd) { let file = zpd[p]; fof.push(o); o = UZIP._writeHeader(data, o, p, file, 0); } let i = 0, ioff = o; for (let p in zpd) { let file = zpd[p]; fof.push(o); o = UZIP._writeHeader(data, o, p, file, 1, fof[i++]); } let csize = o - ioff; wUi(data, o, 0x06054b50); o += 4; o += 4; // disks wUs(data, o, i); o += 2; wUs(data, o, i); o += 2; // number of c d records wUi(data, o, csize); o += 4; wUi(data, o, ioff); o += 4; o += 2; return data.buffer; }; // no need to compress .PNG, .ZIP, .JPEG .... UZIP._noNeed = function(fn) { let ext = fn .split('.') .pop() .toLowerCase(); return 'png,jpg,jpeg,zip'.indexOf(ext) != -1; }; UZIP._writeHeader = function(data, o, p, obj, t, roff) { let wUi = UZIP.bin.writeUint, wUs = UZIP.bin.writeUshort; let file = obj.file; wUi(data, o, t == 0 ? 0x04034b50 : 0x02014b50); o += 4; // sign if (t == 1) o += 2; // ver made by wUs(data, o, 20); o += 2; // ver wUs(data, o, 0); o += 2; // gflip wUs(data, o, obj.cpr ? 8 : 0); o += 2; // cmpr wUi(data, o, 0); o += 4; // time wUi(data, o, obj.crc); o += 4; // crc32 wUi(data, o, file.length); o += 4; // csize wUi(data, o, obj.usize); o += 4; // usize wUs(data, o, UZIP.bin.sizeUTF8(p)); o += 2; // nlen wUs(data, o, 0); o += 2; // elen if (t == 1) { o += 2; // comment length o += 2; // disk number o += 6; // attributes wUi(data, o, roff); o += 4; // usize } let nlen = UZIP.bin.writeUTF8(data, o, p); o += nlen; if (t == 0) { data.set(file, o); o += file.length; } return o; }; UZIP.crc = { table: (function() { let tab = new Uint32Array(256); for (let n = 0; n < 256; n++) { let c = n; for (let k = 0; k < 8; k++) { if (c & 1) c = 0xedb88320 ^ (c >>> 1); else c = c >>> 1; } tab[n] = c; } return tab; })(), update: function(c, buf, off, len) { for (let i = 0; i < len; i++) c = UZIP.crc.table[(c ^ buf[off + i]) & 0xff] ^ (c >>> 8); return c; }, crc: function(b, o, l) { return UZIP.crc.update(0xffffffff, b, o, l) ^ 0xffffffff; } }; UZIP.adler = function(data, o, len) { let a = 1, b = 0; let off = o, end = o + len; while (off < end) { let eend = Math.min(off + 5552, end); while (off < eend) { a += data[off++]; b += a; } a = a % 65521; b = b % 65521; } return (b << 16) | a; }; UZIP.bin = { readUshort: function(buff, p) { return buff[p] | (buff[p + 1] << 8); }, writeUshort: function(buff, p, n) { buff[p] = n & 255; buff[p + 1] = (n >> 8) & 255; }, readUint: function(buff, p) { return buff[p + 3] * (256 * 256 * 256) + ((buff[p + 2] << 16) | (buff[p + 1] << 8) | buff[p]); }, writeUint: function(buff, p, n) { buff[p] = n & 255; buff[p + 1] = (n >> 8) & 255; buff[p + 2] = (n >> 16) & 255; buff[p + 3] = (n >> 24) & 255; }, readASCII: function(buff, p, l) { let s = ''; for (let i = 0; i < l; i++) s += String.fromCharCode(buff[p + i]); return s; }, writeASCII: function(data, p, s) { for (let i = 0; i < s.length; i++) data[p + i] = s.charCodeAt(i); }, pad: function(n) { return n.length < 2 ? '0' + n : n; }, readUTF8: function(buff, p, l) { let s = '', ns; for (let i = 0; i < l; i++) s += '%' + UZIP.bin.pad(buff[p + i].toString(16)); try { ns = decodeURIComponent(s); } catch (e) { return UZIP.bin.readASCII(buff, p, l); } return ns; }, writeUTF8: function(buff, p, str) { let strl = str.length, i = 0; for (let ci = 0; ci < strl; ci++) { let code = str.charCodeAt(ci); if ((code & (0xffffffff - (1 << 7) + 1)) == 0) { buff[p + i] = code; i++; } else if ((code & (0xffffffff - (1 << 11) + 1)) == 0) { buff[p + i] = 192 | (code >> 6); buff[p + i + 1] = 128 | ((code >> 0) & 63); i += 2; } else if ((code & (0xffffffff - (1 << 16) + 1)) == 0) { buff[p + i] = 224 | (code >> 12); buff[p + i + 1] = 128 | ((code >> 6) & 63); buff[p + i + 2] = 128 | ((code >> 0) & 63); i += 3; } else if ((code & (0xffffffff - (1 << 21) + 1)) == 0) { buff[p + i] = 240 | (code >> 18); buff[p + i + 1] = 128 | ((code >> 12) & 63); buff[p + i + 2] = 128 | ((code >> 6) & 63); buff[p + i + 3] = 128 | ((code >> 0) & 63); i += 4; } else throw 'e'; } return i; }, sizeUTF8: function(str) { let strl = str.length, i = 0; for (let ci = 0; ci < strl; ci++) { let code = str.charCodeAt(ci); if ((code & (0xffffffff - (1 << 7) + 1)) == 0) { i++; } else if ((code & (0xffffffff - (1 << 11) + 1)) == 0) { i += 2; } else if ((code & (0xffffffff - (1 << 16) + 1)) == 0) { i += 3; } else if ((code & (0xffffffff - (1 << 21) + 1)) == 0) { i += 4; } else throw 'e'; } return i; } }; UZIP.F = {}; UZIP.F.deflateRaw = function(data, out, opos, lvl) { let opts = [ /* ush good_length; /* reduce lazy search above this match length ush max_lazy; /* do not perform lazy search above this match length ush nice_length; /* quit search above this match length */ /* good lazy nice chain */ /* 0 */ [0, 0, 0, 0, 0] /* store only */, /* 1 */ [4, 4, 8, 4, 0] /* max speed, no lazy matches */, /* 2 */ [4, 5, 16, 8, 0], /* 3 */ [4, 6, 16, 16, 0], /* 4 */ [4, 10, 16, 32, 0] /* lazy matches */, /* 5 */ [8, 16, 32, 32, 0], /* 6 */ [8, 16, 128, 128, 0], /* 7 */ [8, 32, 128, 256, 0], /* 8 */ [32, 128, 258, 1024, 1], /* 9 */ [32, 258, 258, 4096, 1] ]; /* max compression */ let opt = opts[lvl]; let U = UZIP.F.U, goodIndex = UZIP.F._goodIndex, hash = UZIP.F._hash, putsE = UZIP.F._putsE; let i = 0, pos = opos << 3, cvrd = 0, dlen = data.length; if (lvl == 0) { while (i < dlen) { let len = Math.min(0xffff, dlen - i); putsE(out, pos, i + len == dlen ? 1 : 0); pos = UZIP.F._copyExact(data, i, len, out, pos + 8); i += len; } return pos >>> 3; } let lits = U.lits, strt = U.strt, prev = U.prev, li = 0, lc = 0, bs = 0, ebits = 0, c = 0, nc = 0; // last_item, literal_count, block_start if (dlen > 2) { nc = UZIP.F._hash(data, 0); strt[nc] = 0; } let nmch = 0, nmci = 0; for (i = 0; i < dlen; i++) { c = nc; //* if (i + 1 < dlen - 2) { nc = UZIP.F._hash(data, i + 1); let ii = (i + 1) & 0x7fff; prev[ii] = strt[nc]; strt[nc] = ii; } //*/ if (cvrd <= i) { if (li > 14000 || lc > 26697) { if (cvrd < i) { lits[li] = i - cvrd; li += 2; cvrd = i; } pos = UZIP.F._writeBlock(i == dlen - 1 || cvrd == dlen ? 1 : 0, lits, li, ebits, data, bs, i - bs, out, pos); li = lc = ebits = 0; bs = i; } let mch = 0; //if(nmci==i) mch= nmch; else if (i < dlen - 2) mch = UZIP.F._bestMatch(data, i, prev, c, Math.min(opt[2], dlen - i), opt[3]); /* if(mch!=0 && opt[4]==1 && (mch>>>16)<opt[1] && i+1<dlen-2) { nmch = UZIP.F._bestMatch(data, i+1, prev, nc, opt[2], opt[3]); nmci=i+1; //let mch2 = UZIP.F._bestMatch(data, i+2, prev, nnc); //nmci=i+1; if((nmch>>>16)>(mch>>>16)) mch=0; }//*/ let len = mch >>> 16, dst = mch & 0xffff; //if(i-dst<0) throw "e"; if (mch != 0) { let len = mch >>> 16, dst = mch & 0xffff; //if(i-dst<0) throw "e"; let lgi = goodIndex(len, U.of0); U.lhst[257 + lgi]++; let dgi = goodIndex(dst, U.df0); U.dhst[dgi]++; ebits += U.exb[lgi] + U.dxb[dgi]; lits[li] = (len << 23) | (i - cvrd); lits[li + 1] = (dst << 16) | (lgi << 8) | dgi; li += 2; cvrd = i + len; } else { U.lhst[data[i]]++; } lc++; } } if (bs != i || data.length == 0) { if (cvrd < i) { lits[li] = i - cvrd; li += 2; cvrd = i; } pos = UZIP.F._writeBlock(1, lits, li, ebits, data, bs, i - bs, out, pos); li = 0; lc = 0; li = lc = ebits = 0; bs = i; } while ((pos & 7) != 0) pos++; return pos >>> 3; }; UZIP.F._bestMatch = function(data, i, prev, c, nice, chain) { let ci = i & 0x7fff, pi = prev[ci]; //console.log("----", i); let dif = (ci - pi + (1 << 15)) & 0x7fff; if (pi == ci || c != UZIP.F._hash(data, i - dif)) return 0; let tl = 0, td = 0; // top length, top distance let dlim = Math.min(0x7fff, i); while (dif <= dlim && --chain != 0 && pi != ci /*&& c==UZIP.F._hash(data,i-dif)*/) { if (tl == 0 || data[i + tl] == data[i + tl - dif]) { let cl = UZIP.F._howLong(data, i, dif); if (cl > tl) { tl = cl; td = dif; if (tl >= nice) break; //* if (dif + 2 < cl) cl = dif + 2; let maxd = 0; // pi does not point to the start of the word for (let j = 0; j < cl - 2; j++) { let ei = (i - dif + j + (1 << 15)) & 0x7fff; let li = prev[ei]; let curd = (ei - li + (1 << 15)) & 0x7fff; if (curd > maxd) { maxd = curd; pi = ei; } } //*/ } } ci = pi; pi = prev[ci]; dif += (ci - pi + (1 << 15)) & 0x7fff; } return (tl << 16) | td; }; UZIP.F._howLong = function(data, i, dif) { if (data[i] != data[i - dif] || data[i + 1] != data[i + 1 - dif] || data[i + 2] != data[i + 2 - dif]) return 0; let oi = i, l = Math.min(data.length, i + 258); i += 3; //while(i+4<l && data[i]==data[i-dif] && data[i+1]==data[i+1-dif] && data[i+2]==data[i+2-dif] && data[i+3]==data[i+3-dif]) i+=4; while (i < l && data[i] == data[i - dif]) i++; return i - oi; }; UZIP.F._hash = function(data, i) { return (((data[i] << 8) | data[i + 1]) + (data[i + 2] << 4)) & 0xffff; //let hash_shift = 0, hash_mask = 255; //let h = data[i+1] % 251; //h = (((h << 8) + data[i+2]) % 251); //h = (((h << 8) + data[i+2]) % 251); //h = ((h<<hash_shift) ^ (c) ) & hash_mask; //return h | (data[i]<<8); //return (data[i] | (data[i+1]<<8)); }; //UZIP.___toth = 0; UZIP.saved = 0; UZIP.F._writeBlock = function(BFINAL, lits, li, ebits, data, o0, l0, out, pos) { let U = UZIP.F.U, putsF = UZIP.F._putsF, putsE = UZIP.F._putsE; //* let T, ML, MD, MH, numl, numd, numh, lset, dset; U.lhst[256]++; T = UZIP.F.getTrees(); ML = T[0]; MD = T[1]; MH = T[2]; numl = T[3]; numd = T[4]; numh = T[5]; lset = T[6]; dset = T[7]; let cstSize = (((pos + 3) & 7) == 0 ? 0 : 8 - ((pos + 3) & 7)) + 32 + (l0 << 3); let fxdSize = ebits + UZIP.F.contSize(U.fltree, U.lhst) + UZIP.F.contSize(U.fdtree, U.dhst); let dynSize = ebits + UZIP.F.contSize(U.ltree, U.lhst) + UZIP.F.contSize(U.dtree, U.dhst); dynSize += 14 + 3 * numh + UZIP.F.contSize(U.itree, U.ihst) + (U.ihst[16] * 2 + U.ihst[17] * 3 + U.ihst[18] * 7); for (let j = 0; j < 286; j++) U.lhst[j] = 0; for (let j = 0; j < 30; j++) U.dhst[j] = 0; for (let j = 0; j < 19; j++) U.ihst[j] = 0; //*/ let BTYPE = cstSize < fxdSize && cstSize < dynSize ? 0 : fxdSize < dynSize ? 1 : 2; putsF(out, pos, BFINAL); putsF(out, pos + 1, BTYPE); pos += 3; let opos = pos; if (BTYPE == 0) { while ((pos & 7) != 0) pos++; pos = UZIP.F._copyExact(data, o0, l0, out, pos); } else { let ltree, dtree; if (BTYPE == 1) { ltree = U.fltree; dtree = U.fdtree; } if (BTYPE == 2) { UZIP.F.makeCodes(U.ltree, ML); UZIP.F.revCodes(U.ltree, ML); UZIP.F.makeCodes(U.dtree, MD); UZIP.F.revCodes(U.dtree, MD); UZIP.F.makeCodes(U.itree, MH); UZIP.F.revCodes(U.itree, MH); ltree = U.ltree; dtree = U.dtree; putsE(out, pos, numl - 257); pos += 5; // 286 putsE(out, pos, numd - 1); pos += 5; // 30 putsE(out, pos, numh - 4); pos += 4; // 19 for (let i = 0; i < numh; i++) putsE(out, pos + i * 3, U.itree[(U.ordr[i] << 1) + 1]); pos += 3 * numh; pos = UZIP.F._codeTiny(lset, U.itree, out, pos); pos = UZIP.F._codeTiny(dset, U.itree, out, pos); } let off = o0; for (let si = 0; si < li; si += 2) { let qb = lits[si], len = qb >>> 23, end = off + (qb & ((1 << 23) - 1)); while (off < end) pos = UZIP.F._writeLit(data[off++], ltree, out, pos); if (len != 0) { let qc = lits[si + 1], dst = qc >> 16, lgi = (qc >> 8) & 255, dgi = qc & 255; pos = UZIP.F._writeLit(257 + lgi, ltree, out, pos); putsE(out, pos, len - U.of0[lgi]); pos += U.exb[lgi]; pos = UZIP.F._writeLit(dgi, dtree, out, pos); putsF(out, pos, dst - U.df0[dgi]); pos += U.dxb[dgi]; off += len; } } pos = UZIP.F._writeLit(256, ltree, out, pos); } //console.log(pos-opos, fxdSize, dynSize, cstSize); return pos; }; UZIP.F._copyExact = function(data, off, len, out, pos) { let p8 = pos >>> 3; out[p8] = len; out[p8 + 1] = len >>> 8; out[p8 + 2] = 255 - out[p8]; out[p8 + 3] = 255 - out[p8 + 1]; p8 += 4; out.set(new Uint8Array(data.buffer, off, len), p8); //for(let i=0; i<len; i++) out[p8+i]=data[off+i]; return pos + ((len + 4) << 3); }; /* Interesting facts: - decompressed block can have bytes, which do not occur in a Huffman tree (copied from the previous block by reference) */ UZIP.F.getTrees = function() { let U = UZIP.F.U; let ML = UZIP.F._hufTree(U.lhst, U.ltree, 15); let MD = UZIP.F._hufTree(U.dhst, U.dtree, 15); let lset = [], numl = UZIP.F._lenCodes(U.ltree, lset); let dset = [], numd = UZIP.F._lenCodes(U.dtree, dset); for (let i = 0; i < lset.length; i += 2) U.ihst[lset[i]]++; for (let i = 0; i < dset.length; i += 2) U.ihst[dset[i]]++; let MH = UZIP.F._hufTree(U.ihst, U.itree, 7); let numh = 19; while (numh > 4 && U.itree[(U.ordr[numh - 1] << 1) + 1] == 0) numh--; return [ML, MD, MH, numl, numd, numh, lset, dset]; }; UZIP.F.getSecond = function(a) { let b = []; for (let i = 0; i < a.length; i += 2) b.push(a[i + 1]); return b; }; UZIP.F.nonZero = function(a) { let b = ''; for (let i = 0; i < a.length; i += 2) if (a[i + 1] != 0) b += (i >> 1) + ','; return b; }; UZIP.F.contSize = function(tree, hst) { let s = 0; for (let i = 0; i < hst.length; i++) s += hst[i] * tree[(i << 1) + 1]; return s; }; UZIP.F._codeTiny = function(set, tree, out, pos) { for (let i = 0; i < set.length; i += 2) { let l = set[i], rst = set[i + 1]; //console.log(l, pos, tree[(l<<1)+1]); pos = UZIP.F._writeLit(l, tree, out, pos); let rsl = l == 16 ? 2 : l == 17 ? 3 : 7; if (l > 15) { UZIP.F._putsE(out, pos, rst, rsl); pos += rsl; } } return pos; }; UZIP.F._lenCodes = function(tree, set) { let len = tree.length; while (len != 2 && tree[len - 1] == 0) len -= 2; // when no distances, keep one code with length 0 for (let i = 0; i < len; i += 2) { let l = tree[i + 1], nxt = i + 3 < len ? tree[i + 3] : -1, nnxt = i + 5 < len ? tree[i + 5] : -1, prv = i == 0 ? -1 : tree[i - 1]; if (l == 0 && nxt == l && nnxt == l) { let lz = i + 5; while (lz + 2 < len && tree[lz + 2] == l) lz += 2; let zc = Math.min((lz + 1 - i) >>> 1, 138); if (zc < 11) set.push(17, zc - 3); else set.push(18, zc - 11); i += zc * 2 - 2; } else if (l == prv && nxt == l && nnxt == l) { let lz = i + 5; while (lz + 2 < len && tree[lz + 2] == l) lz += 2; let zc = Math.min((lz + 1 - i) >>> 1, 6); set.push(16, zc - 3); i += zc * 2 - 2; } else set.push(l, 0); } return len >>> 1; }; UZIP.F._hufTree = function(hst, tree, MAXL) { let list = [], hl = hst.length, tl = tree.length, i = 0; for (i = 0; i < tl; i += 2) { tree[i] = 0; tree[i + 1] = 0; } for (i = 0; i < hl; i++) if (hst[i] != 0) list.push({ lit: i, f: hst[i] }); let end = list.length, l2 = list.slice(0); if (end == 0) return 0; // empty histogram (usually for dist) if (end == 1) { let lit = list[0].lit, l2 = lit == 0 ? 1 : 0; tree[(lit << 1) + 1] = 1; tree[(l2 << 1) + 1] = 1; return 1; } list.sort(function(a, b) { return a.f - b.f; }); let a = list[0], b = list[1], i0 = 0, i1 = 1, i2 = 2; list[0] = { lit: -1, f: a.f + b.f, l: a, r: b, d: 0 }; while (i1 != end - 1) { if (i0 != i1 && (i2 == end || list[i0].f < list[i2].f)) { a = list[i0++]; } else { a = list[i2++]; } if (i0 != i1 && (i2 == end || list[i0].f < list[i2].f)) { b = list[i0++]; } else { b = list[i2++]; } list[i1++] = { lit: -1, f: a.f + b.f, l: a, r: b }; } let maxl = UZIP.F.setDepth(list[i1 - 1], 0); if (maxl > MAXL) { UZIP.F.restrictDepth(l2, MAXL, maxl); maxl = MAXL; } for (i = 0; i < end; i++) tree[(l2[i].lit << 1) + 1] = l2[i].d; return maxl; }; UZIP.F.setDepth = function(t, d) { if (t.lit != -1) { t.d = d; return d; } return Math.max(UZIP.F.setDepth(t.l, d + 1), UZIP.F.setDepth(t.r, d + 1)); }; UZIP.F.restrictDepth = function(dps, MD, maxl) { let i = 0, bCost = 1 << (maxl - MD), dbt = 0; dps.sort(function(a, b) { return b.d == a.d ? a.f - b.f : b.d - a.d; }); for (i = 0; i < dps.length; i++) if (dps[i].d > MD) { let od = dps[i].d; dps[i].d = MD; dbt += bCost - (1 << (maxl - od)); } else break; dbt = dbt >>> (maxl - MD); while (dbt > 0) { let od = dps[i].d; if (od < MD) { dps[i].d++; dbt -= 1 << (MD - od - 1); } else i++; } for (; i >= 0; i--) if (dps[i].d == MD && dbt < 0) { dps[i].d--; dbt++; } if (dbt != 0) console.log('debt left'); }; UZIP.F._goodIndex = function(v, arr) { let i = 0; if (arr[i | 16] <= v) i |= 16; if (arr[i | 8] <= v) i |= 8; if (arr[i | 4] <= v) i |= 4; if (arr[i | 2] <= v) i |= 2; if (arr[i | 1] <= v) i |= 1; return i; }; UZIP.F._writeLit = function(ch, ltree, out, pos) { UZIP.F._putsF(out, pos, ltree[ch << 1]); return pos + ltree[(ch << 1) + 1]; }; UZIP.F.inflate = function(data, buf) { if (data[0] == 3 && data[1] == 0) return buf ? buf : new Uint8Array(0); let F = UZIP.F, bitsF = F._bitsF, bitsE = F._bitsE, decodeTiny = F._decodeTiny, makeCodes = F.makeCodes, codes2map = F.codes2map, get17 = F._get17; let U = F.U; let noBuf = buf == null; if (noBuf) buf = new Uint8Array((data.length >> 2) << 3); let BFINAL = 0, BTYPE = 0, HLIT = 0, HDIST = 0, HCLEN = 0, ML = 0, MD = 0; let off = 0, pos = 0; let lmap, dmap; while (BFINAL == 0) { BFINAL = bitsF(data, pos, 1); BTYPE = bitsF(data, pos + 1, 2); pos += 3; //console.log(BFINAL, BTYPE); if (BTYPE == 0) { if ((pos & 7) != 0) pos += 8 - (pos & 7); let p8 = (pos >>> 3) + 4, len = data[p8 - 4] | (data[p8 - 3] << 8); //console.log(len);//bitsF(data, pos, 16), if (noBuf) buf = UZIP.F._check(buf, off + len); buf.set(new Uint8Array(data.buffer, data.byteOffset + p8, len), off); //for(let i=0; i<len; i++) buf[off+i] = data[p8+i]; //for(let i=0; i<len; i++) if(buf[off+i] != data[p8+i]) throw "e"; pos = (p8 + len) << 3; off += len; continue; } if (noBuf) buf = UZIP.F._check(buf, off + (1 << 17)); if (BTYPE == 1) { lmap = U.flmap; dmap = U.fdmap; ML = (1 << 9) - 1; MD = (1 << 5) - 1; } if (BTYPE == 2) { HLIT = bitsE(data, pos, 5) + 257; HDIST = bitsE(data, pos + 5, 5) + 1; HCLEN = bitsE(data, pos + 10, 4) + 4; pos += 14; let ppos = pos; for (let i = 0; i < 38; i += 2) { U.itree[i] = 0; U.itree[i + 1] = 0; } let tl = 1; for (let i = 0; i < HCLEN; i++) { let l = bitsE(data, pos + i * 3, 3); U.itree[(U.ordr[i] << 1) + 1] = l; if (l > tl) tl = l; } pos += 3 * HCLEN; //console.log(itree); makeCodes(U.itree, tl); codes2map(U.itree, tl, U.imap); lmap = U.lmap; dmap = U.dmap; let ml = decodeTiny(U.imap, (1 << tl) - 1, HLIT, data, pos, U.ltree); ML = (1 << (ml >>> 24)) - 1; pos += ml & 0xffffff; makeCodes(U.ltree, ml >>> 24); codes2map(U.ltree, ml >>> 24, lmap); let md = decodeTiny(U.imap, (1 << tl) - 1, HDIST, data, pos, U.dtree); MD = (1 << (md >>> 24)) - 1; pos += md & 0xffffff; makeCodes(U.dtree, md >>> 24); codes2map(U.dtree, md >>> 24, dmap); } //let ooff=off, opos=pos; while (true) { let code = lmap[get17(data, pos) & ML]; pos += code & 15; let lit = code >>> 4; //U.lhst[lit]++; if (lit >>> 8 == 0) { buf[off++] = lit; } else if (lit == 256) { break; } else { let end = off + lit - 254; if (lit > 264) { let ebs = U.ldef[lit - 257]; end = off + (ebs >>> 3) + bitsE(data, pos, ebs & 7); pos += ebs & 7; } //UZIP.F.dst[end-off]++; let dcode = dmap[get17(data, pos) & MD]; pos += dcode & 15; let dlit = dcode >>> 4; let dbs = U.ddef[dlit], dst = (dbs >>> 4) + bitsF(data, pos, dbs & 15); pos += dbs & 15; //let o0 = off-dst, stp = Math.min(end-off, dst); //if(stp>20) while(off<end) { buf.copyWithin(off, o0, o0+stp); off+=stp; } else //if(end-dst<=off) buf.copyWithin(off, off-dst, end-dst); else //if(dst==1) buf.fill(buf[off-1], off, end); else while (off < end) { buf[off] = buf[off++ - dst]; buf[off] = buf[off++ - dst]; buf[off] = buf[off++ - dst]; buf[off] = buf[off++ - dst]; } off = end; //while(off!=end) { buf[off]=buf[off++-dst]; } } } //console.log(off-ooff, (pos-opos)>>>3); } //console.log(UZIP.F.dst); //console.log(tlen, dlen, off-tlen+tcnt); return buf.length == off ? buf : buf.slice(0, off); }; UZIP.F._check = function(buf, len) { let bl = buf.length; if (len <= bl) return buf; let nbuf = new Uint8Array(bl << 1); for (let i = 0; i < bl; i += 4) { nbuf[i] = buf[i]; nbuf[i + 1] = buf[i + 1]; nbuf[i + 2] = buf[i + 2]; nbuf[i + 3] = buf[i + 3]; } return nbuf; }; UZIP.F._decodeTiny = function(lmap, LL, len, data, pos, tree) { let opos = pos; let bitsE = UZIP.F._bitsE, get17 = UZIP.F._get17; let dlen = len << 1, i = 0, mx = 0; //if(pos<1000) console.log("--------"); //console.log("----", pos, ":", data[7],data[8], data[9], data[10], data[11]); while (i < dlen) { let code = lmap[get17(data, pos) & LL]; pos += code & 15; let lit = code >>> 4; //if(pos<1000) console.log(lit, i>>>1); //if(i<20)console.log(lit, code>>>9, pos); if (lit <= 15) { tree[i] = 0; tree[i + 1] = lit; if (lit > mx) mx = lit; i += 2; } else { let ll = 0, n = 0; if (lit == 16) { n = (3 + bitsE(data, pos, 2)) << 1; pos += 2; ll = tree[i - 1]; } else if (lit == 17) { n = (3 + bitsE(data, pos, 3)) << 1; pos += 3; } else if (lit == 18) { n = (11 + bitsE(data, pos, 7)) << 1; pos += 7; } let ni = i + n; while (i < ni) { tree[i] = 0; tree[i + 1] = ll; i += 2; } } } let tl = tree.length; while (i < tl) { tree[i + 1] = 0; i += 2; } return (mx << 24) | (pos - opos); }; UZIP.F.makeCodes = function(tree, MAX_BITS) { // code, length let U = UZIP.F.U; let max_code = tree.length; let code, bits, n, i, len; let bl_count = U.bl_count; for (let i = 0; i <= MAX_BITS; i++) bl_count[i] = 0; for (i = 1; i < max_code; i += 2) bl_count[tree[i]]++; let next_code = U.next_code; // smallest code for each length code = 0; bl_count[0] = 0; for (bits = 1; bits <= MAX_BITS; bits++) { code = (code + bl_count[bits - 1]) << 1; next_code[bits] = code; } for (n = 0; n < max_code; n += 2) { len = tree[n + 1]; if (len != 0) { tree[n] = next_code[len]; next_code[len]++; } } }; UZIP.F.codes2map = function(tree, MAX_BITS, map) { let max_code = tree.length; let U = UZIP.F.U, r15 = U.rev15; for (let i = 0; i < max_code; i += 2) if (tree[i + 1] != 0) { let lit = i >> 1; let cl = tree[i + 1], val = (lit << 4) | cl; // : (0x8000 | (U.of0[lit-257]<<7) | (U.exb[lit-257]<<4) | cl); let rest = MAX_BITS - cl, i0 = tree[i] << rest, i1 = i0 + (1 << rest); //tree[i]=r15[i0]>>>(15-MAX_BITS); while (i0 != i1) { let p0 = r15[i0] >>> (15 - MAX_BITS); map[p0] = val; i0++; } } }; UZIP.F.revCodes = function(tree, MAX_BITS) { let r15 = UZIP.F.U.rev15, imb = 15 - MAX_BITS; for (let i = 0; i < tree.length; i += 2) { let i0 = tree[i] << (MAX_BITS - tree[i + 1]); tree[i] = r15[i0] >>> imb; } }; UZIP.F._putsE = function(dt, pos, val) { val = val << (pos & 7); let o = pos >>> 3; dt[o] |= val; dt[o + 1] |= val >>> 8; }; UZIP.F._putsF = function(dt, pos, val) { val = val << (pos & 7); let o = pos >>> 3; dt[o] |= val; dt[o + 1] |= val >>> 8; dt[o + 2] |= val >>> 16; }; UZIP.F._bitsE = function(dt, pos, length) { return ((dt[pos >>> 3] | (dt[(pos >>> 3) + 1] << 8)) >>> (pos & 7)) & ((1 << length) - 1); }; UZIP.F._bitsF = function(dt, pos, length) { return ((dt[pos >>> 3] | (dt[(pos >>> 3) + 1] << 8) | (dt[(pos >>> 3) + 2] << 16)) >>> (pos & 7)) & ((1 << length) - 1); }; /* UZIP.F._get9 = function(dt, pos) { return ((dt[pos>>>3] | (dt[(pos>>>3)+1]<<8))>>>(pos&7))&511; } */ UZIP.F._get17 = function(dt, pos) { // return at least 17 meaningful bytes return (dt[pos >>> 3] | (dt[(pos >>> 3) + 1] << 8) | (dt[(pos >>> 3) + 2] << 16)) >>> (pos & 7); }; UZIP.F._get25 = function(dt, pos) { // return at least 17 meaningful bytes return (dt[pos >>> 3] | (dt[(pos >>> 3) + 1] << 8) | (dt[(pos >>> 3) + 2] << 16) | (dt[(pos >>> 3) + 3] << 24)) >>> (pos & 7); }; UZIP.F.U = { next_code: new Uint16Array(16), bl_count: new Uint16Array(16), ordr: [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15], of0: [3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 999, 999, 999], exb: [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 0, 0, 0], ldef: new Uint16Array(32), df0: [ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 65535, 65535 ], dxb: [0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 0, 0], ddef: new Uint32Array(32), flmap: new Uint16Array(512), fltree: [], fdmap: new Uint16Array(32), fdtree: [], lmap: new Uint16Array(32768), ltree: [], dmap: new Uint16Array(32768), dtree: [], imap: new Uint16Array(512), itree: [], //rev9 : new Uint16Array( 512) rev15: new Uint16Array(1 << 15), lhst: new Uint32Array(286), dhst: new Uint32Array(30), ihst: new Uint32Array(19), lits: new Uint32Array(15000), strt: new Uint16Array(1 << 16), prev: new Uint16Array(1 << 15) }; (function() { let U = UZIP.F.U; let len = 1 << 15; for (let i = 0; i < len; i++) { let x = i; x = ((x & 0xaaaaaaaa) >>> 1) | ((x & 0x55555555) << 1); x = ((x & 0xcccccccc) >>> 2) | ((x & 0x33333333) << 2); x = ((x & 0xf0f0f0f0) >>> 4) | ((x & 0x0f0f0f0f) << 4); x = ((x & 0xff00ff00) >>> 8) | ((x & 0x00ff00ff) << 8); U.rev15[i] = ((x >>> 16) | (x << 16)) >>> 17; } for (let i = 0; i < 32; i++) { U.ldef[i] = (U.of0[i] << 3) | U.exb[i]; U.ddef[i] = (U.df0[i] << 4) | U.dxb[i]; } let i = 0; for (; i <= 143; i++) U.fltree.push(0, 8); for (; i <= 255; i++) U.fltree.push(0, 9); for (; i <= 279; i++) U.fltree.push(0, 7); for (; i <= 287; i++) U.fltree.push(0, 8); UZIP.F.makeCodes(U.fltree, 9); UZIP.F.codes2map(U.fltree, 9, U.flmap); UZIP.F.revCodes(U.fltree, 9); for (i = 0; i < 32; i++) U.fdtree.push(0, 5); UZIP.F.makeCodes(U.fdtree, 5); UZIP.F.codes2map(U.fdtree, 5, U.fdmap); UZIP.F.revCodes(U.fdtree, 5); for (let i = 0; i < 19; i++) U.itree.push(0, 0); for (let i = 0; i < 286; i++) U.ltree.push(0, 0); for (let i = 0; i < 30; i++) U.dtree.push(0, 0); })();