]>
Commit | Line | Data |
---|---|---|
0763e16d JW |
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 InfBlocks{ | |
38 | static final private int MANY=1440; | |
39 | ||
40 | // And'ing with mask[n] masks the lower n bits | |
41 | static final private int[] inflate_mask = { | |
42 | 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f, | |
43 | 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff, | |
44 | 0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff, | |
45 | 0x00007fff, 0x0000ffff | |
46 | }; | |
47 | ||
48 | // Table for deflate from PKZIP's appnote.txt. | |
49 | static final int[] border = { // Order of the bit length code lengths | |
50 | 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 | |
51 | }; | |
52 | ||
53 | static final private int Z_OK=0; | |
54 | static final private int Z_STREAM_END=1; | |
55 | static final private int Z_NEED_DICT=2; | |
56 | static final private int Z_ERRNO=-1; | |
57 | static final private int Z_STREAM_ERROR=-2; | |
58 | static final private int Z_DATA_ERROR=-3; | |
59 | static final private int Z_MEM_ERROR=-4; | |
60 | static final private int Z_BUF_ERROR=-5; | |
61 | static final private int Z_VERSION_ERROR=-6; | |
62 | ||
63 | static final private int TYPE=0; // get type bits (3, including end bit) | |
64 | static final private int LENS=1; // get lengths for stored | |
65 | static final private int STORED=2;// processing stored block | |
66 | static final private int TABLE=3; // get table lengths | |
67 | static final private int BTREE=4; // get bit lengths tree for a dynamic block | |
68 | static final private int DTREE=5; // get length, distance trees for a dynamic block | |
69 | static final private int CODES=6; // processing fixed or dynamic block | |
70 | static final private int DRY=7; // output remaining window bytes | |
71 | static final private int DONE=8; // finished last block, done | |
72 | static final private int BAD=9; // ot a data error--stuck here | |
73 | ||
74 | int mode; // current inflate_block mode | |
75 | ||
76 | int left; // if STORED, bytes left to copy | |
77 | ||
78 | int table; // table lengths (14 bits) | |
79 | int index; // index into blens (or border) | |
80 | int[] blens; // bit lengths of codes | |
81 | int[] bb=new int[1]; // bit length tree depth | |
82 | int[] tb=new int[1]; // bit length decoding tree | |
83 | ||
84 | InfCodes codes=new InfCodes(); // if CODES, current state | |
85 | ||
86 | int last; // true if this block is the last block | |
87 | ||
88 | // mode independent information | |
89 | int bitk; // bits in bit buffer | |
90 | int bitb; // bit buffer | |
91 | int[] hufts; // single malloc for tree space | |
92 | byte[] window; // sliding window | |
93 | int end; // one byte after sliding window | |
94 | int read; // window read pointer | |
95 | int write; // window write pointer | |
96 | Object checkfn; // check function | |
97 | long check; // check on output | |
98 | ||
99 | InfTree inftree=new InfTree(); | |
100 | ||
101 | InfBlocks(ZStream z, Object checkfn, int w){ | |
102 | hufts=new int[MANY*3]; | |
103 | window=new byte[w]; | |
104 | end=w; | |
105 | this.checkfn = checkfn; | |
106 | mode = TYPE; | |
107 | reset(z, null); | |
108 | } | |
109 | ||
110 | void reset(ZStream z, long[] c){ | |
111 | if(c!=null) c[0]=check; | |
112 | if(mode==BTREE || mode==DTREE){ | |
113 | } | |
114 | if(mode==CODES){ | |
115 | codes.free(z); | |
116 | } | |
117 | mode=TYPE; | |
118 | bitk=0; | |
119 | bitb=0; | |
120 | read=write=0; | |
121 | ||
122 | if(checkfn != null) | |
123 | z.adler=check=z._adler.adler32(0L, null, 0, 0); | |
124 | } | |
125 | ||
126 | int proc(ZStream z, int r){ | |
127 | int t; // temporary storage | |
128 | int b; // bit buffer | |
129 | int k; // bits in bit buffer | |
130 | int p; // input data pointer | |
131 | int n; // bytes available there | |
132 | int q; // output window write pointer | |
133 | int m; // bytes to end of window or read pointer | |
134 | ||
135 | // copy input/output information to locals (UPDATE macro restores) | |
136 | {p=z.next_in_index;n=z.avail_in;b=bitb;k=bitk;} | |
137 | {q=write;m=(int)(q<read?read-q-1:end-q);} | |
138 | ||
139 | // process input based on current state | |
140 | while(true){ | |
141 | switch (mode){ | |
142 | case TYPE: | |
143 | ||
144 | while(k<(3)){ | |
145 | if(n!=0){ | |
146 | r=Z_OK; | |
147 | } | |
148 | else{ | |
149 | bitb=b; bitk=k; | |
150 | z.avail_in=n; | |
151 | z.total_in+=p-z.next_in_index;z.next_in_index=p; | |
152 | write=q; | |
153 | return inflate_flush(z,r); | |
154 | }; | |
155 | n--; | |
156 | b|=(z.next_in[p++]&0xff)<<k; | |
157 | k+=8; | |
158 | } | |
159 | t = (int)(b & 7); | |
160 | last = t & 1; | |
161 | ||
162 | switch (t >>> 1){ | |
163 | case 0: // stored | |
164 | {b>>>=(3);k-=(3);} | |
165 | t = k & 7; // go to byte boundary | |
166 | ||
167 | {b>>>=(t);k-=(t);} | |
168 | mode = LENS; // get length of stored block | |
169 | break; | |
170 | case 1: // fixed | |
171 | { | |
172 | int[] bl=new int[1]; | |
173 | int[] bd=new int[1]; | |
174 | int[][] tl=new int[1][]; | |
175 | int[][] td=new int[1][]; | |
176 | ||
177 | InfTree.inflate_trees_fixed(bl, bd, tl, td, z); | |
178 | codes.init(bl[0], bd[0], tl[0], 0, td[0], 0, z); | |
179 | } | |
180 | ||
181 | {b>>>=(3);k-=(3);} | |
182 | ||
183 | mode = CODES; | |
184 | break; | |
185 | case 2: // dynamic | |
186 | ||
187 | {b>>>=(3);k-=(3);} | |
188 | ||
189 | mode = TABLE; | |
190 | break; | |
191 | case 3: // illegal | |
192 | ||
193 | {b>>>=(3);k-=(3);} | |
194 | mode = BAD; | |
195 | z.msg = "invalid block type"; | |
196 | r = Z_DATA_ERROR; | |
197 | ||
198 | bitb=b; bitk=k; | |
199 | z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; | |
200 | write=q; | |
201 | return inflate_flush(z,r); | |
202 | } | |
203 | break; | |
204 | case LENS: | |
205 | ||
206 | while(k<(32)){ | |
207 | if(n!=0){ | |
208 | r=Z_OK; | |
209 | } | |
210 | else{ | |
211 | bitb=b; bitk=k; | |
212 | z.avail_in=n; | |
213 | z.total_in+=p-z.next_in_index;z.next_in_index=p; | |
214 | write=q; | |
215 | return inflate_flush(z,r); | |
216 | }; | |
217 | n--; | |
218 | b|=(z.next_in[p++]&0xff)<<k; | |
219 | k+=8; | |
220 | } | |
221 | ||
222 | if ((((~b) >>> 16) & 0xffff) != (b & 0xffff)){ | |
223 | mode = BAD; | |
224 | z.msg = "invalid stored block lengths"; | |
225 | r = Z_DATA_ERROR; | |
226 | ||
227 | bitb=b; bitk=k; | |
228 | z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; | |
229 | write=q; | |
230 | return inflate_flush(z,r); | |
231 | } | |
232 | left = (b & 0xffff); | |
233 | b = k = 0; // dump bits | |
234 | mode = left!=0 ? STORED : (last!=0 ? DRY : TYPE); | |
235 | break; | |
236 | case STORED: | |
237 | if (n == 0){ | |
238 | bitb=b; bitk=k; | |
239 | z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; | |
240 | write=q; | |
241 | return inflate_flush(z,r); | |
242 | } | |
243 | ||
244 | if(m==0){ | |
245 | if(q==end&&read!=0){ | |
246 | q=0; m=(int)(q<read?read-q-1:end-q); | |
247 | } | |
248 | if(m==0){ | |
249 | write=q; | |
250 | r=inflate_flush(z,r); | |
251 | q=write;m=(int)(q<read?read-q-1:end-q); | |
252 | if(q==end&&read!=0){ | |
253 | q=0; m=(int)(q<read?read-q-1:end-q); | |
254 | } | |
255 | if(m==0){ | |
256 | bitb=b; bitk=k; | |
257 | z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; | |
258 | write=q; | |
259 | return inflate_flush(z,r); | |
260 | } | |
261 | } | |
262 | } | |
263 | r=Z_OK; | |
264 | ||
265 | t = left; | |
266 | if(t>n) t = n; | |
267 | if(t>m) t = m; | |
268 | System.arraycopy(z.next_in, p, window, q, t); | |
269 | p += t; n -= t; | |
270 | q += t; m -= t; | |
271 | if ((left -= t) != 0) | |
272 | break; | |
273 | mode = last!=0 ? DRY : TYPE; | |
274 | break; | |
275 | case TABLE: | |
276 | ||
277 | while(k<(14)){ | |
278 | if(n!=0){ | |
279 | r=Z_OK; | |
280 | } | |
281 | else{ | |
282 | bitb=b; bitk=k; | |
283 | z.avail_in=n; | |
284 | z.total_in+=p-z.next_in_index;z.next_in_index=p; | |
285 | write=q; | |
286 | return inflate_flush(z,r); | |
287 | }; | |
288 | n--; | |
289 | b|=(z.next_in[p++]&0xff)<<k; | |
290 | k+=8; | |
291 | } | |
292 | ||
293 | table = t = (b & 0x3fff); | |
294 | if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29) | |
295 | { | |
296 | mode = BAD; | |
297 | z.msg = "too many length or distance symbols"; | |
298 | r = Z_DATA_ERROR; | |
299 | ||
300 | bitb=b; bitk=k; | |
301 | z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; | |
302 | write=q; | |
303 | return inflate_flush(z,r); | |
304 | } | |
305 | t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f); | |
306 | if(blens==null || blens.length<t){ | |
307 | blens=new int[t]; | |
308 | } | |
309 | else{ | |
310 | for(int i=0; i<t; i++){blens[i]=0;} | |
311 | } | |
312 | ||
313 | {b>>>=(14);k-=(14);} | |
314 | ||
315 | index = 0; | |
316 | mode = BTREE; | |
317 | case BTREE: | |
318 | while (index < 4 + (table >>> 10)){ | |
319 | while(k<(3)){ | |
320 | if(n!=0){ | |
321 | r=Z_OK; | |
322 | } | |
323 | else{ | |
324 | bitb=b; bitk=k; | |
325 | z.avail_in=n; | |
326 | z.total_in+=p-z.next_in_index;z.next_in_index=p; | |
327 | write=q; | |
328 | return inflate_flush(z,r); | |
329 | }; | |
330 | n--; | |
331 | b|=(z.next_in[p++]&0xff)<<k; | |
332 | k+=8; | |
333 | } | |
334 | ||
335 | blens[border[index++]] = b&7; | |
336 | ||
337 | {b>>>=(3);k-=(3);} | |
338 | } | |
339 | ||
340 | while(index < 19){ | |
341 | blens[border[index++]] = 0; | |
342 | } | |
343 | ||
344 | bb[0] = 7; | |
345 | t = inftree.inflate_trees_bits(blens, bb, tb, hufts, z); | |
346 | if (t != Z_OK){ | |
347 | r = t; | |
348 | if (r == Z_DATA_ERROR){ | |
349 | blens=null; | |
350 | mode = BAD; | |
351 | } | |
352 | ||
353 | bitb=b; bitk=k; | |
354 | z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; | |
355 | write=q; | |
356 | return inflate_flush(z,r); | |
357 | } | |
358 | ||
359 | index = 0; | |
360 | mode = DTREE; | |
361 | case DTREE: | |
362 | while (true){ | |
363 | t = table; | |
364 | if(!(index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))){ | |
365 | break; | |
366 | } | |
367 | ||
368 | int[] h; | |
369 | int i, j, c; | |
370 | ||
371 | t = bb[0]; | |
372 | ||
373 | while(k<(t)){ | |
374 | if(n!=0){ | |
375 | r=Z_OK; | |
376 | } | |
377 | else{ | |
378 | bitb=b; bitk=k; | |
379 | z.avail_in=n; | |
380 | z.total_in+=p-z.next_in_index;z.next_in_index=p; | |
381 | write=q; | |
382 | return inflate_flush(z,r); | |
383 | }; | |
384 | n--; | |
385 | b|=(z.next_in[p++]&0xff)<<k; | |
386 | k+=8; | |
387 | } | |
388 | ||
389 | if(tb[0]==-1){ | |
390 | //System.err.println("null..."); | |
391 | } | |
392 | ||
393 | t=hufts[(tb[0]+(b&inflate_mask[t]))*3+1]; | |
394 | c=hufts[(tb[0]+(b&inflate_mask[t]))*3+2]; | |
395 | ||
396 | if (c < 16){ | |
397 | b>>>=(t);k-=(t); | |
398 | blens[index++] = c; | |
399 | } | |
400 | else { // c == 16..18 | |
401 | i = c == 18 ? 7 : c - 14; | |
402 | j = c == 18 ? 11 : 3; | |
403 | ||
404 | while(k<(t+i)){ | |
405 | if(n!=0){ | |
406 | r=Z_OK; | |
407 | } | |
408 | else{ | |
409 | bitb=b; bitk=k; | |
410 | z.avail_in=n; | |
411 | z.total_in+=p-z.next_in_index;z.next_in_index=p; | |
412 | write=q; | |
413 | return inflate_flush(z,r); | |
414 | }; | |
415 | n--; | |
416 | b|=(z.next_in[p++]&0xff)<<k; | |
417 | k+=8; | |
418 | } | |
419 | ||
420 | b>>>=(t);k-=(t); | |
421 | ||
422 | j += (b & inflate_mask[i]); | |
423 | ||
424 | b>>>=(i);k-=(i); | |
425 | ||
426 | i = index; | |
427 | t = table; | |
428 | if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) || | |
429 | (c == 16 && i < 1)){ | |
430 | blens=null; | |
431 | mode = BAD; | |
432 | z.msg = "invalid bit length repeat"; | |
433 | r = Z_DATA_ERROR; | |
434 | ||
435 | bitb=b; bitk=k; | |
436 | z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; | |
437 | write=q; | |
438 | return inflate_flush(z,r); | |
439 | } | |
440 | ||
441 | c = c == 16 ? blens[i-1] : 0; | |
442 | do{ | |
443 | blens[i++] = c; | |
444 | } | |
445 | while (--j!=0); | |
446 | index = i; | |
447 | } | |
448 | } | |
449 | ||
450 | tb[0]=-1; | |
451 | { | |
452 | int[] bl=new int[1]; | |
453 | int[] bd=new int[1]; | |
454 | int[] tl=new int[1]; | |
455 | int[] td=new int[1]; | |
456 | bl[0] = 9; // must be <= 9 for lookahead assumptions | |
457 | bd[0] = 6; // must be <= 9 for lookahead assumptions | |
458 | ||
459 | t = table; | |
460 | t = inftree.inflate_trees_dynamic(257 + (t & 0x1f), | |
461 | 1 + ((t >> 5) & 0x1f), | |
462 | blens, bl, bd, tl, td, hufts, z); | |
463 | ||
464 | if (t != Z_OK){ | |
465 | if (t == Z_DATA_ERROR){ | |
466 | blens=null; | |
467 | mode = BAD; | |
468 | } | |
469 | r = t; | |
470 | ||
471 | bitb=b; bitk=k; | |
472 | z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; | |
473 | write=q; | |
474 | return inflate_flush(z,r); | |
475 | } | |
476 | codes.init(bl[0], bd[0], hufts, tl[0], hufts, td[0], z); | |
477 | } | |
478 | mode = CODES; | |
479 | case CODES: | |
480 | bitb=b; bitk=k; | |
481 | z.avail_in=n; z.total_in+=p-z.next_in_index;z.next_in_index=p; | |
482 | write=q; | |
483 | ||
484 | if ((r = codes.proc(this, z, r)) != Z_STREAM_END){ | |
485 | return inflate_flush(z, r); | |
486 | } | |
487 | r = Z_OK; | |
488 | codes.free(z); | |
489 | ||
490 | p=z.next_in_index; n=z.avail_in;b=bitb;k=bitk; | |
491 | q=write;m=(int)(q<read?read-q-1:end-q); | |
492 | ||
493 | if (last==0){ | |
494 | mode = TYPE; | |
495 | break; | |
496 | } | |
497 | mode = DRY; | |
498 | case DRY: | |
499 | write=q; | |
500 | r=inflate_flush(z, r); | |
501 | q=write; m=(int)(q<read?read-q-1:end-q); | |
502 | if (read != write){ | |
503 | bitb=b; bitk=k; | |
504 | z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; | |
505 | write=q; | |
506 | return inflate_flush(z, r); | |
507 | } | |
508 | mode = DONE; | |
509 | case DONE: | |
510 | r = Z_STREAM_END; | |
511 | ||
512 | bitb=b; bitk=k; | |
513 | z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; | |
514 | write=q; | |
515 | return inflate_flush(z, r); | |
516 | case BAD: | |
517 | r = Z_DATA_ERROR; | |
518 | ||
519 | bitb=b; bitk=k; | |
520 | z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; | |
521 | write=q; | |
522 | return inflate_flush(z, r); | |
523 | ||
524 | default: | |
525 | r = Z_STREAM_ERROR; | |
526 | ||
527 | bitb=b; bitk=k; | |
528 | z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; | |
529 | write=q; | |
530 | return inflate_flush(z, r); | |
531 | } | |
532 | } | |
533 | } | |
534 | ||
535 | void free(ZStream z){ | |
536 | reset(z, null); | |
537 | window=null; | |
538 | hufts=null; | |
539 | //ZFREE(z, s); | |
540 | } | |
541 | ||
542 | void set_dictionary(byte[] d, int start, int n){ | |
543 | System.arraycopy(d, start, window, 0, n); | |
544 | read = write = n; | |
545 | } | |
546 | ||
547 | // Returns true if inflate is currently at the end of a block generated | |
548 | // by Z_SYNC_FLUSH or Z_FULL_FLUSH. | |
549 | int sync_point(){ | |
550 | return mode == LENS ? 1 : 0; | |
551 | } | |
552 | ||
553 | // copy as much as possible from the sliding window to the output area | |
554 | int inflate_flush(ZStream z, int r){ | |
555 | int n; | |
556 | int p; | |
557 | int q; | |
558 | ||
559 | // local copies of source and destination pointers | |
560 | p = z.next_out_index; | |
561 | q = read; | |
562 | ||
563 | // compute number of bytes to copy as far as end of window | |
564 | n = (int)((q <= write ? write : end) - q); | |
565 | if (n > z.avail_out) n = z.avail_out; | |
566 | if (n!=0 && r == Z_BUF_ERROR) r = Z_OK; | |
567 | ||
568 | // update counters | |
569 | z.avail_out -= n; | |
570 | z.total_out += n; | |
571 | ||
572 | // update check information | |
573 | if(checkfn != null) | |
574 | z.adler=check=z._adler.adler32(check, window, q, n); | |
575 | ||
576 | // copy as far as end of window | |
577 | System.arraycopy(window, q, z.next_out, p, n); | |
578 | p += n; | |
579 | q += n; | |
580 | ||
581 | // see if more to copy at beginning of window | |
582 | if (q == end){ | |
583 | // wrap pointers | |
584 | q = 0; | |
585 | if (write == end) | |
586 | write = 0; | |
587 | ||
588 | // compute bytes to copy | |
589 | n = write - q; | |
590 | if (n > z.avail_out) n = z.avail_out; | |
591 | if (n!=0 && r == Z_BUF_ERROR) r = Z_OK; | |
592 | ||
593 | // update counters | |
594 | z.avail_out -= n; | |
595 | z.total_out += n; | |
596 | ||
597 | // update check information | |
598 | if(checkfn != null) | |
599 | z.adler=check=z._adler.adler32(check, window, q, n); | |
600 | ||
601 | // copy | |
602 | System.arraycopy(window, q, z.next_out, p, n); | |
603 | p += n; | |
604 | q += n; | |
605 | } | |
606 | ||
607 | // update pointers | |
608 | z.next_out_index = p; | |
609 | read = q; | |
610 | ||
611 | // done | |
612 | return r; | |
613 | } | |
614 | } |