     1			/* inffast.c -- fast decoding
     2			 * Copyright (C) 1995-2004 Mark Adler
     3			 * For conditions of distribution and use, see copyright notice in zlib.h
     4			 */
     5			
     6			#include "zutil.h"
     7			#include "inftrees.h"
     8			#include "inflate.h"
     9			#include "inffast.h"
    10			
    11			#ifndef ASMINF
    12			
    13			/* Allow machine dependent optimization for post-increment or pre-increment.
    14			   Based on testing to date,
    15			   Pre-increment preferred for:
    16			   - PowerPC G3 (Adler)
    17			   - MIPS R5000 (Randers-Pehrson)
    18			   Post-increment preferred for:
    19			   - none
    20			   No measurable difference:
    21			   - Pentium III (Anderson)
    22			   - M68060 (Nikl)
    23			 */
    24			#ifdef POSTINC
    25			#  define OFF 0
    26			#  define PUP(a) *(a)++
    27			#else
    28			#  define OFF 1
    29			#  define PUP(a) *++(a)
    30			#endif
    31			
    32			/*
    33			   Decode literal, length, and distance codes and write out the resulting
    34			   literal and match bytes until either not enough input or output is
    35			   available, an end-of-block is encountered, or a data error is encountered.
    36			   When large enough input and output buffers are supplied to inflate(), for
    37			   example, a 16K input buffer and a 64K output buffer, more than 95% of the
    38			   inflate execution time is spent in this routine.
    39			
    40			   Entry assumptions:
    41			
    42			        state->mode == LEN
    43			        strm->avail_in >= 6
    44			        strm->avail_out >= 258
    45			        start >= strm->avail_out
    46			        state->bits < 8
    47			
    48			   On return, state->mode is one of:
    49			
    50			        LEN -- ran out of enough output space or enough available input
    51			        TYPE -- reached end of block code, inflate() to interpret next block
    52			        BAD -- error in block data
    53			
    54			   Notes:
    55			
    56			    - The maximum input bits used by a length/distance pair is 15 bits for the
    57			      length code, 5 bits for the length extra, 15 bits for the distance code,
    58			      and 13 bits for the distance extra.  This totals 48 bits, or six bytes.
    59			      Therefore if strm->avail_in >= 6, then there is enough input to avoid
    60			      checking for available input while decoding.
    61			
    62			    - The maximum bytes that a single length/distance pair can output is 258
    63			      bytes, which is the maximum length that can be coded.  inflate_fast()
    64			      requires strm->avail_out >= 258 for each loop to avoid checking for
    65			      output space.
    66			 */
    67			void inflate_fast(strm, start)
    68			z_streamp strm;
    69			unsigned start;         /* inflate()'s starting value for strm->avail_out */
    70	         185    {
    71	         185        struct inflate_state FAR *state;
    72	         185        unsigned char FAR *in;      /* local strm->next_in */
    73	         185        unsigned char FAR *last;    /* while in < last, enough input available */
    74	         185        unsigned char FAR *out;     /* local strm->next_out */
    75	         185        unsigned char FAR *beg;     /* inflate()'s initial strm->next_out */
    76	         185        unsigned char FAR *end;     /* while out < end, enough space available */
    77	         185        unsigned wsize;             /* window size or zero if not using window */
    78	         185        unsigned whave;             /* valid bytes in the window */
    79	         185        unsigned write;             /* window write index */
    80	         185        unsigned char FAR *window;  /* allocated sliding window, if wsize != 0 */
    81	         185        unsigned long hold;         /* local strm->hold */
    82	         185        unsigned bits;              /* local strm->bits */
    83	         185        code const FAR *lcode;      /* local strm->lencode */
    84	         185        code const FAR *dcode;      /* local strm->distcode */
    85	         185        unsigned lmask;             /* mask for first level of length codes */
    86	         185        unsigned dmask;             /* mask for first level of distance codes */
    87	         185        code this;                  /* retrieved table entry */
    88	         185        unsigned op;                /* code bits, operation, extra bits, or */
    89			                                /*  window position, window bytes to copy */
    90	         185        unsigned len;               /* match length, unused bytes */
    91	         185        unsigned dist;              /* match distance */
    92	         185        unsigned char FAR *from;    /* where to copy match from */
    93			
    94			    /* copy state to local variables */
    95	         185        state = (struct inflate_state FAR *)strm->state;
    96	         185        in = strm->next_in - OFF;
    97	         185        last = in + (strm->avail_in - 5);
    98	         185        out = strm->next_out - OFF;
    99	         185        beg = out - (start - strm->avail_out);
   100	         185        end = out + (strm->avail_out - 257);
   101	         185        wsize = state->wsize;
   102	         185        whave = state->whave;
   103	         185        write = state->write;
   104	         185        window = state->window;
   105	         185        hold = state->hold;
   106	         185        bits = state->bits;
   107	         185        lcode = state->lencode;
   108	         185        dcode = state->distcode;
   109	         185        lmask = (1U << state->lenbits) - 1;
   110	         185        dmask = (1U << state->distbits) - 1;
   111			
   112			    /* decode literals and length/distances until end-of-block or not enough
   113			       input data or output space */
   114	       82156        do {
   115	       82156            if (bits < 15) {
   116	       30470                hold += (unsigned long)(PUP(in)) << bits;
   117	       30470                bits += 8;
   118	       30470                hold += (unsigned long)(PUP(in)) << bits;
   119	       30470                bits += 8;
   120			        }
   121	       82156            this = lcode[hold & lmask];
   122			      dolen:
   123	       82783            op = (unsigned)(this.bits);
   124	       82783            hold >>= op;
   125	       82783            bits -= op;
   126	       82783            op = (unsigned)(this.op);
   127	       82783            if (op == 0) {                          /* literal */
   128			            Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ?
   129			                    "inflate:         literal '%c'\n" :
   130			                    "inflate:         literal 0x%02x\n", this.val));
   131	       64107                PUP(out) = (unsigned char)(this.val);
   132			        }
   133	       18676            else if (op & 16) {                     /* length base */
   134	       18011                len = (unsigned)(this.val);
   135	       18011                op &= 15;                           /* number of extra bits */
   136	       18011                if (op) {
   137	        3504                    if (bits < op) {
   138	      ######                        hold += (unsigned long)(PUP(in)) << bits;
   139	      ######                        bits += 8;
   140			                }
   141	        3504                    len += (unsigned)hold & ((1U << op) - 1);
   142	        3504                    hold >>= op;
   143	        3504                    bits -= op;
   144			            }
   145			            Tracevv((stderr, "inflate:         length %u\n", len));
   146	       18011                if (bits < 15) {
   147	        5192                    hold += (unsigned long)(PUP(in)) << bits;
   148	        5192                    bits += 8;
   149	        5192                    hold += (unsigned long)(PUP(in)) << bits;
   150	        5192                    bits += 8;
   151			            }
   152	       18011                this = dcode[hold & dmask];
   153			          dodist:
   154	       18502                op = (unsigned)(this.bits);
   155	       18502                hold >>= op;
   156	       18502                bits -= op;
   157	       18502                op = (unsigned)(this.op);
   158	       18502                if (op & 16) {                      /* distance base */
   159	       18011                    dist = (unsigned)(this.val);
   160	       18011                    op &= 15;                       /* number of extra bits */
   161	       18011                    if (bits < op) {
   162	         231                        hold += (unsigned long)(PUP(in)) << bits;
   163	         231                        bits += 8;
   164	         231                        if (bits < op) {
   165	      ######                            hold += (unsigned long)(PUP(in)) << bits;
   166	      ######                            bits += 8;
   167			                    }
   168			                }
   169	       18011                    dist += (unsigned)hold & ((1U << op) - 1);
   170	       18011                    hold >>= op;
   171	       18011                    bits -= op;
   172			                Tracevv((stderr, "inflate:         distance %u\n", dist));
   173	       18011                    op = (unsigned)(out - beg);     /* max distance in output */
   174	       18011                    if (dist > op) {                /* see if copy from window */
   175	        3259                        op = dist - op;             /* distance back in window */
   176	        3259                        if (op > whave) {
   177	      ######                            strm->msg = (char *)"invalid distance too far back";
   178	      ######                            state->mode = BAD;
   179	      ######                            break;
   180			                    }
   181	        3259                        from = window - OFF;
   182	        3259                        if (write == 0) {           /* very common case */
   183	           1                            from += wsize - op;
   184	           1                            if (op < len) {         /* some from window */
   185	           1                                len -= op;
   186	           1                                do {
   187	           1                                    PUP(out) = PUP(from);
   188	           1                                } while (--op);
   189	           1                                from = out - dist;  /* rest from output */
   190			                        }
   191			                    }
   192	        3258                        else if (write < op) {      /* wrap around window */
   193	      ######                            from += wsize + write - op;
   194	      ######                            op -= write;
   195	      ######                            if (op < len) {         /* some from end of window */
   196	      ######                                len -= op;
   197	      ######                                do {
   198	      ######                                    PUP(out) = PUP(from);
   199	      ######                                } while (--op);
   200	      ######                                from = window - OFF;
   201	      ######                                if (write < len) {  /* some from start of window */
   202	      ######                                    op = write;
   203	      ######                                    len -= op;
   204	      ######                                    do {
   205	      ######                                        PUP(out) = PUP(from);
   206	      ######                                    } while (--op);
   207	      ######                                    from = out - dist;      /* rest from output */
   208			                            }
   209			                        }
   210			                    }
   211			                    else {                      /* contiguous in window */
   212	        3258                            from += write - op;
   213	        3258                            if (op < len) {         /* some from window */
   214	          18                                len -= op;
   215	        2130                                do {
   216	        2130                                    PUP(out) = PUP(from);
   217	        2130                                } while (--op);
   218	          18                                from = out - dist;  /* rest from output */
   219			                        }
   220			                    }
   221	       14885                        while (len > 2) {
   222	       11626                            PUP(out) = PUP(from);
   223	       11626                            PUP(out) = PUP(from);
   224	       11626                            PUP(out) = PUP(from);
   225	       11626                            len -= 3;
   226			                    }
   227	        3259                        if (len) {
   228	        1831                            PUP(out) = PUP(from);
   229	        1831                            if (len > 1)
   230	         735                                PUP(out) = PUP(from);
   231			                    }
   232			                }
   233			                else {
   234	       14752                        from = out - dist;          /* copy direct from output */
   235	       95777                        do {                        /* minimum length is three */
   236	       95777                            PUP(out) = PUP(from);
   237	       95777                            PUP(out) = PUP(from);
   238	       95777                            PUP(out) = PUP(from);
   239	       95777                            len -= 3;
   240	       95777                        } while (len > 2);
   241	       14752                        if (len) {
   242	        8874                            PUP(out) = PUP(from);
   243	        8874                            if (len > 1)
   244	        3674                                PUP(out) = PUP(from);
   245			                    }
   246			                }
   247			            }
   248	         491                else if ((op & 64) == 0) {          /* 2nd level distance code */
   249	         491                    this = dcode[this.val + (hold & ((1U << op) - 1))];
   250	         491                    goto dodist;
   251			            }
   252			            else {
   253	      ######                    strm->msg = (char *)"invalid distance code";
   254	      ######                    state->mode = BAD;
   255	      ######                    break;
   256			            }
   257			        }
   258	         665            else if ((op & 64) == 0) {              /* 2nd level length code */
   259	         627                this = lcode[this.val + (hold & ((1U << op) - 1))];
   260	         627                goto dolen;
   261			        }
   262	          38            else if (op & 32) {                     /* end-of-block */
   263			            Tracevv((stderr, "inflate:         end of block\n"));
   264	          38                state->mode = TYPE;
   265	          38                break;
   266			        }
   267			        else {
   268	      ######                strm->msg = (char *)"invalid literal/length code";
   269	      ######                state->mode = BAD;
   270	      ######                break;
   271			        }
   272	       82118        } while (in < last && out < end);
   273			
   274			    /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
   275	         185        len = bits >> 3;
   276	         185        in -= len;
   277	         185        bits -= len << 3;
   278	         185        hold &= (1U << bits) - 1;
   279			
   280			    /* update state and return */
   281	         185        strm->next_in = in + OFF;
   282	         185        strm->next_out = out + OFF;
   283	         185        strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
   284	         185        strm->avail_out = (unsigned)(out < end ?
   285			                                 257 + (end - out) : 257 - (out - end));
   286	         185        state->hold = hold;
   287	         185        state->bits = bits;
   288			    return;
   289			}
   290			
   291			/*
   292			   inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):
   293			   - Using bit fields for code structure
   294			   - Different op definition to avoid & for extra bits (do & for table bits)
   295			   - Three separate decoding do-loops for direct, window, and write == 0
   296			   - Special case for distance > 1 copies to do overlapped load and store copy
   297			   - Explicit branch predictions (based on measured branch probabilities)
   298			   - Deferring match copy and interspersed it with decoding subsequent codes
   299			   - Swapping literal/length else
   300			   - Swapping window/direct else
   301			   - Larger unrolled copy loops (three is about right)
   302			   - Moving len -= 3 statement into middle of loop
   303			 */
   304			
   305			#endif /* !ASMINF */
