/* inffast.c -- fast decoding1* Copyright (C) 1995-2004 Mark Adler2* For conditions of distribution and use, see copyright notice in zlib.h3*/45#include "zutil.h"6#include "inftrees.h"7#include "inflate.h"8#include "inffast.h"910#ifndef ASMINF1112/* Allow machine dependent optimization for post-increment or pre-increment.13Based on testing to date,14Pre-increment preferred for:15- PowerPC G3 (Adler)16- MIPS R5000 (Randers-Pehrson)17Post-increment preferred for:18- none19No measurable difference:20- Pentium III (Anderson)21- M68060 (Nikl)22*/23#undef OFF /* (ancient) sunos <locale.h> */24#ifdef POSTINC25# define OFF 026# define PUP(a) *(a)++27#else28# define OFF 129# define PUP(a) *++(a)30#endif3132/*33Decode literal, length, and distance codes and write out the resulting34literal and match bytes until either not enough input or output is35available, an end-of-block is encountered, or a data error is encountered.36When large enough input and output buffers are supplied to inflate(), for37example, a 16K input buffer and a 64K output buffer, more than 95% of the38inflate execution time is spent in this routine.3940Entry assumptions:4142state->mode == LEN43strm->avail_in >= 644strm->avail_out >= 25845start >= strm->avail_out46state->bits < 84748On return, state->mode is one of:4950LEN -- ran out of enough output space or enough available input51TYPE -- reached end of block code, inflate() to interpret next block52BAD -- error in block data5354Notes:5556- The maximum input bits used by a length/distance pair is 15 bits for the57length code, 5 bits for the length extra, 15 bits for the distance code,58and 13 bits for the distance extra. This totals 48 bits, or six bytes.59Therefore if strm->avail_in >= 6, then there is enough input to avoid60checking for available input while decoding.6162- The maximum bytes that a single length/distance pair can output is 25863bytes, which is the maximum length that can be coded. inflate_fast()64requires strm->avail_out >= 258 for each loop to avoid checking for65output space.66*/67void inflate_fast(strm, start)68z_streamp strm;69unsigned start; /* inflate()'s starting value for strm->avail_out */70{71struct inflate_state FAR *state;72unsigned char FAR *in; /* local strm->next_in */73unsigned char FAR *last; /* while in < last, enough input available */74unsigned char FAR *out; /* local strm->next_out */75unsigned char FAR *beg; /* inflate()'s initial strm->next_out */76unsigned char FAR *end; /* while out < end, enough space available */77#ifdef INFLATE_STRICT78unsigned dmax; /* maximum distance from zlib header */79#endif80unsigned wsize; /* window size or zero if not using window */81unsigned whave; /* valid bytes in the window */82unsigned write; /* window write index */83unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */84unsigned long hold; /* local strm->hold */85unsigned bits; /* local strm->bits */86code const FAR *lcode; /* local strm->lencode */87code const FAR *dcode; /* local strm->distcode */88unsigned lmask; /* mask for first level of length codes */89unsigned dmask; /* mask for first level of distance codes */90code this; /* retrieved table entry */91unsigned op; /* code bits, operation, extra bits, or */92/* window position, window bytes to copy */93unsigned len; /* match length, unused bytes */94unsigned dist; /* match distance */95unsigned char FAR *from; /* where to copy match from */9697/* copy state to local variables */98state = (struct inflate_state FAR *)strm->state;99in = strm->next_in - OFF;100last = in + (strm->avail_in - 5);101out = strm->next_out - OFF;102beg = out - (start - strm->avail_out);103end = out + (strm->avail_out - 257);104#ifdef INFLATE_STRICT105dmax = state->dmax;106#endif107wsize = state->wsize;108whave = state->whave;109write = state->write;110window = state->window;111hold = state->hold;112bits = state->bits;113lcode = state->lencode;114dcode = state->distcode;115lmask = (1U << state->lenbits) - 1;116dmask = (1U << state->distbits) - 1;117118/* decode literals and length/distances until end-of-block or not enough119input data or output space */120do {121if (bits < 15) {122hold += (unsigned long)(PUP(in)) << bits;123bits += 8;124hold += (unsigned long)(PUP(in)) << bits;125bits += 8;126}127this = lcode[hold & lmask];128dolen:129op = (unsigned)(this.bits);130hold >>= op;131bits -= op;132op = (unsigned)(this.op);133if (op == 0) { /* literal */134Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ?135"inflate: literal '%c'\n" :136"inflate: literal 0x%02x\n", this.val));137PUP(out) = (unsigned char)(this.val);138}139else if (op & 16) { /* length base */140len = (unsigned)(this.val);141op &= 15; /* number of extra bits */142if (op) {143if (bits < op) {144hold += (unsigned long)(PUP(in)) << bits;145bits += 8;146}147len += (unsigned)hold & ((1U << op) - 1);148hold >>= op;149bits -= op;150}151Tracevv((stderr, "inflate: length %u\n", len));152if (bits < 15) {153hold += (unsigned long)(PUP(in)) << bits;154bits += 8;155hold += (unsigned long)(PUP(in)) << bits;156bits += 8;157}158this = dcode[hold & dmask];159dodist:160op = (unsigned)(this.bits);161hold >>= op;162bits -= op;163op = (unsigned)(this.op);164if (op & 16) { /* distance base */165dist = (unsigned)(this.val);166op &= 15; /* number of extra bits */167if (bits < op) {168hold += (unsigned long)(PUP(in)) << bits;169bits += 8;170if (bits < op) {171hold += (unsigned long)(PUP(in)) << bits;172bits += 8;173}174}175dist += (unsigned)hold & ((1U << op) - 1);176#ifdef INFLATE_STRICT177if (dist > dmax) {178strm->msg = (char *)"invalid distance too far back";179state->mode = BAD;180break;181}182#endif183hold >>= op;184bits -= op;185Tracevv((stderr, "inflate: distance %u\n", dist));186op = (unsigned)(out - beg); /* max distance in output */187if (dist > op) { /* see if copy from window */188op = dist - op; /* distance back in window */189if (op > whave) {190strm->msg = (char *)"invalid distance too far back";191state->mode = BAD;192break;193}194from = window - OFF;195if (write == 0) { /* very common case */196from += wsize - op;197if (op < len) { /* some from window */198len -= op;199do {200PUP(out) = PUP(from);201} while (--op);202from = out - dist; /* rest from output */203}204}205else if (write < op) { /* wrap around window */206from += wsize + write - op;207op -= write;208if (op < len) { /* some from end of window */209len -= op;210do {211PUP(out) = PUP(from);212} while (--op);213from = window - OFF;214if (write < len) { /* some from start of window */215op = write;216len -= op;217do {218PUP(out) = PUP(from);219} while (--op);220from = out - dist; /* rest from output */221}222}223}224else { /* contiguous in window */225from += write - op;226if (op < len) { /* some from window */227len -= op;228do {229PUP(out) = PUP(from);230} while (--op);231from = out - dist; /* rest from output */232}233}234while (len > 2) {235PUP(out) = PUP(from);236PUP(out) = PUP(from);237PUP(out) = PUP(from);238len -= 3;239}240if (len) {241PUP(out) = PUP(from);242if (len > 1)243PUP(out) = PUP(from);244}245}246else {247from = out - dist; /* copy direct from output */248do { /* minimum length is three */249PUP(out) = PUP(from);250PUP(out) = PUP(from);251PUP(out) = PUP(from);252len -= 3;253} while (len > 2);254if (len) {255PUP(out) = PUP(from);256if (len > 1)257PUP(out) = PUP(from);258}259}260}261else if ((op & 64) == 0) { /* 2nd level distance code */262this = dcode[this.val + (hold & ((1U << op) - 1))];263goto dodist;264}265else {266strm->msg = (char *)"invalid distance code";267state->mode = BAD;268break;269}270}271else if ((op & 64) == 0) { /* 2nd level length code */272this = lcode[this.val + (hold & ((1U << op) - 1))];273goto dolen;274}275else if (op & 32) { /* end-of-block */276Tracevv((stderr, "inflate: end of block\n"));277state->mode = TYPE;278break;279}280else {281strm->msg = (char *)"invalid literal/length code";282state->mode = BAD;283break;284}285} while (in < last && out < end);286287/* return unused bytes (on entry, bits < 8, so in won't go too far back) */288len = bits >> 3;289in -= len;290bits -= len << 3;291hold &= (1U << bits) - 1;292293/* update state and return */294strm->next_in = in + OFF;295strm->next_out = out + OFF;296strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));297strm->avail_out = (unsigned)(out < end ?298257 + (end - out) : 257 - (out - end));299state->hold = hold;300state->bits = bits;301return;302}303304/*305inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):306- Using bit fields for code structure307- Different op definition to avoid & for extra bits (do & for table bits)308- Three separate decoding do-loops for direct, window, and write == 0309- Special case for distance > 1 copies to do overlapped load and store copy310- Explicit branch predictions (based on measured branch probabilities)311- Deferring match copy and interspersed it with decoding subsequent codes312- Swapping literal/length else313- Swapping window/direct else314- Larger unrolled copy loops (three is about right)315- Moving len -= 3 statement into middle of loop316*/317318#endif /* !ASMINF */319320321