]> git.lizzy.rs Git - zlib.git/blob - inflate.c
zlib 0.79
[zlib.git] / inflate.c
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       START,    /* make new blocks state */
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       ERROR}    /* got an error--stay here */
26     mode;               /* current inflate mode */
27
28   /* mode dependent information */
29   union {
30     uInt method;        /* if FLAGS, method byte */
31     struct inflate_blocks_state
32       *blocks;          /* if BLOCKS, current state */
33     struct {
34       uLong was;                /* computed check value */
35       uLong need;               /* stream check value */
36     } check;            /* if CHECK, check values to compare */
37   } sub;        /* submode */
38
39   /* mode independent information */
40   int  nowrap;          /* flag for no wrapper */
41   uInt wbits;           /* log2(window size)  (8..15, defaults to 15) */
42
43 };
44
45
46 int inflateInit(z)
47 z_stream *z;
48 {
49     return inflateInit2(z, WBITS);
50 }
51
52
53 int inflateInit2(z, w)
54 z_stream *z;
55 int w;
56 {
57   /* initialize state */
58   if (z == Z_NULL)
59     return Z_STREAM_ERROR;
60   if (z->zalloc == Z_NULL) z->zalloc = zcalloc;
61   if (z->zfree == Z_NULL) z->zfree = zcfree;
62   z->total_in = z->total_out = 0;
63   z->msg = Z_NULL;
64   if ((z->state = (struct internal_state *)
65        ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL)
66     return Z_MEM_ERROR;
67   z->state->mode = METHOD;
68
69   /* handle undocumented nowrap option (no zlib header or check) */
70   z->state->nowrap = 0;
71   if (w < 0)
72   {
73     w = - w;
74     z->state->nowrap = 1;
75     z->state->mode = START;
76   }
77
78   /* set window size */
79   if (w < 8 || w > 15)
80   {
81     inflateEnd(z);
82     return Z_STREAM_ERROR;
83   }
84   z->state->wbits = w;
85   return Z_OK;
86 }
87
88
89 #define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++)
90
91 int inflate(z, f)
92 z_stream *z;
93 int f;
94 {
95   int r;
96   uInt b;
97   uLong c;
98
99   if (z == Z_NULL || z->next_in == Z_NULL)
100     return Z_STREAM_ERROR;
101   r = Z_BUF_ERROR;
102   while (1) switch (z->state->mode)
103   {
104     case METHOD:
105       if (z->avail_in == 0) return r;  r = Z_OK;
106       if (((z->state->sub.method = NEXTBYTE) & 0xf != DEFLATED))
107       {
108         z->state->mode = ERROR;
109         z->msg = "unknown compression method";
110         return Z_DATA_ERROR;
111       }
112       if ((z->state->sub.method >> 4) + 8 > z->state->wbits)
113       {
114         z->state->mode = ERROR;
115         z->msg = "invalid window size";
116         return Z_DATA_ERROR;
117       }
118       z->state->mode = FLAG;
119     case FLAG:
120       if (z->avail_in == 0) return r;  r = Z_OK;
121       if ((b = NEXTBYTE) & 0x20)
122       {
123         z->state->mode = ERROR;
124         z->msg = "invalid reserved bit";
125         return Z_DATA_ERROR;
126       }
127       if (((z->state->sub.method << 8) + b) % 31)
128       {
129         z->state->mode = ERROR;
130         z->msg = "incorrect header check";
131         return Z_DATA_ERROR;
132       }
133       z->state->mode = START;
134     case START:
135       if ((z->state->sub.blocks = inflate_blocks_new(z,
136          z->state->nowrap ? Z_NULL : adler32,
137          1<< z->state->wbits)) == Z_NULL)
138         return Z_MEM_ERROR;
139       z->state->mode = BLOCKS;
140     case BLOCKS:
141       if ((r = inflate_blocks(z->state->sub.blocks, z, r)) != Z_STREAM_END)
142         return r;
143       inflate_blocks_free(z->state->sub.blocks, z, &c, &r);
144       if (z->state->nowrap)
145       {
146         if (r != -1)
147           z->msg = "inflate bug--took one too many bytes";
148         z->state->mode = r == -1 ? DONE : ERROR;
149         break;
150       }
151       z->state->sub.check.was = c;
152       if (r != -1)
153       {
154         z->state->sub.check.need = (uLong)r << 24;
155         z->state->mode = CHECK3;
156         r = Z_OK;
157         break;
158       }
159       r = Z_OK;
160       z->state->mode = CHECK4;
161     case CHECK4:
162       if (z->avail_in == 0) return r;  r = Z_OK;
163       z->state->sub.check.need = (uLong)NEXTBYTE << 24;
164       z->state->mode = CHECK3;
165     case CHECK3:
166       if (z->avail_in == 0) return r;  r = Z_OK;
167       z->state->sub.check.need += (uLong)NEXTBYTE << 16;
168       z->state->mode = CHECK2;
169     case CHECK2:
170       if (z->avail_in == 0) return r;  r = Z_OK;
171       z->state->sub.check.need += (uLong)NEXTBYTE << 8;
172       z->state->mode = CHECK1;
173     case CHECK1:
174       if (z->avail_in == 0) return r;  r = Z_OK;
175       z->state->sub.check.need += (uLong)NEXTBYTE;
176       if (z->state->sub.check.was != z->state->sub.check.need)
177       {
178         z->state->mode = ERROR;
179         z->msg = "incorrect data check";
180         return Z_DATA_ERROR;
181       }
182       z->state->mode = DONE;
183     case DONE:
184       return Z_STREAM_END;
185     case ERROR:
186       return Z_DATA_ERROR;
187     default:
188       return Z_STREAM_ERROR;
189   }
190 }
191
192
193 int inflateEnd(z)
194 z_stream *z;
195 {
196   uLong c;
197   int e;
198
199   if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL)
200     return Z_STREAM_ERROR;
201   if (z->state->mode == BLOCKS)
202     inflate_blocks_free(z->state->sub.blocks, z, &c, &e);
203   ZFREE(z, z->state);
204   z->state = Z_NULL;
205   return Z_OK;
206 }
207
208
209 /* inflateSync not implemented yet--this just consumes input */
210 int inflateSync(z)
211 z_stream *z;
212 {
213   if (z == Z_NULL) return Z_STREAM_ERROR;
214   if (z->avail_in == 0) return Z_BUF_ERROR;
215   do {
216     z->total_in++;
217   } while (--z->avail_in);
218   return Z_DATA_ERROR;
219 }
220
221
222 /* inflateReset not fully implemented yet--this frees and reallocates */
223 int inflateReset(z)
224 z_stream *z;
225 {
226   int r;
227
228   if ((r = inflateEnd(z)) != Z_OK)
229     return r;
230   return inflateInit(z);
231 }