public override void Write(byte[] buffer, int offset, int count) { if (count == 0) { return; } this.next_in = buffer; this.next_in_index = offset; this.avail_in = count; do { this.next_out = this._bufffer; this.next_out_index = 0; this.avail_out = this._bufffer.Length; ZLibStatus err = compress ? this.deflate(this.FlushMode) : this.inflate(this.FlushMode); if (err != ZLibStatus.Z_OK) { throw new IOException((compress ? "de" : "in") + "flating: " + this.msg); } this._output.Write(this._bufffer, 0, this._bufffer.Length - this.avail_out); }while (this.avail_in > 0 || this.avail_out == 0); }
public override int Read(byte[] buffer, int offset, int count) { if (count == 0) { return(0); } this._compressor.next_out = buffer; this._compressor.next_out_index = offset; this._compressor.avail_out = count; ZLibStatus err = ZLibStatus.Z_OK; do { if (this._compressor.avail_in == 0 && !_noMoreInput) { // if buffer is empty and more input is available, refill it this._compressor.next_in_index = 0; this._compressor.avail_in = _input.Read(_buffer, 0, _buffer.Length); //(bufsize<z.avail_out ? bufsize : z.avail_out)); if (this._compressor.avail_in <= 0) { this._compressor.avail_in = 0; _noMoreInput = true; } } switch (_compressionMode) { case CompressionMode.Compress: err = this._compressor.deflate(this.FlushMode); break; case CompressionMode.Decompress: err = this._compressor.inflate(this.FlushMode); break; default: break; } if (_noMoreInput && err == ZLibStatus.Z_BUF_ERROR) { return(0); } if (err != ZLibStatus.Z_OK && err != ZLibStatus.Z_STREAM_END) { //throw new IOException((compress ? "de" : "in") + "flating: " + z.msg); throw new IOException(string.Format("{0}ion error: {1}", _compressionMode, this._compressor.msg)); } if ((_noMoreInput || err == ZLibStatus.Z_STREAM_END) && this._compressor.avail_out == count) { return(0); } }while (this._compressor.avail_out == count && err == ZLibStatus.Z_OK); //Console.Error.WriteLine("("+(len-z.avail_out)+")"); return(count - this._compressor.avail_out); }
internal ZLibStatus ProcessCodes(InfBlocks s, ZStream z, ZLibStatus r) { int j; // temporary storage int tindex; // temporary pointer int e; // extra bits or operation int b = 0; // bit buffer int k = 0; // bits in bit buffer int p = 0; // input data pointer int n; // bytes available there int q; // output window write pointer int m; // bytes to end of window or read pointer int f; // pointer to copy strings from // copy input/output information to locals (UPDATE macro restores) p = z.next_in_index; n = z.avail_in; b = s.bitb; k = s.bitk; q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q; // process input and output based on current state while (true) { switch (this._mode) { // waiting for "i:"=input, "o:"=output, "x:"=nothing case InflateCodeMode.START: // x: set up for InflateCodeMode.LEN if (m >= 258 && n >= 10) { s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; r = InflateFast(this._lbits, this._dbits, this._ltree, this._ltreeIndex, this._dtree, _dtreeIndex, s, z); p = z.next_in_index; n = z.avail_in; b = s.bitb; k = s.bitk; q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q; if (r != ZLibStatus.Z_OK) { this._mode = r == ZLibStatus.Z_STREAM_END ? InflateCodeMode.WASH : InflateCodeMode.BADCODE; break; } } this._need = this._lbits; this._tree = this._ltree; this._treeIndex = this._ltreeIndex; this._mode = InflateCodeMode.LEN; goto case InflateCodeMode.LEN; case InflateCodeMode.LEN: // i: get length/literal/eob next j = this._need; while (k < (j)) { if (n != 0) { r = ZLibStatus.Z_OK; } else { s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return(s.inflate_flush(z, r)); } n--; b |= (z.next_in[p++] & 0xff) << k; k += 8; } tindex = (this._treeIndex + (b & inflate_mask[j])) * 3; b >>= (this._tree[tindex + 1]); k -= (this._tree[tindex + 1]); e = this._tree[tindex]; if (e == 0) { // literal this._lit = this._tree[tindex + 2]; this._mode = InflateCodeMode.LIT; break; } if ((e & 16) != 0) { // length this._get = e & 15; this._len = this._tree[tindex + 2]; this._mode = InflateCodeMode.LENEXT; break; } if ((e & 64) == 0) { // next table this._need = e; this._treeIndex = tindex / 3 + this._tree[tindex + 2]; break; } if ((e & 32) != 0) { // end of block this._mode = InflateCodeMode.WASH; break; } this._mode = InflateCodeMode.BADCODE; // invalid code z.msg = "invalid literal/length code"; r = ZLibStatus.Z_DATA_ERROR; s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return(s.inflate_flush(z, r)); case InflateCodeMode.LENEXT: // i: getting length extra (have base) j = this._get; while (k < (j)) { if (n != 0) { r = ZLibStatus.Z_OK; } else { s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return(s.inflate_flush(z, r)); } n--; b |= (z.next_in[p++] & 0xff) << k; k += 8; } this._len += (b & inflate_mask[j]); b >>= j; k -= j; this._need = this._dbits; this._tree = this._dtree; this._treeIndex = _dtreeIndex; this._mode = InflateCodeMode.DIST; goto case InflateCodeMode.DIST; case InflateCodeMode.DIST: // i: get distance next j = this._need; while (k < (j)) { if (n != 0) { r = ZLibStatus.Z_OK; } else { s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return(s.inflate_flush(z, r)); } n--; b |= (z.next_in[p++] & 0xff) << k; k += 8; } tindex = (this._treeIndex + (b & inflate_mask[j])) * 3; b >>= this._tree[tindex + 1]; k -= this._tree[tindex + 1]; e = (this._tree[tindex]); if ((e & 16) != 0) { // distance this._get = e & 15; this._dist = this._tree[tindex + 2]; this._mode = InflateCodeMode.DISTEXT; break; } if ((e & 64) == 0) { // next table this._need = e; this._treeIndex = tindex / 3 + this._tree[tindex + 2]; break; } this._mode = InflateCodeMode.BADCODE; // invalid code z.msg = "invalid distance code"; r = ZLibStatus.Z_DATA_ERROR; s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return(s.inflate_flush(z, r)); case InflateCodeMode.DISTEXT: // i: getting distance extra j = this._get; while (k < (j)) { if (n != 0) { r = ZLibStatus.Z_OK; } else { s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return(s.inflate_flush(z, r)); } n--; b |= (z.next_in[p++] & 0xff) << k; k += 8; } this._dist += (b & inflate_mask[j]); b >>= j; k -= j; this._mode = InflateCodeMode.COPY; goto case InflateCodeMode.COPY; case InflateCodeMode.COPY: // o: copying bytes in window, waiting for space f = q - this._dist; while (f < 0) { // modulo window size-"while" instead f += s.end; // of "if" handles invalid distances } while (this._len != 0) { if (m == 0) { if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; } if (m == 0) { s.write = q; r = s.inflate_flush(z, r); q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q; if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; } if (m == 0) { s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return(s.inflate_flush(z, r)); } } } s.window[q++] = s.window[f++]; m--; if (f == s.end) { f = 0; } this._len--; } this._mode = InflateCodeMode.START; break; case InflateCodeMode.LIT: // o: got literal, waiting for output space if (m == 0) { if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; } if (m == 0) { s.write = q; r = s.inflate_flush(z, r); q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q; if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; } if (m == 0) { s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return(s.inflate_flush(z, r)); } } } r = ZLibStatus.Z_OK; s.window[q++] = (byte)this._lit; m--; this._mode = InflateCodeMode.START; break; case InflateCodeMode.WASH: // o: got eob, possibly more output if (k > 7) { // return unused byte, if any k -= 8; n++; p--; // can always return one } s.write = q; r = s.inflate_flush(z, r); q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q; if (s.read != s.write) { s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return(s.inflate_flush(z, r)); } this._mode = InflateCodeMode.END; goto case InflateCodeMode.END; case InflateCodeMode.END: r = ZLibStatus.Z_STREAM_END; s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return(s.inflate_flush(z, r)); case InflateCodeMode.BADCODE: // x: got error r = ZLibStatus.Z_DATA_ERROR; s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return(s.inflate_flush(z, r)); default: r = ZLibStatus.Z_STREAM_ERROR; s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return(s.inflate_flush(z, r)); } } }
// copy as much as possible from the sliding window to the output area internal ZLibStatus inflate_flush(ICompressor z, ZLibStatus 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 == ZLibStatus.Z_BUF_ERROR) r = ZLibStatus.Z_OK; // update counters z.avail_out -= n; z.total_out += n; // update check information if (checkfn != null) z.adler = check = Adler32.adler32(check, window, q, n); // copy as far as end of window System.Array.Copy(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 == ZLibStatus.Z_BUF_ERROR) r = ZLibStatus.Z_OK; // update counters z.avail_out -= n; z.total_out += n; // update check information if (checkfn != null) z.adler = check = Adler32.adler32(check, window, q, n); // copy System.Array.Copy(window, q, z.next_out, p, n); p += n; q += n; } // update pointers z.next_out_index = p; read = q; // done return r; }
internal ZLibStatus proc(ICompressor z, ZLibStatus r) { int t; // temporary storage ZLibStatus tt; 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 InflateBlockMode.TYPE: while (k < (3)) { if (n != 0) { r = ZLibStatus.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 = InflateBlockMode.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][]; InflateTree.InflateTreesFixed(bl, bd, tl, td); codesinit(bl[0], bd[0], tl[0], 0, td[0], 0); } { b >>= (3); k -= (3); } mode = InflateBlockMode.CODES; break; case 2: { // dynamic b >>= (3); k -= (3); } mode = InflateBlockMode.TABLE; break; case 3: { // illegal b >>= (3); k -= (3); } mode = InflateBlockMode.BAD; z.msg = "invalid block type"; r = ZLibStatus.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 InflateBlockMode.LENS: while (k < (32)) { if (n != 0) { r = ZLibStatus.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 = InflateBlockMode.BAD; z.msg = "invalid stored block lengths"; r = ZLibStatus.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 ? InflateBlockMode.STORED : (last != 0 ? InflateBlockMode.DRY : InflateBlockMode.TYPE); break; case InflateBlockMode.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 = ZLibStatus.Z_OK; t = left; if (t > n) t = n; if (t > m) t = m; System.Array.Copy(z.next_in, p, window, q, t); p += t; n -= t; q += t; m -= t; if ((left -= t) != 0) break; mode = last != 0 ? InflateBlockMode.DRY : InflateBlockMode.TYPE; break; case InflateBlockMode.TABLE: while (k < (14)) { if (n != 0) { r = ZLibStatus.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 = InflateBlockMode.BAD; z.msg = "too many length or distance symbols"; r = ZLibStatus.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 = InflateBlockMode.BTREE; goto case InflateBlockMode.BTREE; case InflateBlockMode.BTREE: while (index < 4 + (table >> 10)) { while (k < (3)) { if (n != 0) { r = ZLibStatus.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; tt = inftree.InflateTreesBits(blens, bb, tb, hufts, z); if (tt != ZLibStatus.Z_OK) { r = tt; if (r == ZLibStatus.Z_DATA_ERROR) { blens = null; mode = InflateBlockMode.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 = InflateBlockMode.DTREE; goto case InflateBlockMode.DTREE; case InflateBlockMode.DTREE: while (true) { t = table; if (!(index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))) { break; } int i, j, c; t = bb[0]; while (k < (t)) { if (n != 0) { r = ZLibStatus.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 = ZLibStatus.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 = InflateBlockMode.BAD; z.msg = "invalid bit length repeat"; r = ZLibStatus.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; tt = inftree.InflateTreesDynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f), blens, bl, bd, tl, td, hufts, z); if (tt != ZLibStatus.Z_OK) { if (tt == ZLibStatus.Z_DATA_ERROR) { blens = null; mode = InflateBlockMode.BAD; } r = tt; 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); } codesinit(bl[0], bd[0], hufts, tl[0], hufts, td[0]); } mode = InflateBlockMode.CODES; goto case InflateBlockMode.CODES; case InflateBlockMode.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 = codesproc(this, z, r)) != ZLibStatus.Z_STREAM_END) { return inflate_flush(z, r); } r = ZLibStatus.Z_OK; 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 = InflateBlockMode.TYPE; break; } mode = InflateBlockMode.DRY; goto case InflateBlockMode.DRY; case InflateBlockMode.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 = InflateBlockMode.DONE; goto case InflateBlockMode.DONE; case InflateBlockMode.DONE: r = ZLibStatus.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 InflateBlockMode.BAD: r = ZLibStatus.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 = ZLibStatus.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); } } }
internal ZLibStatus codesproc(InflateBlocks s, ZStream z, ZLibStatus r) { int j; // temporary storage int tindex; // temporary pointer int e; // extra bits or operation int b = 0; // bit buffer int k = 0; // bits in bit buffer int p = 0; // input data pointer int n; // bytes available there int q; // output window write pointer int m; // bytes to end of window or read pointer int f; // pointer to copy strings from // copy input/output information to locals (UPDATE macro restores) p = z.next_in_index; n = z.avail_in; b = s.bitb; k = s.bitk; q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q; // process input and output based on current state while (true) { switch (mode) { // waiting for "i:"=input, "o:"=output, "x:"=nothing case InflateCodeMode.START: // x: set up for LEN if (m >= 258 && n >= 10) { s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; r = inflate_fast(lbits, dbits, ltree, ltree_index, dtree, dtree_index, s, z); p = z.next_in_index; n = z.avail_in; b = s.bitb; k = s.bitk; q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q; if (r != ZLibStatus.Z_OK) { mode = r == ZLibStatus.Z_STREAM_END ? InflateCodeMode.WASH : InflateCodeMode.BADCODE; break; } } need = lbits; tree = ltree; tree_index = ltree_index; mode = InflateCodeMode.LEN; goto case InflateCodeMode.LEN; case InflateCodeMode.LEN: // i: get length/literal/eob next j = need; while (k < (j)) { if (n != 0) r = ZLibStatus.Z_OK; else { s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return s.inflate_flush(z, r); } n--; b |= (z.next_in[p++] & 0xff) << k; k += 8; } tindex = (tree_index + (b & inflate_mask[j])) * 3; b >>= (tree[tindex + 1]); k -= (tree[tindex + 1]); e = tree[tindex]; if (e == 0) { // literal lit = tree[tindex + 2]; mode = InflateCodeMode.LIT; break; } if ((e & 16) != 0) { // length get = e & 15; len = tree[tindex + 2]; mode = InflateCodeMode.LENEXT; break; } if ((e & 64) == 0) { // next table need = e; tree_index = tindex / 3 + tree[tindex + 2]; break; } if ((e & 32) != 0) { // end of block mode = InflateCodeMode.WASH; break; } mode = InflateCodeMode.BADCODE; // invalid code z.msg = "invalid literal/length code"; r = ZLibStatus.Z_DATA_ERROR; s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return s.inflate_flush(z, r); case InflateCodeMode.LENEXT: // i: getting length extra (have base) j = get; while (k < (j)) { if (n != 0) r = ZLibStatus.Z_OK; else { s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return s.inflate_flush(z, r); } n--; b |= (z.next_in[p++] & 0xff) << k; k += 8; } len += (b & inflate_mask[j]); b >>= j; k -= j; need = dbits; tree = dtree; tree_index = dtree_index; mode = InflateCodeMode.DIST; goto case InflateCodeMode.DIST; case InflateCodeMode.DIST: // i: get distance next j = need; while (k < (j)) { if (n != 0) r = ZLibStatus.Z_OK; else { s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return s.inflate_flush(z, r); } n--; b |= (z.next_in[p++] & 0xff) << k; k += 8; } tindex = (tree_index + (b & inflate_mask[j])) * 3; b >>= tree[tindex + 1]; k -= tree[tindex + 1]; e = (tree[tindex]); if ((e & 16) != 0) { // distance get = e & 15; dist = tree[tindex + 2]; mode = InflateCodeMode.DISTEXT; break; } if ((e & 64) == 0) { // next table need = e; tree_index = tindex / 3 + tree[tindex + 2]; break; } mode = InflateCodeMode.BADCODE; // invalid code z.msg = "invalid distance code"; r = ZLibStatus.Z_DATA_ERROR; s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return s.inflate_flush(z, r); case InflateCodeMode.DISTEXT: // i: getting distance extra j = get; while (k < (j)) { if (n != 0) r = ZLibStatus.Z_OK; else { s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return s.inflate_flush(z, r); } n--; b |= (z.next_in[p++] & 0xff) << k; k += 8; } dist += (b & inflate_mask[j]); b >>= j; k -= j; mode = InflateCodeMode.COPY; goto case InflateCodeMode.COPY; case InflateCodeMode.COPY: // o: copying bytes in window, waiting for space f = q - dist; while (f < 0) { // modulo window size-"while" instead f += s.end; // of "if" handles invalid distances } while (len != 0) { if (m == 0) { if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; } if (m == 0) { s.write = q; r = s.inflate_flush(z, r); q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q; if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; } if (m == 0) { s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return s.inflate_flush(z, r); } } } s.window[q++] = s.window[f++]; m--; if (f == s.end) f = 0; len--; } mode = InflateCodeMode.START; break; case InflateCodeMode.LIT: // o: got literal, waiting for output space if (m == 0) { if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; } if (m == 0) { s.write = q; r = s.inflate_flush(z, r); q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q; if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; } if (m == 0) { s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return s.inflate_flush(z, r); } } } r = ZLibStatus.Z_OK; s.window[q++] = (byte)lit; m--; mode = InflateCodeMode.START; break; case InflateCodeMode.WASH: // o: got eob, possibly more output if (k > 7) { // return unused byte, if any k -= 8; n++; p--; // can always return one } s.write = q; r = s.inflate_flush(z, r); q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q; if (s.read != s.write) { s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return s.inflate_flush(z, r); } mode = InflateCodeMode.END; goto case InflateCodeMode.END; case InflateCodeMode.END: r = ZLibStatus.Z_STREAM_END; s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return s.inflate_flush(z, r); case InflateCodeMode.BADCODE: // x: got error r = ZLibStatus.Z_DATA_ERROR; s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return s.inflate_flush(z, r); default: r = ZLibStatus.Z_STREAM_ERROR; s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return s.inflate_flush(z, r); } } }
// copy as much as possible from the sliding window to the output area internal ZLibStatus inflate_flush(ICompressor z, ZLibStatus 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 == ZLibStatus.Z_BUF_ERROR) { r = ZLibStatus.Z_OK; } // update counters z.avail_out -= n; z.total_out += n; // update check information if (checkfn != null) { z.adler = check = Adler32.adler32(check, window, q, n); } // copy as far as end of window System.Array.Copy(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 == ZLibStatus.Z_BUF_ERROR) { r = ZLibStatus.Z_OK; } // update counters z.avail_out -= n; z.total_out += n; // update check information if (checkfn != null) { z.adler = check = Adler32.adler32(check, window, q, n); } // copy System.Array.Copy(window, q, z.next_out, p, n); p += n; q += n; } // update pointers z.next_out_index = p; read = q; // done return(r); }
internal ZLibStatus proc(ICompressor z, ZLibStatus r) { int t; // temporary storage ZLibStatus tt; 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 InflateBlockMode.TYPE: while (k < (3)) { if (n != 0) { r = ZLibStatus.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 = InflateBlockMode.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][]; InflateTree.InflateTreesFixed(bl, bd, tl, td, z); codesinit(bl[0], bd[0], tl[0], 0, td[0], 0, z); } { b >>= (3); k -= (3); } mode = InflateBlockMode.CODES; break; case 2: { // dynamic b >>= (3); k -= (3); } mode = InflateBlockMode.TABLE; break; case 3: { // illegal b >>= (3); k -= (3); } mode = InflateBlockMode.BAD; z.msg = "invalid block type"; r = ZLibStatus.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 InflateBlockMode.LENS: while (k < (32)) { if (n != 0) { r = ZLibStatus.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 = InflateBlockMode.BAD; z.msg = "invalid stored block lengths"; r = ZLibStatus.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 ? InflateBlockMode.STORED : (last != 0 ? InflateBlockMode.DRY : InflateBlockMode.TYPE); break; case InflateBlockMode.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 = ZLibStatus.Z_OK; t = left; if (t > n) { t = n; } if (t > m) { t = m; } System.Array.Copy(z.next_in, p, window, q, t); p += t; n -= t; q += t; m -= t; if ((left -= t) != 0) { break; } mode = last != 0 ? InflateBlockMode.DRY : InflateBlockMode.TYPE; break; case InflateBlockMode.TABLE: while (k < (14)) { if (n != 0) { r = ZLibStatus.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 = InflateBlockMode.BAD; z.msg = "too many length or distance symbols"; r = ZLibStatus.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 = InflateBlockMode.BTREE; goto case InflateBlockMode.BTREE; case InflateBlockMode.BTREE: while (index < 4 + (table >> 10)) { while (k < (3)) { if (n != 0) { r = ZLibStatus.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; tt = inftree.InflateTreesBits(blens, bb, tb, hufts, z); if (tt != ZLibStatus.Z_OK) { r = tt; if (r == ZLibStatus.Z_DATA_ERROR) { blens = null; mode = InflateBlockMode.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 = InflateBlockMode.DTREE; goto case InflateBlockMode.DTREE; case InflateBlockMode.DTREE: while (true) { t = table; if (!(index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))) { break; } int i, j, c; t = bb[0]; while (k < (t)) { if (n != 0) { r = ZLibStatus.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 = ZLibStatus.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 = InflateBlockMode.BAD; z.msg = "invalid bit length repeat"; r = ZLibStatus.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; tt = inftree.InflateTreesDynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f), blens, bl, bd, tl, td, hufts, z); if (tt != ZLibStatus.Z_OK) { if (tt == ZLibStatus.Z_DATA_ERROR) { blens = null; mode = InflateBlockMode.BAD; } r = tt; 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)); } codesinit(bl[0], bd[0], hufts, tl[0], hufts, td[0], z); } mode = InflateBlockMode.CODES; goto case InflateBlockMode.CODES; case InflateBlockMode.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 = codesproc(this, z, r)) != ZLibStatus.Z_STREAM_END) { return(inflate_flush(z, r)); } r = ZLibStatus.Z_OK; codesfree(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 = InflateBlockMode.TYPE; break; } mode = InflateBlockMode.DRY; goto case InflateBlockMode.DRY; case InflateBlockMode.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 = InflateBlockMode.DONE; goto case InflateBlockMode.DONE; case InflateBlockMode.DONE: r = ZLibStatus.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 InflateBlockMode.BAD: r = ZLibStatus.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 = ZLibStatus.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)); } } }