internal int Process(InflateBlocks blocks, ZlibCodec z, int 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.NextIn; n = z.AvailableBytesIn; b = blocks.bitb; k = blocks.bitk; q = blocks.write; m = q < blocks.read ? blocks.read - q - 1 : blocks.end - q; // process input and output based on current state while (true) { switch (mode) { // waiting for "i:"=input, "o:"=output, "x:"=nothing case START: // x: set up for LEN if (m >= 258 && n >= 10) { blocks.bitb = b; blocks.bitk = k; z.AvailableBytesIn = n; z.TotalBytesIn += p - z.NextIn; z.NextIn = p; blocks.write = q; r = InflateFast (lbits, dbits, ltree, ltree_index, dtree, dtree_index, blocks, z); p = z.NextIn; n = z.AvailableBytesIn; b = blocks.bitb; k = blocks.bitk; q = blocks.write; m = q < blocks.read ? blocks.read - q - 1 : blocks.end - q; if (r != ZlibConstants.Z_OK) { mode = (r == ZlibConstants.Z_STREAM_END) ? WASH : BADCODE; break; } } need = lbits; tree = ltree; tree_index = ltree_index; mode = LEN; goto case LEN; case LEN: // i: get length/literal/eob next j = need; while (k < (j)) { if (n != 0) r = ZlibConstants.Z_OK; else { blocks.bitb = b; blocks.bitk = k; z.AvailableBytesIn = n; z.TotalBytesIn += p - z.NextIn; z.NextIn = p; blocks.write = q; return blocks.Flush (z, r); } n--; b |= (z.InputBuffer [p++] & 0xff) << k; k += 8; } tindex = (tree_index + (b & inflate_mask [j])) * 3; b = SharedUtils.URShift (b, (tree [tindex + 1])); k -= (tree [tindex + 1]); e = tree [tindex]; if (e == 0) { // literal lit = tree [tindex + 2]; mode = LIT; break; } if ((e & 16) != 0) { // length get_Renamed = e & 15; len = tree [tindex + 2]; mode = 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 = WASH; break; } mode = BADCODE; // invalid code z.Message = "invalid literal/length code"; r = ZlibConstants.Z_DATA_ERROR; blocks.bitb = b; blocks.bitk = k; z.AvailableBytesIn = n; z.TotalBytesIn += p - z.NextIn; z.NextIn = p; blocks.write = q; return blocks.Flush (z, r); case LENEXT: // i: getting length extra (have base) j = get_Renamed; while (k < (j)) { if (n != 0) r = ZlibConstants.Z_OK; else { blocks.bitb = b; blocks.bitk = k; z.AvailableBytesIn = n; z.TotalBytesIn += p - z.NextIn; z.NextIn = p; blocks.write = q; return blocks.Flush (z, r); } n--; b |= (z.InputBuffer [p++] & 0xff) << k; k += 8; } len += (b & inflate_mask [j]); b >>= j; k -= j; need = dbits; tree = dtree; tree_index = dtree_index; mode = DIST; goto case DIST; case DIST: // i: get distance next j = need; while (k < (j)) { if (n != 0) r = ZlibConstants.Z_OK; else { blocks.bitb = b; blocks.bitk = k; z.AvailableBytesIn = n; z.TotalBytesIn += p - z.NextIn; z.NextIn = p; blocks.write = q; return blocks.Flush (z, r); } n--; b |= (z.InputBuffer [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_Renamed = e & 15; dist = tree [tindex + 2]; mode = DISTEXT; break; } if ((e & 64) == 0) { // next table need = e; tree_index = tindex / 3 + tree [tindex + 2]; break; } mode = BADCODE; // invalid code z.Message = "invalid distance code"; r = ZlibConstants.Z_DATA_ERROR; blocks.bitb = b; blocks.bitk = k; z.AvailableBytesIn = n; z.TotalBytesIn += p - z.NextIn; z.NextIn = p; blocks.write = q; return blocks.Flush (z, r); case DISTEXT: // i: getting distance extra j = get_Renamed; while (k < (j)) { if (n != 0) r = ZlibConstants.Z_OK; else { blocks.bitb = b; blocks.bitk = k; z.AvailableBytesIn = n; z.TotalBytesIn += p - z.NextIn; z.NextIn = p; blocks.write = q; return blocks.Flush (z, r); } n--; b |= (z.InputBuffer [p++] & 0xff) << k; k += 8; } dist += (b & inflate_mask [j]); b >>= j; k -= j; mode = COPY; goto case COPY; case COPY: // o: copying bytes in window, waiting for space f = q - dist; while (f < 0) { // modulo window size-"while" instead f += blocks.end; // of "if" handles invalid distances } while (len != 0) { if (m == 0) { if (q == blocks.end && blocks.read != 0) { q = 0; m = q < blocks.read ? blocks.read - q - 1 : blocks.end - q; } if (m == 0) { blocks.write = q; r = blocks.Flush (z, r); q = blocks.write; m = q < blocks.read ? blocks.read - q - 1 : blocks.end - q; if (q == blocks.end && blocks.read != 0) { q = 0; m = q < blocks.read ? blocks.read - q - 1 : blocks.end - q; } if (m == 0) { blocks.bitb = b; blocks.bitk = k; z.AvailableBytesIn = n; z.TotalBytesIn += p - z.NextIn; z.NextIn = p; blocks.write = q; return blocks.Flush (z, r); } } } blocks.window [q++] = blocks.window [f++]; m--; if (f == blocks.end) f = 0; len--; } mode = START; break; case LIT: // o: got literal, waiting for output space if (m == 0) { if (q == blocks.end && blocks.read != 0) { q = 0; m = q < blocks.read ? blocks.read - q - 1 : blocks.end - q; } if (m == 0) { blocks.write = q; r = blocks.Flush (z, r); q = blocks.write; m = q < blocks.read ? blocks.read - q - 1 : blocks.end - q; if (q == blocks.end && blocks.read != 0) { q = 0; m = q < blocks.read ? blocks.read - q - 1 : blocks.end - q; } if (m == 0) { blocks.bitb = b; blocks.bitk = k; z.AvailableBytesIn = n; z.TotalBytesIn += p - z.NextIn; z.NextIn = p; blocks.write = q; return blocks.Flush (z, r); } } } r = ZlibConstants.Z_OK; blocks.window [q++] = (byte)lit; m--; mode = START; break; case WASH: // o: got eob, possibly more output if (k > 7) { // return unused byte, if any k -= 8; n++; p--; // can always return one } blocks.write = q; r = blocks.Flush (z, r); q = blocks.write; m = q < blocks.read ? blocks.read - q - 1 : blocks.end - q; if (blocks.read != blocks.write) { blocks.bitb = b; blocks.bitk = k; z.AvailableBytesIn = n; z.TotalBytesIn += p - z.NextIn; z.NextIn = p; blocks.write = q; return blocks.Flush (z, r); } mode = END; goto case END; case END: r = ZlibConstants.Z_STREAM_END; blocks.bitb = b; blocks.bitk = k; z.AvailableBytesIn = n; z.TotalBytesIn += p - z.NextIn; z.NextIn = p; blocks.write = q; return blocks.Flush (z, r); case BADCODE: // x: got error r = ZlibConstants.Z_DATA_ERROR; blocks.bitb = b; blocks.bitk = k; z.AvailableBytesIn = n; z.TotalBytesIn += p - z.NextIn; z.NextIn = p; blocks.write = q; return blocks.Flush (z, r); default: r = ZlibConstants.Z_STREAM_ERROR; blocks.bitb = b; blocks.bitk = k; z.AvailableBytesIn = n; z.TotalBytesIn += p - z.NextIn; z.NextIn = p; blocks.write = q; return blocks.Flush (z, r); } } }