mirror of
				https://github.com/alexandrebobkov/ESP-Nodes.git
				synced 2025-11-04 09:21:05 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			345 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			345 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
'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
 | 
						|
const BAD = 16209;       /* got a data error -- remain here until reset */
 | 
						|
const TYPE = 16191;      /* 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) {
 | 
						|
  let _in;                    /* local strm.input */
 | 
						|
  let last;                   /* have enough input while in < last */
 | 
						|
  let _out;                   /* local strm.output */
 | 
						|
  let beg;                    /* inflate()'s initial strm.output */
 | 
						|
  let end;                    /* while out < end, enough space available */
 | 
						|
//#ifdef INFLATE_STRICT
 | 
						|
  let dmax;                   /* maximum distance from zlib header */
 | 
						|
//#endif
 | 
						|
  let wsize;                  /* window size or zero if not using window */
 | 
						|
  let whave;                  /* valid bytes in the window */
 | 
						|
  let wnext;                  /* window write index */
 | 
						|
  // Use `s_window` instead `window`, avoid conflict with instrumentation tools
 | 
						|
  let s_window;               /* allocated sliding window, if wsize != 0 */
 | 
						|
  let hold;                   /* local strm.hold */
 | 
						|
  let bits;                   /* local strm.bits */
 | 
						|
  let lcode;                  /* local strm.lencode */
 | 
						|
  let dcode;                  /* local strm.distcode */
 | 
						|
  let lmask;                  /* mask for first level of length codes */
 | 
						|
  let dmask;                  /* mask for first level of distance codes */
 | 
						|
  let here;                   /* retrieved table entry */
 | 
						|
  let op;                     /* code bits, operation, extra bits, or */
 | 
						|
                              /*  window position, window bytes to copy */
 | 
						|
  let len;                    /* match length, unused bytes */
 | 
						|
  let dist;                   /* match distance */
 | 
						|
  let from;                   /* where to copy match from */
 | 
						|
  let from_source;
 | 
						|
 | 
						|
 | 
						|
  let input, output; // JS specific, because we have no pointers
 | 
						|
 | 
						|
  /* copy state to local variables */
 | 
						|
  const 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;
 | 
						|
};
 |