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