internal int InflateFast(int bl, int bd, int[] tl, int tl_index, int[] td, int td_index, InflateBlocks s, ZlibCodec z)
{
int t; // temporary pointer
int[] tp; // temporary pointer
int tp_index; // temporary pointer
int e; // extra bits or operation
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
int ml; // mask for literal/length tree
int md; // mask for distance tree
int c; // bytes to copy
int d; // distance back to copy from
int r; // copy source pointer
int tp_index_t_3; // (tp_index+t)*3
// load input, output, bit values
p = z.NextIn;
n = z.AvailableBytesIn;
b = s.bitb;
k = s.bitk;
q = s.write;
m = q < s.read ? s.read - q - 1 : s.end - q;
// initialize masks
ml = inflate_mask [bl];
md = inflate_mask [bd];
// do until not enough input or output space for fast loop
do {
// assume called with m >= 258 && n >= 10
// get literal/length code
while (k < (20)) {
// max bits for literal/length code
n--;
b |= (z.InputBuffer [p++] & 0xff) << k;
k += 8;
}
t = b & ml;
tp = tl;
tp_index = tl_index;
tp_index_t_3 = (tp_index + t) * 3;
if ((e = tp [tp_index_t_3]) == 0) {
b >>= (tp [tp_index_t_3 + 1]);
k -= (tp [tp_index_t_3 + 1]);
s.window [q++] = (byte)tp [tp_index_t_3 + 2];
m--;
continue;
}
do {
b >>= (tp [tp_index_t_3 + 1]);
k -= (tp [tp_index_t_3 + 1]);
if ((e & 16) != 0) {
e &= 15;
c = tp [tp_index_t_3 + 2] + ((int)b & inflate_mask [e]);
b >>= e;
k -= e;
// decode distance base of block to copy
while (k < (15)) {
// max bits for distance code
n--;
b |= (z.InputBuffer [p++] & 0xff) << k;
k += 8;
}
t = b & md;
tp = td;
tp_index = td_index;
tp_index_t_3 = (tp_index + t) * 3;
e = tp [tp_index_t_3];
do {
b >>= (tp [tp_index_t_3 + 1]);
k -= (tp [tp_index_t_3 + 1]);
if ((e & 16) != 0) {
// get extra bits to add to distance base
e &= 15;
while (k < (e)) {
// get extra bits (up to 13)
n--;
b |= (z.InputBuffer [p++] & 0xff) << k;
k += 8;
}
d = tp [tp_index_t_3 + 2] + (b & inflate_mask [e]);
b >>= (e);
k -= (e);
// do the copy
m -= c;
if (q >= d) {
// offset before dest
// just copy
r = q - d;
if (q - r > 0 && 2 > (q - r)) {
s.window [q++] = s.window [r++]; // minimum count is three,
s.window [q++] = s.window [r++]; // so unroll loop a little
c -= 2;
} else {
Array.Copy (s.window, r, s.window, q, 2);
q += 2;
r += 2;
c -= 2;
}
} else {
// else offset after destination
r = q - d;
do {
r += s.end; // force pointer in window
} while (r < 0); // covers invalid distances
e = s.end - r;
if (c > e) {
// if source crosses,
c -= e; // wrapped copy
if (q - r > 0 && e > (q - r)) {
do {
s.window [q++] = s.window [r++];
} while (--e != 0);
} else {
Array.Copy (s.window, r, s.window, q, e);
q += e;
r += e;
e = 0;
}
r = 0; // copy rest from start of window
}
}
// copy all or what's left
if (q - r > 0 && c > (q - r)) {
do {
s.window [q++] = s.window [r++];
} while (--c != 0);
} else {
Array.Copy (s.window, r, s.window, q, c);
q += c;
r += c;
c = 0;
}
break;
} else if ((e & 64) == 0) {
t += tp [tp_index_t_3 + 2];
t += (b & inflate_mask [e]);
tp_index_t_3 = (tp_index + t) * 3;
e = tp [tp_index_t_3];
} else {
z.Message = "invalid distance code";
c = z.AvailableBytesIn - n;
c = (k >> 3) < c ? k >> 3 : c;
n += c;
p -= c;
k -= (c << 3);
s.bitb = b;
s.bitk = k;
z.AvailableBytesIn = n;
z.TotalBytesIn += p - z.NextIn;
z.NextIn = p;
s.write = q;
return ZlibConstants.Z_DATA_ERROR;
}
} while (true);
break;
}
if ((e & 64) == 0) {
t += tp [tp_index_t_3 + 2];
t += (b & inflate_mask [e]);
tp_index_t_3 = (tp_index + t) * 3;
if ((e = tp [tp_index_t_3]) == 0) {
b >>= (tp [tp_index_t_3 + 1]);
k -= (tp [tp_index_t_3 + 1]);
s.window [q++] = (byte)tp [tp_index_t_3 + 2];
m--;
break;
}
} else if ((e & 32) != 0) {
c = z.AvailableBytesIn - n;
c = (k >> 3) < c ? k >> 3 : c;
n += c;
p -= c;
k -= (c << 3);
s.bitb = b;
s.bitk = k;
z.AvailableBytesIn = n;
z.TotalBytesIn += p - z.NextIn;
z.NextIn = p;
s.write = q;
return ZlibConstants.Z_STREAM_END;
} else {
z.Message = "invalid literal/length code";
c = z.AvailableBytesIn - n;
c = (k >> 3) < c ? k >> 3 : c;
n += c;
p -= c;
k -= (c << 3);
s.bitb = b;
s.bitk = k;
z.AvailableBytesIn = n;
z.TotalBytesIn += p - z.NextIn;
z.NextIn = p;
s.write = q;
return ZlibConstants.Z_DATA_ERROR;
}
} while (true);
} while (m >= 258 && n >= 10);
// not enough input or output--restore pointers and return
c = z.AvailableBytesIn - n;
c = (k >> 3) < c ? k >> 3 : c;
n += c;
p -= c;
k -= (c << 3);
s.bitb = b;
s.bitk = k;
z.AvailableBytesIn = n;
z.TotalBytesIn += p - z.NextIn;
z.NextIn = p;
s.write = q;
return ZlibConstants.Z_OK;
}