/// <summary> /// Skips n decompressed bytes in the stream. /// </summary> /// <param name="n">The number of bytes to skip.</param> public long Skip(long n) { int len = 512; if (n < len) { len = (int)n; } byte[] tmp = new byte[len]; return((long)ZLibUtil.ReadInput(this, tmp, 0, tmp.Length)); }
///<summary> /// Reverse the first count bits of a code, using straightforward code (a faster /// method would use a table) ///</summary> private static int bi_reverse(int code, int len) { int res = 0; do { res |= code & 1; code = ZLibUtil.URShift(code, 1); res <<= 1; }while (--len > 0); return(ZLibUtil.URShift(res, 1)); }
/// <summary> /// Mapping from a distance to a distance code. dist is the distance - 1 and /// must not have side effects. _dist_code[256] and _dist_code[257] are never /// used. /// </summary> internal static int d_code(int dist) { return((dist) < 256 ? ZLibUtil._dist_code[dist] : ZLibUtil._dist_code[256 + (ZLibUtil.URShift((dist), 7))]); }
/// <summary> /// Block processing functions /// </summary> internal 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 WritePos pointer int m; // bytes to End of Window or ReadPos pointer // copy input/output information to locals (UPDATE macro restores) { p = z.next_in_index; n = z.avail_in; b = BitB; k = BitK; } { q = WritePos; m = (int)(q < ReadPos ? ReadPos - q - 1 : End - q); } // process input based on current state while (true) { switch (mode) { case InflateBlockMode.TYPE: while (k < (3)) { if (n != 0) { r = (int)ZLibResultCode.Z_OK; } else { BitB = b; BitK = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; WritePos = q; return(inflate_flush(z, r)); } ; n--; b |= (z.next_in[p++] & 0xff) << k; k += 8; } t = (int)(b & 7); last = t & 1; switch (ZLibUtil.URShift(t, 1)) { case 0: // stored { b = ZLibUtil.URShift(b, (3)); k -= (3); } t = k & 7; // go to byte boundary { b = ZLibUtil.URShift(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][]; InfTree.inflate_trees_fixed(bl, bd, tl, td, z); codes = new InfCodes(bl[0], bd[0], tl[0], td[0], z); } { b = ZLibUtil.URShift(b, (3)); k -= (3); } mode = InflateBlockMode.CODES; break; case 2: // dynamic { b = ZLibUtil.URShift(b, (3)); k -= (3); } mode = InflateBlockMode.TABLE; break; case 3: // illegal { b = ZLibUtil.URShift(b, (3)); k -= (3); } mode = InflateBlockMode.BAD; z.msg = "invalid block type"; r = (int)ZLibResultCode.Z_DATA_ERROR; BitB = b; BitK = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; WritePos = q; return(inflate_flush(z, r)); } break; case InflateBlockMode.LENS: while (k < (32)) { if (n != 0) { r = (int)ZLibResultCode.Z_OK; } else { BitB = b; BitK = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; WritePos = q; return(inflate_flush(z, r)); } ; n--; b |= (z.next_in[p++] & 0xff) << k; k += 8; } if (((ZLibUtil.URShift((~b), 16)) & 0xffff) != (b & 0xffff)) { mode = InflateBlockMode.BAD; z.msg = "invalid stored block lengths"; r = (int)ZLibResultCode.Z_DATA_ERROR; BitB = b; BitK = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; WritePos = 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; WritePos = q; return(inflate_flush(z, r)); } if (m == 0) { if (q == End && ReadPos != 0) { q = 0; m = (int)(q < ReadPos ? ReadPos - q - 1 : End - q); } if (m == 0) { WritePos = q; r = inflate_flush(z, r); q = WritePos; m = (int)(q < ReadPos ? ReadPos - q - 1 : End - q); if (q == End && ReadPos != 0) { q = 0; m = (int)(q < ReadPos ? ReadPos - 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; WritePos = q; return(inflate_flush(z, r)); } } } r = (int)ZLibResultCode.Z_OK; t = left; if (t > n) { t = n; } if (t > m) { t = m; } 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 = (int)ZLibResultCode.Z_OK; } else { BitB = b; BitK = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; WritePos = 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 = (int)ZLibResultCode.Z_DATA_ERROR; BitB = b; BitK = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; WritePos = q; return(inflate_flush(z, r)); } t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f); blens = new int[t]; { b = ZLibUtil.URShift(b, (14)); k -= (14); } index = 0; mode = InflateBlockMode.BTREE; goto case InflateBlockMode.BTREE; case InflateBlockMode.BTREE: while (index < 4 + (ZLibUtil.URShift(table, 10))) { while (k < (3)) { if (n != 0) { r = (int)ZLibResultCode.Z_OK; } else { BitB = b; BitK = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; WritePos = q; return(inflate_flush(z, r)); } ; n--; b |= (z.next_in[p++] & 0xff) << k; k += 8; } blens[ZLibUtil.border[index++]] = b & 7; { b = ZLibUtil.URShift(b, (3)); k -= (3); } } while (index < 19) { blens[ZLibUtil.border[index++]] = 0; } bb[0] = 7; t = InfTree.inflate_trees_bits(blens, bb, tb, hufts, z); if (t != (int)ZLibResultCode.Z_OK) { r = t; if (r == (int)ZLibResultCode.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; WritePos = 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 = (int)ZLibResultCode.Z_OK; } else { BitB = b; BitK = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; WritePos = q; return(inflate_flush(z, r)); } ; n--; b |= (z.next_in[p++] & 0xff) << k; k += 8; } t = hufts[(tb[0] + (b & ZLibUtil.inflate_mask[t])) * 3 + 1]; c = hufts[(tb[0] + (b & ZLibUtil.inflate_mask[t])) * 3 + 2]; if (c < 16) { b = ZLibUtil.URShift(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 = (int)ZLibResultCode.Z_OK; } else { BitB = b; BitK = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; WritePos = q; return(inflate_flush(z, r)); } ; n--; b |= (z.next_in[p++] & 0xff) << k; k += 8; } b = ZLibUtil.URShift(b, (t)); k -= (t); j += (b & ZLibUtil.inflate_mask[i]); b = ZLibUtil.URShift(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 = (int)ZLibResultCode.Z_DATA_ERROR; BitB = b; BitK = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; WritePos = 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 != (int)ZLibResultCode.Z_OK) { if (t == (int)ZLibResultCode.Z_DATA_ERROR) { blens = null; mode = InflateBlockMode.BAD; } r = t; BitB = b; BitK = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; WritePos = q; return(inflate_flush(z, r)); } codes = new InfCodes(bl[0], bd[0], hufts, tl[0], hufts, td[0], z); } blens = null; 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; WritePos = q; if ((r = codes.proc(this, z, r)) != (int)ZLibResultCode.Z_STREAM_END) { return(inflate_flush(z, r)); } r = (int)ZLibResultCode.Z_OK; codes.free(z); p = z.next_in_index; n = z.avail_in; b = BitB; k = BitK; q = WritePos; m = (int)(q < ReadPos ? ReadPos - q - 1 : End - q); if (last == 0) { mode = InflateBlockMode.TYPE; break; } mode = InflateBlockMode.DRY; goto case InflateBlockMode.DRY; case InflateBlockMode.DRY: WritePos = q; r = inflate_flush(z, r); q = WritePos; m = (int)(q < ReadPos ? ReadPos - q - 1 : End - q); if (ReadPos != WritePos) { BitB = b; BitK = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; WritePos = q; return(inflate_flush(z, r)); } mode = InflateBlockMode.DONE; goto case InflateBlockMode.DONE; case InflateBlockMode.DONE: r = (int)ZLibResultCode.Z_STREAM_END; BitB = b; BitK = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; WritePos = q; return(inflate_flush(z, r)); case InflateBlockMode.BAD: r = (int)ZLibResultCode.Z_DATA_ERROR; BitB = b; BitK = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; WritePos = q; return(inflate_flush(z, r)); default: r = (int)ZLibResultCode.Z_STREAM_ERROR; BitB = b; BitK = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; WritePos = q; return(inflate_flush(z, r)); } } }
/// <summary> /// Given a list of code lengths and a maximum table size, make a set of /// tables to decode that set of codes. /// </summary> /// <returns>Return (int)ZLibResultCode.Z_OK on success, (int)ZLibResultCode.Z_DATA_ERROR if the given code set is incomplete (the tables are still built in this case), (int)ZLibResultCode.Z_DATA_ERROR if the input is invalid (an over-subscribed set of lengths), or (int)ZLibResultCode.Z_DATA_ERROR if not enough memory. /// </returns> private static int huft_build(int[] b, int bindex, int n, int s, int[] d, int[] e, int[] t, int[] m, int[] hp, int[] hn, int[] v) { int a; // counter for codes of length k int[] c = new int[InfTreeUtil.BMAX + 1]; // bit length count table int f; // i repeats in table every internalFlush entries int g; // maximum code length int h; // table level int i; // counter, current code int j; // counter int k; // number of bits in current code int l; // bits per table (returned in m) int mask; // (1 << windowBits) - 1, to avoid cc -O bug on HP int p; // pointer into c[], buffer[], or v[] int q; // points to current table int[] r = new int[3]; // table entry for structure assignment int[] u = new int[InfTreeUtil.BMAX]; // table stack int w; // bits before this table == (l * h) int[] x = new int[InfTreeUtil.BMAX + 1]; // bit offsets, then code stack int xp; // pointer into x int y; // number of dummy codes added int z; // number of entries in current table // Generate counts for each bit length p = 0; i = n; do { c[b[bindex + p]]++; p++; i--; // assume all entries <= BMAX }while (i != 0); if (c[0] == n) { // null input--all zero length codes t[0] = -1; m[0] = 0; return((int)ZLibResultCode.Z_OK); } // Find minimum and maximum length, bound *m by those l = m[0]; for (j = 1; j <= InfTreeUtil.BMAX; j++) { if (c[j] != 0) { break; } } k = j; // minimum code length if (l < j) { l = j; } for (i = InfTreeUtil.BMAX; i != 0; i--) { if (c[i] != 0) { break; } } g = i; // maximum code length if (l > i) { l = i; } m[0] = l; // Adjust last length count to fill out codes, if needed for (y = 1 << j; j < i; j++, y <<= 1) { if ((y -= c[j]) < 0) { return((int)ZLibResultCode.Z_DATA_ERROR); } } if ((y -= c[i]) < 0) { return((int)ZLibResultCode.Z_DATA_ERROR); } c[i] += y; // Generate starting offsets into the value table for each length x[1] = j = 0; p = 1; xp = 2; while (--i != 0) { // note that i == g from above x[xp] = (j += c[p]); xp++; p++; } // Make a table of values in order of bit lengths i = 0; p = 0; do { if ((j = b[bindex + p]) != 0) { v[x[j]++] = i; } p++; }while (++i < n); n = x[g]; // set n to length of v // Generate the Huffman codes and for each, make the table entries x[0] = i = 0; // first Huffman code is zero p = 0; // grab values in bit order h = -1; // no tables yet--level -1 w = -l; // bits decoded == (l * h) u[0] = 0; // just to keep compilers happy q = 0; // ditto z = 0; // ditto // go through the bit lengths (k already is bits in shortest code) for (; k <= g; k++) { a = c[k]; while (a-- != 0) { // here i is the Huffman code of length k bits for value *p // make tables up to required level while (k > w + l) { h++; w += l; // previous table always l bits // compute minimum size table less than or equal to l bits z = g - w; z = (z > l)?l:z; // table size upper limit if ((f = 1 << (j = k - w)) > a + 1) { // try a k-windowBits bit table // too few codes for k-windowBits bit table f -= (a + 1); // deduct codes from patterns left xp = k; if (j < z) { while (++j < z) { // try smaller tables up to z bits if ((f <<= 1) <= c[++xp]) { break; // enough codes to use up j bits } f -= c[xp]; // else deduct codes from patterns } } } z = 1 << j; // table entries for j-bit table // allocate new table if (hn[0] + z > InfTreeUtil.MANY) { // (note: doesn't matter for fixed) return((int)ZLibResultCode.Z_DATA_ERROR); // overflow of MANY } u[h] = q = hn[0]; // DEBUG hn[0] += z; // connect to last table, if there is one if (h != 0) { x[h] = i; // save pattern for backing up r[0] = (byte)j; // bits in this table r[1] = (byte)l; // bits to dump before this table j = ZLibUtil.URShift(i, (w - l)); r[2] = (int)(q - u[h - 1] - j); // offset to this table Array.Copy(r, 0, hp, (u[h - 1] + j) * 3, 3); // connect to last table } else { t[0] = q; // first table is returned result } } // set up table entry in r r[1] = (byte)(k - w); if (p >= n) { r[0] = 128 + 64; // out of values--invalid code } else if (v[p] < s) { r[0] = (byte)(v[p] < 256?0:32 + 64); // 256 is End-of-block r[2] = v[p++]; // simple code is just the value } else { r[0] = (byte)(e[v[p] - s] + 16 + 64); // non-simple--look up in lists r[2] = d[v[p++] - s]; } // fill code-like entries with r f = 1 << (k - w); for (j = ZLibUtil.URShift(i, w); j < z; j += f) { Array.Copy(r, 0, hp, (q + j) * 3, 3); } // backwards increment the k-bit code i for (j = 1 << (k - 1); (i & j) != 0; j = ZLibUtil.URShift(j, 1)) { i ^= j; } i ^= j; // backup over finished tables mask = (1 << w) - 1; // needed on HP, cc -O bug while ((i & mask) != x[h]) { h--; // don't need to update q w -= l; mask = (1 << w) - 1; } } } // Return (int)ZLibResultCode.Z_DATA_ERROR if we were given an incomplete table return(y != 0 && g != 1 ? (int)ZLibResultCode.Z_BUF_ERROR : (int)ZLibResultCode.Z_OK); }
/// <summary> /// Block processing method /// </summary> /// <param name="s">An instance of the InfBlocks class</param> /// <param name="z">A ZStream object</param> /// <param name="r">A result code</param> internal int proc(InfBlocks s, ZStream z, int r) { int j; // temporary storage //int[] t; // temporary pointer 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 WritePos pointer int m; // bytes to End of Window or ReadPos 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.WritePos; m = q < s.ReadPos?s.ReadPos - 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 InflateCodesMode.START: // x: set up for InflateCodesMode.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.WritePos = 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.WritePos; m = q < s.ReadPos?s.ReadPos - q - 1:s.End - q; if (r != (int)ZLibResultCode.Z_OK) { mode = r == (int)ZLibResultCode.Z_STREAM_END? InflateCodesMode.WASH: InflateCodesMode.BADCODE; break; } } need = lbits; tree = ltree; tree_index = ltree_index; mode = InflateCodesMode.LEN; goto case InflateCodesMode.LEN; case InflateCodesMode.LEN: // i: get length/literal/eob next j = need; while (k < (j)) { if (n != 0) { r = (int)ZLibResultCode.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.WritePos = q; return(s.inflate_flush(z, r)); } n--; b |= (z.next_in[p++] & 0xff) << k; k += 8; } tindex = (tree_index + (b & ZLibUtil.inflate_mask[j])) * 3; b = ZLibUtil.URShift(b, (tree[tindex + 1])); k -= (tree[tindex + 1]); e = tree[tindex]; if (e == 0) { // literal lit = tree[tindex + 2]; mode = InflateCodesMode.LIT; break; } if ((e & 16) != 0) { // length get_Renamed = e & 15; count = tree[tindex + 2]; mode = InflateCodesMode.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 = InflateCodesMode.WASH; break; } mode = InflateCodesMode.BADCODE; // invalid code z.msg = "invalid literal/length code"; r = (int)ZLibResultCode.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.WritePos = q; return(s.inflate_flush(z, r)); case InflateCodesMode.LENEXT: // i: getting length extra (have base) j = get_Renamed; while (k < (j)) { if (n != 0) { r = (int)ZLibResultCode.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.WritePos = q; return(s.inflate_flush(z, r)); } n--; b |= (z.next_in[p++] & 0xff) << k; k += 8; } count += (b & ZLibUtil.inflate_mask[j]); b >>= j; k -= j; need = dbits; tree = dtree; tree_index = dtree_index; mode = InflateCodesMode.DIST; goto case InflateCodesMode.DIST; case InflateCodesMode.DIST: // i: get distance next j = need; while (k < (j)) { if (n != 0) { r = (int)ZLibResultCode.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.WritePos = q; return(s.inflate_flush(z, r)); } n--; b |= (z.next_in[p++] & 0xff) << k; k += 8; } tindex = (tree_index + (b & ZLibUtil.inflate_mask[j])) * 3; b >>= tree[tindex + 1]; k -= tree[tindex + 1]; e = (tree[tindex]); if ((e & 16) != 0) { // distance get_Renamed = e & 15; dist = tree[tindex + 2]; mode = InflateCodesMode.DISTEXT; break; } if ((e & 64) == 0) { // next table need = e; tree_index = tindex / 3 + tree[tindex + 2]; break; } mode = InflateCodesMode.BADCODE; // invalid code z.msg = "invalid distance code"; r = (int)ZLibResultCode.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.WritePos = q; return(s.inflate_flush(z, r)); case InflateCodesMode.DISTEXT: // i: getting distance extra j = get_Renamed; while (k < (j)) { if (n != 0) { r = (int)ZLibResultCode.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.WritePos = q; return(s.inflate_flush(z, r)); } n--; b |= (z.next_in[p++] & 0xff) << k; k += 8; } dist += (b & ZLibUtil.inflate_mask[j]); b >>= j; k -= j; mode = InflateCodesMode.COPY; goto case InflateCodesMode.COPY; case InflateCodesMode.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 (count != 0) { if (m == 0) { if (q == s.End && s.ReadPos != 0) { q = 0; m = q < s.ReadPos?s.ReadPos - q - 1:s.End - q; } if (m == 0) { s.WritePos = q; r = s.inflate_flush(z, r); q = s.WritePos; m = q < s.ReadPos?s.ReadPos - q - 1:s.End - q; if (q == s.End && s.ReadPos != 0) { q = 0; m = q < s.ReadPos?s.ReadPos - 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.WritePos = q; return(s.inflate_flush(z, r)); } } } s.Window[q++] = s.Window[f++]; m--; if (f == s.End) { f = 0; } count--; } mode = InflateCodesMode.START; break; case InflateCodesMode.LIT: // o: got literal, waiting for output space if (m == 0) { if (q == s.End && s.ReadPos != 0) { q = 0; m = q < s.ReadPos?s.ReadPos - q - 1:s.End - q; } if (m == 0) { s.WritePos = q; r = s.inflate_flush(z, r); q = s.WritePos; m = q < s.ReadPos?s.ReadPos - q - 1:s.End - q; if (q == s.End && s.ReadPos != 0) { q = 0; m = q < s.ReadPos?s.ReadPos - 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.WritePos = q; return(s.inflate_flush(z, r)); } } } r = (int)ZLibResultCode.Z_OK; s.Window[q++] = (byte)lit; m--; mode = InflateCodesMode.START; break; case InflateCodesMode.WASH: // o: got eob, possibly more output if (k > 7) { // return unused byte, if any k -= 8; n++; p--; // can always return one } s.WritePos = q; r = s.inflate_flush(z, r); q = s.WritePos; m = q < s.ReadPos?s.ReadPos - q - 1:s.End - q; if (s.ReadPos != s.WritePos) { s.BitB = b; s.BitK = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.WritePos = q; return(s.inflate_flush(z, r)); } mode = InflateCodesMode.END; goto case InflateCodesMode.END; case InflateCodesMode.END: r = (int)ZLibResultCode.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.WritePos = q; return(s.inflate_flush(z, r)); case InflateCodesMode.BADCODE: // x: got error r = (int)ZLibResultCode.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.WritePos = q; return(s.inflate_flush(z, r)); default: r = (int)ZLibResultCode.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.WritePos = q; return(s.inflate_flush(z, r)); } } }
/// <summary> /// Reads a number of decompressed bytes into the specified byte array. /// </summary> /// <param name="buffer">The array used to store decompressed bytes.</param> /// <param name="offset">The location in the array to begin reading.</param> /// <param name="count">The number of decompressed bytes to read.</param> /// <returns>The number of bytes that were decompressed into the byte array.</returns> /// <example> The following code demonstrates how to use the <c>ZInputStream</c> to decompresses data /// <code> /// [C#] /// private void decompressFile(string inFile, string outFile) /// { /// /* Create a file to store decompressed data */ /// System.IO.FileStream decompressedFile = new System.IO.FileStream(@"c:\data\decompressed.dat", System.IO.FileMode.Create); /// /* Open a file containing compressed data */ /// System.IO.FileStream compressedFile = new System.IO.FileStream(@"c:\data\compressed.dat", System.IO.FileMode.Open); /// /* Create ZInputStream for decompression */ /// ZInputStream decompressionStream = new ZInputStream(compressedFile); /// /// try /// { /// byte[] buffer = new byte[2000]; /// int len; /// /* Read and decompress data */ /// while ((len = decompressionStream.Read(buffer, 0, 2000)) > 0) /// { /// /* Store decompressed data */ /// decompressedFile.Write(buffer, 0, len); /// } /// } /// finally /// { /// decompressionStream.Close(); /// decompressedFile.Close(); /// compressedFile.Close(); /// } /// } /// </code> /// </example> public override int Read(byte[] buffer, int offset, int count) { if (count == 0) { return(0); } if (this.needCopyArrays && ZLibUtil.CopyLargeArrayToSmall.GetRemainingDataSize() > 0) { return(ZLibUtil.CopyLargeArrayToSmall.CopyData()); } else { this.needCopyArrays = false; } bool call_finish = false; int err; z.next_out = buffer; z.next_out_index = offset; z.avail_out = count; do { if ((z.avail_in == 0) && (!nomoreinput)) { // if buffer is empty and more input is available, refill it z.next_in_index = 0; z.avail_in = ZLibUtil.ReadInput(_stream, buf, 0, ZLibUtil.zLibBufSize); //(ZLibUtil.zLibBufSize<z._avail_out ? ZLibUtil.zLibBufSize : z._avail_out)); if (z.avail_in == -1) { z.avail_in = 0; nomoreinput = true; } } if ((z.avail_in == 0) && nomoreinput) { call_finish = true; break; } err = z.inflate(flush); if (nomoreinput && (err == (int)ZLibResultCode.Z_BUF_ERROR)) { return(-1); } if (err != (int)ZLibResultCode.Z_OK && err != (int)ZLibResultCode.Z_STREAM_END) { throw new ZStreamException("inflating: " + z.msg); } if (nomoreinput && (z.avail_out == count)) { return(-1); } }while (z.avail_out == count && err == (int)ZLibResultCode.Z_OK); if (call_finish) { return(Finish(buffer, offset, count)); } return(count - z.avail_out); }