Mercurial > 510Connectbot
comparison src/com/jcraft/jzlib/Inflate.java @ 0:0ce5cc452d02
initial version
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Thu, 22 May 2014 10:41:19 -0700 |
parents | |
children | 46c2115ae1c8 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:0ce5cc452d02 |
---|---|
1 /* -*-mode:java; c-basic-offset:2; -*- */ | |
2 /* | |
3 Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved. | |
4 | |
5 Redistribution and use in source and binary forms, with or without | |
6 modification, are permitted provided that the following conditions are met: | |
7 | |
8 1. Redistributions of source code must retain the above copyright notice, | |
9 this list of conditions and the following disclaimer. | |
10 | |
11 2. Redistributions in binary form must reproduce the above copyright | |
12 notice, this list of conditions and the following disclaimer in | |
13 the documentation and/or other materials provided with the distribution. | |
14 | |
15 3. The names of the authors may not be used to endorse or promote products | |
16 derived from this software without specific prior written permission. | |
17 | |
18 THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, | |
19 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND | |
20 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, | |
21 INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, | |
22 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
23 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, | |
24 OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
25 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
26 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, | |
27 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
28 */ | |
29 /* | |
30 * This program is based on zlib-1.1.3, so all credit should go authors | |
31 * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) | |
32 * and contributors of zlib. | |
33 */ | |
34 | |
35 package com.jcraft.jzlib; | |
36 | |
37 final class Inflate { | |
38 | |
39 static final private int MAX_WBITS = 15; // 32K LZ77 window | |
40 | |
41 // preset dictionary flag in zlib header | |
42 static final private int PRESET_DICT = 0x20; | |
43 | |
44 static final int Z_NO_FLUSH = 0; | |
45 static final int Z_PARTIAL_FLUSH = 1; | |
46 static final int Z_SYNC_FLUSH = 2; | |
47 static final int Z_FULL_FLUSH = 3; | |
48 static final int Z_FINISH = 4; | |
49 | |
50 static final private int Z_DEFLATED = 8; | |
51 | |
52 static final private int Z_OK = 0; | |
53 static final private int Z_STREAM_END = 1; | |
54 static final private int Z_NEED_DICT = 2; | |
55 static final private int Z_ERRNO = -1; | |
56 static final private int Z_STREAM_ERROR = -2; | |
57 static final private int Z_DATA_ERROR = -3; | |
58 static final private int Z_MEM_ERROR = -4; | |
59 static final private int Z_BUF_ERROR = -5; | |
60 static final private int Z_VERSION_ERROR = -6; | |
61 | |
62 static final private int METHOD = 0; // waiting for method byte | |
63 static final private int FLAG = 1; // waiting for flag byte | |
64 static final private int DICT4 = 2; // four dictionary check bytes to go | |
65 static final private int DICT3 = 3; // three dictionary check bytes to go | |
66 static final private int DICT2 = 4; // two dictionary check bytes to go | |
67 static final private int DICT1 = 5; // one dictionary check byte to go | |
68 static final private int DICT0 = 6; // waiting for inflateSetDictionary | |
69 static final private int BLOCKS = 7; // decompressing blocks | |
70 static final private int CHECK4 = 8; // four check bytes to go | |
71 static final private int CHECK3 = 9; // three check bytes to go | |
72 static final private int CHECK2 = 10; // two check bytes to go | |
73 static final private int CHECK1 = 11; // one check byte to go | |
74 static final private int DONE = 12; // finished check, done | |
75 static final private int BAD = 13; // got an error--stay here | |
76 | |
77 int mode; // current inflate mode | |
78 | |
79 // mode dependent information | |
80 int method; // if FLAGS, method byte | |
81 | |
82 // if CHECK, check values to compare | |
83 long[] was = new long[1] ; // computed check value | |
84 long need; // stream check value | |
85 | |
86 // if BAD, inflateSync's marker bytes count | |
87 int marker; | |
88 | |
89 // mode independent information | |
90 int nowrap; // flag for no wrapper | |
91 int wbits; // log2(window size) (8..15, defaults to 15) | |
92 | |
93 InfBlocks blocks; // current inflate_blocks state | |
94 | |
95 int inflateReset(ZStream z) { | |
96 if (z == null || z.istate == null) return Z_STREAM_ERROR; | |
97 | |
98 z.total_in = z.total_out = 0; | |
99 z.msg = null; | |
100 z.istate.mode = z.istate.nowrap != 0 ? BLOCKS : METHOD; | |
101 z.istate.blocks.reset(z, null); | |
102 return Z_OK; | |
103 } | |
104 | |
105 int inflateEnd(ZStream z) { | |
106 if (blocks != null) | |
107 blocks.free(z); | |
108 | |
109 blocks = null; | |
110 // ZFREE(z, z->state); | |
111 return Z_OK; | |
112 } | |
113 | |
114 int inflateInit(ZStream z, int w) { | |
115 z.msg = null; | |
116 blocks = null; | |
117 // handle undocumented nowrap option (no zlib header or check) | |
118 nowrap = 0; | |
119 | |
120 if (w < 0) { | |
121 w = - w; | |
122 nowrap = 1; | |
123 } | |
124 | |
125 // set window size | |
126 if (w < 8 || w > 15) { | |
127 inflateEnd(z); | |
128 return Z_STREAM_ERROR; | |
129 } | |
130 | |
131 wbits = w; | |
132 z.istate.blocks = new InfBlocks(z, | |
133 z.istate.nowrap != 0 ? null : this, | |
134 1 << w); | |
135 // reset state | |
136 inflateReset(z); | |
137 return Z_OK; | |
138 } | |
139 | |
140 int inflate(ZStream z, int f) { | |
141 int r; | |
142 int b; | |
143 | |
144 if (z == null || z.istate == null || z.next_in == null) | |
145 return Z_STREAM_ERROR; | |
146 | |
147 f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK; | |
148 r = Z_BUF_ERROR; | |
149 | |
150 while (true) { | |
151 //System.out.println("mode: "+z.istate.mode); | |
152 switch (z.istate.mode) { | |
153 case METHOD: | |
154 if (z.avail_in == 0)return r; r = f; | |
155 | |
156 z.avail_in--; z.total_in++; | |
157 | |
158 if (((z.istate.method = z.next_in[z.next_in_index++]) & 0xf) != Z_DEFLATED) { | |
159 z.istate.mode = BAD; | |
160 z.msg = "unknown compression method"; | |
161 z.istate.marker = 5; // can't try inflateSync | |
162 break; | |
163 } | |
164 | |
165 if ((z.istate.method >> 4) + 8 > z.istate.wbits) { | |
166 z.istate.mode = BAD; | |
167 z.msg = "invalid window size"; | |
168 z.istate.marker = 5; // can't try inflateSync | |
169 break; | |
170 } | |
171 | |
172 z.istate.mode = FLAG; | |
173 | |
174 case FLAG: | |
175 if (z.avail_in == 0)return r; r = f; | |
176 | |
177 z.avail_in--; z.total_in++; | |
178 b = (z.next_in[z.next_in_index++]) & 0xff; | |
179 | |
180 if ((((z.istate.method << 8) + b) % 31) != 0) { | |
181 z.istate.mode = BAD; | |
182 z.msg = "incorrect header check"; | |
183 z.istate.marker = 5; // can't try inflateSync | |
184 break; | |
185 } | |
186 | |
187 if ((b & PRESET_DICT) == 0) { | |
188 z.istate.mode = BLOCKS; | |
189 break; | |
190 } | |
191 | |
192 z.istate.mode = DICT4; | |
193 | |
194 case DICT4: | |
195 if (z.avail_in == 0)return r; r = f; | |
196 | |
197 z.avail_in--; z.total_in++; | |
198 z.istate.need = ((z.next_in[z.next_in_index++] & 0xff) << 24) & 0xff000000L; | |
199 z.istate.mode = DICT3; | |
200 | |
201 case DICT3: | |
202 if (z.avail_in == 0)return r; r = f; | |
203 | |
204 z.avail_in--; z.total_in++; | |
205 z.istate.need += ((z.next_in[z.next_in_index++] & 0xff) << 16) & 0xff0000L; | |
206 z.istate.mode = DICT2; | |
207 | |
208 case DICT2: | |
209 if (z.avail_in == 0)return r; r = f; | |
210 | |
211 z.avail_in--; z.total_in++; | |
212 z.istate.need += ((z.next_in[z.next_in_index++] & 0xff) << 8) & 0xff00L; | |
213 z.istate.mode = DICT1; | |
214 | |
215 case DICT1: | |
216 if (z.avail_in == 0)return r; r = f; | |
217 | |
218 z.avail_in--; z.total_in++; | |
219 z.istate.need += (z.next_in[z.next_in_index++] & 0xffL); | |
220 z.adler = z.istate.need; | |
221 z.istate.mode = DICT0; | |
222 return Z_NEED_DICT; | |
223 | |
224 case DICT0: | |
225 z.istate.mode = BAD; | |
226 z.msg = "need dictionary"; | |
227 z.istate.marker = 0; // can try inflateSync | |
228 return Z_STREAM_ERROR; | |
229 | |
230 case BLOCKS: | |
231 r = z.istate.blocks.proc(z, r); | |
232 | |
233 if (r == Z_DATA_ERROR) { | |
234 z.istate.mode = BAD; | |
235 z.istate.marker = 0; // can try inflateSync | |
236 break; | |
237 } | |
238 | |
239 if (r == Z_OK) { | |
240 r = f; | |
241 } | |
242 | |
243 if (r != Z_STREAM_END) { | |
244 return r; | |
245 } | |
246 | |
247 r = f; | |
248 z.istate.blocks.reset(z, z.istate.was); | |
249 | |
250 if (z.istate.nowrap != 0) { | |
251 z.istate.mode = DONE; | |
252 break; | |
253 } | |
254 | |
255 z.istate.mode = CHECK4; | |
256 | |
257 case CHECK4: | |
258 if (z.avail_in == 0)return r; r = f; | |
259 | |
260 z.avail_in--; z.total_in++; | |
261 z.istate.need = ((z.next_in[z.next_in_index++] & 0xff) << 24) & 0xff000000L; | |
262 z.istate.mode = CHECK3; | |
263 | |
264 case CHECK3: | |
265 if (z.avail_in == 0)return r; r = f; | |
266 | |
267 z.avail_in--; z.total_in++; | |
268 z.istate.need += ((z.next_in[z.next_in_index++] & 0xff) << 16) & 0xff0000L; | |
269 z.istate.mode = CHECK2; | |
270 | |
271 case CHECK2: | |
272 if (z.avail_in == 0)return r; r = f; | |
273 | |
274 z.avail_in--; z.total_in++; | |
275 z.istate.need += ((z.next_in[z.next_in_index++] & 0xff) << 8) & 0xff00L; | |
276 z.istate.mode = CHECK1; | |
277 | |
278 case CHECK1: | |
279 if (z.avail_in == 0)return r; r = f; | |
280 | |
281 z.avail_in--; z.total_in++; | |
282 z.istate.need += (z.next_in[z.next_in_index++] & 0xffL); | |
283 | |
284 if (((int)(z.istate.was[0])) != ((int)(z.istate.need))) { | |
285 z.istate.mode = BAD; | |
286 z.msg = "incorrect data check"; | |
287 z.istate.marker = 5; // can't try inflateSync | |
288 break; | |
289 } | |
290 | |
291 z.istate.mode = DONE; | |
292 | |
293 case DONE: | |
294 return Z_STREAM_END; | |
295 | |
296 case BAD: | |
297 return Z_DATA_ERROR; | |
298 | |
299 default: | |
300 return Z_STREAM_ERROR; | |
301 } | |
302 } | |
303 } | |
304 | |
305 | |
306 int inflateSetDictionary(ZStream z, byte[] dictionary, int dictLength) { | |
307 int index = 0; | |
308 int length = dictLength; | |
309 | |
310 if (z == null || z.istate == null || z.istate.mode != DICT0) | |
311 return Z_STREAM_ERROR; | |
312 | |
313 if (z._adler.adler32(1L, dictionary, 0, dictLength) != z.adler) { | |
314 return Z_DATA_ERROR; | |
315 } | |
316 | |
317 z.adler = z._adler.adler32(0, null, 0, 0); | |
318 | |
319 if (length >= (1 << z.istate.wbits)) { | |
320 length = (1 << z.istate.wbits) - 1; | |
321 index = dictLength - length; | |
322 } | |
323 | |
324 z.istate.blocks.set_dictionary(dictionary, index, length); | |
325 z.istate.mode = BLOCKS; | |
326 return Z_OK; | |
327 } | |
328 | |
329 static private byte[] mark = { (byte)0, (byte)0, (byte)0xff, (byte)0xff}; | |
330 | |
331 int inflateSync(ZStream z) { | |
332 int n; // number of bytes to look at | |
333 int p; // pointer to bytes | |
334 int m; // number of marker bytes found in a row | |
335 long r, w; // temporaries to save total_in and total_out | |
336 | |
337 // set up | |
338 if (z == null || z.istate == null) | |
339 return Z_STREAM_ERROR; | |
340 | |
341 if (z.istate.mode != BAD) { | |
342 z.istate.mode = BAD; | |
343 z.istate.marker = 0; | |
344 } | |
345 | |
346 if ((n = z.avail_in) == 0) | |
347 return Z_BUF_ERROR; | |
348 | |
349 p = z.next_in_index; | |
350 m = z.istate.marker; | |
351 | |
352 // search | |
353 while (n != 0 && m < 4) { | |
354 if (z.next_in[p] == mark[m]) { | |
355 m++; | |
356 } | |
357 else if (z.next_in[p] != 0) { | |
358 m = 0; | |
359 } | |
360 else { | |
361 m = 4 - m; | |
362 } | |
363 | |
364 p++; n--; | |
365 } | |
366 | |
367 // restore | |
368 z.total_in += p - z.next_in_index; | |
369 z.next_in_index = p; | |
370 z.avail_in = n; | |
371 z.istate.marker = m; | |
372 | |
373 // return no joy or set up to restart on a new block | |
374 if (m != 4) { | |
375 return Z_DATA_ERROR; | |
376 } | |
377 | |
378 r = z.total_in; w = z.total_out; | |
379 inflateReset(z); | |
380 z.total_in = r; z.total_out = w; | |
381 z.istate.mode = BLOCKS; | |
382 return Z_OK; | |
383 } | |
384 | |
385 // Returns true if inflate is currently at the end of a block generated | |
386 // by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP | |
387 // implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH | |
388 // but removes the length bytes of the resulting empty stored block. When | |
389 // decompressing, PPP checks that at the end of input packet, inflate is | |
390 // waiting for these length bytes. | |
391 int inflateSyncPoint(ZStream z) { | |
392 if (z == null || z.istate == null || z.istate.blocks == null) | |
393 return Z_STREAM_ERROR; | |
394 | |
395 return z.istate.blocks.sync_point(); | |
396 } | |
397 } |