INLINE USHORT decode_p(void){ USHORT i, j, m; j = pt_table[GETBITS(8)]; if (j < np) { DROPBITS(pt_len[j]); } else { DROPBITS(8); i = GETBITS(16); m = 0x8000; do { if (i & m) j = right[j]; else j = left [j]; m >>= 1; } while (j >= np); DROPBITS(pt_len[j] - 8); } if (j != np-1) { if (j > 0) { j = (USHORT)(GETBITS(i=(USHORT)(j-1)) | (1U << (j-1))); DROPBITS(i); } lastlen=j; } return lastlen; }
INLINE USHORT DecodePosition(void){ USHORT i, j, c; i = GETBITS(8); DROPBITS(8); c = (USHORT) (d_code[i] << 8); j = d_len[i]; i = (USHORT) (((i << j) | GETBITS(j)) & 0xff); DROPBITS(j); return (USHORT) (c | i) ; }
INLINE USHORT decode_c(void){ USHORT i, j, m; j = c_table[GETBITS(12)]; if (j < N1) { DROPBITS(c_len[j]); } else { DROPBITS(12); i = GETBITS(16); m = 0x8000; do { if (i & m) j = right[j]; else j = left [j]; m >>= 1; } while (j >= N1); DROPBITS(c_len[j] - 12); } return j; }
static USHORT read_tree_p(void){ USHORT i,n; n = GETBITS(5); DROPBITS(5); if (n>0){ for (i=0; i<n; i++) { pt_len[i] = (UCHAR)GETBITS(4); DROPBITS(4); } for (i=n; i<np; i++) pt_len[i] = 0; if (make_table(np,pt_len,8,pt_table)) return 1; } else { n = GETBITS(5); DROPBITS(5); for (i=0; i<np; i++) pt_len[i] = 0; for (i=0; i<256; i++) pt_table[i] = n; } return 0; }
static USHORT read_tree_c(void){ USHORT i,n; n = GETBITS(9); DROPBITS(9); if (n>0){ for (i=0; i<n; i++) { c_len[i] = (UCHAR)GETBITS(5); DROPBITS(5); } for (i=n; i<510; i++) c_len[i] = 0; if (make_table(510,c_len,12,c_table)) return 1; } else { n = GETBITS(9); DROPBITS(9); for (i=0; i<510; i++) c_len[i] = 0; for (i=0; i<4096; i++) c_table[i] = n; } return 0; }
USHORT Unpack_QUICK(UCHAR *in, UCHAR *out, USHORT origsize){ USHORT i, j; UCHAR *outend; initbitbuf(in); outend = out+origsize; while (out < outend) { if (GETBITS(1)!=0) { DROPBITS(1); *out++ = text[quick_text_loc++ & QBITMASK] = (UCHAR)GETBITS(8); DROPBITS(8); } else { DROPBITS(1); j = (USHORT) (GETBITS(2)+2); DROPBITS(2); i = (USHORT) (quick_text_loc - GETBITS(8) - 1); DROPBITS(8); while(j--) { *out++ = text[quick_text_loc++ & QBITMASK] = text[i++ & QBITMASK]; } } } quick_text_loc = (USHORT)((quick_text_loc+5) & QBITMASK); return 0; }
INLINE USHORT DecodeChar(void){ USHORT c; c = son[R]; /* travel from root to leaf, */ /* choosing the smaller child node (son[]) if the read bit is 0, */ /* the bigger (son[]+1} if 1 */ while (c < T) { c = son[c + GETBITS(1)]; DROPBITS(1); } c -= T; update(c); return c; }
/* 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. */ void ZLIB_INTERNAL inflate_fast(z_stream *strm, unsigned long start) { /* start: inflate()'s starting value for strm->avail_out */ struct inflate_state *state; const unsigned char *in; /* local strm->next_in */ const unsigned char *last; /* have enough input while in < last */ unsigned char *out; /* local strm->next_out */ unsigned char *beg; /* inflate()'s initial strm->next_out */ unsigned char *end; /* while out < end, enough space available */ #ifdef INFLATE_STRICT unsigned dmax; /* maximum distance from zlib header */ #endif unsigned wsize; /* window size or zero if not using window */ unsigned whave; /* valid bytes in the window */ unsigned wnext; /* window write index */ unsigned char *window; /* allocated sliding window, if wsize != 0 */ uint32_t hold; /* local strm->hold */ unsigned bits; /* local strm->bits */ code const *lcode; /* local strm->lencode */ code const *dcode; /* local strm->distcode */ unsigned lmask; /* mask for first level of length codes */ unsigned dmask; /* mask for first level of distance codes */ code here; /* retrieved table entry */ unsigned op; /* code bits, operation, extra bits, or */ /* window position, window bytes to copy */ unsigned len; /* match length, unused bytes */ unsigned dist; /* match distance */ unsigned char *from; /* where to copy match from */ /* copy state to local variables */ state = (struct inflate_state *)strm->state; in = strm->next_in - OFF; last = in + (strm->avail_in - 5); out = strm->next_out - OFF; 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; window = state->window; hold = state->hold; bits = state->bits; lcode = state->lencode; dcode = state->distcode; lmask = (1U << state->lenbits) - 1; dmask = (1U << state->distbits) - 1; /* decode literals and length/distances until end-of-block or not enough input data or output space */ do { if (bits < 15) { hold += (PUP(in) << bits); bits += 8; hold += (PUP(in) << bits); bits += 8; } here = lcode[hold & lmask]; dolen: DROPBITS(here.bits); op = 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)); PUP(out) = (unsigned char)(here.val); } else if (op & 16) { /* length base */ len = here.val; op &= 15; /* number of extra bits */ if (op) { if (bits < op) { hold += (PUP(in) << bits); bits += 8; } len += BITS(op); DROPBITS(op); } Tracevv((stderr, "inflate: length %u\n", len)); if (bits < 15) { hold += (PUP(in) << bits); bits += 8; hold += (PUP(in) << bits); bits += 8; } here = dcode[hold & dmask]; dodist: DROPBITS(here.bits); op = here.op; if (op & 16) { /* distance base */ dist = here.val; op &= 15; /* number of extra bits */ if (bits < op) { hold += (PUP(in) << bits); bits += 8; if (bits < op) { hold += (PUP(in) << bits); bits += 8; } } dist += BITS(op); #ifdef INFLATE_STRICT if (dist > dmax) { strm->msg = (char *)"invalid distance too far back"; state->mode = BAD; break; } #endif DROPBITS(op); Tracevv((stderr, "inflate: distance %u\n", dist)); op = (unsigned)(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 = (char *)"invalid distance too far back"; state->mode = BAD; break; } #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR if (len <= op - whave) { do { PUP(out) = 0; } while (--len); continue; } len -= op - whave; do { PUP(out) = 0; } while (--op > whave); if (op == 0) { from = out - dist; do { PUP(out) = PUP(from); } while (--len); continue; } #endif } from = window - OFF; if (wnext == 0) { /* very common case */ from += wsize - op; if (op < len) { /* some from window */ len -= op; do { PUP(out) = PUP(from); } while (--op); from = out - dist; /* rest from 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 { PUP(out) = PUP(from); } while (--op); from = window - OFF; if (wnext < len) { /* some from start of window */ op = wnext; len -= op; do { PUP(out) = PUP(from); } while (--op); from = out - dist; /* rest from output */ } } } else { /* contiguous in window */ from += wnext - op; if (op < len) { /* some from window */ len -= op; do { PUP(out) = PUP(from); } while (--op); from = out - dist; /* rest from output */ } } while (len > 2) { PUP(out) = PUP(from); PUP(out) = PUP(from); PUP(out) = PUP(from); len -= 3; } if (len) { PUP(out) = PUP(from); if (len > 1) PUP(out) = PUP(from); } } else { from = out - dist; /* copy direct from output */ do { /* minimum length is three */ PUP(out) = PUP(from); PUP(out) = PUP(from); PUP(out) = PUP(from); len -= 3; } while (len > 2); if (len) { PUP(out) = PUP(from); if (len > 1) PUP(out) = PUP(from); } } } else if ((op & 64) == 0) { /* 2nd level distance code */ here = dcode[here.val + BITS(op)]; goto dodist; } else { strm->msg = (char *)"invalid distance code"; state->mode = BAD; break; } } else if ((op & 64) == 0) { /* 2nd level length code */ here = lcode[here.val + BITS(op)]; goto dolen; } else if (op & 32) { /* end-of-block */ Tracevv((stderr, "inflate: end of block\n")); state->mode = TYPE; break; } else { strm->msg = (char *)"invalid literal/length code"; state->mode = BAD; break; } } 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 &= (1U << bits) - 1; /* update state and return */ strm->next_in = in + OFF; strm->next_out = out + OFF; strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); strm->avail_out = (unsigned)(out < end ? 257 + (end - out) : 257 - (out - end)); state->hold = hold; state->bits = bits; return; }