Mercurial > ~darius > hgwebdir.cgi > paradise_client
comparison zlib/inflate.c @ 3:5a977ccbc7a9 default tip
Empty changelog
author | darius |
---|---|
date | Sat, 06 Dec 1997 05:41:29 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
2:fba0b6e6cdc7 | 3:5a977ccbc7a9 |
---|---|
1 /* inflate.c -- zlib interface to inflate modules | |
2 * Copyright (C) 1995 Mark Adler | |
3 * For conditions of distribution and use, see copyright notice in zlib.h | |
4 */ | |
5 | |
6 #include "zutil.h" | |
7 #include "infblock.h" | |
8 | |
9 struct inflate_blocks_state {int dummy;}; /* for buggy compilers */ | |
10 | |
11 /* inflate private state */ | |
12 struct internal_state { | |
13 | |
14 /* mode */ | |
15 enum { | |
16 METHOD, /* waiting for method byte */ | |
17 FLAG, /* waiting for flag byte */ | |
18 BLOCKS, /* decompressing blocks */ | |
19 CHECK4, /* four check bytes to go */ | |
20 CHECK3, /* three check bytes to go */ | |
21 CHECK2, /* two check bytes to go */ | |
22 CHECK1, /* one check byte to go */ | |
23 DONE, /* finished check, done */ | |
24 BAD} /* got an error--stay here */ | |
25 mode; /* current inflate mode */ | |
26 | |
27 /* mode dependent information */ | |
28 union { | |
29 uInt method; /* if FLAGS, method byte */ | |
30 struct { | |
31 uLong was; /* computed check value */ | |
32 uLong need; /* stream check value */ | |
33 } check; /* if CHECK, check values to compare */ | |
34 uInt marker; /* if BAD, inflateSync's marker bytes count */ | |
35 } sub; /* submode */ | |
36 | |
37 /* mode independent information */ | |
38 int nowrap; /* flag for no wrapper */ | |
39 uInt wbits; /* log2(window size) (8..15, defaults to 15) */ | |
40 struct inflate_blocks_state | |
41 *blocks; /* current inflate_blocks state */ | |
42 | |
43 }; | |
44 | |
45 | |
46 int inflateReset(z) | |
47 z_stream *z; | |
48 { | |
49 uLong c; | |
50 | |
51 if (z == Z_NULL || z->state == Z_NULL) | |
52 return Z_STREAM_ERROR; | |
53 z->total_in = z->total_out = 0; | |
54 z->msg = Z_NULL; | |
55 z->state->mode = z->state->nowrap ? BLOCKS : METHOD; | |
56 inflate_blocks_reset(z->state->blocks, z, &c); | |
57 Trace((stderr, "inflate: reset\n")); | |
58 return Z_OK; | |
59 } | |
60 | |
61 | |
62 int inflateEnd(z) | |
63 z_stream *z; | |
64 { | |
65 uLong c; | |
66 | |
67 if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL) | |
68 return Z_STREAM_ERROR; | |
69 if (z->state->blocks != Z_NULL) | |
70 inflate_blocks_free(z->state->blocks, z, &c); | |
71 ZFREE(z, z->state); | |
72 z->state = Z_NULL; | |
73 Trace((stderr, "inflate: end\n")); | |
74 return Z_OK; | |
75 } | |
76 | |
77 | |
78 int inflateInit2(z, w) | |
79 z_stream *z; | |
80 int w; | |
81 { | |
82 /* initialize state */ | |
83 if (z == Z_NULL) | |
84 return Z_STREAM_ERROR; | |
85 if (z->zalloc == Z_NULL) z->zalloc = zcalloc; | |
86 if (z->zfree == Z_NULL) z->zfree = zcfree; | |
87 if ((z->state = (struct internal_state *) | |
88 ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL) | |
89 return Z_MEM_ERROR; | |
90 z->state->blocks = Z_NULL; | |
91 | |
92 /* handle undocumented nowrap option (no zlib header or check) */ | |
93 z->state->nowrap = 0; | |
94 if (w < 0) | |
95 { | |
96 w = - w; | |
97 z->state->nowrap = 1; | |
98 } | |
99 | |
100 /* set window size */ | |
101 if (w < 8 || w > 15) | |
102 { | |
103 inflateEnd(z); | |
104 return Z_STREAM_ERROR; | |
105 } | |
106 z->state->wbits = (uInt)w; | |
107 | |
108 /* create inflate_blocks state */ | |
109 if ((z->state->blocks = | |
110 inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, 1 << w)) | |
111 == Z_NULL) | |
112 { | |
113 inflateEnd(z); | |
114 return Z_MEM_ERROR; | |
115 } | |
116 Trace((stderr, "inflate: allocated\n")); | |
117 | |
118 /* reset state */ | |
119 inflateReset(z); | |
120 return Z_OK; | |
121 } | |
122 | |
123 | |
124 int inflateInit(z) | |
125 z_stream *z; | |
126 { | |
127 return inflateInit2(z, DEF_WBITS); | |
128 } | |
129 | |
130 | |
131 #define NEEDBYTE {if(z->avail_in==0)return r;r=Z_OK;} | |
132 #define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++) | |
133 | |
134 int inflate(z, f) | |
135 z_stream *z; | |
136 int f; | |
137 { | |
138 int r = f; /* to avoid warning about unused f */ | |
139 uInt b; | |
140 | |
141 if (z == Z_NULL || z->next_in == Z_NULL) | |
142 return Z_STREAM_ERROR; | |
143 r = Z_BUF_ERROR; | |
144 while (1) switch (z->state->mode) | |
145 { | |
146 case METHOD: | |
147 NEEDBYTE | |
148 if (((z->state->sub.method = NEXTBYTE) & 0xf) != DEFLATED) | |
149 { | |
150 z->state->mode = BAD; | |
151 z->msg = "unknown compression method"; | |
152 z->state->sub.marker = 5; /* can't try inflateSync */ | |
153 break; | |
154 } | |
155 if ((z->state->sub.method >> 4) + 8 > z->state->wbits) | |
156 { | |
157 z->state->mode = BAD; | |
158 z->msg = "invalid window size"; | |
159 z->state->sub.marker = 5; /* can't try inflateSync */ | |
160 break; | |
161 } | |
162 z->state->mode = FLAG; | |
163 case FLAG: | |
164 NEEDBYTE | |
165 if ((b = NEXTBYTE) & 0x20) | |
166 { | |
167 z->state->mode = BAD; | |
168 z->msg = "invalid reserved bit"; | |
169 z->state->sub.marker = 5; /* can't try inflateSync */ | |
170 break; | |
171 } | |
172 if (((z->state->sub.method << 8) + b) % 31) | |
173 { | |
174 z->state->mode = BAD; | |
175 z->msg = "incorrect header check"; | |
176 z->state->sub.marker = 5; /* can't try inflateSync */ | |
177 break; | |
178 } | |
179 Trace((stderr, "inflate: zlib header ok\n")); | |
180 z->state->mode = BLOCKS; | |
181 case BLOCKS: | |
182 r = inflate_blocks(z->state->blocks, z, r); | |
183 if (r == Z_DATA_ERROR) | |
184 { | |
185 z->state->mode = BAD; | |
186 z->state->sub.marker = 0; /* can try inflateSync */ | |
187 break; | |
188 } | |
189 if (r != Z_STREAM_END) | |
190 return r; | |
191 r = Z_OK; | |
192 inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was); | |
193 if (z->state->nowrap) | |
194 { | |
195 z->state->mode = DONE; | |
196 break; | |
197 } | |
198 z->state->mode = CHECK4; | |
199 case CHECK4: | |
200 NEEDBYTE | |
201 z->state->sub.check.need = (uLong)NEXTBYTE << 24; | |
202 z->state->mode = CHECK3; | |
203 case CHECK3: | |
204 NEEDBYTE | |
205 z->state->sub.check.need += (uLong)NEXTBYTE << 16; | |
206 z->state->mode = CHECK2; | |
207 case CHECK2: | |
208 NEEDBYTE | |
209 z->state->sub.check.need += (uLong)NEXTBYTE << 8; | |
210 z->state->mode = CHECK1; | |
211 case CHECK1: | |
212 NEEDBYTE | |
213 z->state->sub.check.need += (uLong)NEXTBYTE; | |
214 | |
215 if (z->state->sub.check.was != z->state->sub.check.need) | |
216 { | |
217 z->state->mode = BAD; | |
218 z->msg = "incorrect data check"; | |
219 z->state->sub.marker = 5; /* can't try inflateSync */ | |
220 break; | |
221 } | |
222 Trace((stderr, "inflate: zlib check ok\n")); | |
223 z->state->mode = DONE; | |
224 case DONE: | |
225 return Z_STREAM_END; | |
226 case BAD: | |
227 return Z_DATA_ERROR; | |
228 default: | |
229 return Z_STREAM_ERROR; | |
230 } | |
231 } | |
232 | |
233 | |
234 int inflateSync(z) | |
235 z_stream *z; | |
236 { | |
237 uInt n; /* number of bytes to look at */ | |
238 Byte *p; /* pointer to bytes */ | |
239 uInt m; /* number of marker bytes found in a row */ | |
240 uLong r, w; /* temporaries to save total_in and total_out */ | |
241 | |
242 /* set up */ | |
243 if (z == Z_NULL || z->state == Z_NULL) | |
244 return Z_STREAM_ERROR; | |
245 if (z->state->mode != BAD) | |
246 { | |
247 z->state->mode = BAD; | |
248 z->state->sub.marker = 0; | |
249 } | |
250 if ((n = z->avail_in) == 0) | |
251 return Z_BUF_ERROR; | |
252 p = z->next_in; | |
253 m = z->state->sub.marker; | |
254 | |
255 /* search */ | |
256 while (n && m < 4) | |
257 { | |
258 if (*p == (Byte)(m < 2 ? 0 : 0xff)) | |
259 m++; | |
260 else if (*p) | |
261 m = 0; | |
262 else | |
263 m = 4 - m; | |
264 p++, n--; | |
265 } | |
266 | |
267 /* restore */ | |
268 z->total_in += p - z->next_in; | |
269 z->next_in = p; | |
270 z->avail_in = n; | |
271 z->state->sub.marker = m; | |
272 | |
273 /* return no joy or set up to restart on a new block */ | |
274 if (m != 4) | |
275 return Z_DATA_ERROR; | |
276 r = z->total_in; w = z->total_out; | |
277 inflateReset(z); | |
278 z->total_in = r; z->total_out = w; | |
279 z->state->mode = BLOCKS; | |
280 return Z_OK; | |
281 } |