xref: /aosp_15_r20/external/libwebsockets/win32port/zlib/infback.c (revision 1c60b9aca93fdbc9b5f19b2d2194c91294b22281)
1*1c60b9acSAndroid Build Coastguard Worker /* infback.c -- inflate using a call-back interface
2*1c60b9acSAndroid Build Coastguard Worker  * Copyright (C) 1995-2009 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 /*
7*1c60b9acSAndroid Build Coastguard Worker    This code is largely copied from inflate.c.  Normally either infback.o or
8*1c60b9acSAndroid Build Coastguard Worker    inflate.o would be linked into an application--not both.  The interface
9*1c60b9acSAndroid Build Coastguard Worker    with inffast.c is retained so that optimized assembler-coded versions of
10*1c60b9acSAndroid Build Coastguard Worker    inflate_fast() can be used with either inflate.c or infback.c.
11*1c60b9acSAndroid Build Coastguard Worker  */
12*1c60b9acSAndroid Build Coastguard Worker 
13*1c60b9acSAndroid Build Coastguard Worker #include "zutil.h"
14*1c60b9acSAndroid Build Coastguard Worker #include "inftrees.h"
15*1c60b9acSAndroid Build Coastguard Worker #include "inflate.h"
16*1c60b9acSAndroid Build Coastguard Worker #include "inffast.h"
17*1c60b9acSAndroid Build Coastguard Worker 
18*1c60b9acSAndroid Build Coastguard Worker /* function prototypes */
19*1c60b9acSAndroid Build Coastguard Worker local void fixedtables OF((struct inflate_state FAR *state));
20*1c60b9acSAndroid Build Coastguard Worker 
21*1c60b9acSAndroid Build Coastguard Worker /*
22*1c60b9acSAndroid Build Coastguard Worker    strm provides memory allocation functions in zalloc and zfree, or
23*1c60b9acSAndroid Build Coastguard Worker    Z_NULL to use the library memory allocation functions.
24*1c60b9acSAndroid Build Coastguard Worker 
25*1c60b9acSAndroid Build Coastguard Worker    windowBits is in the range 8..15, and window is a user-supplied
26*1c60b9acSAndroid Build Coastguard Worker    window and output buffer that is 2**windowBits bytes.
27*1c60b9acSAndroid Build Coastguard Worker  */
inflateBackInit_(strm,windowBits,window,version,stream_size)28*1c60b9acSAndroid Build Coastguard Worker int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size)
29*1c60b9acSAndroid Build Coastguard Worker z_streamp strm;
30*1c60b9acSAndroid Build Coastguard Worker int windowBits;
31*1c60b9acSAndroid Build Coastguard Worker unsigned char FAR *window;
32*1c60b9acSAndroid Build Coastguard Worker const char *version;
33*1c60b9acSAndroid Build Coastguard Worker int stream_size;
34*1c60b9acSAndroid Build Coastguard Worker {
35*1c60b9acSAndroid Build Coastguard Worker     struct inflate_state FAR *state;
36*1c60b9acSAndroid Build Coastguard Worker 
37*1c60b9acSAndroid Build Coastguard Worker     if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
38*1c60b9acSAndroid Build Coastguard Worker         stream_size != (int)(sizeof(z_stream)))
39*1c60b9acSAndroid Build Coastguard Worker         return Z_VERSION_ERROR;
40*1c60b9acSAndroid Build Coastguard Worker     if (strm == Z_NULL || window == Z_NULL ||
41*1c60b9acSAndroid Build Coastguard Worker         windowBits < 8 || windowBits > 15)
42*1c60b9acSAndroid Build Coastguard Worker         return Z_STREAM_ERROR;
43*1c60b9acSAndroid Build Coastguard Worker     strm->msg = Z_NULL;                 /* in case we return an error */
44*1c60b9acSAndroid Build Coastguard Worker     if (strm->zalloc == (alloc_func)0) {
45*1c60b9acSAndroid Build Coastguard Worker         strm->zalloc = zcalloc;
46*1c60b9acSAndroid Build Coastguard Worker         strm->opaque = (voidpf)0;
47*1c60b9acSAndroid Build Coastguard Worker     }
48*1c60b9acSAndroid Build Coastguard Worker     if (strm->zfree == (free_func)0) strm->zfree = zcfree;
49*1c60b9acSAndroid Build Coastguard Worker     state = (struct inflate_state FAR *)ZALLOC(strm, 1,
50*1c60b9acSAndroid Build Coastguard Worker                                                sizeof(struct inflate_state));
51*1c60b9acSAndroid Build Coastguard Worker     if (state == Z_NULL) return Z_MEM_ERROR;
52*1c60b9acSAndroid Build Coastguard Worker     Tracev((stderr, "inflate: allocated\n"));
53*1c60b9acSAndroid Build Coastguard Worker     strm->state = (struct internal_state FAR *)state;
54*1c60b9acSAndroid Build Coastguard Worker     state->dmax = 32768U;
55*1c60b9acSAndroid Build Coastguard Worker     state->wbits = windowBits;
56*1c60b9acSAndroid Build Coastguard Worker     state->wsize = 1U << windowBits;
57*1c60b9acSAndroid Build Coastguard Worker     state->window = window;
58*1c60b9acSAndroid Build Coastguard Worker     state->wnext = 0;
59*1c60b9acSAndroid Build Coastguard Worker     state->whave = 0;
60*1c60b9acSAndroid Build Coastguard Worker     return Z_OK;
61*1c60b9acSAndroid Build Coastguard Worker }
62*1c60b9acSAndroid Build Coastguard Worker 
63*1c60b9acSAndroid Build Coastguard Worker /*
64*1c60b9acSAndroid Build Coastguard Worker    Return state with length and distance decoding tables and index sizes set to
65*1c60b9acSAndroid Build Coastguard Worker    fixed code decoding.  Normally this returns fixed tables from inffixed.h.
66*1c60b9acSAndroid Build Coastguard Worker    If BUILDFIXED is defined, then instead this routine builds the tables the
67*1c60b9acSAndroid Build Coastguard Worker    first time it's called, and returns those tables the first time and
68*1c60b9acSAndroid Build Coastguard Worker    thereafter.  This reduces the size of the code by about 2K bytes, in
69*1c60b9acSAndroid Build Coastguard Worker    exchange for a little execution time.  However, BUILDFIXED should not be
70*1c60b9acSAndroid Build Coastguard Worker    used for threaded applications, since the rewriting of the tables and virgin
71*1c60b9acSAndroid Build Coastguard Worker    may not be thread-safe.
72*1c60b9acSAndroid Build Coastguard Worker  */
fixedtables(state)73*1c60b9acSAndroid Build Coastguard Worker local void fixedtables(state)
74*1c60b9acSAndroid Build Coastguard Worker struct inflate_state FAR *state;
75*1c60b9acSAndroid Build Coastguard Worker {
76*1c60b9acSAndroid Build Coastguard Worker #ifdef BUILDFIXED
77*1c60b9acSAndroid Build Coastguard Worker     static int virgin = 1;
78*1c60b9acSAndroid Build Coastguard Worker     static code *lenfix, *distfix;
79*1c60b9acSAndroid Build Coastguard Worker     static code fixed[544];
80*1c60b9acSAndroid Build Coastguard Worker 
81*1c60b9acSAndroid Build Coastguard Worker     /* build fixed huffman tables if first call (may not be thread safe) */
82*1c60b9acSAndroid Build Coastguard Worker     if (virgin) {
83*1c60b9acSAndroid Build Coastguard Worker         unsigned sym, bits;
84*1c60b9acSAndroid Build Coastguard Worker         static code *next;
85*1c60b9acSAndroid Build Coastguard Worker 
86*1c60b9acSAndroid Build Coastguard Worker         /* literal/length table */
87*1c60b9acSAndroid Build Coastguard Worker         sym = 0;
88*1c60b9acSAndroid Build Coastguard Worker         while (sym < 144) state->lens[sym++] = 8;
89*1c60b9acSAndroid Build Coastguard Worker         while (sym < 256) state->lens[sym++] = 9;
90*1c60b9acSAndroid Build Coastguard Worker         while (sym < 280) state->lens[sym++] = 7;
91*1c60b9acSAndroid Build Coastguard Worker         while (sym < 288) state->lens[sym++] = 8;
92*1c60b9acSAndroid Build Coastguard Worker         next = fixed;
93*1c60b9acSAndroid Build Coastguard Worker         lenfix = next;
94*1c60b9acSAndroid Build Coastguard Worker         bits = 9;
95*1c60b9acSAndroid Build Coastguard Worker         inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
96*1c60b9acSAndroid Build Coastguard Worker 
97*1c60b9acSAndroid Build Coastguard Worker         /* distance table */
98*1c60b9acSAndroid Build Coastguard Worker         sym = 0;
99*1c60b9acSAndroid Build Coastguard Worker         while (sym < 32) state->lens[sym++] = 5;
100*1c60b9acSAndroid Build Coastguard Worker         distfix = next;
101*1c60b9acSAndroid Build Coastguard Worker         bits = 5;
102*1c60b9acSAndroid Build Coastguard Worker         inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
103*1c60b9acSAndroid Build Coastguard Worker 
104*1c60b9acSAndroid Build Coastguard Worker         /* do this just once */
105*1c60b9acSAndroid Build Coastguard Worker         virgin = 0;
106*1c60b9acSAndroid Build Coastguard Worker     }
107*1c60b9acSAndroid Build Coastguard Worker #else /* !BUILDFIXED */
108*1c60b9acSAndroid Build Coastguard Worker #   include "inffixed.h"
109*1c60b9acSAndroid Build Coastguard Worker #endif /* BUILDFIXED */
110*1c60b9acSAndroid Build Coastguard Worker     state->lencode = lenfix;
111*1c60b9acSAndroid Build Coastguard Worker     state->lenbits = 9;
112*1c60b9acSAndroid Build Coastguard Worker     state->distcode = distfix;
113*1c60b9acSAndroid Build Coastguard Worker     state->distbits = 5;
114*1c60b9acSAndroid Build Coastguard Worker }
115*1c60b9acSAndroid Build Coastguard Worker 
116*1c60b9acSAndroid Build Coastguard Worker /* Macros for inflateBack(): */
117*1c60b9acSAndroid Build Coastguard Worker 
118*1c60b9acSAndroid Build Coastguard Worker /* Load returned state from inflate_fast() */
119*1c60b9acSAndroid Build Coastguard Worker #define LOAD() \
120*1c60b9acSAndroid Build Coastguard Worker     do { \
121*1c60b9acSAndroid Build Coastguard Worker         put = strm->next_out; \
122*1c60b9acSAndroid Build Coastguard Worker         left = strm->avail_out; \
123*1c60b9acSAndroid Build Coastguard Worker         next = strm->next_in; \
124*1c60b9acSAndroid Build Coastguard Worker         have = strm->avail_in; \
125*1c60b9acSAndroid Build Coastguard Worker         hold = state->hold; \
126*1c60b9acSAndroid Build Coastguard Worker         bits = state->bits; \
127*1c60b9acSAndroid Build Coastguard Worker     } while (0)
128*1c60b9acSAndroid Build Coastguard Worker 
129*1c60b9acSAndroid Build Coastguard Worker /* Set state from registers for inflate_fast() */
130*1c60b9acSAndroid Build Coastguard Worker #define RESTORE() \
131*1c60b9acSAndroid Build Coastguard Worker     do { \
132*1c60b9acSAndroid Build Coastguard Worker         strm->next_out = put; \
133*1c60b9acSAndroid Build Coastguard Worker         strm->avail_out = left; \
134*1c60b9acSAndroid Build Coastguard Worker         strm->next_in = next; \
135*1c60b9acSAndroid Build Coastguard Worker         strm->avail_in = have; \
136*1c60b9acSAndroid Build Coastguard Worker         state->hold = hold; \
137*1c60b9acSAndroid Build Coastguard Worker         state->bits = bits; \
138*1c60b9acSAndroid Build Coastguard Worker     } while (0)
139*1c60b9acSAndroid Build Coastguard Worker 
140*1c60b9acSAndroid Build Coastguard Worker /* Clear the input bit accumulator */
141*1c60b9acSAndroid Build Coastguard Worker #define INITBITS() \
142*1c60b9acSAndroid Build Coastguard Worker     do { \
143*1c60b9acSAndroid Build Coastguard Worker         hold = 0; \
144*1c60b9acSAndroid Build Coastguard Worker         bits = 0; \
145*1c60b9acSAndroid Build Coastguard Worker     } while (0)
146*1c60b9acSAndroid Build Coastguard Worker 
147*1c60b9acSAndroid Build Coastguard Worker /* Assure that some input is available.  If input is requested, but denied,
148*1c60b9acSAndroid Build Coastguard Worker    then return a Z_BUF_ERROR from inflateBack(). */
149*1c60b9acSAndroid Build Coastguard Worker #define PULL() \
150*1c60b9acSAndroid Build Coastguard Worker     do { \
151*1c60b9acSAndroid Build Coastguard Worker         if (have == 0) { \
152*1c60b9acSAndroid Build Coastguard Worker             have = in(in_desc, &next); \
153*1c60b9acSAndroid Build Coastguard Worker             if (have == 0) { \
154*1c60b9acSAndroid Build Coastguard Worker                 next = Z_NULL; \
155*1c60b9acSAndroid Build Coastguard Worker                 ret = Z_BUF_ERROR; \
156*1c60b9acSAndroid Build Coastguard Worker                 goto inf_leave; \
157*1c60b9acSAndroid Build Coastguard Worker             } \
158*1c60b9acSAndroid Build Coastguard Worker         } \
159*1c60b9acSAndroid Build Coastguard Worker     } while (0)
160*1c60b9acSAndroid Build Coastguard Worker 
161*1c60b9acSAndroid Build Coastguard Worker /* Get a byte of input into the bit accumulator, or return from inflateBack()
162*1c60b9acSAndroid Build Coastguard Worker    with an error if there is no input available. */
163*1c60b9acSAndroid Build Coastguard Worker #define PULLBYTE() \
164*1c60b9acSAndroid Build Coastguard Worker     do { \
165*1c60b9acSAndroid Build Coastguard Worker         PULL(); \
166*1c60b9acSAndroid Build Coastguard Worker         have--; \
167*1c60b9acSAndroid Build Coastguard Worker         hold += (unsigned long)(*next++) << bits; \
168*1c60b9acSAndroid Build Coastguard Worker         bits += 8; \
169*1c60b9acSAndroid Build Coastguard Worker     } while (0)
170*1c60b9acSAndroid Build Coastguard Worker 
171*1c60b9acSAndroid Build Coastguard Worker /* Assure that there are at least n bits in the bit accumulator.  If there is
172*1c60b9acSAndroid Build Coastguard Worker    not enough available input to do that, then return from inflateBack() with
173*1c60b9acSAndroid Build Coastguard Worker    an error. */
174*1c60b9acSAndroid Build Coastguard Worker #define NEEDBITS(n) \
175*1c60b9acSAndroid Build Coastguard Worker     do { \
176*1c60b9acSAndroid Build Coastguard Worker         while (bits < (unsigned)(n)) \
177*1c60b9acSAndroid Build Coastguard Worker             PULLBYTE(); \
178*1c60b9acSAndroid Build Coastguard Worker     } while (0)
179*1c60b9acSAndroid Build Coastguard Worker 
180*1c60b9acSAndroid Build Coastguard Worker /* Return the low n bits of the bit accumulator (n < 16) */
181*1c60b9acSAndroid Build Coastguard Worker #define BITS(n) \
182*1c60b9acSAndroid Build Coastguard Worker     ((unsigned)hold & ((1U << (n)) - 1))
183*1c60b9acSAndroid Build Coastguard Worker 
184*1c60b9acSAndroid Build Coastguard Worker /* Remove n bits from the bit accumulator */
185*1c60b9acSAndroid Build Coastguard Worker #define DROPBITS(n) \
186*1c60b9acSAndroid Build Coastguard Worker     do { \
187*1c60b9acSAndroid Build Coastguard Worker         hold >>= (n); \
188*1c60b9acSAndroid Build Coastguard Worker         bits -= (unsigned)(n); \
189*1c60b9acSAndroid Build Coastguard Worker     } while (0)
190*1c60b9acSAndroid Build Coastguard Worker 
191*1c60b9acSAndroid Build Coastguard Worker /* Remove zero to seven bits as needed to go to a byte boundary */
192*1c60b9acSAndroid Build Coastguard Worker #define BYTEBITS() \
193*1c60b9acSAndroid Build Coastguard Worker     do { \
194*1c60b9acSAndroid Build Coastguard Worker         hold >>= bits & 7; \
195*1c60b9acSAndroid Build Coastguard Worker         bits -= bits & 7; \
196*1c60b9acSAndroid Build Coastguard Worker     } while (0)
197*1c60b9acSAndroid Build Coastguard Worker 
198*1c60b9acSAndroid Build Coastguard Worker /* Assure that some output space is available, by writing out the window
199*1c60b9acSAndroid Build Coastguard Worker    if it's full.  If the write fails, return from inflateBack() with a
200*1c60b9acSAndroid Build Coastguard Worker    Z_BUF_ERROR. */
201*1c60b9acSAndroid Build Coastguard Worker #define ROOM() \
202*1c60b9acSAndroid Build Coastguard Worker     do { \
203*1c60b9acSAndroid Build Coastguard Worker         if (left == 0) { \
204*1c60b9acSAndroid Build Coastguard Worker             put = state->window; \
205*1c60b9acSAndroid Build Coastguard Worker             left = state->wsize; \
206*1c60b9acSAndroid Build Coastguard Worker             state->whave = left; \
207*1c60b9acSAndroid Build Coastguard Worker             if (out(out_desc, put, left)) { \
208*1c60b9acSAndroid Build Coastguard Worker                 ret = Z_BUF_ERROR; \
209*1c60b9acSAndroid Build Coastguard Worker                 goto inf_leave; \
210*1c60b9acSAndroid Build Coastguard Worker             } \
211*1c60b9acSAndroid Build Coastguard Worker         } \
212*1c60b9acSAndroid Build Coastguard Worker     } while (0)
213*1c60b9acSAndroid Build Coastguard Worker 
214*1c60b9acSAndroid Build Coastguard Worker /*
215*1c60b9acSAndroid Build Coastguard Worker    strm provides the memory allocation functions and window buffer on input,
216*1c60b9acSAndroid Build Coastguard Worker    and provides information on the unused input on return.  For Z_DATA_ERROR
217*1c60b9acSAndroid Build Coastguard Worker    returns, strm will also provide an error message.
218*1c60b9acSAndroid Build Coastguard Worker 
219*1c60b9acSAndroid Build Coastguard Worker    in() and out() are the call-back input and output functions.  When
220*1c60b9acSAndroid Build Coastguard Worker    inflateBack() needs more input, it calls in().  When inflateBack() has
221*1c60b9acSAndroid Build Coastguard Worker    filled the window with output, or when it completes with data in the
222*1c60b9acSAndroid Build Coastguard Worker    window, it calls out() to write out the data.  The application must not
223*1c60b9acSAndroid Build Coastguard Worker    change the provided input until in() is called again or inflateBack()
224*1c60b9acSAndroid Build Coastguard Worker    returns.  The application must not change the window/output buffer until
225*1c60b9acSAndroid Build Coastguard Worker    inflateBack() returns.
226*1c60b9acSAndroid Build Coastguard Worker 
227*1c60b9acSAndroid Build Coastguard Worker    in() and out() are called with a descriptor parameter provided in the
228*1c60b9acSAndroid Build Coastguard Worker    inflateBack() call.  This parameter can be a structure that provides the
229*1c60b9acSAndroid Build Coastguard Worker    information required to do the read or write, as well as accumulated
230*1c60b9acSAndroid Build Coastguard Worker    information on the input and output such as totals and check values.
231*1c60b9acSAndroid Build Coastguard Worker 
232*1c60b9acSAndroid Build Coastguard Worker    in() should return zero on failure.  out() should return non-zero on
233*1c60b9acSAndroid Build Coastguard Worker    failure.  If either in() or out() fails, than inflateBack() returns a
234*1c60b9acSAndroid Build Coastguard Worker    Z_BUF_ERROR.  strm->next_in can be checked for Z_NULL to see whether it
235*1c60b9acSAndroid Build Coastguard Worker    was in() or out() that caused in the error.  Otherwise,  inflateBack()
236*1c60b9acSAndroid Build Coastguard Worker    returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format
237*1c60b9acSAndroid Build Coastguard Worker    error, or Z_MEM_ERROR if it could not allocate memory for the state.
238*1c60b9acSAndroid Build Coastguard Worker    inflateBack() can also return Z_STREAM_ERROR if the input parameters
239*1c60b9acSAndroid Build Coastguard Worker    are not correct, i.e. strm is Z_NULL or the state was not initialized.
240*1c60b9acSAndroid Build Coastguard Worker  */
inflateBack(strm,in,in_desc,out,out_desc)241*1c60b9acSAndroid Build Coastguard Worker int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc)
242*1c60b9acSAndroid Build Coastguard Worker z_streamp strm;
243*1c60b9acSAndroid Build Coastguard Worker in_func in;
244*1c60b9acSAndroid Build Coastguard Worker void FAR *in_desc;
245*1c60b9acSAndroid Build Coastguard Worker out_func out;
246*1c60b9acSAndroid Build Coastguard Worker void FAR *out_desc;
247*1c60b9acSAndroid Build Coastguard Worker {
248*1c60b9acSAndroid Build Coastguard Worker     struct inflate_state FAR *state;
249*1c60b9acSAndroid Build Coastguard Worker     unsigned char FAR *next;    /* next input */
250*1c60b9acSAndroid Build Coastguard Worker     unsigned char FAR *put;     /* next output */
251*1c60b9acSAndroid Build Coastguard Worker     unsigned have, left;        /* available input and output */
252*1c60b9acSAndroid Build Coastguard Worker     unsigned long hold;         /* bit buffer */
253*1c60b9acSAndroid Build Coastguard Worker     unsigned bits;              /* bits in bit buffer */
254*1c60b9acSAndroid Build Coastguard Worker     unsigned copy;              /* number of stored or match bytes to copy */
255*1c60b9acSAndroid Build Coastguard Worker     unsigned char FAR *from;    /* where to copy match bytes from */
256*1c60b9acSAndroid Build Coastguard Worker     code here;                  /* current decoding table entry */
257*1c60b9acSAndroid Build Coastguard Worker     code last;                  /* parent table entry */
258*1c60b9acSAndroid Build Coastguard Worker     unsigned len;               /* length to copy for repeats, bits to drop */
259*1c60b9acSAndroid Build Coastguard Worker     int ret;                    /* return code */
260*1c60b9acSAndroid Build Coastguard Worker     static const unsigned short order[19] = /* permutation of code lengths */
261*1c60b9acSAndroid Build Coastguard Worker         {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
262*1c60b9acSAndroid Build Coastguard Worker 
263*1c60b9acSAndroid Build Coastguard Worker     /* Check that the strm exists and that the state was initialized */
264*1c60b9acSAndroid Build Coastguard Worker     if (strm == Z_NULL || strm->state == Z_NULL)
265*1c60b9acSAndroid Build Coastguard Worker         return Z_STREAM_ERROR;
266*1c60b9acSAndroid Build Coastguard Worker     state = (struct inflate_state FAR *)strm->state;
267*1c60b9acSAndroid Build Coastguard Worker 
268*1c60b9acSAndroid Build Coastguard Worker     /* Reset the state */
269*1c60b9acSAndroid Build Coastguard Worker     strm->msg = Z_NULL;
270*1c60b9acSAndroid Build Coastguard Worker     state->mode = TYPE;
271*1c60b9acSAndroid Build Coastguard Worker     state->last = 0;
272*1c60b9acSAndroid Build Coastguard Worker     state->whave = 0;
273*1c60b9acSAndroid Build Coastguard Worker     next = strm->next_in;
274*1c60b9acSAndroid Build Coastguard Worker     have = next != Z_NULL ? strm->avail_in : 0;
275*1c60b9acSAndroid Build Coastguard Worker     hold = 0;
276*1c60b9acSAndroid Build Coastguard Worker     bits = 0;
277*1c60b9acSAndroid Build Coastguard Worker     put = state->window;
278*1c60b9acSAndroid Build Coastguard Worker     left = state->wsize;
279*1c60b9acSAndroid Build Coastguard Worker 
280*1c60b9acSAndroid Build Coastguard Worker     /* Inflate until end of block marked as last */
281*1c60b9acSAndroid Build Coastguard Worker     for (;;)
282*1c60b9acSAndroid Build Coastguard Worker         switch (state->mode) {
283*1c60b9acSAndroid Build Coastguard Worker         case TYPE:
284*1c60b9acSAndroid Build Coastguard Worker             /* determine and dispatch block type */
285*1c60b9acSAndroid Build Coastguard Worker             if (state->last) {
286*1c60b9acSAndroid Build Coastguard Worker                 BYTEBITS();
287*1c60b9acSAndroid Build Coastguard Worker                 state->mode = DONE;
288*1c60b9acSAndroid Build Coastguard Worker                 break;
289*1c60b9acSAndroid Build Coastguard Worker             }
290*1c60b9acSAndroid Build Coastguard Worker             NEEDBITS(3);
291*1c60b9acSAndroid Build Coastguard Worker             state->last = BITS(1);
292*1c60b9acSAndroid Build Coastguard Worker             DROPBITS(1);
293*1c60b9acSAndroid Build Coastguard Worker             switch (BITS(2)) {
294*1c60b9acSAndroid Build Coastguard Worker             case 0:                             /* stored block */
295*1c60b9acSAndroid Build Coastguard Worker                 Tracev((stderr, "inflate:     stored block%s\n",
296*1c60b9acSAndroid Build Coastguard Worker                         state->last ? " (last)" : ""));
297*1c60b9acSAndroid Build Coastguard Worker                 state->mode = STORED;
298*1c60b9acSAndroid Build Coastguard Worker                 break;
299*1c60b9acSAndroid Build Coastguard Worker             case 1:                             /* fixed block */
300*1c60b9acSAndroid Build Coastguard Worker                 fixedtables(state);
301*1c60b9acSAndroid Build Coastguard Worker                 Tracev((stderr, "inflate:     fixed codes block%s\n",
302*1c60b9acSAndroid Build Coastguard Worker                         state->last ? " (last)" : ""));
303*1c60b9acSAndroid Build Coastguard Worker                 state->mode = LEN;              /* decode codes */
304*1c60b9acSAndroid Build Coastguard Worker                 break;
305*1c60b9acSAndroid Build Coastguard Worker             case 2:                             /* dynamic block */
306*1c60b9acSAndroid Build Coastguard Worker                 Tracev((stderr, "inflate:     dynamic codes block%s\n",
307*1c60b9acSAndroid Build Coastguard Worker                         state->last ? " (last)" : ""));
308*1c60b9acSAndroid Build Coastguard Worker                 state->mode = TABLE;
309*1c60b9acSAndroid Build Coastguard Worker                 break;
310*1c60b9acSAndroid Build Coastguard Worker             case 3:
311*1c60b9acSAndroid Build Coastguard Worker                 strm->msg = (char *)"invalid block type";
312*1c60b9acSAndroid Build Coastguard Worker                 state->mode = BAD;
313*1c60b9acSAndroid Build Coastguard Worker             }
314*1c60b9acSAndroid Build Coastguard Worker             DROPBITS(2);
315*1c60b9acSAndroid Build Coastguard Worker             break;
316*1c60b9acSAndroid Build Coastguard Worker 
317*1c60b9acSAndroid Build Coastguard Worker         case STORED:
318*1c60b9acSAndroid Build Coastguard Worker             /* get and verify stored block length */
319*1c60b9acSAndroid Build Coastguard Worker             BYTEBITS();                         /* go to byte boundary */
320*1c60b9acSAndroid Build Coastguard Worker             NEEDBITS(32);
321*1c60b9acSAndroid Build Coastguard Worker             if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
322*1c60b9acSAndroid Build Coastguard Worker                 strm->msg = (char *)"invalid stored block lengths";
323*1c60b9acSAndroid Build Coastguard Worker                 state->mode = BAD;
324*1c60b9acSAndroid Build Coastguard Worker                 break;
325*1c60b9acSAndroid Build Coastguard Worker             }
326*1c60b9acSAndroid Build Coastguard Worker             state->length = (unsigned)hold & 0xffff;
327*1c60b9acSAndroid Build Coastguard Worker             Tracev((stderr, "inflate:       stored length %u\n",
328*1c60b9acSAndroid Build Coastguard Worker                     state->length));
329*1c60b9acSAndroid Build Coastguard Worker             INITBITS();
330*1c60b9acSAndroid Build Coastguard Worker 
331*1c60b9acSAndroid Build Coastguard Worker             /* copy stored block from input to output */
332*1c60b9acSAndroid Build Coastguard Worker             while (state->length != 0) {
333*1c60b9acSAndroid Build Coastguard Worker                 copy = state->length;
334*1c60b9acSAndroid Build Coastguard Worker                 PULL();
335*1c60b9acSAndroid Build Coastguard Worker                 ROOM();
336*1c60b9acSAndroid Build Coastguard Worker                 if (copy > have) copy = have;
337*1c60b9acSAndroid Build Coastguard Worker                 if (copy > left) copy = left;
338*1c60b9acSAndroid Build Coastguard Worker                 zmemcpy(put, next, copy);
339*1c60b9acSAndroid Build Coastguard Worker                 have -= copy;
340*1c60b9acSAndroid Build Coastguard Worker                 next += copy;
341*1c60b9acSAndroid Build Coastguard Worker                 left -= copy;
342*1c60b9acSAndroid Build Coastguard Worker                 put += copy;
343*1c60b9acSAndroid Build Coastguard Worker                 state->length -= copy;
344*1c60b9acSAndroid Build Coastguard Worker             }
345*1c60b9acSAndroid Build Coastguard Worker             Tracev((stderr, "inflate:       stored end\n"));
346*1c60b9acSAndroid Build Coastguard Worker             state->mode = TYPE;
347*1c60b9acSAndroid Build Coastguard Worker             break;
348*1c60b9acSAndroid Build Coastguard Worker 
349*1c60b9acSAndroid Build Coastguard Worker         case TABLE:
350*1c60b9acSAndroid Build Coastguard Worker             /* get dynamic table entries descriptor */
351*1c60b9acSAndroid Build Coastguard Worker             NEEDBITS(14);
352*1c60b9acSAndroid Build Coastguard Worker             state->nlen = BITS(5) + 257;
353*1c60b9acSAndroid Build Coastguard Worker             DROPBITS(5);
354*1c60b9acSAndroid Build Coastguard Worker             state->ndist = BITS(5) + 1;
355*1c60b9acSAndroid Build Coastguard Worker             DROPBITS(5);
356*1c60b9acSAndroid Build Coastguard Worker             state->ncode = BITS(4) + 4;
357*1c60b9acSAndroid Build Coastguard Worker             DROPBITS(4);
358*1c60b9acSAndroid Build Coastguard Worker #ifndef PKZIP_BUG_WORKAROUND
359*1c60b9acSAndroid Build Coastguard Worker             if (state->nlen > 286 || state->ndist > 30) {
360*1c60b9acSAndroid Build Coastguard Worker                 strm->msg = (char *)"too many length or distance symbols";
361*1c60b9acSAndroid Build Coastguard Worker                 state->mode = BAD;
362*1c60b9acSAndroid Build Coastguard Worker                 break;
363*1c60b9acSAndroid Build Coastguard Worker             }
364*1c60b9acSAndroid Build Coastguard Worker #endif
365*1c60b9acSAndroid Build Coastguard Worker             Tracev((stderr, "inflate:       table sizes ok\n"));
366*1c60b9acSAndroid Build Coastguard Worker 
367*1c60b9acSAndroid Build Coastguard Worker             /* get code length code lengths (not a typo) */
368*1c60b9acSAndroid Build Coastguard Worker             state->have = 0;
369*1c60b9acSAndroid Build Coastguard Worker             while (state->have < state->ncode) {
370*1c60b9acSAndroid Build Coastguard Worker                 NEEDBITS(3);
371*1c60b9acSAndroid Build Coastguard Worker                 state->lens[order[state->have++]] = (unsigned short)BITS(3);
372*1c60b9acSAndroid Build Coastguard Worker                 DROPBITS(3);
373*1c60b9acSAndroid Build Coastguard Worker             }
374*1c60b9acSAndroid Build Coastguard Worker             while (state->have < 19)
375*1c60b9acSAndroid Build Coastguard Worker                 state->lens[order[state->have++]] = 0;
376*1c60b9acSAndroid Build Coastguard Worker             state->next = state->codes;
377*1c60b9acSAndroid Build Coastguard Worker             state->lencode = (code const FAR *)(state->next);
378*1c60b9acSAndroid Build Coastguard Worker             state->lenbits = 7;
379*1c60b9acSAndroid Build Coastguard Worker             ret = inflate_table(CODES, state->lens, 19, &(state->next),
380*1c60b9acSAndroid Build Coastguard Worker                                 &(state->lenbits), state->work);
381*1c60b9acSAndroid Build Coastguard Worker             if (ret) {
382*1c60b9acSAndroid Build Coastguard Worker                 strm->msg = (char *)"invalid code lengths set";
383*1c60b9acSAndroid Build Coastguard Worker                 state->mode = BAD;
384*1c60b9acSAndroid Build Coastguard Worker                 break;
385*1c60b9acSAndroid Build Coastguard Worker             }
386*1c60b9acSAndroid Build Coastguard Worker             Tracev((stderr, "inflate:       code lengths ok\n"));
387*1c60b9acSAndroid Build Coastguard Worker 
388*1c60b9acSAndroid Build Coastguard Worker             /* get length and distance code code lengths */
389*1c60b9acSAndroid Build Coastguard Worker             state->have = 0;
390*1c60b9acSAndroid Build Coastguard Worker             while (state->have < state->nlen + state->ndist) {
391*1c60b9acSAndroid Build Coastguard Worker                 for (;;) {
392*1c60b9acSAndroid Build Coastguard Worker                     here = state->lencode[BITS(state->lenbits)];
393*1c60b9acSAndroid Build Coastguard Worker                     if ((unsigned)(here.bits) <= bits) break;
394*1c60b9acSAndroid Build Coastguard Worker                     PULLBYTE();
395*1c60b9acSAndroid Build Coastguard Worker                 }
396*1c60b9acSAndroid Build Coastguard Worker                 if (here.val < 16) {
397*1c60b9acSAndroid Build Coastguard Worker                     NEEDBITS(here.bits);
398*1c60b9acSAndroid Build Coastguard Worker                     DROPBITS(here.bits);
399*1c60b9acSAndroid Build Coastguard Worker                     state->lens[state->have++] = here.val;
400*1c60b9acSAndroid Build Coastguard Worker                 }
401*1c60b9acSAndroid Build Coastguard Worker                 else {
402*1c60b9acSAndroid Build Coastguard Worker                     if (here.val == 16) {
403*1c60b9acSAndroid Build Coastguard Worker                         NEEDBITS(here.bits + 2);
404*1c60b9acSAndroid Build Coastguard Worker                         DROPBITS(here.bits);
405*1c60b9acSAndroid Build Coastguard Worker                         if (state->have == 0) {
406*1c60b9acSAndroid Build Coastguard Worker                             strm->msg = (char *)"invalid bit length repeat";
407*1c60b9acSAndroid Build Coastguard Worker                             state->mode = BAD;
408*1c60b9acSAndroid Build Coastguard Worker                             break;
409*1c60b9acSAndroid Build Coastguard Worker                         }
410*1c60b9acSAndroid Build Coastguard Worker                         len = (unsigned)(state->lens[state->have - 1]);
411*1c60b9acSAndroid Build Coastguard Worker                         copy = 3 + BITS(2);
412*1c60b9acSAndroid Build Coastguard Worker                         DROPBITS(2);
413*1c60b9acSAndroid Build Coastguard Worker                     }
414*1c60b9acSAndroid Build Coastguard Worker                     else if (here.val == 17) {
415*1c60b9acSAndroid Build Coastguard Worker                         NEEDBITS(here.bits + 3);
416*1c60b9acSAndroid Build Coastguard Worker                         DROPBITS(here.bits);
417*1c60b9acSAndroid Build Coastguard Worker                         len = 0;
418*1c60b9acSAndroid Build Coastguard Worker                         copy = 3 + BITS(3);
419*1c60b9acSAndroid Build Coastguard Worker                         DROPBITS(3);
420*1c60b9acSAndroid Build Coastguard Worker                     }
421*1c60b9acSAndroid Build Coastguard Worker                     else {
422*1c60b9acSAndroid Build Coastguard Worker                         NEEDBITS(here.bits + 7);
423*1c60b9acSAndroid Build Coastguard Worker                         DROPBITS(here.bits);
424*1c60b9acSAndroid Build Coastguard Worker                         len = 0;
425*1c60b9acSAndroid Build Coastguard Worker                         copy = 11 + BITS(7);
426*1c60b9acSAndroid Build Coastguard Worker                         DROPBITS(7);
427*1c60b9acSAndroid Build Coastguard Worker                     }
428*1c60b9acSAndroid Build Coastguard Worker                     if (state->have + copy > state->nlen + state->ndist) {
429*1c60b9acSAndroid Build Coastguard Worker                         strm->msg = (char *)"invalid bit length repeat";
430*1c60b9acSAndroid Build Coastguard Worker                         state->mode = BAD;
431*1c60b9acSAndroid Build Coastguard Worker                         break;
432*1c60b9acSAndroid Build Coastguard Worker                     }
433*1c60b9acSAndroid Build Coastguard Worker                     while (copy--)
434*1c60b9acSAndroid Build Coastguard Worker                         state->lens[state->have++] = (unsigned short)len;
435*1c60b9acSAndroid Build Coastguard Worker                 }
436*1c60b9acSAndroid Build Coastguard Worker             }
437*1c60b9acSAndroid Build Coastguard Worker 
438*1c60b9acSAndroid Build Coastguard Worker             /* handle error breaks in while */
439*1c60b9acSAndroid Build Coastguard Worker             if (state->mode == BAD) break;
440*1c60b9acSAndroid Build Coastguard Worker 
441*1c60b9acSAndroid Build Coastguard Worker             /* check for end-of-block code (better have one) */
442*1c60b9acSAndroid Build Coastguard Worker             if (state->lens[256] == 0) {
443*1c60b9acSAndroid Build Coastguard Worker                 strm->msg = (char *)"invalid code -- missing end-of-block";
444*1c60b9acSAndroid Build Coastguard Worker                 state->mode = BAD;
445*1c60b9acSAndroid Build Coastguard Worker                 break;
446*1c60b9acSAndroid Build Coastguard Worker             }
447*1c60b9acSAndroid Build Coastguard Worker 
448*1c60b9acSAndroid Build Coastguard Worker             /* build code tables -- note: do not change the lenbits or distbits
449*1c60b9acSAndroid Build Coastguard Worker                values here (9 and 6) without reading the comments in inftrees.h
450*1c60b9acSAndroid Build Coastguard Worker                concerning the ENOUGH constants, which depend on those values */
451*1c60b9acSAndroid Build Coastguard Worker             state->next = state->codes;
452*1c60b9acSAndroid Build Coastguard Worker             state->lencode = (code const FAR *)(state->next);
453*1c60b9acSAndroid Build Coastguard Worker             state->lenbits = 9;
454*1c60b9acSAndroid Build Coastguard Worker             ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
455*1c60b9acSAndroid Build Coastguard Worker                                 &(state->lenbits), state->work);
456*1c60b9acSAndroid Build Coastguard Worker             if (ret) {
457*1c60b9acSAndroid Build Coastguard Worker                 strm->msg = (char *)"invalid literal/lengths set";
458*1c60b9acSAndroid Build Coastguard Worker                 state->mode = BAD;
459*1c60b9acSAndroid Build Coastguard Worker                 break;
460*1c60b9acSAndroid Build Coastguard Worker             }
461*1c60b9acSAndroid Build Coastguard Worker             state->distcode = (code const FAR *)(state->next);
462*1c60b9acSAndroid Build Coastguard Worker             state->distbits = 6;
463*1c60b9acSAndroid Build Coastguard Worker             ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
464*1c60b9acSAndroid Build Coastguard Worker                             &(state->next), &(state->distbits), state->work);
465*1c60b9acSAndroid Build Coastguard Worker             if (ret) {
466*1c60b9acSAndroid Build Coastguard Worker                 strm->msg = (char *)"invalid distances set";
467*1c60b9acSAndroid Build Coastguard Worker                 state->mode = BAD;
468*1c60b9acSAndroid Build Coastguard Worker                 break;
469*1c60b9acSAndroid Build Coastguard Worker             }
470*1c60b9acSAndroid Build Coastguard Worker             Tracev((stderr, "inflate:       codes ok\n"));
471*1c60b9acSAndroid Build Coastguard Worker             state->mode = LEN;
472*1c60b9acSAndroid Build Coastguard Worker 
473*1c60b9acSAndroid Build Coastguard Worker         case LEN:
474*1c60b9acSAndroid Build Coastguard Worker             /* use inflate_fast() if we have enough input and output */
475*1c60b9acSAndroid Build Coastguard Worker             if (have >= 6 && left >= 258) {
476*1c60b9acSAndroid Build Coastguard Worker                 RESTORE();
477*1c60b9acSAndroid Build Coastguard Worker                 if (state->whave < state->wsize)
478*1c60b9acSAndroid Build Coastguard Worker                     state->whave = state->wsize - left;
479*1c60b9acSAndroid Build Coastguard Worker                 inflate_fast(strm, state->wsize);
480*1c60b9acSAndroid Build Coastguard Worker                 LOAD();
481*1c60b9acSAndroid Build Coastguard Worker                 break;
482*1c60b9acSAndroid Build Coastguard Worker             }
483*1c60b9acSAndroid Build Coastguard Worker 
484*1c60b9acSAndroid Build Coastguard Worker             /* get a literal, length, or end-of-block code */
485*1c60b9acSAndroid Build Coastguard Worker             for (;;) {
486*1c60b9acSAndroid Build Coastguard Worker                 here = state->lencode[BITS(state->lenbits)];
487*1c60b9acSAndroid Build Coastguard Worker                 if ((unsigned)(here.bits) <= bits) break;
488*1c60b9acSAndroid Build Coastguard Worker                 PULLBYTE();
489*1c60b9acSAndroid Build Coastguard Worker             }
490*1c60b9acSAndroid Build Coastguard Worker             if (here.op && (here.op & 0xf0) == 0) {
491*1c60b9acSAndroid Build Coastguard Worker                 last = here;
492*1c60b9acSAndroid Build Coastguard Worker                 for (;;) {
493*1c60b9acSAndroid Build Coastguard Worker                     here = state->lencode[last.val +
494*1c60b9acSAndroid Build Coastguard Worker                             (BITS(last.bits + last.op) >> last.bits)];
495*1c60b9acSAndroid Build Coastguard Worker                     if ((unsigned)(last.bits + here.bits) <= bits) break;
496*1c60b9acSAndroid Build Coastguard Worker                     PULLBYTE();
497*1c60b9acSAndroid Build Coastguard Worker                 }
498*1c60b9acSAndroid Build Coastguard Worker                 DROPBITS(last.bits);
499*1c60b9acSAndroid Build Coastguard Worker             }
500*1c60b9acSAndroid Build Coastguard Worker             DROPBITS(here.bits);
501*1c60b9acSAndroid Build Coastguard Worker             state->length = (unsigned)here.val;
502*1c60b9acSAndroid Build Coastguard Worker 
503*1c60b9acSAndroid Build Coastguard Worker             /* process literal */
504*1c60b9acSAndroid Build Coastguard Worker             if (here.op == 0) {
505*1c60b9acSAndroid Build Coastguard Worker                 Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
506*1c60b9acSAndroid Build Coastguard Worker                         "inflate:         literal '%c'\n" :
507*1c60b9acSAndroid Build Coastguard Worker                         "inflate:         literal 0x%02x\n", here.val));
508*1c60b9acSAndroid Build Coastguard Worker                 ROOM();
509*1c60b9acSAndroid Build Coastguard Worker                 *put++ = (unsigned char)(state->length);
510*1c60b9acSAndroid Build Coastguard Worker                 left--;
511*1c60b9acSAndroid Build Coastguard Worker                 state->mode = LEN;
512*1c60b9acSAndroid Build Coastguard Worker                 break;
513*1c60b9acSAndroid Build Coastguard Worker             }
514*1c60b9acSAndroid Build Coastguard Worker 
515*1c60b9acSAndroid Build Coastguard Worker             /* process end of block */
516*1c60b9acSAndroid Build Coastguard Worker             if (here.op & 32) {
517*1c60b9acSAndroid Build Coastguard Worker                 Tracevv((stderr, "inflate:         end of block\n"));
518*1c60b9acSAndroid Build Coastguard Worker                 state->mode = TYPE;
519*1c60b9acSAndroid Build Coastguard Worker                 break;
520*1c60b9acSAndroid Build Coastguard Worker             }
521*1c60b9acSAndroid Build Coastguard Worker 
522*1c60b9acSAndroid Build Coastguard Worker             /* invalid code */
523*1c60b9acSAndroid Build Coastguard Worker             if (here.op & 64) {
524*1c60b9acSAndroid Build Coastguard Worker                 strm->msg = (char *)"invalid literal/length code";
525*1c60b9acSAndroid Build Coastguard Worker                 state->mode = BAD;
526*1c60b9acSAndroid Build Coastguard Worker                 break;
527*1c60b9acSAndroid Build Coastguard Worker             }
528*1c60b9acSAndroid Build Coastguard Worker 
529*1c60b9acSAndroid Build Coastguard Worker             /* length code -- get extra bits, if any */
530*1c60b9acSAndroid Build Coastguard Worker             state->extra = (unsigned)(here.op) & 15;
531*1c60b9acSAndroid Build Coastguard Worker             if (state->extra != 0) {
532*1c60b9acSAndroid Build Coastguard Worker                 NEEDBITS(state->extra);
533*1c60b9acSAndroid Build Coastguard Worker                 state->length += BITS(state->extra);
534*1c60b9acSAndroid Build Coastguard Worker                 DROPBITS(state->extra);
535*1c60b9acSAndroid Build Coastguard Worker             }
536*1c60b9acSAndroid Build Coastguard Worker             Tracevv((stderr, "inflate:         length %u\n", state->length));
537*1c60b9acSAndroid Build Coastguard Worker 
538*1c60b9acSAndroid Build Coastguard Worker             /* get distance code */
539*1c60b9acSAndroid Build Coastguard Worker             for (;;) {
540*1c60b9acSAndroid Build Coastguard Worker                 here = state->distcode[BITS(state->distbits)];
541*1c60b9acSAndroid Build Coastguard Worker                 if ((unsigned)(here.bits) <= bits) break;
542*1c60b9acSAndroid Build Coastguard Worker                 PULLBYTE();
543*1c60b9acSAndroid Build Coastguard Worker             }
544*1c60b9acSAndroid Build Coastguard Worker             if ((here.op & 0xf0) == 0) {
545*1c60b9acSAndroid Build Coastguard Worker                 last = here;
546*1c60b9acSAndroid Build Coastguard Worker                 for (;;) {
547*1c60b9acSAndroid Build Coastguard Worker                     here = state->distcode[last.val +
548*1c60b9acSAndroid Build Coastguard Worker                             (BITS(last.bits + last.op) >> last.bits)];
549*1c60b9acSAndroid Build Coastguard Worker                     if ((unsigned)(last.bits + here.bits) <= bits) break;
550*1c60b9acSAndroid Build Coastguard Worker                     PULLBYTE();
551*1c60b9acSAndroid Build Coastguard Worker                 }
552*1c60b9acSAndroid Build Coastguard Worker                 DROPBITS(last.bits);
553*1c60b9acSAndroid Build Coastguard Worker             }
554*1c60b9acSAndroid Build Coastguard Worker             DROPBITS(here.bits);
555*1c60b9acSAndroid Build Coastguard Worker             if (here.op & 64) {
556*1c60b9acSAndroid Build Coastguard Worker                 strm->msg = (char *)"invalid distance code";
557*1c60b9acSAndroid Build Coastguard Worker                 state->mode = BAD;
558*1c60b9acSAndroid Build Coastguard Worker                 break;
559*1c60b9acSAndroid Build Coastguard Worker             }
560*1c60b9acSAndroid Build Coastguard Worker             state->offset = (unsigned)here.val;
561*1c60b9acSAndroid Build Coastguard Worker 
562*1c60b9acSAndroid Build Coastguard Worker             /* get distance extra bits, if any */
563*1c60b9acSAndroid Build Coastguard Worker             state->extra = (unsigned)(here.op) & 15;
564*1c60b9acSAndroid Build Coastguard Worker             if (state->extra != 0) {
565*1c60b9acSAndroid Build Coastguard Worker                 NEEDBITS(state->extra);
566*1c60b9acSAndroid Build Coastguard Worker                 state->offset += BITS(state->extra);
567*1c60b9acSAndroid Build Coastguard Worker                 DROPBITS(state->extra);
568*1c60b9acSAndroid Build Coastguard Worker             }
569*1c60b9acSAndroid Build Coastguard Worker             if (state->offset > state->wsize - (state->whave < state->wsize ?
570*1c60b9acSAndroid Build Coastguard Worker                                                 left : 0)) {
571*1c60b9acSAndroid Build Coastguard Worker                 strm->msg = (char *)"invalid distance too far back";
572*1c60b9acSAndroid Build Coastguard Worker                 state->mode = BAD;
573*1c60b9acSAndroid Build Coastguard Worker                 break;
574*1c60b9acSAndroid Build Coastguard Worker             }
575*1c60b9acSAndroid Build Coastguard Worker             Tracevv((stderr, "inflate:         distance %u\n", state->offset));
576*1c60b9acSAndroid Build Coastguard Worker 
577*1c60b9acSAndroid Build Coastguard Worker             /* copy match from window to output */
578*1c60b9acSAndroid Build Coastguard Worker             do {
579*1c60b9acSAndroid Build Coastguard Worker                 ROOM();
580*1c60b9acSAndroid Build Coastguard Worker                 copy = state->wsize - state->offset;
581*1c60b9acSAndroid Build Coastguard Worker                 if (copy < left) {
582*1c60b9acSAndroid Build Coastguard Worker                     from = put + copy;
583*1c60b9acSAndroid Build Coastguard Worker                     copy = left - copy;
584*1c60b9acSAndroid Build Coastguard Worker                 }
585*1c60b9acSAndroid Build Coastguard Worker                 else {
586*1c60b9acSAndroid Build Coastguard Worker                     from = put - state->offset;
587*1c60b9acSAndroid Build Coastguard Worker                     copy = left;
588*1c60b9acSAndroid Build Coastguard Worker                 }
589*1c60b9acSAndroid Build Coastguard Worker                 if (copy > state->length) copy = state->length;
590*1c60b9acSAndroid Build Coastguard Worker                 state->length -= copy;
591*1c60b9acSAndroid Build Coastguard Worker                 left -= copy;
592*1c60b9acSAndroid Build Coastguard Worker                 do {
593*1c60b9acSAndroid Build Coastguard Worker                     *put++ = *from++;
594*1c60b9acSAndroid Build Coastguard Worker                 } while (--copy);
595*1c60b9acSAndroid Build Coastguard Worker             } while (state->length != 0);
596*1c60b9acSAndroid Build Coastguard Worker             break;
597*1c60b9acSAndroid Build Coastguard Worker 
598*1c60b9acSAndroid Build Coastguard Worker         case DONE:
599*1c60b9acSAndroid Build Coastguard Worker             /* inflate stream terminated properly -- write leftover output */
600*1c60b9acSAndroid Build Coastguard Worker             ret = Z_STREAM_END;
601*1c60b9acSAndroid Build Coastguard Worker             if (left < state->wsize) {
602*1c60b9acSAndroid Build Coastguard Worker                 if (out(out_desc, state->window, state->wsize - left))
603*1c60b9acSAndroid Build Coastguard Worker                     ret = Z_BUF_ERROR;
604*1c60b9acSAndroid Build Coastguard Worker             }
605*1c60b9acSAndroid Build Coastguard Worker             goto inf_leave;
606*1c60b9acSAndroid Build Coastguard Worker 
607*1c60b9acSAndroid Build Coastguard Worker         case BAD:
608*1c60b9acSAndroid Build Coastguard Worker             ret = Z_DATA_ERROR;
609*1c60b9acSAndroid Build Coastguard Worker             goto inf_leave;
610*1c60b9acSAndroid Build Coastguard Worker 
611*1c60b9acSAndroid Build Coastguard Worker         default:                /* can't happen, but makes compilers happy */
612*1c60b9acSAndroid Build Coastguard Worker             ret = Z_STREAM_ERROR;
613*1c60b9acSAndroid Build Coastguard Worker             goto inf_leave;
614*1c60b9acSAndroid Build Coastguard Worker         }
615*1c60b9acSAndroid Build Coastguard Worker 
616*1c60b9acSAndroid Build Coastguard Worker     /* Return unused input */
617*1c60b9acSAndroid Build Coastguard Worker   inf_leave:
618*1c60b9acSAndroid Build Coastguard Worker     strm->next_in = next;
619*1c60b9acSAndroid Build Coastguard Worker     strm->avail_in = have;
620*1c60b9acSAndroid Build Coastguard Worker     return ret;
621*1c60b9acSAndroid Build Coastguard Worker }
622*1c60b9acSAndroid Build Coastguard Worker 
inflateBackEnd(strm)623*1c60b9acSAndroid Build Coastguard Worker int ZEXPORT inflateBackEnd(strm)
624*1c60b9acSAndroid Build Coastguard Worker z_streamp strm;
625*1c60b9acSAndroid Build Coastguard Worker {
626*1c60b9acSAndroid Build Coastguard Worker     if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
627*1c60b9acSAndroid Build Coastguard Worker         return Z_STREAM_ERROR;
628*1c60b9acSAndroid Build Coastguard Worker     ZFREE(strm, strm->state);
629*1c60b9acSAndroid Build Coastguard Worker     strm->state = Z_NULL;
630*1c60b9acSAndroid Build Coastguard Worker     Tracev((stderr, "inflate: end\n"));
631*1c60b9acSAndroid Build Coastguard Worker     return Z_OK;
632*1c60b9acSAndroid Build Coastguard Worker }
633