
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
'use strict';
// 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 defailts,
// 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;
};