internal int Process(InflateBlocks blocks, 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 ZlibCodec z = blocks._codec; // copy input/output information to locals (UPDATE macro restores) p = z.NextIn; n = z.AvailableBytesIn; b = blocks.bitb; k = blocks.bitk; q = blocks.writeAt; m = q < blocks.readAt ? blocks.readAt - 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.writeAt = 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.writeAt; m = q < blocks.readAt ? blocks.readAt - 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.writeAt = q; return blocks.Flush(r); } n--; b |= (z.InputBuffer[p++] & 0xff) << k; k += 8; } tindex = (tree_index + (b & InternalInflateConstants.InflateMask[j])) * 3; 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 bitsToGet = 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.writeAt = q; return blocks.Flush(r); case LENEXT: // i: getting length extra (have base) j = bitsToGet; 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.writeAt = q; return blocks.Flush(r); } n--; b |= (z.InputBuffer[p++] & 0xff) << k; k += 8; } len += (b & InternalInflateConstants.InflateMask[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.writeAt = q; return blocks.Flush(r); } n--; b |= (z.InputBuffer[p++] & 0xff) << k; k += 8; } tindex = (tree_index + (b & InternalInflateConstants.InflateMask[j])) * 3; b >>= tree[tindex + 1]; k -= tree[tindex + 1]; e = (tree[tindex]); if ((e & 0x10) != 0) { // distance bitsToGet = 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.writeAt = q; return blocks.Flush(r); case DISTEXT: // i: getting distance extra j = bitsToGet; 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.writeAt = q; return blocks.Flush(r); } n--; b |= (z.InputBuffer[p++] & 0xff) << k; k += 8; } dist += (b & InternalInflateConstants.InflateMask[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.readAt != 0) { q = 0; m = q < blocks.readAt ? blocks.readAt - q - 1 : blocks.end - q; } if (m == 0) { blocks.writeAt = q; r = blocks.Flush(r); q = blocks.writeAt; m = q < blocks.readAt ? blocks.readAt - q - 1 : blocks.end - q; if (q == blocks.end && blocks.readAt != 0) { q = 0; m = q < blocks.readAt ? blocks.readAt - 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.writeAt = q; return blocks.Flush(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.readAt != 0) { q = 0; m = q < blocks.readAt ? blocks.readAt - q - 1 : blocks.end - q; } if (m == 0) { blocks.writeAt = q; r = blocks.Flush(r); q = blocks.writeAt; m = q < blocks.readAt ? blocks.readAt - q - 1 : blocks.end - q; if (q == blocks.end && blocks.readAt != 0) { q = 0; m = q < blocks.readAt ? blocks.readAt - 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.writeAt = q; return blocks.Flush(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.writeAt = q; r = blocks.Flush(r); q = blocks.writeAt; m = q < blocks.readAt ? blocks.readAt - q - 1 : blocks.end - q; if (blocks.readAt != blocks.writeAt) { blocks.bitb = b; blocks.bitk = k; z.AvailableBytesIn = n; z.TotalBytesIn += p - z.NextIn; z.NextIn = p; blocks.writeAt = q; return blocks.Flush(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.writeAt = q; return blocks.Flush(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.writeAt = q; return blocks.Flush(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.writeAt = q; return blocks.Flush(r); } } }