1*37da2899SCharles.Forsyth /* infcodes.c -- process literals and length/distance pairs
2*37da2899SCharles.Forsyth * Copyright (C) 1995-2002 Mark Adler
3*37da2899SCharles.Forsyth * For conditions of distribution and use, see copyright notice in zlib.h
4*37da2899SCharles.Forsyth */
5*37da2899SCharles.Forsyth
6*37da2899SCharles.Forsyth #include "zutil.h"
7*37da2899SCharles.Forsyth #include "inftrees.h"
8*37da2899SCharles.Forsyth #include "infblock.h"
9*37da2899SCharles.Forsyth #include "infcodes.h"
10*37da2899SCharles.Forsyth #include "infutil.h"
11*37da2899SCharles.Forsyth
12*37da2899SCharles.Forsyth /* simplify the use of the inflate_huft type with some defines */
13*37da2899SCharles.Forsyth #define exop word.what.Exop
14*37da2899SCharles.Forsyth #define bits word.what.Bits
15*37da2899SCharles.Forsyth
16*37da2899SCharles.Forsyth typedef enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
17*37da2899SCharles.Forsyth START, /* x: set up for LEN */
18*37da2899SCharles.Forsyth LEN, /* i: get length/literal/eob next */
19*37da2899SCharles.Forsyth LENEXT, /* i: getting length extra (have base) */
20*37da2899SCharles.Forsyth DIST, /* i: get distance next */
21*37da2899SCharles.Forsyth DISTEXT, /* i: getting distance extra */
22*37da2899SCharles.Forsyth COPY, /* o: copying bytes in window, waiting for space */
23*37da2899SCharles.Forsyth LIT, /* o: got literal, waiting for output space */
24*37da2899SCharles.Forsyth WASH, /* o: got eob, possibly still output waiting */
25*37da2899SCharles.Forsyth END, /* x: got eob and all data flushed */
26*37da2899SCharles.Forsyth BADCODE} /* x: got error */
27*37da2899SCharles.Forsyth inflate_codes_mode;
28*37da2899SCharles.Forsyth
29*37da2899SCharles.Forsyth /* inflate codes private state */
30*37da2899SCharles.Forsyth struct inflate_codes_state {
31*37da2899SCharles.Forsyth
32*37da2899SCharles.Forsyth /* mode */
33*37da2899SCharles.Forsyth inflate_codes_mode mode; /* current inflate_codes mode */
34*37da2899SCharles.Forsyth
35*37da2899SCharles.Forsyth /* mode dependent information */
36*37da2899SCharles.Forsyth uInt len;
37*37da2899SCharles.Forsyth union {
38*37da2899SCharles.Forsyth struct {
39*37da2899SCharles.Forsyth inflate_huft *tree; /* pointer into tree */
40*37da2899SCharles.Forsyth uInt need; /* bits needed */
41*37da2899SCharles.Forsyth } code; /* if LEN or DIST, where in tree */
42*37da2899SCharles.Forsyth uInt lit; /* if LIT, literal */
43*37da2899SCharles.Forsyth struct {
44*37da2899SCharles.Forsyth uInt get; /* bits to get for extra */
45*37da2899SCharles.Forsyth uInt dist; /* distance back to copy from */
46*37da2899SCharles.Forsyth } copy; /* if EXT or COPY, where and how much */
47*37da2899SCharles.Forsyth } sub; /* submode */
48*37da2899SCharles.Forsyth
49*37da2899SCharles.Forsyth /* mode independent information */
50*37da2899SCharles.Forsyth Byte lbits; /* ltree bits decoded per branch */
51*37da2899SCharles.Forsyth Byte dbits; /* dtree bits decoder per branch */
52*37da2899SCharles.Forsyth inflate_huft *ltree; /* literal/length/eob tree */
53*37da2899SCharles.Forsyth inflate_huft *dtree; /* distance tree */
54*37da2899SCharles.Forsyth
55*37da2899SCharles.Forsyth };
56*37da2899SCharles.Forsyth
57*37da2899SCharles.Forsyth
inflate_codes_new(bl,bd,tl,td,z)58*37da2899SCharles.Forsyth local inflate_codes_statef *inflate_codes_new(bl, bd, tl, td, z)
59*37da2899SCharles.Forsyth uInt bl, bd;
60*37da2899SCharles.Forsyth inflate_huft *tl;
61*37da2899SCharles.Forsyth inflate_huft *td; /* need separate declaration for Borland C++ */
62*37da2899SCharles.Forsyth z_streamp z;
63*37da2899SCharles.Forsyth {
64*37da2899SCharles.Forsyth inflate_codes_statef *c;
65*37da2899SCharles.Forsyth
66*37da2899SCharles.Forsyth if ((c = (inflate_codes_statef *)
67*37da2899SCharles.Forsyth ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL)
68*37da2899SCharles.Forsyth {
69*37da2899SCharles.Forsyth c->mode = START;
70*37da2899SCharles.Forsyth c->lbits = (Byte)bl;
71*37da2899SCharles.Forsyth c->dbits = (Byte)bd;
72*37da2899SCharles.Forsyth c->ltree = tl;
73*37da2899SCharles.Forsyth c->dtree = td;
74*37da2899SCharles.Forsyth Tracev((stderr, "inflate: codes new\n"));
75*37da2899SCharles.Forsyth }
76*37da2899SCharles.Forsyth return c;
77*37da2899SCharles.Forsyth }
78*37da2899SCharles.Forsyth
79*37da2899SCharles.Forsyth
inflate_codes(s,z,r)80*37da2899SCharles.Forsyth local int inflate_codes(s, z, r)
81*37da2899SCharles.Forsyth inflate_blocks_statef *s;
82*37da2899SCharles.Forsyth z_streamp z;
83*37da2899SCharles.Forsyth int r;
84*37da2899SCharles.Forsyth {
85*37da2899SCharles.Forsyth uInt j; /* temporary storage */
86*37da2899SCharles.Forsyth inflate_huft *t; /* temporary pointer */
87*37da2899SCharles.Forsyth uInt e; /* extra bits or operation */
88*37da2899SCharles.Forsyth uLong b; /* bit buffer */
89*37da2899SCharles.Forsyth uInt k; /* bits in bit buffer */
90*37da2899SCharles.Forsyth Bytef *p; /* input data pointer */
91*37da2899SCharles.Forsyth uInt n; /* bytes available there */
92*37da2899SCharles.Forsyth Bytef *q; /* output window write pointer */
93*37da2899SCharles.Forsyth uInt m; /* bytes to end of window or read pointer */
94*37da2899SCharles.Forsyth Bytef *f; /* pointer to copy strings from */
95*37da2899SCharles.Forsyth inflate_codes_statef *c = s->sub.decode.codes; /* codes state */
96*37da2899SCharles.Forsyth
97*37da2899SCharles.Forsyth /* copy input/output information to locals (UPDATE macro restores) */
98*37da2899SCharles.Forsyth LOAD
99*37da2899SCharles.Forsyth
100*37da2899SCharles.Forsyth /* process input and output based on current state */
101*37da2899SCharles.Forsyth while (1) switch (c->mode)
102*37da2899SCharles.Forsyth { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
103*37da2899SCharles.Forsyth case START: /* x: set up for LEN */
104*37da2899SCharles.Forsyth #ifndef SLOW
105*37da2899SCharles.Forsyth if (m >= 258 && n >= 10)
106*37da2899SCharles.Forsyth {
107*37da2899SCharles.Forsyth UPDATE
108*37da2899SCharles.Forsyth r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z);
109*37da2899SCharles.Forsyth LOAD
110*37da2899SCharles.Forsyth if (r != Z_OK)
111*37da2899SCharles.Forsyth {
112*37da2899SCharles.Forsyth c->mode = r == Z_STREAM_END ? WASH : BADCODE;
113*37da2899SCharles.Forsyth break;
114*37da2899SCharles.Forsyth }
115*37da2899SCharles.Forsyth }
116*37da2899SCharles.Forsyth #endif /* !SLOW */
117*37da2899SCharles.Forsyth c->sub.code.need = c->lbits;
118*37da2899SCharles.Forsyth c->sub.code.tree = c->ltree;
119*37da2899SCharles.Forsyth c->mode = LEN;
120*37da2899SCharles.Forsyth case LEN: /* i: get length/literal/eob next */
121*37da2899SCharles.Forsyth j = c->sub.code.need;
122*37da2899SCharles.Forsyth NEEDBITS(j)
123*37da2899SCharles.Forsyth t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
124*37da2899SCharles.Forsyth DUMPBITS(t->bits)
125*37da2899SCharles.Forsyth e = (uInt)(t->exop);
126*37da2899SCharles.Forsyth if (e == 0) /* literal */
127*37da2899SCharles.Forsyth {
128*37da2899SCharles.Forsyth c->sub.lit = t->base;
129*37da2899SCharles.Forsyth Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
130*37da2899SCharles.Forsyth "inflate: literal '%c'\n" :
131*37da2899SCharles.Forsyth "inflate: literal 0x%02x\n", t->base));
132*37da2899SCharles.Forsyth c->mode = LIT;
133*37da2899SCharles.Forsyth break;
134*37da2899SCharles.Forsyth }
135*37da2899SCharles.Forsyth if (e & 16) /* length */
136*37da2899SCharles.Forsyth {
137*37da2899SCharles.Forsyth c->sub.copy.get = e & 15;
138*37da2899SCharles.Forsyth c->len = t->base;
139*37da2899SCharles.Forsyth c->mode = LENEXT;
140*37da2899SCharles.Forsyth break;
141*37da2899SCharles.Forsyth }
142*37da2899SCharles.Forsyth if ((e & 64) == 0) /* next table */
143*37da2899SCharles.Forsyth {
144*37da2899SCharles.Forsyth c->sub.code.need = e;
145*37da2899SCharles.Forsyth c->sub.code.tree = t + t->base;
146*37da2899SCharles.Forsyth break;
147*37da2899SCharles.Forsyth }
148*37da2899SCharles.Forsyth if (e & 32) /* end of block */
149*37da2899SCharles.Forsyth {
150*37da2899SCharles.Forsyth Tracevv((stderr, "inflate: end of block\n"));
151*37da2899SCharles.Forsyth c->mode = WASH;
152*37da2899SCharles.Forsyth break;
153*37da2899SCharles.Forsyth }
154*37da2899SCharles.Forsyth c->mode = BADCODE; /* invalid code */
155*37da2899SCharles.Forsyth z->msg = (char*)"invalid literal/length code";
156*37da2899SCharles.Forsyth r = Z_DATA_ERROR;
157*37da2899SCharles.Forsyth LEAVE
158*37da2899SCharles.Forsyth case LENEXT: /* i: getting length extra (have base) */
159*37da2899SCharles.Forsyth j = c->sub.copy.get;
160*37da2899SCharles.Forsyth NEEDBITS(j)
161*37da2899SCharles.Forsyth c->len += (uInt)b & inflate_mask[j];
162*37da2899SCharles.Forsyth DUMPBITS(j)
163*37da2899SCharles.Forsyth c->sub.code.need = c->dbits;
164*37da2899SCharles.Forsyth c->sub.code.tree = c->dtree;
165*37da2899SCharles.Forsyth Tracevv((stderr, "inflate: length %u\n", c->len));
166*37da2899SCharles.Forsyth c->mode = DIST;
167*37da2899SCharles.Forsyth case DIST: /* i: get distance next */
168*37da2899SCharles.Forsyth j = c->sub.code.need;
169*37da2899SCharles.Forsyth NEEDBITS(j)
170*37da2899SCharles.Forsyth t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
171*37da2899SCharles.Forsyth DUMPBITS(t->bits)
172*37da2899SCharles.Forsyth e = (uInt)(t->exop);
173*37da2899SCharles.Forsyth if (e & 16) /* distance */
174*37da2899SCharles.Forsyth {
175*37da2899SCharles.Forsyth c->sub.copy.get = e & 15;
176*37da2899SCharles.Forsyth c->sub.copy.dist = t->base;
177*37da2899SCharles.Forsyth c->mode = DISTEXT;
178*37da2899SCharles.Forsyth break;
179*37da2899SCharles.Forsyth }
180*37da2899SCharles.Forsyth if ((e & 64) == 0) /* next table */
181*37da2899SCharles.Forsyth {
182*37da2899SCharles.Forsyth c->sub.code.need = e;
183*37da2899SCharles.Forsyth c->sub.code.tree = t + t->base;
184*37da2899SCharles.Forsyth break;
185*37da2899SCharles.Forsyth }
186*37da2899SCharles.Forsyth c->mode = BADCODE; /* invalid code */
187*37da2899SCharles.Forsyth z->msg = (char*)"invalid distance code";
188*37da2899SCharles.Forsyth r = Z_DATA_ERROR;
189*37da2899SCharles.Forsyth LEAVE
190*37da2899SCharles.Forsyth case DISTEXT: /* i: getting distance extra */
191*37da2899SCharles.Forsyth j = c->sub.copy.get;
192*37da2899SCharles.Forsyth NEEDBITS(j)
193*37da2899SCharles.Forsyth c->sub.copy.dist += (uInt)b & inflate_mask[j];
194*37da2899SCharles.Forsyth DUMPBITS(j)
195*37da2899SCharles.Forsyth Tracevv((stderr, "inflate: distance %u\n", c->sub.copy.dist));
196*37da2899SCharles.Forsyth c->mode = COPY;
197*37da2899SCharles.Forsyth case COPY: /* o: copying bytes in window, waiting for space */
198*37da2899SCharles.Forsyth f = q - c->sub.copy.dist;
199*37da2899SCharles.Forsyth while (f < s->window) /* modulo window size-"while" instead */
200*37da2899SCharles.Forsyth f += s->end - s->window; /* of "if" handles invalid distances */
201*37da2899SCharles.Forsyth while (c->len)
202*37da2899SCharles.Forsyth {
203*37da2899SCharles.Forsyth NEEDOUT
204*37da2899SCharles.Forsyth OUTBYTE(*f++)
205*37da2899SCharles.Forsyth if (f == s->end)
206*37da2899SCharles.Forsyth f = s->window;
207*37da2899SCharles.Forsyth c->len--;
208*37da2899SCharles.Forsyth }
209*37da2899SCharles.Forsyth c->mode = START;
210*37da2899SCharles.Forsyth break;
211*37da2899SCharles.Forsyth case LIT: /* o: got literal, waiting for output space */
212*37da2899SCharles.Forsyth NEEDOUT
213*37da2899SCharles.Forsyth OUTBYTE(c->sub.lit)
214*37da2899SCharles.Forsyth c->mode = START;
215*37da2899SCharles.Forsyth break;
216*37da2899SCharles.Forsyth case WASH: /* o: got eob, possibly more output */
217*37da2899SCharles.Forsyth if (k > 7) /* return unused byte, if any */
218*37da2899SCharles.Forsyth {
219*37da2899SCharles.Forsyth Assert(k < 16, "inflate_codes grabbed too many bytes")
220*37da2899SCharles.Forsyth k -= 8;
221*37da2899SCharles.Forsyth n++;
222*37da2899SCharles.Forsyth p--; /* can always return one */
223*37da2899SCharles.Forsyth }
224*37da2899SCharles.Forsyth FLUSH
225*37da2899SCharles.Forsyth if (s->read != s->write)
226*37da2899SCharles.Forsyth LEAVE
227*37da2899SCharles.Forsyth c->mode = END;
228*37da2899SCharles.Forsyth case END:
229*37da2899SCharles.Forsyth r = Z_STREAM_END;
230*37da2899SCharles.Forsyth LEAVE
231*37da2899SCharles.Forsyth case BADCODE: /* x: got error */
232*37da2899SCharles.Forsyth r = Z_DATA_ERROR;
233*37da2899SCharles.Forsyth LEAVE
234*37da2899SCharles.Forsyth default:
235*37da2899SCharles.Forsyth r = Z_STREAM_ERROR;
236*37da2899SCharles.Forsyth LEAVE
237*37da2899SCharles.Forsyth }
238*37da2899SCharles.Forsyth #ifdef NEED_DUMMY_RETURN
239*37da2899SCharles.Forsyth return Z_STREAM_ERROR; /* Some dumb compilers complain without this */
240*37da2899SCharles.Forsyth #endif
241*37da2899SCharles.Forsyth }
242*37da2899SCharles.Forsyth
243*37da2899SCharles.Forsyth
inflate_codes_free(c,z)244*37da2899SCharles.Forsyth local void inflate_codes_free(c, z)
245*37da2899SCharles.Forsyth inflate_codes_statef *c;
246*37da2899SCharles.Forsyth z_streamp z;
247*37da2899SCharles.Forsyth {
248*37da2899SCharles.Forsyth ZFREE(z, c);
249*37da2899SCharles.Forsyth Tracev((stderr, "inflate: codes free\n"));
250*37da2899SCharles.Forsyth }
251