using System; namespace ComponentAce.Compression.Libs.zlib { internal sealed class InfBlocks { private const int MANY = 1440; private static readonly int[] inflate_mask = new int[17] { 0, 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383, 32767, 65535 }; internal static readonly int[] border = new int[19] { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 }; private const int Z_OK = 0; private const int Z_STREAM_END = 1; private const int Z_NEED_DICT = 2; private const int Z_ERRNO = -1; private const int Z_STREAM_ERROR = -2; private const int Z_DATA_ERROR = -3; private const int Z_MEM_ERROR = -4; private const int Z_BUF_ERROR = -5; private const int Z_VERSION_ERROR = -6; private const int TYPE = 0; private const int LENS = 1; private const int STORED = 2; private const int TABLE = 3; private const int BTREE = 4; private const int DTREE = 5; private const int CODES = 6; private const int DRY = 7; private const int DONE = 8; private const int BAD = 9; internal int mode; internal int left; internal int table; internal int index; internal int[] blens; internal int[] bb = new int[1]; internal int[] tb = new int[1]; internal InfCodes codes; internal int last; internal int bitk; internal int bitb; internal int[] hufts; internal byte[] window; internal int end; internal int read; internal int write; internal object checkfn; internal long check; internal InfBlocks(ZStream z, object checkfn, int w) { hufts = new int[4320]; window = new byte[w]; end = w; this.checkfn = checkfn; mode = 0; reset(z, null); } internal void reset(ZStream z, long[] c) { if (c != null) { c[0] = check; } if (mode == 4 || mode == 5) { blens = null; } if (mode == 6) { codes.free(z); } mode = 0; bitk = 0; bitb = 0; read = (write = 0); if (checkfn != null) { z.adler = (check = z._adler.adler32(0L, null, 0, 0)); } } internal int proc(ZStream z, int r) { int num = z.next_in_index; int num2 = z.avail_in; int num3 = bitb; int i = bitk; int num4 = write; int num5 = ((num4 < read) ? (read - num4 - 1) : (end - num4)); while (true) { switch (mode) { case 0: { for (; i < 3; i += 8) { if (num2 != 0) { r = 0; num2--; num3 |= (z.next_in[num++] & 0xFF) << i; continue; } bitb = num3; bitk = i; z.avail_in = num2; z.total_in += num - z.next_in_index; z.next_in_index = num; write = num4; return inflate_flush(z, r); } int num6 = num3 & 7; last = num6 & 1; switch (SupportClass.URShift(num6, 1)) { case 0: num3 = SupportClass.URShift(num3, 3); i -= 3; num6 = i & 7; num3 = SupportClass.URShift(num3, num6); i -= num6; mode = 1; break; case 1: { int[] array5 = new int[1]; int[] array6 = new int[1]; int[][] array7 = new int[1][]; int[][] array8 = new int[1][]; InfTree.inflate_trees_fixed(array5, array6, array7, array8, z); codes = new InfCodes(array5[0], array6[0], array7[0], array8[0], z); num3 = SupportClass.URShift(num3, 3); i -= 3; mode = 6; break; } case 2: num3 = SupportClass.URShift(num3, 3); i -= 3; mode = 3; break; case 3: num3 = SupportClass.URShift(num3, 3); i -= 3; mode = 9; z.msg = "invalid block type"; r = -3; bitb = num3; bitk = i; z.avail_in = num2; z.total_in += num - z.next_in_index; z.next_in_index = num; write = num4; return inflate_flush(z, r); } break; } case 1: for (; i < 32; i += 8) { if (num2 != 0) { r = 0; num2--; num3 |= (z.next_in[num++] & 0xFF) << i; continue; } bitb = num3; bitk = i; z.avail_in = num2; z.total_in += num - z.next_in_index; z.next_in_index = num; write = num4; return inflate_flush(z, r); } if ((SupportClass.URShift(~num3, 16) & 0xFFFF) != (num3 & 0xFFFF)) { mode = 9; z.msg = "invalid stored block lengths"; r = -3; bitb = num3; bitk = i; z.avail_in = num2; z.total_in += num - z.next_in_index; z.next_in_index = num; write = num4; return inflate_flush(z, r); } left = num3 & 0xFFFF; num3 = (i = 0); mode = ((left != 0) ? 2 : ((last != 0) ? 7 : 0)); break; case 2: { if (num2 == 0) { bitb = num3; bitk = i; z.avail_in = num2; z.total_in += num - z.next_in_index; z.next_in_index = num; write = num4; return inflate_flush(z, r); } if (num5 == 0) { if (num4 == end && read != 0) { num4 = 0; num5 = ((num4 < read) ? (read - num4 - 1) : (end - num4)); } if (num5 == 0) { write = num4; r = inflate_flush(z, r); num4 = write; num5 = ((num4 < read) ? (read - num4 - 1) : (end - num4)); if (num4 == end && read != 0) { num4 = 0; num5 = ((num4 < read) ? (read - num4 - 1) : (end - num4)); } if (num5 == 0) { bitb = num3; bitk = i; z.avail_in = num2; z.total_in += num - z.next_in_index; z.next_in_index = num; write = num4; return inflate_flush(z, r); } } } r = 0; int num6 = left; if (num6 > num2) { num6 = num2; } if (num6 > num5) { num6 = num5; } Array.Copy(z.next_in, num, window, num4, num6); num += num6; num2 -= num6; num4 += num6; num5 -= num6; if ((left -= num6) == 0) { mode = ((last != 0) ? 7 : 0); } break; } case 3: { for (; i < 14; i += 8) { if (num2 != 0) { r = 0; num2--; num3 |= (z.next_in[num++] & 0xFF) << i; continue; } bitb = num3; bitk = i; z.avail_in = num2; z.total_in += num - z.next_in_index; z.next_in_index = num; write = num4; return inflate_flush(z, r); } int num6 = (table = num3 & 0x3FFF); if ((num6 & 0x1F) > 29 || ((num6 >> 5) & 0x1F) > 29) { mode = 9; z.msg = "too many length or distance symbols"; r = -3; bitb = num3; bitk = i; z.avail_in = num2; z.total_in += num - z.next_in_index; z.next_in_index = num; write = num4; return inflate_flush(z, r); } num6 = 258 + (num6 & 0x1F) + ((num6 >> 5) & 0x1F); blens = new int[num6]; num3 = SupportClass.URShift(num3, 14); i -= 14; index = 0; mode = 4; goto case 4; } case 4: { while (index < 4 + SupportClass.URShift(table, 10)) { for (; i < 3; i += 8) { if (num2 != 0) { r = 0; num2--; num3 |= (z.next_in[num++] & 0xFF) << i; continue; } bitb = num3; bitk = i; z.avail_in = num2; z.total_in += num - z.next_in_index; z.next_in_index = num; write = num4; return inflate_flush(z, r); } blens[border[index++]] = num3 & 7; num3 = SupportClass.URShift(num3, 3); i -= 3; } while (index < 19) { blens[border[index++]] = 0; } bb[0] = 7; int num6 = InfTree.inflate_trees_bits(blens, bb, tb, hufts, z); if (num6 != 0) { r = num6; if (r == -3) { blens = null; mode = 9; } bitb = num3; bitk = i; z.avail_in = num2; z.total_in += num - z.next_in_index; z.next_in_index = num; write = num4; return inflate_flush(z, r); } index = 0; mode = 5; goto case 5; } case 5: { int num6; while (true) { num6 = table; if (index >= 258 + (num6 & 0x1F) + ((num6 >> 5) & 0x1F)) { break; } for (num6 = bb[0]; i < num6; i += 8) { if (num2 != 0) { r = 0; num2--; num3 |= (z.next_in[num++] & 0xFF) << i; continue; } bitb = num3; bitk = i; z.avail_in = num2; z.total_in += num - z.next_in_index; z.next_in_index = num; write = num4; return inflate_flush(z, r); } _ = tb[0]; _ = -1; num6 = hufts[(tb[0] + (num3 & inflate_mask[num6])) * 3 + 1]; int num7 = hufts[(tb[0] + (num3 & inflate_mask[num6])) * 3 + 2]; if (num7 < 16) { num3 = SupportClass.URShift(num3, num6); i -= num6; blens[index++] = num7; continue; } int num8 = ((num7 == 18) ? 7 : (num7 - 14)); int num9 = ((num7 == 18) ? 11 : 3); for (; i < num6 + num8; i += 8) { if (num2 != 0) { r = 0; num2--; num3 |= (z.next_in[num++] & 0xFF) << i; continue; } bitb = num3; bitk = i; z.avail_in = num2; z.total_in += num - z.next_in_index; z.next_in_index = num; write = num4; return inflate_flush(z, r); } num3 = SupportClass.URShift(num3, num6); i -= num6; num9 += num3 & inflate_mask[num8]; num3 = SupportClass.URShift(num3, num8); i -= num8; num8 = index; num6 = table; if (num8 + num9 > 258 + (num6 & 0x1F) + ((num6 >> 5) & 0x1F) || (num7 == 16 && num8 < 1)) { blens = null; mode = 9; z.msg = "invalid bit length repeat"; r = -3; bitb = num3; bitk = i; z.avail_in = num2; z.total_in += num - z.next_in_index; z.next_in_index = num; write = num4; return inflate_flush(z, r); } num7 = ((num7 == 16) ? blens[num8 - 1] : 0); do { blens[num8++] = num7; } while (--num9 != 0); index = num8; } tb[0] = -1; int[] array = new int[1]; int[] array2 = new int[1]; int[] array3 = new int[1]; int[] array4 = new int[1]; array[0] = 9; array2[0] = 6; num6 = table; num6 = InfTree.inflate_trees_dynamic(257 + (num6 & 0x1F), 1 + ((num6 >> 5) & 0x1F), blens, array, array2, array3, array4, hufts, z); if (num6 != 0) { if (num6 == -3) { blens = null; mode = 9; } r = num6; bitb = num3; bitk = i; z.avail_in = num2; z.total_in += num - z.next_in_index; z.next_in_index = num; write = num4; return inflate_flush(z, r); } codes = new InfCodes(array[0], array2[0], hufts, array3[0], hufts, array4[0], z); blens = null; mode = 6; goto case 6; } case 6: bitb = num3; bitk = i; z.avail_in = num2; z.total_in += num - z.next_in_index; z.next_in_index = num; write = num4; if ((r = codes.proc(this, z, r)) != 1) { return inflate_flush(z, r); } r = 0; codes.free(z); num = z.next_in_index; num2 = z.avail_in; num3 = bitb; i = bitk; num4 = write; num5 = ((num4 < read) ? (read - num4 - 1) : (end - num4)); if (last == 0) { mode = 0; break; } mode = 7; goto case 7; case 7: write = num4; r = inflate_flush(z, r); num4 = write; num5 = ((num4 < read) ? (read - num4 - 1) : (end - num4)); if (read != write) { bitb = num3; bitk = i; z.avail_in = num2; z.total_in += num - z.next_in_index; z.next_in_index = num; write = num4; return inflate_flush(z, r); } mode = 8; goto case 8; case 8: r = 1; bitb = num3; bitk = i; z.avail_in = num2; z.total_in += num - z.next_in_index; z.next_in_index = num; write = num4; return inflate_flush(z, r); case 9: r = -3; bitb = num3; bitk = i; z.avail_in = num2; z.total_in += num - z.next_in_index; z.next_in_index = num; write = num4; return inflate_flush(z, r); default: r = -2; bitb = num3; bitk = i; z.avail_in = num2; z.total_in += num - z.next_in_index; z.next_in_index = num; write = num4; return inflate_flush(z, r); } } } internal void free(ZStream z) { reset(z, null); window = null; hufts = null; } internal void set_dictionary(byte[] d, int start, int n) { Array.Copy(d, start, window, 0, n); read = (write = n); } internal int sync_point() { if (mode != 1) { return 0; } return 1; } internal int inflate_flush(ZStream z, int r) { int next_out_index = z.next_out_index; int num = read; int num2 = ((num <= write) ? write : end) - num; if (num2 > z.avail_out) { num2 = z.avail_out; } if (num2 != 0 && r == -5) { r = 0; } z.avail_out -= num2; z.total_out += num2; if (checkfn != null) { z.adler = (check = z._adler.adler32(check, window, num, num2)); } Array.Copy(window, num, z.next_out, next_out_index, num2); next_out_index += num2; num += num2; if (num == end) { num = 0; if (write == end) { write = 0; } num2 = write - num; if (num2 > z.avail_out) { num2 = z.avail_out; } if (num2 != 0 && r == -5) { r = 0; } z.avail_out -= num2; z.total_out += num2; if (checkfn != null) { z.adler = (check = z._adler.adler32(check, window, num, num2)); } Array.Copy(window, num, z.next_out, next_out_index, num2); next_out_index += num2; num += num2; } z.next_out_index = next_out_index; read = num; return r; } } }