blob: ea5619463046b160a9cb074f2c580045debfc416 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3 *
4 * This code is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 2 only, as
6 * published by the Free Software Foundation. Sun designates this
7 * particular file as subject to the "Classpath" exception as provided
8 * by Sun in the LICENSE file that accompanied this code.
9 *
10 * This code is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21 * CA 95054 USA or visit www.sun.com if you need additional information or
22 * have any questions.
23 */
24
25/*
26 * This file is available under and governed by the GNU General Public
27 * License version 2 only, as published by the Free Software Foundation.
28 * However, the following notice accompanied the original version of this
29 * file and, per its terms, should not be removed:
30 *
31 * infcodes.c -- process literals and length/distance pairs
32 * Copyright (C) 1995-1998 Mark Adler
33 * For conditions of distribution and use, see copyright notice in zlib.h
34 */
35
36#include "zutil.h"
37#include "inftrees.h"
38#include "infblock.h"
39#include "infcodes.h"
40#include "infutil.h"
41#include "inffast.h"
42
43/* simplify the use of the inflate_huft type with some defines */
44#define exop word.what.Exop
45#define bits word.what.Bits
46
47typedef enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
48 START, /* x: set up for LEN */
49 LEN, /* i: get length/literal/eob next */
50 LENEXT, /* i: getting length extra (have base) */
51 DIST, /* i: get distance next */
52 DISTEXT, /* i: getting distance extra */
53 COPY, /* o: copying bytes in window, waiting for space */
54 LIT, /* o: got literal, waiting for output space */
55 WASH, /* o: got eob, possibly still output waiting */
56 END, /* x: got eob and all data flushed */
57 BADCODE} /* x: got error */
58inflate_codes_mode;
59
60/* inflate codes private state */
61struct inflate_codes_state {
62
63 /* mode */
64 inflate_codes_mode mode; /* current inflate_codes mode */
65
66 /* mode dependent information */
67 uInt len;
68 union {
69 struct {
70 inflate_huft *tree; /* pointer into tree */
71 uInt need; /* bits needed */
72 } code; /* if LEN or DIST, where in tree */
73 uInt lit; /* if LIT, literal */
74 struct {
75 uInt get; /* bits to get for extra */
76 uInt dist; /* distance back to copy from */
77 } copy; /* if EXT or COPY, where and how much */
78 } sub; /* submode */
79
80 /* mode independent information */
81 Byte lbits; /* ltree bits decoded per branch */
82 Byte dbits; /* dtree bits decoder per branch */
83 inflate_huft *ltree; /* literal/length/eob tree */
84 inflate_huft *dtree; /* distance tree */
85
86};
87
88
89inflate_codes_statef *inflate_codes_new(bl, bd, tl, td, z)
90uInt bl, bd;
91inflate_huft *tl;
92inflate_huft *td; /* need separate declaration for Borland C++ */
93z_streamp z;
94{
95 inflate_codes_statef *c;
96
97 if ((c = (inflate_codes_statef *)
98 ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL)
99 {
100 c->mode = START;
101 c->lbits = (Byte)bl;
102 c->dbits = (Byte)bd;
103 c->ltree = tl;
104 c->dtree = td;
105 Tracev((stderr, "inflate: codes new\n"));
106 }
107 return c;
108}
109
110
111int inflate_codes(s, z, r)
112inflate_blocks_statef *s;
113z_streamp z;
114int r;
115{
116 uInt j; /* temporary storage */
117 inflate_huft *t; /* temporary pointer */
118 uInt e; /* extra bits or operation */
119 uLong b; /* bit buffer */
120 uInt k; /* bits in bit buffer */
121 Bytef *p; /* input data pointer */
122 uInt n; /* bytes available there */
123 Bytef *q; /* output window write pointer */
124 uInt m; /* bytes to end of window or read pointer */
125 Bytef *f; /* pointer to copy strings from */
126 inflate_codes_statef *c = s->sub.decode.codes; /* codes state */
127
128 /* copy input/output information to locals (UPDATE macro restores) */
129 LOAD
130
131 /* process input and output based on current state */
132 while (1) switch (c->mode)
133 { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
134 case START: /* x: set up for LEN */
135#ifndef SLOW
136 if (m >= 258 && n >= 10)
137 {
138 UPDATE
139 r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z);
140 LOAD
141 if (r != Z_OK)
142 {
143 c->mode = r == Z_STREAM_END ? WASH : BADCODE;
144 break;
145 }
146 }
147#endif /* !SLOW */
148 c->sub.code.need = c->lbits;
149 c->sub.code.tree = c->ltree;
150 c->mode = LEN;
151 case LEN: /* i: get length/literal/eob next */
152 j = c->sub.code.need;
153 NEEDBITS(j)
154 t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
155 DUMPBITS(t->bits)
156 e = (uInt)(t->exop);
157 if (e == 0) /* literal */
158 {
159 c->sub.lit = t->base;
160 Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
161 "inflate: literal '%c'\n" :
162 "inflate: literal 0x%02x\n", t->base));
163 c->mode = LIT;
164 break;
165 }
166 if (e & 16) /* length */
167 {
168 c->sub.copy.get = e & 15;
169 c->len = t->base;
170 c->mode = LENEXT;
171 break;
172 }
173 if ((e & 64) == 0) /* next table */
174 {
175 c->sub.code.need = e;
176 c->sub.code.tree = t + t->base;
177 break;
178 }
179 if (e & 32) /* end of block */
180 {
181 Tracevv((stderr, "inflate: end of block\n"));
182 c->mode = WASH;
183 break;
184 }
185 c->mode = BADCODE; /* invalid code */
186 z->msg = (char*)"invalid literal/length code";
187 r = Z_DATA_ERROR;
188 LEAVE
189 case LENEXT: /* i: getting length extra (have base) */
190 j = c->sub.copy.get;
191 NEEDBITS(j)
192 c->len += (uInt)b & inflate_mask[j];
193 DUMPBITS(j)
194 c->sub.code.need = c->dbits;
195 c->sub.code.tree = c->dtree;
196 Tracevv((stderr, "inflate: length %u\n", c->len));
197 c->mode = DIST;
198 case DIST: /* i: get distance next */
199 j = c->sub.code.need;
200 NEEDBITS(j)
201 t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
202 DUMPBITS(t->bits)
203 e = (uInt)(t->exop);
204 if (e & 16) /* distance */
205 {
206 c->sub.copy.get = e & 15;
207 c->sub.copy.dist = t->base;
208 c->mode = DISTEXT;
209 break;
210 }
211 if ((e & 64) == 0) /* next table */
212 {
213 c->sub.code.need = e;
214 c->sub.code.tree = t + t->base;
215 break;
216 }
217 c->mode = BADCODE; /* invalid code */
218 z->msg = (char*)"invalid distance code";
219 r = Z_DATA_ERROR;
220 LEAVE
221 case DISTEXT: /* i: getting distance extra */
222 j = c->sub.copy.get;
223 NEEDBITS(j)
224 c->sub.copy.dist += (uInt)b & inflate_mask[j];
225 DUMPBITS(j)
226 Tracevv((stderr, "inflate: distance %u\n", c->sub.copy.dist));
227 c->mode = COPY;
228 case COPY: /* o: copying bytes in window, waiting for space */
229#ifndef __TURBOC__ /* Turbo C bug for following expression */
230 f = (uInt)(q - s->window) < c->sub.copy.dist ?
231 s->end - (c->sub.copy.dist - (q - s->window)) :
232 q - c->sub.copy.dist;
233#else
234 f = q - c->sub.copy.dist;
235 if ((uInt)(q - s->window) < c->sub.copy.dist)
236 f = s->end - (c->sub.copy.dist - (uInt)(q - s->window));
237#endif
238 while (c->len)
239 {
240 NEEDOUT
241 OUTBYTE(*f++)
242 if (f == s->end)
243 f = s->window;
244 c->len--;
245 }
246 c->mode = START;
247 break;
248 case LIT: /* o: got literal, waiting for output space */
249 NEEDOUT
250 OUTBYTE(c->sub.lit)
251 c->mode = START;
252 break;
253 case WASH: /* o: got eob, possibly more output */
254 if (k > 7) /* return unused byte, if any */
255 {
256 Assert(k < 16, "inflate_codes grabbed too many bytes")
257 k -= 8;
258 n++;
259 p--; /* can always return one */
260 }
261 FLUSH
262 if (s->read != s->write)
263 LEAVE
264 c->mode = END;
265 case END:
266 r = Z_STREAM_END;
267 LEAVE
268 case BADCODE: /* x: got error */
269 r = Z_DATA_ERROR;
270 LEAVE
271 default:
272 r = Z_STREAM_ERROR;
273 LEAVE
274 }
275#ifdef NEED_DUMMY_RETURN
276 return Z_STREAM_ERROR; /* Some dumb compilers complain without this */
277#endif
278}
279
280
281void inflate_codes_free(c, z)
282inflate_codes_statef *c;
283z_streamp z;
284{
285 ZFREE(z, c);
286 Tracev((stderr, "inflate: codes free\n"));
287}