summaryrefslogtreecommitdiff
path: root/inflate.c
diff options
context:
space:
mode:
Diffstat (limited to 'inflate.c')
-rw-r--r--inflate.c221
1 files changed, 221 insertions, 0 deletions
diff --git a/inflate.c b/inflate.c
new file mode 100644
index 0000000..478f46d
--- /dev/null
+++ b/inflate.c
@@ -0,0 +1,221 @@
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
9struct inflate_blocks_state {int dummy;}; /* for buggy compilers */
10
11/* inflate private state */
12struct 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 int no_header;
29 uInt w_size; /* LZ77 window size (32K by default) */
30 uInt w_bits; /* log2(w_size) (8..16) */
31
32 /* mode dependent information */
33 union {
34 uInt method; /* if FLAGS, method byte */
35 struct inflate_blocks_state
36 *blocks; /* if BLOCKS, current state */
37 struct {
38 uLong was; /* computed check value */
39 uLong need; /* stream check value */
40 } check; /* if CHECK, check values to compare */
41 } sub; /* submode */
42};
43
44
45int inflateInit (strm)
46z_stream *strm;
47{
48 return inflateInit2(strm, WBITS);
49}
50
51int inflateInit2(z, windowBits)
52z_stream *z;
53int windowBits;
54{
55 if (z == Z_NULL)
56 return Z_STREAM_ERROR;
57 if (z->zalloc == Z_NULL) z->zalloc = zcalloc;
58 if (z->zfree == Z_NULL) z->zfree = zcfree;
59 z->total_in = z->total_out = 0;
60 z->msg = Z_NULL;
61 if ((z->state = (struct internal_state *)
62 ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL)
63 return Z_MEM_ERROR;
64 z->state->mode = METHOD;
65
66 z->state->no_header = 0;
67 if (windowBits < 0) { /* undocumented feature: no zlib header */
68 windowBits = - windowBits;
69 z->state->no_header = 1;
70 z->state->sub.method = DEFLATED;
71 z->state->mode = START;
72 }
73 if (windowBits < 8 || windowBits > 15) {
74 inflateEnd(z);
75 return Z_STREAM_ERROR;
76 }
77 z->state->w_bits = windowBits;
78 z->state->w_size = 1<<windowBits;
79 return Z_OK;
80}
81
82
83#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++)
84
85int inflate(z, f)
86z_stream *z;
87int f;
88{
89 int r;
90 uInt b;
91 uLong c;
92
93 if (z == Z_NULL || z->next_in == Z_NULL)
94 return Z_STREAM_ERROR;
95 r = Z_BUF_ERROR;
96 while (1) switch (z->state->mode)
97 {
98 case METHOD:
99 if (z->avail_in == 0) return r; r = Z_OK;
100 if (((z->state->sub.method = NEXTBYTE) & 0xf != DEFLATED))
101 {
102 z->state->mode = ERROR;
103 z->msg = "unknown compression method";
104 return Z_DATA_ERROR;
105 }
106 if ((z->state->sub.method >> 4) > z->state->w_bits)
107 {
108 z->state->mode = ERROR;
109 z->msg = "invalid window size";
110 return Z_DATA_ERROR;
111 }
112 z->state->mode = FLAG;
113 case FLAG:
114 if (z->avail_in == 0) return r; r = Z_OK;
115 if ((b = NEXTBYTE) & 0x20)
116 {
117 z->state->mode = ERROR;
118 z->msg = "invalid reserved bit";
119 return Z_DATA_ERROR;
120 }
121 if (((z->state->sub.method << 8) + b) % 31)
122 {
123 z->state->mode = ERROR;
124 z->msg = "incorrect header check";
125 return Z_DATA_ERROR;
126 }
127 z->state->mode = START;
128 case START:
129 if ((z->state->sub.blocks = inflate_blocks_new(z,z->state->w_size))
130 == Z_NULL)
131 return Z_MEM_ERROR;
132 z->state->mode = BLOCKS;
133 case BLOCKS:
134 if ((r = inflate_blocks(z->state->sub.blocks, z, r)) != Z_STREAM_END)
135 return r;
136 inflate_blocks_free(z->state->sub.blocks, z, &c, &r);
137 if (z->state->no_header) {
138 z->state->mode = DONE;
139 return Z_STREAM_END;
140 }
141 z->state->sub.check.was = c;
142 if (r != -1)
143 {
144 z->state->sub.check.need = (uLong)r << 24;
145 z->state->mode = CHECK3;
146 r = Z_OK;
147 break;
148 }
149 r = Z_OK;
150 z->state->mode = CHECK4;
151 case CHECK4:
152 if (z->avail_in == 0) return r; r = Z_OK;
153 z->state->sub.check.need = (uLong)NEXTBYTE << 24;
154 z->state->mode = CHECK3;
155 case CHECK3:
156 if (z->avail_in == 0) return r; r = Z_OK;
157 z->state->sub.check.need += (uLong)NEXTBYTE << 16;
158 z->state->mode = CHECK2;
159 case CHECK2:
160 if (z->avail_in == 0) return r; r = Z_OK;
161 z->state->sub.check.need += (uLong)NEXTBYTE << 8;
162 z->state->mode = CHECK1;
163 case CHECK1:
164 if (z->avail_in == 0) return r; r = Z_OK;
165 z->state->sub.check.need += (uLong)NEXTBYTE;
166 if (z->state->sub.check.was != z->state->sub.check.need)
167 {
168 z->state->mode = ERROR;
169 z->msg = "incorrect data check";
170 return Z_DATA_ERROR;
171 }
172 z->state->mode = DONE;
173 case DONE:
174 return Z_STREAM_END;
175 case ERROR:
176 return Z_DATA_ERROR;
177 default:
178 return Z_STREAM_ERROR;
179 }
180}
181
182
183int inflateEnd(z)
184z_stream *z;
185{
186 uLong c;
187 int e;
188
189 if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL)
190 return Z_STREAM_ERROR;
191 if (z->state->mode == BLOCKS)
192 inflate_blocks_free(z->state->sub.blocks, z, &c, &e);
193 ZFREE(z, z->state);
194 z->state = Z_NULL;
195 return Z_OK;
196}
197
198
199/* inflateSync not implemented yet--this just consumes input */
200int inflateSync(z)
201z_stream *z;
202{
203 if (z == Z_NULL) return Z_STREAM_ERROR;
204 if (z->avail_in == 0) return Z_BUF_ERROR;
205 do {
206 z->total_in++;
207 } while (--z->avail_in);
208 return Z_DATA_ERROR;
209}
210
211
212/* inflateReset not fully implemented yet--this frees and reallocates */
213int inflateReset(z)
214z_stream *z;
215{
216 int r;
217
218 if ((r = inflateEnd(z)) != Z_OK)
219 return r;
220 return inflateInit(z);
221}