		/* inffast.c -- fast decoding
		 * Copyright (C) 1995-2004 Mark Adler
		 * For conditions of distribution and use, see copyright notice in zlib.h
		 */
		
		#include "zutil.h"
		#include "inftrees.h"
		#include "inflate.h"
		#include "inffast.h"
		
		#ifndef ASMINF
		
		/* Allow machine dependent optimization for post-increment or pre-increment.
		   Based on testing to date,
		   Pre-increment preferred for:
		   - PowerPC G3 (Adler)
		   - MIPS R5000 (Randers-Pehrson)
		   Post-increment preferred for:
		   - none
		   No measurable difference:
		   - Pentium III (Anderson)
		   - M68060 (Nikl)
		 */
		#ifdef POSTINC
		#  define OFF 0
		#  define PUP(a) *(a)++
		#else
		#  define OFF 1
		#  define PUP(a) *++(a)
		#endif
		
		/*
		   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 inflate_fast(strm, start)
		z_streamp strm;
		unsigned start;         /* inflate()'s starting value for strm->avail_out */
         185    {
         185        struct inflate_state FAR *state;
         185        unsigned char FAR *in;      /* local strm->next_in */
         185        unsigned char FAR *last;    /* while in < last, enough input available */
         185        unsigned char FAR *out;     /* local strm->next_out */
         185        unsigned char FAR *beg;     /* inflate()'s initial strm->next_out */
         185        unsigned char FAR *end;     /* while out < end, enough space available */
         185        unsigned wsize;             /* window size or zero if not using window */
         185        unsigned whave;             /* valid bytes in the window */
         185        unsigned write;             /* window write index */
         185        unsigned char FAR *window;  /* allocated sliding window, if wsize != 0 */
         185        unsigned long hold;         /* local strm->hold */
         185        unsigned bits;              /* local strm->bits */
         185        code const FAR *lcode;      /* local strm->lencode */
         185        code const FAR *dcode;      /* local strm->distcode */
         185        unsigned lmask;             /* mask for first level of length codes */
         185        unsigned dmask;             /* mask for first level of distance codes */
         185        code this;                  /* retrieved table entry */
         185        unsigned op;                /* code bits, operation, extra bits, or */
		                                /*  window position, window bytes to copy */
         185        unsigned len;               /* match length, unused bytes */
         185        unsigned dist;              /* match distance */
         185        unsigned char FAR *from;    /* where to copy match from */
		
		    /* copy state to local variables */
         185        state = (struct inflate_state FAR *)strm->state;
         185        in = strm->next_in - OFF;
         185        last = in + (strm->avail_in - 5);
         185        out = strm->next_out - OFF;
         185        beg = out - (start - strm->avail_out);
         185        end = out + (strm->avail_out - 257);
         185        wsize = state->wsize;
         185        whave = state->whave;
         185        write = state->write;
         185        window = state->window;
         185        hold = state->hold;
         185        bits = state->bits;
         185        lcode = state->lencode;
         185        dcode = state->distcode;
         185        lmask = (1U << state->lenbits) - 1;
         185        dmask = (1U << state->distbits) - 1;
		
		    /* decode literals and length/distances until end-of-block or not enough
		       input data or output space */
       82156        do {
       82156            if (bits < 15) {
       30470                hold += (unsigned long)(PUP(in)) << bits;
       30470                bits += 8;
       30470                hold += (unsigned long)(PUP(in)) << bits;
       30470                bits += 8;
		        }
       82156            this = lcode[hold & lmask];
		      dolen:
       82783            op = (unsigned)(this.bits);
       82783            hold >>= op;
       82783            bits -= op;
       82783            op = (unsigned)(this.op);
       82783            if (op == 0) {                          /* literal */
		            Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ?
		                    "inflate:         literal '%c'\n" :
		                    "inflate:         literal 0x%02x\n", this.val));
       64107                PUP(out) = (unsigned char)(this.val);
		        }
       18676            else if (op & 16) {                     /* length base */
       18011                len = (unsigned)(this.val);
       18011                op &= 15;                           /* number of extra bits */
       18011                if (op) {
        3504                    if (bits < op) {
      ######                        hold += (unsigned long)(PUP(in)) << bits;
      ######                        bits += 8;
		                }
        3504                    len += (unsigned)hold & ((1U << op) - 1);
        3504                    hold >>= op;
        3504                    bits -= op;
		            }
		            Tracevv((stderr, "inflate:         length %u\n", len));
       18011                if (bits < 15) {
        5192                    hold += (unsigned long)(PUP(in)) << bits;
        5192                    bits += 8;
        5192                    hold += (unsigned long)(PUP(in)) << bits;
        5192                    bits += 8;
		            }
       18011                this = dcode[hold & dmask];
		          dodist:
       18502                op = (unsigned)(this.bits);
       18502                hold >>= op;
       18502                bits -= op;
       18502                op = (unsigned)(this.op);
       18502                if (op & 16) {                      /* distance base */
       18011                    dist = (unsigned)(this.val);
       18011                    op &= 15;                       /* number of extra bits */
       18011                    if (bits < op) {
         231                        hold += (unsigned long)(PUP(in)) << bits;
         231                        bits += 8;
         231                        if (bits < op) {
      ######                            hold += (unsigned long)(PUP(in)) << bits;
      ######                            bits += 8;
		                    }
		                }
       18011                    dist += (unsigned)hold & ((1U << op) - 1);
       18011                    hold >>= op;
       18011                    bits -= op;
		                Tracevv((stderr, "inflate:         distance %u\n", dist));
       18011                    op = (unsigned)(out - beg);     /* max distance in output */
       18011                    if (dist > op) {                /* see if copy from window */
        3259                        op = dist - op;             /* distance back in window */
        3259                        if (op > whave) {
      ######                            strm->msg = (char *)"invalid distance too far back";
      ######                            state->mode = BAD;
      ######                            break;
		                    }
        3259                        from = window - OFF;
        3259                        if (write == 0) {           /* very common case */
           1                            from += wsize - op;
           1                            if (op < len) {         /* some from window */
           1                                len -= op;
           1                                do {
           1                                    PUP(out) = PUP(from);
           1                                } while (--op);
           1                                from = out - dist;  /* rest from output */
		                        }
		                    }
        3258                        else if (write < op) {      /* wrap around window */
      ######                            from += wsize + write - op;
      ######                            op -= write;
      ######                            if (op < len) {         /* some from end of window */
      ######                                len -= op;
      ######                                do {
      ######                                    PUP(out) = PUP(from);
      ######                                } while (--op);
      ######                                from = window - OFF;
      ######                                if (write < len) {  /* some from start of window */
      ######                                    op = write;
      ######                                    len -= op;
      ######                                    do {
      ######                                        PUP(out) = PUP(from);
      ######                                    } while (--op);
      ######                                    from = out - dist;      /* rest from output */
		                            }
		                        }
		                    }
		                    else {                      /* contiguous in window */
        3258                            from += write - op;
        3258                            if (op < len) {         /* some from window */
          18                                len -= op;
        2130                                do {
        2130                                    PUP(out) = PUP(from);
        2130                                } while (--op);
          18                                from = out - dist;  /* rest from output */
		                        }
		                    }
       14885                        while (len > 2) {
       11626                            PUP(out) = PUP(from);
       11626                            PUP(out) = PUP(from);
       11626                            PUP(out) = PUP(from);
       11626                            len -= 3;
		                    }
        3259                        if (len) {
        1831                            PUP(out) = PUP(from);
        1831                            if (len > 1)
         735                                PUP(out) = PUP(from);
		                    }
		                }
		                else {
       14752                        from = out - dist;          /* copy direct from output */
       95777                        do {                        /* minimum length is three */
       95777                            PUP(out) = PUP(from);
       95777                            PUP(out) = PUP(from);
       95777                            PUP(out) = PUP(from);
       95777                            len -= 3;
       95777                        } while (len > 2);
       14752                        if (len) {
        8874                            PUP(out) = PUP(from);
        8874                            if (len > 1)
        3674                                PUP(out) = PUP(from);
		                    }
		                }
		            }
         491                else if ((op & 64) == 0) {          /* 2nd level distance code */
         491                    this = dcode[this.val + (hold & ((1U << op) - 1))];
         491                    goto dodist;
		            }
		            else {
      ######                    strm->msg = (char *)"invalid distance code";
      ######                    state->mode = BAD;
      ######                    break;
		            }
		        }
         665            else if ((op & 64) == 0) {              /* 2nd level length code */
         627                this = lcode[this.val + (hold & ((1U << op) - 1))];
         627                goto dolen;
		        }
          38            else if (op & 32) {                     /* end-of-block */
		            Tracevv((stderr, "inflate:         end of block\n"));
          38                state->mode = TYPE;
          38                break;
		        }
		        else {
      ######                strm->msg = (char *)"invalid literal/length code";
      ######                state->mode = BAD;
      ######                break;
		        }
       82118        } while (in < last && out < end);
		
		    /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
         185        len = bits >> 3;
         185        in -= len;
         185        bits -= len << 3;
         185        hold &= (1U << bits) - 1;
		
		    /* update state and return */
         185        strm->next_in = in + OFF;
         185        strm->next_out = out + OFF;
         185        strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
         185        strm->avail_out = (unsigned)(out < end ?
		                                 257 + (end - out) : 257 - (out - end));
         185        state->hold = hold;
         185        state->bits = bits;
		    return;
		}
		
		/*
		   inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):
		   - Using bit fields for code structure
		   - Different op definition to avoid & for extra bits (do & for table bits)
		   - Three separate decoding do-loops for direct, window, and write == 0
		   - Special case for distance > 1 copies to do overlapped load and store copy
		   - Explicit branch predictions (based on measured branch probabilities)
		   - Deferring match copy and interspersed it with decoding subsequent codes
		   - Swapping literal/length else
		   - Swapping window/direct else
		   - Larger unrolled copy loops (three is about right)
		   - Moving len -= 3 statement into middle of loop
		 */
		
		#endif /* !ASMINF */
