Mercurial > 510Connectbot
diff src/com/jcraft/jzlib/InfBlocks.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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/com/jcraft/jzlib/InfBlocks.java Thu May 22 10:41:19 2014 -0700 @@ -0,0 +1,652 @@ +/* -*-mode:java; c-basic-offset:2; -*- */ +/* +Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +package com.jcraft.jzlib; + +final class InfBlocks { + static final private int MANY = 1440; + + // And'ing with mask[n] masks the lower n bits + static final private int[] inflate_mask = { + 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f, + 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff, + 0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff, + 0x00007fff, 0x0000ffff + }; + + // Table for deflate from PKZIP's appnote.txt. + static final int[] border = { // Order of the bit length code lengths + 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 + }; + + static final private int Z_OK = 0; + static final private int Z_STREAM_END = 1; + static final private int Z_NEED_DICT = 2; + static final private int Z_ERRNO = -1; + static final private int Z_STREAM_ERROR = -2; + static final private int Z_DATA_ERROR = -3; + static final private int Z_MEM_ERROR = -4; + static final private int Z_BUF_ERROR = -5; + static final private int Z_VERSION_ERROR = -6; + + static final private int TYPE = 0; // get type bits (3, including end bit) + static final private int LENS = 1; // get lengths for stored + static final private int STORED = 2; // processing stored block + static final private int TABLE = 3; // get table lengths + static final private int BTREE = 4; // get bit lengths tree for a dynamic block + static final private int DTREE = 5; // get length, distance trees for a dynamic block + static final private int CODES = 6; // processing fixed or dynamic block + static final private int DRY = 7; // output remaining window bytes + static final private int DONE = 8; // finished last block, done + static final private int BAD = 9; // ot a data error--stuck here + + int mode; // current inflate_block mode + + int left; // if STORED, bytes left to copy + + int table; // table lengths (14 bits) + int index; // index into blens (or border) + int[] blens; // bit lengths of codes + int[] bb = new int[1]; // bit length tree depth + int[] tb = new int[1]; // bit length decoding tree + + InfCodes codes = new InfCodes(); // if CODES, current state + + int last; // true if this block is the last block + + // mode independent information + int bitk; // bits in bit buffer + int bitb; // bit buffer + int[] hufts; // single malloc for tree space + byte[] window; // sliding window + int end; // one byte after sliding window + int read; // window read pointer + int write; // window write pointer + Object checkfn; // check function + long check; // check on output + + InfTree inftree = new InfTree(); + + InfBlocks(ZStream z, Object checkfn, int w) { + hufts = new int[MANY * 3]; + window = new byte[w]; + end = w; + this.checkfn = checkfn; + mode = TYPE; + reset(z, null); + } + + void reset(ZStream z, long[] c) { + if (c != null) c[0] = check; + + if (mode == BTREE || mode == DTREE) { + } + + if (mode == CODES) { + codes.free(z); + } + + mode = TYPE; + bitk = 0; + bitb = 0; + read = write = 0; + + if (checkfn != null) + z.adler = check = z._adler.adler32(0L, null, 0, 0); + } + + int proc(ZStream z, int r) { + int t; // temporary storage + int b; // bit buffer + int k; // bits in bit buffer + int p; // input data pointer + int n; // bytes available there + int q; // output window write pointer + int m; // bytes to end of window or read pointer + // copy input/output information to locals (UPDATE macro restores) + {p = z.next_in_index; n = z.avail_in; b = bitb; k = bitk;} + {q = write; m = (int)(q < read ? read - q - 1 : end - q);} + + // process input based on current state + while (true) { + switch (mode) { + case TYPE: + while (k < (3)) { + if (n != 0) { + r = Z_OK; + } + else { + bitb = b; bitk = k; + z.avail_in = n; + z.total_in += p - z.next_in_index; z.next_in_index = p; + write = q; + return inflate_flush(z, r); + }; + + n--; + + b |= (z.next_in[p++] & 0xff) << k; + + k += 8; + } + + t = (int)(b & 7); + last = t & 1; + + switch (t >>> 1) { + case 0: // stored + {b >>>= (3); k -= (3);} + + t = k & 7; // go to byte boundary + {b >>>= (t); k -= (t);} + mode = LENS; // get length of stored block + break; + + case 1: { // fixed + int[] bl = new int[1]; + int[] bd = new int[1]; + int[][] tl = new int[1][]; + int[][] td = new int[1][]; + InfTree.inflate_trees_fixed(bl, bd, tl, td, z); + codes.init(bl[0], bd[0], tl[0], 0, td[0], 0, z); + } + + {b >>>= (3); k -= (3);} + + mode = CODES; + break; + + case 2: // dynamic + {b >>>= (3); k -= (3);} + + mode = TABLE; + break; + + case 3: // illegal + {b >>>= (3); k -= (3);} + + mode = BAD; + z.msg = "invalid block type"; + r = Z_DATA_ERROR; + bitb = b; bitk = k; + z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; + write = q; + return inflate_flush(z, r); + } + + break; + + case LENS: + while (k < (32)) { + if (n != 0) { + r = Z_OK; + } + else { + bitb = b; bitk = k; + z.avail_in = n; + z.total_in += p - z.next_in_index; z.next_in_index = p; + write = q; + return inflate_flush(z, r); + }; + + n--; + + b |= (z.next_in[p++] & 0xff) << k; + + k += 8; + } + + if ((((~b) >>> 16) & 0xffff) != (b & 0xffff)) { + mode = BAD; + z.msg = "invalid stored block lengths"; + r = Z_DATA_ERROR; + bitb = b; bitk = k; + z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; + write = q; + return inflate_flush(z, r); + } + + left = (b & 0xffff); + b = k = 0; // dump bits + mode = left != 0 ? STORED : (last != 0 ? DRY : TYPE); + break; + + case STORED: + if (n == 0) { + bitb = b; bitk = k; + z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; + write = q; + return inflate_flush(z, r); + } + + if (m == 0) { + if (q == end && read != 0) { + q = 0; m = (int)(q < read ? read - q - 1 : end - q); + } + + if (m == 0) { + write = q; + r = inflate_flush(z, r); + q = write; m = (int)(q < read ? read - q - 1 : end - q); + + if (q == end && read != 0) { + q = 0; m = (int)(q < read ? read - q - 1 : end - q); + } + + if (m == 0) { + bitb = b; bitk = k; + z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; + write = q; + return inflate_flush(z, r); + } + } + } + + r = Z_OK; + t = left; + + if (t > n) t = n; + + if (t > m) t = m; + + System.arraycopy(z.next_in, p, window, q, t); + p += t; n -= t; + q += t; m -= t; + + if ((left -= t) != 0) + break; + + mode = last != 0 ? DRY : TYPE; + break; + + case TABLE: + while (k < (14)) { + if (n != 0) { + r = Z_OK; + } + else { + bitb = b; bitk = k; + z.avail_in = n; + z.total_in += p - z.next_in_index; z.next_in_index = p; + write = q; + return inflate_flush(z, r); + }; + + n--; + + b |= (z.next_in[p++] & 0xff) << k; + + k += 8; + } + + table = t = (b & 0x3fff); + + if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29) { + mode = BAD; + z.msg = "too many length or distance symbols"; + r = Z_DATA_ERROR; + bitb = b; bitk = k; + z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; + write = q; + return inflate_flush(z, r); + } + + t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f); + + if (blens == null || blens.length < t) { + blens = new int[t]; + } + else { + for (int i = 0; i < t; i++) {blens[i] = 0;} + } + + {b >>>= (14); k -= (14);} + + index = 0; + mode = BTREE; + + case BTREE: + while (index < 4 + (table >>> 10)) { + while (k < (3)) { + if (n != 0) { + r = Z_OK; + } + else { + bitb = b; bitk = k; + z.avail_in = n; + z.total_in += p - z.next_in_index; z.next_in_index = p; + write = q; + return inflate_flush(z, r); + }; + + n--; + + b |= (z.next_in[p++] & 0xff) << k; + + k += 8; + } + + blens[border[index++]] = b & 7; + {b >>>= (3); k -= (3);} + } + + while (index < 19) { + blens[border[index++]] = 0; + } + + bb[0] = 7; + t = inftree.inflate_trees_bits(blens, bb, tb, hufts, z); + + if (t != Z_OK) { + r = t; + + if (r == Z_DATA_ERROR) { + blens = null; + mode = BAD; + } + + bitb = b; bitk = k; + z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; + write = q; + return inflate_flush(z, r); + } + + index = 0; + mode = DTREE; + + case DTREE: + while (true) { + t = table; + + if (!(index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))) { + break; + } + + int[] h; + int i, j, c; + t = bb[0]; + + while (k < (t)) { + if (n != 0) { + r = Z_OK; + } + else { + bitb = b; bitk = k; + z.avail_in = n; + z.total_in += p - z.next_in_index; z.next_in_index = p; + write = q; + return inflate_flush(z, r); + }; + + n--; + + b |= (z.next_in[p++] & 0xff) << k; + + k += 8; + } + + if (tb[0] == -1) { + //System.err.println("null..."); + } + + t = hufts[(tb[0] + (b & inflate_mask[t])) * 3 + 1]; + c = hufts[(tb[0] + (b & inflate_mask[t])) * 3 + 2]; + + if (c < 16) { + b >>>= (t); k -= (t); + blens[index++] = c; + } + else { // c == 16..18 + i = c == 18 ? 7 : c - 14; + j = c == 18 ? 11 : 3; + + while (k < (t + i)) { + if (n != 0) { + r = Z_OK; + } + else { + bitb = b; bitk = k; + z.avail_in = n; + z.total_in += p - z.next_in_index; z.next_in_index = p; + write = q; + return inflate_flush(z, r); + }; + + n--; + + b |= (z.next_in[p++] & 0xff) << k; + + k += 8; + } + + b >>>= (t); k -= (t); + j += (b & inflate_mask[i]); + b >>>= (i); k -= (i); + i = index; + t = table; + + if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) || + (c == 16 && i < 1)) { + blens = null; + mode = BAD; + z.msg = "invalid bit length repeat"; + r = Z_DATA_ERROR; + bitb = b; bitk = k; + z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; + write = q; + return inflate_flush(z, r); + } + + c = c == 16 ? blens[i - 1] : 0; + + do { + blens[i++] = c; + } + while (--j != 0); + + index = i; + } + } + + tb[0] = -1; + { + int[] bl = new int[1]; + int[] bd = new int[1]; + int[] tl = new int[1]; + int[] td = new int[1]; + bl[0] = 9; // must be <= 9 for lookahead assumptions + bd[0] = 6; // must be <= 9 for lookahead assumptions + t = table; + t = inftree.inflate_trees_dynamic(257 + (t & 0x1f), + 1 + ((t >> 5) & 0x1f), + blens, bl, bd, tl, td, hufts, z); + + if (t != Z_OK) { + if (t == Z_DATA_ERROR) { + blens = null; + mode = BAD; + } + + r = t; + bitb = b; bitk = k; + z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; + write = q; + return inflate_flush(z, r); + } + + codes.init(bl[0], bd[0], hufts, tl[0], hufts, td[0], z); + } + mode = CODES; + + case CODES: + bitb = b; bitk = k; + z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; + write = q; + + if ((r = codes.proc(this, z, r)) != Z_STREAM_END) { + return inflate_flush(z, r); + } + + r = Z_OK; + codes.free(z); + p = z.next_in_index; n = z.avail_in; b = bitb; k = bitk; + q = write; m = (int)(q < read ? read - q - 1 : end - q); + + if (last == 0) { + mode = TYPE; + break; + } + + mode = DRY; + + case DRY: + write = q; + r = inflate_flush(z, r); + q = write; m = (int)(q < read ? read - q - 1 : end - q); + + if (read != write) { + bitb = b; bitk = k; + z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; + write = q; + return inflate_flush(z, r); + } + + mode = DONE; + + case DONE: + r = Z_STREAM_END; + bitb = b; bitk = k; + z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; + write = q; + return inflate_flush(z, r); + + case BAD: + r = Z_DATA_ERROR; + bitb = b; bitk = k; + z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; + write = q; + return inflate_flush(z, r); + + default: + r = Z_STREAM_ERROR; + bitb = b; bitk = k; + z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; + write = q; + return inflate_flush(z, r); + } + } + } + + void free(ZStream z) { + reset(z, null); + window = null; + hufts = null; + //ZFREE(z, s); + } + + void set_dictionary(byte[] d, int start, int n) { + System.arraycopy(d, start, window, 0, n); + read = write = n; + } + + // Returns true if inflate is currently at the end of a block generated + // by Z_SYNC_FLUSH or Z_FULL_FLUSH. + int sync_point() { + return mode == LENS ? 1 : 0; + } + + // copy as much as possible from the sliding window to the output area + int inflate_flush(ZStream z, int r) { + int n; + int p; + int q; + // local copies of source and destination pointers + p = z.next_out_index; + q = read; + // compute number of bytes to copy as far as end of window + n = (int)((q <= write ? write : end) - q); + + if (n > z.avail_out) n = z.avail_out; + + if (n != 0 && r == Z_BUF_ERROR) r = Z_OK; + + // update counters + z.avail_out -= n; + z.total_out += n; + + // update check information + if (checkfn != null) + z.adler = check = z._adler.adler32(check, window, q, n); + + // copy as far as end of window + System.arraycopy(window, q, z.next_out, p, n); + p += n; + q += n; + + // see if more to copy at beginning of window + if (q == end) { + // wrap pointers + q = 0; + + if (write == end) + write = 0; + + // compute bytes to copy + n = write - q; + + if (n > z.avail_out) n = z.avail_out; + + if (n != 0 && r == Z_BUF_ERROR) r = Z_OK; + + // update counters + z.avail_out -= n; + z.total_out += n; + + // update check information + if (checkfn != null) + z.adler = check = z._adler.adler32(check, window, q, n); + + // copy + System.arraycopy(window, q, z.next_out, p, n); + p += n; + q += n; + } + + // update pointers + z.next_out_index = p; + read = q; + // done + return r; + } +}