diff --git a/lib/inflate.js b/lib/inflate.js index 67b028f..5b94154 100644 --- a/lib/inflate.js +++ b/lib/inflate.js @@ -147,8 +147,7 @@ Inflate.prototype.push = function(data, mode) { var status, _mode; if (this.ended) { return false; } - - _mode = (mode === ~~mode) ? mode : ((mode === true) ? c.Z_FINISH : c.Z_NO_FLUSH); + _mode = c.Z_NO_FLUSH; strm.next_in = data; strm.next_in_index = 0; @@ -174,6 +173,7 @@ Inflate.prototype.push = function(data, mode) { } } while (strm.avail_in > 0 || strm.avail_out === 0); + _mode = (mode === ~~mode) ? mode : ((mode === true) ? c.Z_FINISH : c.Z_NO_FLUSH); // Finalize on the last chunk. if (_mode === c.Z_FINISH) { status = zlib_inflate.inflateEnd(this.strm); @@ -251,7 +251,7 @@ function inflate(input, options) { inflator.push(input, true); // That will never happens, if you don't cheat with options :) - if (inflator.err) { throw msg[inflator.err]; } + if (inflator.err) { throw msg[inflator.err]+':'+inflator.strm.msg; } return inflator.result; } diff --git a/lib/zlib/inffast.js b/lib/zlib/inffast.js index 36d26bb..c0596ed 100644 --- a/lib/zlib/inffast.js +++ b/lib/zlib/inffast.js @@ -65,12 +65,14 @@ module.exports = function inflate_fast(strm, start) { var len; /* match length, unused bytes */ var dist; /* match distance */ var from; /* where to copy match from */ + var idx = 0; var input, output; // JS specific, because we have no pointers /* copy state to local variables */ state = strm.state; + here = state.here; _in = strm.next_in_index; input = strm.next_in; last = strm.avail_in - 5; @@ -103,7 +105,10 @@ module.exports = function inflate_fast(strm, start) { hold += input[_in++] << bits; bits += 8; } - here = lcode[hold & lmask]; + idx = hold & lmask; + here.op = lcode.op[idx]; + here.val = lcode.val[idx]; + here.bits = lcode.bits[idx]; dolen: do { // Goto emulation @@ -136,7 +141,7 @@ module.exports = function inflate_fast(strm, start) { hold += input[_in++] << bits; bits += 8; } - here = dcode[hold & dmask]; + dcode.fill(hold & dmask, here); dodist: do { // goto emulation @@ -266,7 +271,7 @@ module.exports = function inflate_fast(strm, start) { } } else if ((op & 64) === 0) { /* 2nd level distance code */ - here = dcode[here.val + (hold & ((1 << op) - 1))]; + dcode.fill(here.val + (hold & ((1 << op) - 1)), here); continue dodist; } else { @@ -277,7 +282,7 @@ module.exports = function inflate_fast(strm, start) { } while (0); } else if ((op & 64) === 0) { /* 2nd level length code */ - here = lcode[here.val + (hold & ((1 << op) - 1))]; + lcode.fill(here.val + (hold & ((1 << op) - 1)), here); continue dolen; } else if (op & 32) { /* end-of-block */ diff --git a/lib/zlib/inflate.js b/lib/zlib/inflate.js index d8681ab..0a8bb2e 100644 --- a/lib/zlib/inflate.js +++ b/lib/zlib/inflate.js @@ -4,8 +4,12 @@ var utils = require('./utils'); var adler32 = require('./adler32'); var crc32 = require('./crc32'); -var inflate_fast = null;//require('./inf_fast'); +var inflate_fast = require('./inffast'); +var inflate_table = require('./inftrees'); +var CODES = 0; +var LENS = 1; +var DISTS = 2; /* Public constants ==========================================================*/ /* ===========================================================================*/ @@ -87,11 +91,29 @@ var MAX_WBITS = 15; /* 32K LZ77 window */ var DEF_WBITS = MAX_WBITS; -//function Code() { -// this.op = 0; /* operation, extra bits, table bits */ -// this.bits = 0; /* bits in this part of the code */ -// this.val = 0; /* offset in table or code value */ -//} +function Code() { + this.op = 0; /* operation, extra bits, table bits */ + this.bits = 0; /* bits in this part of the code */ + this.val = 0; /* offset in table or code value */ +} + +function CodeTable(length) { + this.op = length ? utils.array16Create(length) : null; + this.val = length ? utils.array16Create(length): null; + this.bits = length ? utils.array16Create(length) : null; +} + +CodeTable.prototype.fill = function(idx, code) { + code.bits = this.bits[idx]; + code.op = this.op[idx]; + code.val = this.val[idx]; +}; + +CodeTable.prototype.set = function(idx, code) { + this.bits[idx] = code.bits; + this.op[idx] = code.op; + this.val[idx] = code.val; +}; function InflateState() { this.mode = 0; /* current inflate mode */ @@ -124,8 +146,8 @@ function InflateState() { this.extra = 0; /* extra bits needed */ /* fixed and dynamic code tables */ - this.lencode = 0; /* starting table for length/literal codes */ - this.distcode = 0; /* starting table for distance codes */ + this.lencode = null; /* starting table for length/literal codes */ + this.distcode = null; /* starting table for distance codes */ this.lenbits = 0; /* index bits for lencode */ this.distbits = 0; /* index bits for distcode */ @@ -134,18 +156,32 @@ function InflateState() { this.nlen = 0; /* number of length code lengths */ this.ndist = 0; /* number of distance code lengths */ this.have = 0; /* number of code lengths in lens[] */ - this.next = 0; /* next available space in codes[] */ + this.next = null; /* next available space in codes[] */ + this.next_index = 0; //unsigned short array //todo: test later with Uint16Array - this.lens = new utils.createArray16(320); /* temporary storage for code lengths */ - this.work = new utils.createArray16(280); /* work area for code table building */ + this.lens = utils.array16Create(320); /* temporary storage for code lengths */ + this.work = utils.array16Create(280); /* work area for code table building */ // TODO: 8 or 16 bits? - this.codes = new utils.createArray16(ENOUGH); /* space for code tables */ + this.codes = new CodeTable(ENOUGH); /* space for code tables */ this.sane = 0; /* if false, allow invalid distance too far */ this.back = 0; /* bits back of last unprocessed length/lit */ this.was = 0; /* initial length of match */ + + this.here = new Code(); +} + +function InfTableOptions(type, lens, codes, table, table_index, bits, work) { + this.type = type; + this.lens = lens; + this.codes = codes; + this.table = table; + this.table_index = table_index; + this.bits = bits; + this.work = work; + this.here = new Code(); } function inflateResetKeep(strm) { @@ -270,8 +306,58 @@ function inflatePrime(strm, bits, value) { used for threaded applications, since the rewriting of the tables and virgin may not be thread-safe. */ -function fixedtables(/*state*/) { +//var virgin = true; +//var lenfix, distfix; +//var fixed = new CodeTable(544); +var lenfix = new CodeTable(); +lenfix.op = utils.array16Create([96,0,0,20,18,0,0,0,16,0,0,0,0,0,0,0,16,0,0,0,19,0,0,0,17,0,0,0,0,0,0,0,16,0,0,21,19,0,0,0,17,0,0,0,0,0,0,0,16,0,0,0,20,0,0,0,18,0,0,0,0,0,0,0,16,0,0,21,19,0,0,0,17,0,0,0,0,0,0,0,16,0,0,0,20,0,0,0,18,0,0,0,0,0,0,0,16,0,0,64,19,0,0,0,17,0,0,0,0,0,0,0,16,0,0,0,20,0,0,0,18,0,0,0,0,0,0,0,96,0,0,21,18,0,0,0,16,0,0,0,0,0,0,0,16,0,0,0,19,0,0,0,17,0,0,0,0,0,0,0,16,0,0,16,19,0,0,0,17,0,0,0,0,0,0,0,16,0,0,0,20,0,0,0,18,0,0,0,0,0,0,0,16,0,0,21,19,0,0,0,17,0,0,0,0,0,0,0,16,0,0,0,20,0,0,0,18,0,0,0,0,0,0,0,16,0,0,64,19,0,0,0,17,0,0,0,0,0,0,0,16,0,0,0,20,0,0,0,18,0,0,0,0,0,0,0,96,0,0,20,18,0,0,0,16,0,0,0,0,0,0,0,16,0,0,0,19,0,0,0,17,0,0,0,0,0,0,0,16,0,0,21,19,0,0,0,17,0,0,0,0,0,0,0,16,0,0,0,20,0,0,0,18,0,0,0,0,0,0,0,16,0,0,21,19,0,0,0,17,0,0,0,0,0,0,0,16,0,0,0,20,0,0,0,18,0,0,0,0,0,0,0,16,0,0,64,19,0,0,0,17,0,0,0,0,0,0,0,16,0,0,0,20,0,0,0,18,0,0,0,0,0,0,0,96,0,0,21,18,0,0,0,16,0,0,0,0,0,0,0,16,0,0,0,19,0,0,0,17,0,0,0,0,0,0,0,16,0,0,16,19,0,0,0,17,0,0,0,0,0,0,0,16,0,0,0,20,0,0,0,18,0,0,0,0,0,0,0,16,0,0,21,19,0,0,0,17,0,0,0,0,0,0,0,16,0,0,0,20,0,0,0,18,0,0,0,0,0,0,0,16,0,0,64,19,0,0,0,17,0,0,0,0,0,0,0,16,0,0,0,20,0,0,0,18,0,0,0,0,0,0,0]); +lenfix.bits = utils.array16Create([7,8,8,8,7,8,8,9,7,8,8,9,8,8,8,9,7,8,8,9,7,8,8,9,7,8,8,9,8,8,8,9,7,8,8,8,7,8,8,9,7,8,8,9,8,8,8,9,7,8,8,9,7,8,8,9,7,8,8,9,8,8,8,9,7,8,8,8,7,8,8,9,7,8,8,9,8,8,8,9,7,8,8,9,7,8,8,9,7,8,8,9,8,8,8,9,7,8,8,8,7,8,8,9,7,8,8,9,8,8,8,9,7,8,8,9,7,8,8,9,7,8,8,9,8,8,8,9,7,8,8,8,7,8,8,9,7,8,8,9,8,8,8,9,7,8,8,9,7,8,8,9,7,8,8,9,8,8,8,9,7,8,8,8,7,8,8,9,7,8,8,9,8,8,8,9,7,8,8,9,7,8,8,9,7,8,8,9,8,8,8,9,7,8,8,8,7,8,8,9,7,8,8,9,8,8,8,9,7,8,8,9,7,8,8,9,7,8,8,9,8,8,8,9,7,8,8,8,7,8,8,9,7,8,8,9,8,8,8,9,7,8,8,9,7,8,8,9,7,8,8,9,8,8,8,9,7,8,8,8,7,8,8,9,7,8,8,9,8,8,8,9,7,8,8,9,7,8,8,9,7,8,8,9,8,8,8,9,7,8,8,8,7,8,8,9,7,8,8,9,8,8,8,9,7,8,8,9,7,8,8,9,7,8,8,9,8,8,8,9,7,8,8,8,7,8,8,9,7,8,8,9,8,8,8,9,7,8,8,9,7,8,8,9,7,8,8,9,8,8,8,9,7,8,8,8,7,8,8,9,7,8,8,9,8,8,8,9,7,8,8,9,7,8,8,9,7,8,8,9,8,8,8,9,7,8,8,8,7,8,8,9,7,8,8,9,8,8,8,9,7,8,8,9,7,8,8,9,7,8,8,9,8,8,8,9,7,8,8,8,7,8,8,9,7,8,8,9,8,8,8,9,7,8,8,9,7,8,8,9,7,8,8,9,8,8,8,9,7,8,8,8,7,8,8,9,7,8,8,9,8,8,8,9,7,8,8,9,7,8,8,9,7,8,8,9,8,8,8,9,7,8,8,8,7,8,8,9,7,8,8,9,8,8,8,9,7,8,8,9,7,8,8,9,7,8,8,9,8,8,8,9]); +lenfix.val = utils.array16Create([0,80,16,115,31,112,48,192,10,96,32,160,0,128,64,224,6,88,24,144,59,120,56,208,17,104,40,176,8,136,72,240,4,84,20,227,43,116,52,200,13,100,36,168,4,132,68,232,8,92,28,152,83,124,60,216,23,108,44,184,12,140,76,248,3,82,18,163,35,114,50,196,11,98,34,164,2,130,66,228,7,90,26,148,67,122,58,212,19,106,42,180,10,138,74,244,5,86,22,0,51,118,54,204,15,102,38,172,6,134,70,236,9,94,30,156,99,126,62,220,27,110,46,188,14,142,78,252,0,81,17,131,31,113,49,194,10,97,33,162,1,129,65,226,6,89,25,146,59,121,57,210,17,105,41,178,9,137,73,242,4,85,21,258,43,117,53,202,13,101,37,170,5,133,69,234,8,93,29,154,83,125,61,218,23,109,45,186,13,141,77,250,3,83,19,195,35,115,51,198,11,99,35,166,3,131,67,230,7,91,27,150,67,123,59,214,19,107,43,182,11,139,75,246,5,87,23,0,51,119,55,206,15,103,39,174,7,135,71,238,9,95,31,158,99,127,63,222,27,111,47,190,15,143,79,254,0,80,16,115,31,112,48,193,10,96,32,161,0,128,64,225,6,88,24,145,59,120,56,209,17,104,40,177,8,136,72,241,4,84,20,227,43,116,52,201,13,100,36,169,4,132,68,233,8,92,28,153,83,124,60,217,23,108,44,185,12,140,76,249,3,82,18,163,35,114,50,197,11,98,34,165,2,130,66,229,7,90,26,149,67,122,58,213,19,106,42,181,10,138,74,245,5,86,22,0,51,118,54,205,15,102,38,173,6,134,70,237,9,94,30,157,99,126,62,221,27,110,46,189,14,142,78,253,0,81,17,131,31,113,49,195,10,97,33,163,1,129,65,227,6,89,25,147,59,121,57,211,17,105,41,179,9,137,73,243,4,85,21,258,43,117,53,203,13,101,37,171,5,133,69,235,8,93,29,155,83,125,61,219,23,109,45,187,13,141,77,251,3,83,19,195,35,115,51,199,11,99,35,167,3,131,67,231,7,91,27,151,67,123,59,215,19,107,43,183,11,139,75,247,5,87,23,0,51,119,55,207,15,103,39,175,7,135,71,239,9,95,31,159,99,127,63,223,27,111,47,191,15,143,79,255]); + +var distfix = new CodeTable(); +distfix.op = utils.array16Create([16,23,19,27,17,25,21,29,16,24,20,28,18,26,22,64,16,23,19,27,17,25,21,29,16,24,20,28,18,26,22,64]); +distfix.bits = utils.array16Create([5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5]); +distfix.val = utils.array16Create([1,257,17,4097,5,1025,65,16385,3,513,33,8193,9,2049,129,0,2,385,25,6145,7,1537,97,24577,4,769,49,12289,13,3073,193,0]); + + +function fixedtables(state) { +//#ifdef BUILDFIXED + +// /* build fixed huffman tables if first call (may not be thread safe) */ +// if (virgin) { +// var sym, bits; +// var next; +// +// /* literal/length table */ +// sym = 0; +// while (sym < 144) state.lens[sym++] = 8; +// while (sym < 256) state.lens[sym++] = 9; +// while (sym < 280) state.lens[sym++] = 7; +// while (sym < 288) state.lens[sym++] = 8; +// next = fixed; +// lenfix = next; +// bits = 9; +// inflate_table(new InfTableOptions(LENS, state.lens, 288, next,0, bits, state.work)); +// +// /* distance table */ +// sym = 0; +// while (sym < 32) state.lens[sym++] = 5; +// distfix = next; +// bits = 5; +// +// inflate_table(new InfTableOptions(DISTS, state.lens, 32, next,0, bits, state.work)); +// +// /* do this just once */ +// virgin = false; +// } +//#else /* !BUILDFIXED */ +//# include "inffixed.h" +//#endif /* BUILDFIXED */ + state.lencode = lenfix; + state.lenbits = 9; + state.distcode = distfix; + state.distbits = 5; } /* @@ -326,11 +412,13 @@ function inflate(strm, flush) { var _in, _out; /* save starting available input and output */ var copy; /* number of stored or match bytes to copy */ var from; /* where to copy match bytes from */ - var here; /* current decoding table entry */ + var from_source; + var here = new Code(); /* current decoding table entry */ var last; /* parent table entry */ var len; /* length to copy for repeats, bits to drop */ var ret; /* return code */ - var hbuf = utils.createArray(4); /* buffer for gzip header crc calculation */ + var hbuf = utils.arrayCreate(4); /* buffer for gzip header crc calculation */ + var opts; var n; // temporary var for NEED_BITS @@ -887,10 +975,14 @@ function inflate(strm, flush) { } state.next = state.codes; // TODO: - /*state.lencode = (const code FAR *)(state.next); + state.lencode = state.next; state.lenbits = 7; - ret = inflate_table(CODES, state.lens, 19, &(state.next), &(state.lenbits), state.work); - */ + + opts = new InfTableOptions(CODES, state.lens, 19, state.next, state.next_index, state.lenbits, state.work); + ret = inflate_table(opts); + state.next_index = opts.table_index; + state.lenbits = opts.bits; + if (ret) { strm.msg = 'invalid code lengths set'; state.mode = BAD; @@ -903,7 +995,7 @@ function inflate(strm, flush) { case CODELENS: while (state.have < state.nlen + state.ndist) { for (;;) { - here = state.lencode[(hold & ((1 << state.lenbits) - 1))/*BITS(state.lenbits)*/]; + state.lencode(hold & ((1 << state.lenbits) - 1), here);/*BITS(state.lenbits)*/ if ((here.bits) <= bits) { break; } //--- PULLBYTE() ---// if (have === 0) { return inf_leave(); } @@ -1000,10 +1092,10 @@ function inflate(strm, flush) { } /* handle error breaks in while */ - /* if (state.mode === BAD) { break; } + if (state.mode === BAD) { break; } /* check for end-of-block code (better have one) */ - /* if (state.lens[256] === 0) { + if (state.lens[256] === 0) { strm.msg = 'invalid code -- missing end-of-block'; state.mode = BAD; break; @@ -1012,20 +1104,28 @@ function inflate(strm, flush) { /* build code tables -- note: do not change the lenbits or distbits values here (9 and 6) without reading the comments in inftrees.h concerning the ENOUGH constants, which depend on those values */ - /* state.next = state.codes; - state.lencode = (const code FAR *)(state.next); + state.next = state.codes; + state.lencode = state.next; state.lenbits = 9; - ret = inflate_table(LENS, state.lens, state.nlen, &(state.next), - &(state.lenbits), state.work); + + opts = new InfTableOptions(LENS, state.lens, state.nlen,state.next,state.next_index, state.lenbits, state.work); + ret = inflate_table(opts); + state.next_index = opts.table_index; + state.lenbits = opts.bits; + if (ret) { strm.msg = 'invalid literal/lengths set'; state.mode = BAD; break; } - state.distcode = (const code FAR *)(state.next); + state.distcode = state.next; state.distbits = 6; - ret = inflate_table(DISTS, state.lens + state.nlen, state.ndist, - &(state.next), &(state.distbits), state.work); + + opts = new InfTableOptions(DISTS, state.lens + state.nlen, state.ndist, state.next,state.next_index, state.distbits, state.work); + ret = inflate_table(opts); + state.next_index = opts.table_index; + state.lenbits = opts.bits; + if (ret) { strm.msg = 'invalid distances set'; state.mode = BAD; @@ -1050,7 +1150,7 @@ function inflate(strm, flush) { } state.back = 0; for (;;) { - here = state.lencode[hold & ((1 << state.lenbits) -1)/*BITS(state.lenbits)*/]; + state.lencode.fill(hold & ((1 << state.lenbits) -1),here); /*BITS(state.lenbits)*/ if (here.bits <= bits) { break; } //--- PULLBYTE() ---// if (have === 0) { return inf_leave(); } @@ -1062,8 +1162,8 @@ function inflate(strm, flush) { if (here.op && (here.op & 0xf0) === 0) { last = here; for (;;) { - here = state.lencode[last.val + - ((hold & ((1 << (last.bits + last.op)) -1))/*BITS(last.bits + last.op)*/ >> last.bits)]; + state.lencode(last.val + + ((hold & ((1 << (last.bits + last.op)) -1))/*BITS(last.bits + last.op)*/ >> last.bits), here); if ((last.bits + here.bits) <= bits) { break; } //--- PULLBYTE() ---// if (have === 0) { return inf_leave(); } @@ -1129,7 +1229,7 @@ function inflate(strm, flush) { /* falls through */ case DIST: for (;;) { - here = state.distcode[hold & ((1 << state.distbits) -1)/*BITS(state.distbits)*/]; + state.distcode.fill(hold & ((1 << state.distbits) -1), here);/*BITS(state.distbits)*/ if ((here.bits) <= bits) { break; } //--- PULLBYTE() ---// if (have === 0) { return inf_leave(); } @@ -1141,8 +1241,8 @@ function inflate(strm, flush) { if ((here.op & 0xf0) === 0) { last = here; for (;;) { - here = state.distcode[last.val + - (hold & ((1 << (last.bits + last.op)) -1)/*BITS(last.bits + last.op)*/ >> last.bits)]; + state.distcode.fill(last.val + + (hold & ((1 << (last.bits + last.op)) -1)/*BITS(last.bits + last.op)*/ >> last.bits), here); if ((last.bits + here.bits) <= bits) { break; } //--- PULLBYTE() ---// if (have === 0) { return inf_leave(); } @@ -1212,16 +1312,16 @@ function inflate(strm, flush) { } //#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR //Trace((stderr, "inflate.c too far\n")); - copy -= state.whave; - if (copy > state.length) { copy = state.length; } - if (copy > left) { copy = left; } - left -= copy; - state.length -= copy; - do { - output[put++] = 0; - } while (--copy); - if (state.length === 0) { state.mode = LEN; } - break; +// copy -= state.whave; +// if (copy > state.length) { copy = state.length; } +// if (copy > left) { copy = left; } +// left -= copy; +// state.length -= copy; +// do { +// output[put++] = 0; +// } while (--copy); +// if (state.length === 0) { state.mode = LEN; } +// break; //#endif } if (copy > state.wnext) { @@ -1232,8 +1332,10 @@ function inflate(strm, flush) { from = state.wnext - copy; } if (copy > state.length) { copy = state.length; } + from_source = state.window; } else { /* copy from output */ + from_source = output; from = put - state.offset; copy = state.length; } @@ -1241,7 +1343,7 @@ function inflate(strm, flush) { left -= copy; state.length -= copy; do { - output[put++] = state.window[from++]; + output[put++] = from_source[from++]; } while (--copy); if (state.length === 0) { state.mode = LEN; } break; @@ -1323,8 +1425,15 @@ function inflate(strm, flush) { } } -function inflateEnd(/*strm*/) { - +function inflateEnd(strm) { +// if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) +// return Z_STREAM_ERROR; + var state = strm.state; + if (state.window) { + state.window = null; + } + strm.state = null; + return Z_OK; } function inflateGetDictionary(/*strm, dictionary, dictLength*/) { diff --git a/lib/zlib/inftrees.js b/lib/zlib/inftrees.js new file mode 100644 index 0000000..4461c51 --- /dev/null +++ b/lib/zlib/inftrees.js @@ -0,0 +1,320 @@ +'use strict'; + + +var utils = require('./utils'); + +var MAXBITS = 15; +var ENOUGH_LENS = 852; +var ENOUGH_DISTS = 592; +//var ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS); + +var CODES = 0; +var LENS = 1; +var DISTS = 2; + +var lbase = [ /* Length codes 257..285 base */ + 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, 0, 0 +]; + +var lext = [ /* Length codes 257..285 extra */ + 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78 +]; + +var dbase = [ /* Distance codes 0..29 base */ + 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, 0, 0 +]; + +var dext = [ /* Distance codes 0..29 extra */ + 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 28, 28, 29, 29, 64, 64 +]; + +module.exports = function inflate_table(opts) +{ + var type = opts.type, + lens = opts.lens, + codes = opts.codes, + table = opts.table, + bits = opts.bits, + work = opts.work, + here = opts.here; /* table entry for duplication */ + + var len = 0; /* a code's length in bits */ + var sym = 0; /* index of code symbols */ + var min = 0, max = 0; /* minimum and maximum code lengths */ + var root = 0; /* number of index bits for root table */ + var curr = 0; /* number of index bits for current table */ + var drop = 0; /* code bits to drop for sub-table */ + var left = 0; /* number of prefix codes available */ + var used = 0; /* code entries in table used */ + var huff = 0; /* Huffman code */ + var incr; /* for incrementing code, index */ + var fill; /* index for replicating entries */ + var low; /* low bits for current root entry */ + var mask; /* mask for low root bits */ + var next; /* next available space in table */ + var base = null; /* base value table to use */ + var base_index = 0; +// var shoextra; /* extra bits table to use */ + var end; /* use base and extra for symbol > end */ + var count = utils.array16Create(MAXBITS+1); //[MAXBITS+1]; /* number of codes of each length */ + var offs = utils.array16Create(MAXBITS+1); //[MAXBITS+1]; /* offsets in table for each length */ + var extra = null; + var extra_index = 0; + + + /* + Process a set of code lengths to create a canonical Huffman code. The + code lengths are lens[0..codes-1]. Each length corresponds to the + symbols 0..codes-1. The Huffman code is generated by first sorting the + symbols by length from short to long, and retaining the symbol order + for codes with equal lengths. Then the code starts with all zero bits + for the first code of the shortest length, and the codes are integer + increments for the same length, and zeros are appended as the length + increases. For the deflate format, these bits are stored backwards + from their more natural integer increment ordering, and so when the + decoding tables are built in the large loop below, the integer codes + are incremented backwards. + + This routine assumes, but does not check, that all of the entries in + lens[] are in the range 0..MAXBITS. The caller must assure this. + 1..MAXBITS is interpreted as that code length. zero means that that + symbol does not occur in this code. + + The codes are sorted by computing a count of codes for each length, + creating from that a table of starting indices for each length in the + sorted table, and then entering the symbols in order in the sorted + table. The sorted table is work[], with that space being provided by + the caller. + + The length counts are used for other purposes as well, i.e. finding + the minimum and maximum length codes, determining if there are any + codes at all, checking for a valid set of lengths, and looking ahead + at length counts to determine sub-table sizes when building the + decoding tables. + */ + + /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ + for (len = 0; len <= MAXBITS; len++) { + count[len] = 0; + } + for (sym = 0; sym < codes; sym++) { + count[lens[sym]]++; + } + + /* bound code lengths, force root to be within code lengths */ + root = bits; + for (max = MAXBITS; max >= 1; max--) { + if (count[max] !== 0) { break; } + } + if (root > max) { + root = max; + } + if (max === 0) { /* no symbols to code at all */ + table.op[opts.table_index] = 64; //here.op = (var char)64; /* invalid code marker */ + table.bits[opts.table_index] = 1; //here.bits = (var char)1; + table.val[opts.table_index++] = 0; //here.val = (var short)0; + + table.op[opts.table_index] = 64; + table.bits[opts.table_index] = 1; + table.val[opts.table_index++] = 0; + opts.bits = 1; + return 0; /* no symbols, but wait for decoding to report error */ + } + for (min = 1; min < max; min++) { + if (count[min] !== 0) { break; } + } + if (root < min) { + root = min; + } + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) { return -1; } /* over-subscribed */ + } + if (left > 0 && (type === CODES || max !== 1)) { + return -1; /* incomplete set */ + } + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) { + offs[len + 1] = offs[len] + count[len]; + } + + /* sort symbols by length, by symbol order within each length */ + for (sym = 0; sym < codes; sym++) { + if (lens[sym] !== 0) { + work[offs[lens[sym]]++] = sym; + } + } + + /* + Create and fill in decoding tables. In this loop, the table being + filled is at next and has curr index bits. The code being used is huff + with length len. That code is converted to an index by dropping drop + bits off of the bottom. For codes where len is less than drop + curr, + those top drop + curr - len bits are incremented through all values to + fill the table with replicated entries. + + root is the number of index bits for the root table. When len exceeds + root, sub-tables are created pointed to by the root entry with an index + of the low root bits of huff. This is saved in low to check for when a + new sub-table should be started. drop is zero when the root table is + being filled, and drop is root when sub-tables are being filled. + + When a new sub-table is needed, it is necessary to look ahead in the + code lengths to determine what size sub-table is needed. The length + counts are used for this, and so count[] is decremented as codes are + entered in the tables. + + used keeps track of how many table entries have been allocated from the + provided *table space. It is checked for LENS and DIST tables against + the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in + the initial root table size constants. See the comments in inftrees.h + for more information. + + sym increments through all symbols, and the loop terminates when + all codes of length max, i.e. all codes, have been processed. This + routine permits incomplete codes, so another loop after this one fills + in the rest of the decoding tables with invalid code markers. + */ + + /* set up for code type */ + switch (type) { + case CODES: + base = extra = work; /* dummy value--not used */ + end = 19; + break; + case LENS: + base = lbase; + base_index -= 257; + extra = lext; + extra_index -= 257; + end = 256; + break; + default: /* DISTS */ + base = dbase; + extra = dext; + end = -1; + } + + /* initialize opts for loop */ + huff = 0; /* starting code */ + sym = 0; /* starting code symbol */ + len = min; /* starting code length */ + next = opts.table_index; /* current table to fill in */ + curr = root; /* current table index bits */ + drop = 0; /* current bits to drop from code for index */ + low = -1; /* trigger new sub-table when len > root */ + used = 1 << root; /* use root table entries */ + mask = used - 1; /* mask for comparing low */ + + /* check available table space */ + if ((type === LENS && used > ENOUGH_LENS) || + (type === DISTS && used > ENOUGH_DISTS)) { + return 1; + } + + /* process all codes and make table entries */ + for (;;) { + /* create table entry */ + here.bits = len - drop; + if (work[sym] < end) { + here.op = 0; + here.val = work[sym]; + } + else if (work[sym] > end) { + here.op = extra[extra_index + work[sym]]; + here.val = base[base_index + work[sym]]; + } + else { + here.op = 32 + 64; /* end of block */ + here.val = 0; + } + + /* replicate for those indices with low len bits equal to huff */ + incr = 1 << (len - drop); + fill = 1 << curr; + min = fill; /* save offset to next table */ + do { + fill -= incr; + table.set(next + (huff >> drop) + fill, here); + } while (fill !== 0); + + /* backwards increment the len-bit code huff */ + incr = 1 << (len - 1); + while (huff & incr) { + incr >>= 1; + } + if (incr !== 0) { + huff &= incr - 1; + huff += incr; + } else { + huff = 0; + } + + /* go to next symbol, update count, len */ + sym++; + if (--(count[len]) === 0) { + if (len === max) { break; } + len = lens[work[sym]]; + } + + /* create new sub-table if needed */ + if (len > root && (huff & mask) !== low) { + /* if first time, transition to sub-tables */ + if (drop === 0) { + drop = root; + } + + /* increment past last table */ + next += min; /* here min is 1 << curr */ + + /* determine length of next table */ + curr = len - drop; + left = 1 << curr; + while (curr + drop < max) { + left -= count[curr + drop]; + if (left <= 0) { break; } + curr++; + left <<= 1; + } + + /* check for enough space */ + used += 1 << curr; + if ((type === LENS && used > ENOUGH_LENS) || + (type === DISTS && used > ENOUGH_DISTS)) { + return 1; + } + + /* point entry in root table to sub-table */ + low = huff & mask; + table.op[low] = curr; + table.bits[low] = root; + table.val[low] = next - opts.table_index; + } + } + + /* fill in remaining table entry if code is incomplete (guaranteed to have + at most one remaining entry, since if the code is incomplete, the + maximum code length that was allowed to get this far is one bit) */ + if (huff !== 0) { + table.op[next + huff] = 64; /* invalid code marker */ + table.bits[next + huff] = len - drop; + table.val[next + huff] = 0; + } + + /* set return parameters */ + opts.table_index += used; + opts.bits = root; + return 0; +}; \ No newline at end of file