| 'use strict'; |
| |
| // (C) 1995-2013 Jean-loup Gailly and Mark Adler |
| // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin |
| // |
| // This software is provided 'as-is', without any express or implied |
| // warranty. In no event will the authors be held liable for any damages |
| // arising from the use of this software. |
| // |
| // Permission is granted to anyone to use this software for any purpose, |
| // including commercial applications, and to alter it and redistribute it |
| // freely, subject to the following restrictions: |
| // |
| // 1. The origin of this software must not be misrepresented; you must not |
| // claim that you wrote the original software. If you use this software |
| // in a product, an acknowledgment in the product documentation would be |
| // appreciated but is not required. |
| // 2. Altered source versions must be plainly marked as such, and must not be |
| // misrepresented as being the original software. |
| // 3. This notice may not be removed or altered from any source distribution. |
| |
| // See state defs from inflate.js |
| var BAD = 30; /* got a data error -- remain here until reset */ |
| var TYPE = 12; /* i: waiting for type bits, including last-flag bit */ |
| |
| /* |
| Decode literal, length, and distance codes and write out the resulting |
| literal and match bytes until either not enough input or output is |
| available, an end-of-block is encountered, or a data error is encountered. |
| When large enough input and output buffers are supplied to inflate(), for |
| example, a 16K input buffer and a 64K output buffer, more than 95% of the |
| inflate execution time is spent in this routine. |
| |
| Entry assumptions: |
| |
| state.mode === LEN |
| strm.avail_in >= 6 |
| strm.avail_out >= 258 |
| start >= strm.avail_out |
| state.bits < 8 |
| |
| On return, state.mode is one of: |
| |
| LEN -- ran out of enough output space or enough available input |
| TYPE -- reached end of block code, inflate() to interpret next block |
| BAD -- error in block data |
| |
| Notes: |
| |
| - The maximum input bits used by a length/distance pair is 15 bits for the |
| length code, 5 bits for the length extra, 15 bits for the distance code, |
| and 13 bits for the distance extra. This totals 48 bits, or six bytes. |
| Therefore if strm.avail_in >= 6, then there is enough input to avoid |
| checking for available input while decoding. |
| |
| - The maximum bytes that a single length/distance pair can output is 258 |
| bytes, which is the maximum length that can be coded. inflate_fast() |
| requires strm.avail_out >= 258 for each loop to avoid checking for |
| output space. |
| */ |
| module.exports = function inflate_fast(strm, start) { |
| var state; |
| var _in; /* local strm.input */ |
| var last; /* have enough input while in < last */ |
| var _out; /* local strm.output */ |
| var beg; /* inflate()'s initial strm.output */ |
| var end; /* while out < end, enough space available */ |
| //#ifdef INFLATE_STRICT |
| var dmax; /* maximum distance from zlib header */ |
| //#endif |
| var wsize; /* window size or zero if not using window */ |
| var whave; /* valid bytes in the window */ |
| var wnext; /* window write index */ |
| // Use `s_window` instead `window`, avoid conflict with instrumentation tools |
| var s_window; /* allocated sliding window, if wsize != 0 */ |
| var hold; /* local strm.hold */ |
| var bits; /* local strm.bits */ |
| var lcode; /* local strm.lencode */ |
| var dcode; /* local strm.distcode */ |
| var lmask; /* mask for first level of length codes */ |
| var dmask; /* mask for first level of distance codes */ |
| var here; /* retrieved table entry */ |
| var op; /* code bits, operation, extra bits, or */ |
| /* window position, window bytes to copy */ |
| var len; /* match length, unused bytes */ |
| var dist; /* match distance */ |
| var from; /* where to copy match from */ |
| var from_source; |
| |
| |
| 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; |
| input = strm.input; |
| last = _in + (strm.avail_in - 5); |
| _out = strm.next_out; |
| output = strm.output; |
| beg = _out - (start - strm.avail_out); |
| end = _out + (strm.avail_out - 257); |
| //#ifdef INFLATE_STRICT |
| dmax = state.dmax; |
| //#endif |
| wsize = state.wsize; |
| whave = state.whave; |
| wnext = state.wnext; |
| s_window = state.window; |
| hold = state.hold; |
| bits = state.bits; |
| lcode = state.lencode; |
| dcode = state.distcode; |
| lmask = (1 << state.lenbits) - 1; |
| dmask = (1 << state.distbits) - 1; |
| |
| |
| /* decode literals and length/distances until end-of-block or not enough |
| input data or output space */ |
| |
| top: |
| do { |
| if (bits < 15) { |
| hold += input[_in++] << bits; |
| bits += 8; |
| hold += input[_in++] << bits; |
| bits += 8; |
| } |
| |
| here = lcode[hold & lmask]; |
| |
| dolen: |
| for (;;) { // Goto emulation |
| op = here >>> 24/*here.bits*/; |
| hold >>>= op; |
| bits -= op; |
| op = (here >>> 16) & 0xff/*here.op*/; |
| if (op === 0) { /* literal */ |
| //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? |
| // "inflate: literal '%c'\n" : |
| // "inflate: literal 0x%02x\n", here.val)); |
| output[_out++] = here & 0xffff/*here.val*/; |
| } |
| else if (op & 16) { /* length base */ |
| len = here & 0xffff/*here.val*/; |
| op &= 15; /* number of extra bits */ |
| if (op) { |
| if (bits < op) { |
| hold += input[_in++] << bits; |
| bits += 8; |
| } |
| len += hold & ((1 << op) - 1); |
| hold >>>= op; |
| bits -= op; |
| } |
| //Tracevv((stderr, "inflate: length %u\n", len)); |
| if (bits < 15) { |
| hold += input[_in++] << bits; |
| bits += 8; |
| hold += input[_in++] << bits; |
| bits += 8; |
| } |
| here = dcode[hold & dmask]; |
| |
| dodist: |
| for (;;) { // goto emulation |
| op = here >>> 24/*here.bits*/; |
| hold >>>= op; |
| bits -= op; |
| op = (here >>> 16) & 0xff/*here.op*/; |
| |
| if (op & 16) { /* distance base */ |
| dist = here & 0xffff/*here.val*/; |
| op &= 15; /* number of extra bits */ |
| if (bits < op) { |
| hold += input[_in++] << bits; |
| bits += 8; |
| if (bits < op) { |
| hold += input[_in++] << bits; |
| bits += 8; |
| } |
| } |
| dist += hold & ((1 << op) - 1); |
| //#ifdef INFLATE_STRICT |
| if (dist > dmax) { |
| strm.msg = 'invalid distance too far back'; |
| state.mode = BAD; |
| break top; |
| } |
| //#endif |
| hold >>>= op; |
| bits -= op; |
| //Tracevv((stderr, "inflate: distance %u\n", dist)); |
| op = _out - beg; /* max distance in output */ |
| if (dist > op) { /* see if copy from window */ |
| op = dist - op; /* distance back in window */ |
| if (op > whave) { |
| if (state.sane) { |
| strm.msg = 'invalid distance too far back'; |
| state.mode = BAD; |
| break top; |
| } |
| |
| // (!) This block is disabled in zlib defaults, |
| // don't enable it for binary compatibility |
| //#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR |
| // if (len <= op - whave) { |
| // do { |
| // output[_out++] = 0; |
| // } while (--len); |
| // continue top; |
| // } |
| // len -= op - whave; |
| // do { |
| // output[_out++] = 0; |
| // } while (--op > whave); |
| // if (op === 0) { |
| // from = _out - dist; |
| // do { |
| // output[_out++] = output[from++]; |
| // } while (--len); |
| // continue top; |
| // } |
| //#endif |
| } |
| from = 0; // window index |
| from_source = s_window; |
| if (wnext === 0) { /* very common case */ |
| from += wsize - op; |
| if (op < len) { /* some from window */ |
| len -= op; |
| do { |
| output[_out++] = s_window[from++]; |
| } while (--op); |
| from = _out - dist; /* rest from output */ |
| from_source = output; |
| } |
| } |
| else if (wnext < op) { /* wrap around window */ |
| from += wsize + wnext - op; |
| op -= wnext; |
| if (op < len) { /* some from end of window */ |
| len -= op; |
| do { |
| output[_out++] = s_window[from++]; |
| } while (--op); |
| from = 0; |
| if (wnext < len) { /* some from start of window */ |
| op = wnext; |
| len -= op; |
| do { |
| output[_out++] = s_window[from++]; |
| } while (--op); |
| from = _out - dist; /* rest from output */ |
| from_source = output; |
| } |
| } |
| } |
| else { /* contiguous in window */ |
| from += wnext - op; |
| if (op < len) { /* some from window */ |
| len -= op; |
| do { |
| output[_out++] = s_window[from++]; |
| } while (--op); |
| from = _out - dist; /* rest from output */ |
| from_source = output; |
| } |
| } |
| while (len > 2) { |
| output[_out++] = from_source[from++]; |
| output[_out++] = from_source[from++]; |
| output[_out++] = from_source[from++]; |
| len -= 3; |
| } |
| if (len) { |
| output[_out++] = from_source[from++]; |
| if (len > 1) { |
| output[_out++] = from_source[from++]; |
| } |
| } |
| } |
| else { |
| from = _out - dist; /* copy direct from output */ |
| do { /* minimum length is three */ |
| output[_out++] = output[from++]; |
| output[_out++] = output[from++]; |
| output[_out++] = output[from++]; |
| len -= 3; |
| } while (len > 2); |
| if (len) { |
| output[_out++] = output[from++]; |
| if (len > 1) { |
| output[_out++] = output[from++]; |
| } |
| } |
| } |
| } |
| else if ((op & 64) === 0) { /* 2nd level distance code */ |
| here = dcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))]; |
| continue dodist; |
| } |
| else { |
| strm.msg = 'invalid distance code'; |
| state.mode = BAD; |
| break top; |
| } |
| |
| break; // need to emulate goto via "continue" |
| } |
| } |
| else if ((op & 64) === 0) { /* 2nd level length code */ |
| here = lcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))]; |
| continue dolen; |
| } |
| else if (op & 32) { /* end-of-block */ |
| //Tracevv((stderr, "inflate: end of block\n")); |
| state.mode = TYPE; |
| break top; |
| } |
| else { |
| strm.msg = 'invalid literal/length code'; |
| state.mode = BAD; |
| break top; |
| } |
| |
| break; // need to emulate goto via "continue" |
| } |
| } while (_in < last && _out < end); |
| |
| /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ |
| len = bits >> 3; |
| _in -= len; |
| bits -= len << 3; |
| hold &= (1 << bits) - 1; |
| |
| /* update state and return */ |
| strm.next_in = _in; |
| strm.next_out = _out; |
| strm.avail_in = (_in < last ? 5 + (last - _in) : 5 - (_in - last)); |
| strm.avail_out = (_out < end ? 257 + (end - _out) : 257 - (_out - end)); |
| state.hold = hold; |
| state.bits = bits; |
| return; |
| }; |