// Called with number of bytes left to write in window at least 258 // (the maximum string length) and number of input bytes available // at least ten. The ten bytes are six bytes for the longest length/ // distance pair plus four bytes for overloading the bit buffer. internal static 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.writeAt; m = q < s.readAt ? s.readAt - q - 1 : s.end - q; // initialize masks ml = InternalInflateConstants.InflateMask[bl]; md = InternalInflateConstants.InflateMask[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] + (b & InternalInflateConstants.InflateMask[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 & InternalInflateConstants.InflateMask[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 = 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; } break; } if ((e & 64) == 0) { t += tp[tp_index_t_3 + 2]; t += b & InternalInflateConstants.InflateMask[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.writeAt = q; return(ZlibConstants.Z_DATA_ERROR); } } while (true); break; } if ((e & 64) == 0) { t += tp[tp_index_t_3 + 2]; t += b & InternalInflateConstants.InflateMask[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.writeAt = 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.writeAt = 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.writeAt = q; return(ZlibConstants.Z_OK); }