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);
}
}
}