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