source: trunk/third/zlib/inflate.c @ 15211

Revision 15211, 9.4 KB checked in by ghudson, 24 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r15210, which included commits to RCS files with non-trunk default branches.
Line 
1/* inflate.c -- zlib interface to inflate modules
2 * Copyright (C) 1995-1998 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
9struct inflate_blocks_state {int dummy;}; /* for buggy compilers */
10
11typedef enum {
12      METHOD,   /* waiting for method byte */
13      FLAG,     /* waiting for flag byte */
14      DICT4,    /* four dictionary check bytes to go */
15      DICT3,    /* three dictionary check bytes to go */
16      DICT2,    /* two dictionary check bytes to go */
17      DICT1,    /* one dictionary check byte to go */
18      DICT0,    /* waiting for inflateSetDictionary */
19      BLOCKS,   /* decompressing blocks */
20      CHECK4,   /* four check bytes to go */
21      CHECK3,   /* three check bytes to go */
22      CHECK2,   /* two check bytes to go */
23      CHECK1,   /* one check byte to go */
24      DONE,     /* finished check, done */
25      BAD}      /* got an error--stay here */
26inflate_mode;
27
28/* inflate private state */
29struct internal_state {
30
31  /* mode */
32  inflate_mode  mode;   /* current inflate mode */
33
34  /* mode dependent information */
35  union {
36    uInt method;        /* if FLAGS, method byte */
37    struct {
38      uLong was;                /* computed check value */
39      uLong need;               /* stream check value */
40    } check;            /* if CHECK, check values to compare */
41    uInt marker;        /* if BAD, inflateSync's marker bytes count */
42  } sub;        /* submode */
43
44  /* mode independent information */
45  int  nowrap;          /* flag for no wrapper */
46  uInt wbits;           /* log2(window size)  (8..15, defaults to 15) */
47  inflate_blocks_statef
48    *blocks;            /* current inflate_blocks state */
49
50};
51
52
53int ZEXPORT inflateReset(z)
54z_streamp z;
55{
56  if (z == Z_NULL || z->state == Z_NULL)
57    return Z_STREAM_ERROR;
58  z->total_in = z->total_out = 0;
59  z->msg = Z_NULL;
60  z->state->mode = z->state->nowrap ? BLOCKS : METHOD;
61  inflate_blocks_reset(z->state->blocks, z, Z_NULL);
62  Tracev((stderr, "inflate: reset\n"));
63  return Z_OK;
64}
65
66
67int ZEXPORT inflateEnd(z)
68z_streamp z;
69{
70  if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL)
71    return Z_STREAM_ERROR;
72  if (z->state->blocks != Z_NULL)
73    inflate_blocks_free(z->state->blocks, z);
74  ZFREE(z, z->state);
75  z->state = Z_NULL;
76  Tracev((stderr, "inflate: end\n"));
77  return Z_OK;
78}
79
80
81int ZEXPORT inflateInit2_(z, w, version, stream_size)
82z_streamp z;
83int w;
84const char *version;
85int stream_size;
86{
87  if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
88      stream_size != sizeof(z_stream))
89      return Z_VERSION_ERROR;
90
91  /* initialize state */
92  if (z == Z_NULL)
93    return Z_STREAM_ERROR;
94  z->msg = Z_NULL;
95  if (z->zalloc == Z_NULL)
96  {
97    z->zalloc = zcalloc;
98    z->opaque = (voidpf)0;
99  }
100  if (z->zfree == Z_NULL) z->zfree = zcfree;
101  if ((z->state = (struct internal_state FAR *)
102       ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL)
103    return Z_MEM_ERROR;
104  z->state->blocks = Z_NULL;
105
106  /* handle undocumented nowrap option (no zlib header or check) */
107  z->state->nowrap = 0;
108  if (w < 0)
109  {
110    w = - w;
111    z->state->nowrap = 1;
112  }
113
114  /* set window size */
115  if (w < 8 || w > 15)
116  {
117    inflateEnd(z);
118    return Z_STREAM_ERROR;
119  }
120  z->state->wbits = (uInt)w;
121
122  /* create inflate_blocks state */
123  if ((z->state->blocks =
124      inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w))
125      == Z_NULL)
126  {
127    inflateEnd(z);
128    return Z_MEM_ERROR;
129  }
130  Tracev((stderr, "inflate: allocated\n"));
131
132  /* reset state */
133  inflateReset(z);
134  return Z_OK;
135}
136
137
138int ZEXPORT inflateInit_(z, version, stream_size)
139z_streamp z;
140const char *version;
141int stream_size;
142{
143  return inflateInit2_(z, DEF_WBITS, version, stream_size);
144}
145
146
147#define NEEDBYTE {if(z->avail_in==0)return r;r=f;}
148#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++)
149
150int ZEXPORT inflate(z, f)
151z_streamp z;
152int f;
153{
154  int r;
155  uInt b;
156
157  if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL)
158    return Z_STREAM_ERROR;
159  f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK;
160  r = Z_BUF_ERROR;
161  while (1) switch (z->state->mode)
162  {
163    case METHOD:
164      NEEDBYTE
165      if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED)
166      {
167        z->state->mode = BAD;
168        z->msg = (char*)"unknown compression method";
169        z->state->sub.marker = 5;       /* can't try inflateSync */
170        break;
171      }
172      if ((z->state->sub.method >> 4) + 8 > z->state->wbits)
173      {
174        z->state->mode = BAD;
175        z->msg = (char*)"invalid window size";
176        z->state->sub.marker = 5;       /* can't try inflateSync */
177        break;
178      }
179      z->state->mode = FLAG;
180    case FLAG:
181      NEEDBYTE
182      b = NEXTBYTE;
183      if (((z->state->sub.method << 8) + b) % 31)
184      {
185        z->state->mode = BAD;
186        z->msg = (char*)"incorrect header check";
187        z->state->sub.marker = 5;       /* can't try inflateSync */
188        break;
189      }
190      Tracev((stderr, "inflate: zlib header ok\n"));
191      if (!(b & PRESET_DICT))
192      {
193        z->state->mode = BLOCKS;
194        break;
195      }
196      z->state->mode = DICT4;
197    case DICT4:
198      NEEDBYTE
199      z->state->sub.check.need = (uLong)NEXTBYTE << 24;
200      z->state->mode = DICT3;
201    case DICT3:
202      NEEDBYTE
203      z->state->sub.check.need += (uLong)NEXTBYTE << 16;
204      z->state->mode = DICT2;
205    case DICT2:
206      NEEDBYTE
207      z->state->sub.check.need += (uLong)NEXTBYTE << 8;
208      z->state->mode = DICT1;
209    case DICT1:
210      NEEDBYTE
211      z->state->sub.check.need += (uLong)NEXTBYTE;
212      z->adler = z->state->sub.check.need;
213      z->state->mode = DICT0;
214      return Z_NEED_DICT;
215    case DICT0:
216      z->state->mode = BAD;
217      z->msg = (char*)"need dictionary";
218      z->state->sub.marker = 0;       /* can try inflateSync */
219      return Z_STREAM_ERROR;
220    case BLOCKS:
221      r = inflate_blocks(z->state->blocks, z, r);
222      if (r == Z_DATA_ERROR)
223      {
224        z->state->mode = BAD;
225        z->state->sub.marker = 0;       /* can try inflateSync */
226        break;
227      }
228      if (r == Z_OK)
229        r = f;
230      if (r != Z_STREAM_END)
231        return r;
232      r = f;
233      inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was);
234      if (z->state->nowrap)
235      {
236        z->state->mode = DONE;
237        break;
238      }
239      z->state->mode = CHECK4;
240    case CHECK4:
241      NEEDBYTE
242      z->state->sub.check.need = (uLong)NEXTBYTE << 24;
243      z->state->mode = CHECK3;
244    case CHECK3:
245      NEEDBYTE
246      z->state->sub.check.need += (uLong)NEXTBYTE << 16;
247      z->state->mode = CHECK2;
248    case CHECK2:
249      NEEDBYTE
250      z->state->sub.check.need += (uLong)NEXTBYTE << 8;
251      z->state->mode = CHECK1;
252    case CHECK1:
253      NEEDBYTE
254      z->state->sub.check.need += (uLong)NEXTBYTE;
255
256      if (z->state->sub.check.was != z->state->sub.check.need)
257      {
258        z->state->mode = BAD;
259        z->msg = (char*)"incorrect data check";
260        z->state->sub.marker = 5;       /* can't try inflateSync */
261        break;
262      }
263      Tracev((stderr, "inflate: zlib check ok\n"));
264      z->state->mode = DONE;
265    case DONE:
266      return Z_STREAM_END;
267    case BAD:
268      return Z_DATA_ERROR;
269    default:
270      return Z_STREAM_ERROR;
271  }
272#ifdef NEED_DUMMY_RETURN
273  return Z_STREAM_ERROR;  /* Some dumb compilers complain without this */
274#endif
275}
276
277
278int ZEXPORT inflateSetDictionary(z, dictionary, dictLength)
279z_streamp z;
280const Bytef *dictionary;
281uInt  dictLength;
282{
283  uInt length = dictLength;
284
285  if (z == Z_NULL || z->state == Z_NULL || z->state->mode != DICT0)
286    return Z_STREAM_ERROR;
287
288  if (adler32(1L, dictionary, dictLength) != z->adler) return Z_DATA_ERROR;
289  z->adler = 1L;
290
291  if (length >= ((uInt)1<<z->state->wbits))
292  {
293    length = (1<<z->state->wbits)-1;
294    dictionary += dictLength - length;
295  }
296  inflate_set_dictionary(z->state->blocks, dictionary, length);
297  z->state->mode = BLOCKS;
298  return Z_OK;
299}
300
301
302int ZEXPORT inflateSync(z)
303z_streamp z;
304{
305  uInt n;       /* number of bytes to look at */
306  Bytef *p;     /* pointer to bytes */
307  uInt m;       /* number of marker bytes found in a row */
308  uLong r, w;   /* temporaries to save total_in and total_out */
309
310  /* set up */
311  if (z == Z_NULL || z->state == Z_NULL)
312    return Z_STREAM_ERROR;
313  if (z->state->mode != BAD)
314  {
315    z->state->mode = BAD;
316    z->state->sub.marker = 0;
317  }
318  if ((n = z->avail_in) == 0)
319    return Z_BUF_ERROR;
320  p = z->next_in;
321  m = z->state->sub.marker;
322
323  /* search */
324  while (n && m < 4)
325  {
326    static const Byte mark[4] = {0, 0, 0xff, 0xff};
327    if (*p == mark[m])
328      m++;
329    else if (*p)
330      m = 0;
331    else
332      m = 4 - m;
333    p++, n--;
334  }
335
336  /* restore */
337  z->total_in += p - z->next_in;
338  z->next_in = p;
339  z->avail_in = n;
340  z->state->sub.marker = m;
341
342  /* return no joy or set up to restart on a new block */
343  if (m != 4)
344    return Z_DATA_ERROR;
345  r = z->total_in;  w = z->total_out;
346  inflateReset(z);
347  z->total_in = r;  z->total_out = w;
348  z->state->mode = BLOCKS;
349  return Z_OK;
350}
351
352
353/* Returns true if inflate is currently at the end of a block generated
354 * by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
355 * implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH
356 * but removes the length bytes of the resulting empty stored block. When
357 * decompressing, PPP checks that at the end of input packet, inflate is
358 * waiting for these length bytes.
359 */
360int ZEXPORT inflateSyncPoint(z)
361z_streamp z;
362{
363  if (z == Z_NULL || z->state == Z_NULL || z->state->blocks == Z_NULL)
364    return Z_STREAM_ERROR;
365  return inflate_blocks_sync_point(z->state->blocks);
366}
Note: See TracBrowser for help on using the repository browser.