using System; namespace ComponentAce.Compression.Libs.zlib { public sealed class Deflate { internal class Config { internal int good_length; internal int max_lazy; internal int nice_length; internal int max_chain; internal int func; internal Config(int good_length, int max_lazy, int nice_length, int max_chain, int func) { this.good_length = good_length; this.max_lazy = max_lazy; this.nice_length = nice_length; this.max_chain = max_chain; this.func = func; } } private const int MAX_MEM_LEVEL = 9; private const int Z_DEFAULT_COMPRESSION = -1; private const int MAX_WBITS = 15; private const int DEF_MEM_LEVEL = 8; private const int STORED = 0; private const int FAST = 1; private const int SLOW = 2; private static Config[] config_table; private static readonly string[] z_errmsg; private const int NeedMore = 0; private const int BlockDone = 1; private const int FinishStarted = 2; private const int FinishDone = 3; private const int PRESET_DICT = 32; private const int Z_FILTERED = 1; private const int Z_HUFFMAN_ONLY = 2; private const int Z_DEFAULT_STRATEGY = 0; private const int Z_NO_FLUSH = 0; private const int Z_PARTIAL_FLUSH = 1; private const int Z_SYNC_FLUSH = 2; private const int Z_FULL_FLUSH = 3; private const int Z_FINISH = 4; 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 INIT_STATE = 42; private const int BUSY_STATE = 113; private const int FINISH_STATE = 666; private const int Z_DEFLATED = 8; private const int STORED_BLOCK = 0; private const int STATIC_TREES = 1; private const int DYN_TREES = 2; private const int Z_BINARY = 0; private const int Z_ASCII = 1; private const int Z_UNKNOWN = 2; private const int Buf_size = 16; private const int REP_3_6 = 16; private const int REPZ_3_10 = 17; private const int REPZ_11_138 = 18; private const int MIN_MATCH = 3; private const int MAX_MATCH = 258; private static readonly int MIN_LOOKAHEAD; private const int MAX_BITS = 15; private const int D_CODES = 30; private const int BL_CODES = 19; private const int LENGTH_CODES = 29; private const int LITERALS = 256; private static readonly int L_CODES; private static readonly int HEAP_SIZE; private const int END_BLOCK = 256; internal ZStream strm; internal int status; internal byte[] pending_buf; internal int pending_buf_size; internal int pending_out; internal int pending; internal int noheader; internal byte data_type; internal byte method; internal int last_flush; internal int w_size; internal int w_bits; internal int w_mask; internal byte[] window; internal int window_size; internal short[] prev; internal short[] head; internal int ins_h; internal int hash_size; internal int hash_bits; internal int hash_mask; internal int hash_shift; internal int block_start; internal int match_length; internal int prev_match; internal int match_available; internal int strstart; internal int match_start; internal int lookahead; internal int prev_length; internal int max_chain_length; internal int max_lazy_match; internal int level; internal int strategy; internal int good_match; internal int nice_match; internal short[] dyn_ltree; internal short[] dyn_dtree; internal short[] bl_tree; internal Tree l_desc = new Tree(); internal Tree d_desc = new Tree(); internal Tree bl_desc = new Tree(); internal short[] bl_count = new short[16]; internal int[] heap = new int[2 * L_CODES + 1]; internal int heap_len; internal int heap_max; internal byte[] depth = new byte[2 * L_CODES + 1]; internal int l_buf; internal int lit_bufsize; internal int last_lit; internal int d_buf; internal int opt_len; internal int static_len; internal int matches; internal int last_eob_len; internal short bi_buf; internal int bi_valid; internal Deflate() { dyn_ltree = new short[HEAP_SIZE * 2]; dyn_dtree = new short[122]; bl_tree = new short[78]; } internal void lm_init() { window_size = 2 * w_size; head[hash_size - 1] = 0; for (int i = 0; i < hash_size - 1; i++) { head[i] = 0; } max_lazy_match = config_table[level].max_lazy; good_match = config_table[level].good_length; nice_match = config_table[level].nice_length; max_chain_length = config_table[level].max_chain; strstart = 0; block_start = 0; lookahead = 0; match_length = (prev_length = 2); match_available = 0; ins_h = 0; } internal void tr_init() { l_desc.dyn_tree = dyn_ltree; l_desc.stat_desc = StaticTree.static_l_desc; d_desc.dyn_tree = dyn_dtree; d_desc.stat_desc = StaticTree.static_d_desc; bl_desc.dyn_tree = bl_tree; bl_desc.stat_desc = StaticTree.static_bl_desc; bi_buf = 0; bi_valid = 0; last_eob_len = 8; init_block(); } internal void init_block() { for (int i = 0; i < L_CODES; i++) { dyn_ltree[i * 2] = 0; } for (int j = 0; j < 30; j++) { dyn_dtree[j * 2] = 0; } for (int k = 0; k < 19; k++) { bl_tree[k * 2] = 0; } dyn_ltree[512] = 1; opt_len = (static_len = 0); last_lit = (matches = 0); } internal void pqdownheap(short[] tree, int k) { int num = heap[k]; for (int num2 = k << 1; num2 <= heap_len; num2 <<= 1) { if (num2 < heap_len && smaller(tree, heap[num2 + 1], heap[num2], depth)) { num2++; } if (smaller(tree, num, heap[num2], depth)) { break; } heap[k] = heap[num2]; k = num2; } heap[k] = num; } internal static bool smaller(short[] tree, int n, int m, byte[] depth) { if (tree[n * 2] >= tree[m * 2]) { if (tree[n * 2] == tree[m * 2]) { return depth[n] <= depth[m]; } return false; } return true; } internal void scan_tree(short[] tree, int max_code) { int num = -1; int num2 = tree[1]; int num3 = 0; int num4 = 7; int num5 = 4; if (num2 == 0) { num4 = 138; num5 = 3; } tree[(max_code + 1) * 2 + 1] = (short)SupportClass.Identity(65535L); for (int i = 0; i <= max_code; i++) { int num6 = num2; num2 = tree[(i + 1) * 2 + 1]; if (++num3 < num4 && num6 == num2) { continue; } if (num3 < num5) { bl_tree[num6 * 2] = (short)(bl_tree[num6 * 2] + num3); } else if (num6 != 0) { if (num6 != num) { bl_tree[num6 * 2]++; } bl_tree[32]++; } else if (num3 <= 10) { bl_tree[34]++; } else { bl_tree[36]++; } num3 = 0; num = num6; if (num2 == 0) { num4 = 138; num5 = 3; } else if (num6 == num2) { num4 = 6; num5 = 3; } else { num4 = 7; num5 = 4; } } } internal int build_bl_tree() { scan_tree(dyn_ltree, l_desc.max_code); scan_tree(dyn_dtree, d_desc.max_code); bl_desc.build_tree(this); int num = 18; while (num >= 3 && bl_tree[Tree.bl_order[num] * 2 + 1] == 0) { num--; } opt_len += 3 * (num + 1) + 5 + 5 + 4; return num; } internal void send_all_trees(int lcodes, int dcodes, int blcodes) { send_bits(lcodes - 257, 5); send_bits(dcodes - 1, 5); send_bits(blcodes - 4, 4); for (int i = 0; i < blcodes; i++) { send_bits(bl_tree[Tree.bl_order[i] * 2 + 1], 3); } send_tree(dyn_ltree, lcodes - 1); send_tree(dyn_dtree, dcodes - 1); } internal void send_tree(short[] tree, int max_code) { int num = -1; int num2 = tree[1]; int num3 = 0; int num4 = 7; int num5 = 4; if (num2 == 0) { num4 = 138; num5 = 3; } for (int i = 0; i <= max_code; i++) { int num6 = num2; num2 = tree[(i + 1) * 2 + 1]; if (++num3 < num4 && num6 == num2) { continue; } if (num3 < num5) { do { send_code(num6, bl_tree); } while (--num3 != 0); } else if (num6 != 0) { if (num6 != num) { send_code(num6, bl_tree); num3--; } send_code(16, bl_tree); send_bits(num3 - 3, 2); } else if (num3 <= 10) { send_code(17, bl_tree); send_bits(num3 - 3, 3); } else { send_code(18, bl_tree); send_bits(num3 - 11, 7); } num3 = 0; num = num6; if (num2 == 0) { num4 = 138; num5 = 3; } else if (num6 == num2) { num4 = 6; num5 = 3; } else { num4 = 7; num5 = 4; } } } internal void put_byte(byte[] p, int start, int len) { Array.Copy(p, start, pending_buf, pending, len); pending += len; } internal void put_byte(byte c) { pending_buf[pending++] = c; } internal void put_short(int w) { put_byte((byte)w); put_byte((byte)SupportClass.URShift(w, 8)); } internal void putShortMSB(int b) { put_byte((byte)(b >> 8)); put_byte((byte)b); } internal void send_code(int c, short[] tree) { send_bits(tree[c * 2] & 0xFFFF, tree[c * 2 + 1] & 0xFFFF); } internal void send_bits(int value_Renamed, int length) { if (bi_valid > 16 - length) { bi_buf = (short)((ushort)bi_buf | (ushort)((value_Renamed << bi_valid) & 0xFFFF)); put_short(bi_buf); bi_buf = (short)SupportClass.URShift(value_Renamed, 16 - bi_valid); bi_valid += length - 16; } else { bi_buf = (short)((ushort)bi_buf | (ushort)((value_Renamed << bi_valid) & 0xFFFF)); bi_valid += length; } } internal void _tr_align() { send_bits(2, 3); send_code(256, StaticTree.static_ltree); bi_flush(); if (1 + last_eob_len + 10 - bi_valid < 9) { send_bits(2, 3); send_code(256, StaticTree.static_ltree); bi_flush(); } last_eob_len = 7; } internal bool _tr_tally(int dist, int lc) { pending_buf[d_buf + last_lit * 2] = (byte)SupportClass.URShift(dist, 8); pending_buf[d_buf + last_lit * 2 + 1] = (byte)dist; pending_buf[l_buf + last_lit] = (byte)lc; last_lit++; if (dist == 0) { dyn_ltree[lc * 2]++; } else { matches++; dist--; dyn_ltree[(Tree._length_code[lc] + 256 + 1) * 2]++; dyn_dtree[Tree.d_code(dist) * 2]++; } if ((last_lit & 0x1FFF) == 0 && level > 2) { int num = last_lit * 8; int num2 = strstart - block_start; for (int i = 0; i < 30; i++) { num = (int)(num + dyn_dtree[i * 2] * (5L + (long)Tree.extra_dbits[i])); } num = SupportClass.URShift(num, 3); if (matches < last_lit / 2 && num < num2 / 2) { return true; } } return last_lit == lit_bufsize - 1; } internal void compress_block(short[] ltree, short[] dtree) { int num = 0; if (last_lit != 0) { do { int num2 = ((pending_buf[d_buf + num * 2] << 8) & 0xFF00) | (pending_buf[d_buf + num * 2 + 1] & 0xFF); int num3 = pending_buf[l_buf + num] & 0xFF; num++; if (num2 == 0) { send_code(num3, ltree); continue; } int num4 = Tree._length_code[num3]; send_code(num4 + 256 + 1, ltree); int num5 = Tree.extra_lbits[num4]; if (num5 != 0) { num3 -= Tree.base_length[num4]; send_bits(num3, num5); } num2--; num4 = Tree.d_code(num2); send_code(num4, dtree); num5 = Tree.extra_dbits[num4]; if (num5 != 0) { num2 -= Tree.base_dist[num4]; send_bits(num2, num5); } } while (num < last_lit); } send_code(256, ltree); last_eob_len = ltree[513]; } internal void set_data_type() { int i = 0; int num = 0; int num2 = 0; for (; i < 7; i++) { num2 += dyn_ltree[i * 2]; } for (; i < 128; i++) { num += dyn_ltree[i * 2]; } for (; i < 256; i++) { num2 += dyn_ltree[i * 2]; } data_type = (byte)((num2 <= SupportClass.URShift(num, 2)) ? 1u : 0u); } internal void bi_flush() { if (bi_valid == 16) { put_short(bi_buf); bi_buf = 0; bi_valid = 0; } else if (bi_valid >= 8) { put_byte((byte)bi_buf); bi_buf = (short)SupportClass.URShift(bi_buf, 8); bi_valid -= 8; } } internal void bi_windup() { if (bi_valid > 8) { put_short(bi_buf); } else if (bi_valid > 0) { put_byte((byte)bi_buf); } bi_buf = 0; bi_valid = 0; } internal void copy_block(int buf, int len, bool header) { bi_windup(); last_eob_len = 8; if (header) { put_short((short)len); put_short((short)(~len)); } put_byte(window, buf, len); } internal void flush_block_only(bool eof) { _tr_flush_block((block_start >= 0) ? block_start : (-1), strstart - block_start, eof); block_start = strstart; strm.flush_pending(); } internal int deflate_stored(int flush) { int num = 65535; if (num > pending_buf_size - 5) { num = pending_buf_size - 5; } while (true) { if (lookahead <= 1) { fill_window(); if (lookahead == 0 && flush == 0) { return 0; } if (lookahead == 0) { break; } } strstart += lookahead; lookahead = 0; int num2 = block_start + num; if (strstart == 0 || strstart >= num2) { lookahead = strstart - num2; strstart = num2; flush_block_only(eof: false); if (strm.avail_out == 0) { return 0; } } if (strstart - block_start >= w_size - MIN_LOOKAHEAD) { flush_block_only(eof: false); if (strm.avail_out == 0) { return 0; } } } flush_block_only(flush == 4); if (strm.avail_out == 0) { if (flush != 4) { return 0; } return 2; } if (flush != 4) { return 1; } return 3; } internal void _tr_stored_block(int buf, int stored_len, bool eof) { send_bits(eof ? 1 : 0, 3); copy_block(buf, stored_len, header: true); } internal void _tr_flush_block(int buf, int stored_len, bool eof) { int num = 0; int num2; int num3; if (level > 0) { if (data_type == 2) { set_data_type(); } l_desc.build_tree(this); d_desc.build_tree(this); num = build_bl_tree(); num2 = SupportClass.URShift(opt_len + 3 + 7, 3); num3 = SupportClass.URShift(static_len + 3 + 7, 3); if (num3 <= num2) { num2 = num3; } } else { num2 = (num3 = stored_len + 5); } if (stored_len + 4 <= num2 && buf != -1) { _tr_stored_block(buf, stored_len, eof); } else if (num3 == num2) { send_bits(2 + (eof ? 1 : 0), 3); compress_block(StaticTree.static_ltree, StaticTree.static_dtree); } else { send_bits(4 + (eof ? 1 : 0), 3); send_all_trees(l_desc.max_code + 1, d_desc.max_code + 1, num + 1); compress_block(dyn_ltree, dyn_dtree); } init_block(); if (eof) { bi_windup(); } } internal void fill_window() { do { int num = window_size - lookahead - strstart; int num2; if (num == 0 && strstart == 0 && lookahead == 0) { num = w_size; } else if (num == -1) { num--; } else if (strstart >= w_size + w_size - MIN_LOOKAHEAD) { Array.Copy(window, w_size, window, 0, w_size); match_start -= w_size; strstart -= w_size; block_start -= w_size; num2 = hash_size; int num3 = num2; do { int num4 = head[--num3] & 0xFFFF; head[num3] = (short)((num4 >= w_size) ? (num4 - w_size) : 0); } while (--num2 != 0); num2 = w_size; num3 = num2; do { int num4 = prev[--num3] & 0xFFFF; prev[num3] = (short)((num4 >= w_size) ? (num4 - w_size) : 0); } while (--num2 != 0); num += w_size; } if (strm.avail_in == 0) { break; } num2 = strm.read_buf(window, strstart + lookahead, num); lookahead += num2; if (lookahead >= 3) { ins_h = window[strstart] & 0xFF; ins_h = ((ins_h << hash_shift) ^ (window[strstart + 1] & 0xFF)) & hash_mask; } } while (lookahead < MIN_LOOKAHEAD && strm.avail_in != 0); } internal int deflate_fast(int flush) { int num = 0; while (true) { if (lookahead < MIN_LOOKAHEAD) { fill_window(); if (lookahead < MIN_LOOKAHEAD && flush == 0) { return 0; } if (lookahead == 0) { break; } } if (lookahead >= 3) { ins_h = ((ins_h << hash_shift) ^ (window[strstart + 2] & 0xFF)) & hash_mask; num = head[ins_h] & 0xFFFF; prev[strstart & w_mask] = head[ins_h]; head[ins_h] = (short)strstart; } if (num != 0L && ((strstart - num) & 0xFFFF) <= w_size - MIN_LOOKAHEAD && strategy != 2) { match_length = longest_match(num); } bool flag; if (match_length >= 3) { flag = _tr_tally(strstart - match_start, match_length - 3); lookahead -= match_length; if (match_length <= max_lazy_match && lookahead >= 3) { match_length--; do { strstart++; ins_h = ((ins_h << hash_shift) ^ (window[strstart + 2] & 0xFF)) & hash_mask; num = head[ins_h] & 0xFFFF; prev[strstart & w_mask] = head[ins_h]; head[ins_h] = (short)strstart; } while (--match_length != 0); strstart++; } else { strstart += match_length; match_length = 0; ins_h = window[strstart] & 0xFF; ins_h = ((ins_h << hash_shift) ^ (window[strstart + 1] & 0xFF)) & hash_mask; } } else { flag = _tr_tally(0, window[strstart] & 0xFF); lookahead--; strstart++; } if (flag) { flush_block_only(eof: false); if (strm.avail_out == 0) { return 0; } } } flush_block_only(flush == 4); if (strm.avail_out == 0) { if (flush == 4) { return 2; } return 0; } if (flush != 4) { return 1; } return 3; } internal int deflate_slow(int flush) { int num = 0; while (true) { if (lookahead < MIN_LOOKAHEAD) { fill_window(); if (lookahead < MIN_LOOKAHEAD && flush == 0) { return 0; } if (lookahead == 0) { break; } } if (lookahead >= 3) { ins_h = ((ins_h << hash_shift) ^ (window[strstart + 2] & 0xFF)) & hash_mask; num = head[ins_h] & 0xFFFF; prev[strstart & w_mask] = head[ins_h]; head[ins_h] = (short)strstart; } prev_length = match_length; prev_match = match_start; match_length = 2; if (num != 0 && prev_length < max_lazy_match && ((strstart - num) & 0xFFFF) <= w_size - MIN_LOOKAHEAD) { if (strategy != 2) { match_length = longest_match(num); } if (match_length <= 5 && (strategy == 1 || (match_length == 3 && strstart - match_start > 4096))) { match_length = 2; } } if (prev_length >= 3 && match_length <= prev_length) { int num2 = strstart + lookahead - 3; bool flag = _tr_tally(strstart - 1 - prev_match, prev_length - 3); lookahead -= prev_length - 1; prev_length -= 2; do { if (++strstart <= num2) { ins_h = ((ins_h << hash_shift) ^ (window[strstart + 2] & 0xFF)) & hash_mask; num = head[ins_h] & 0xFFFF; prev[strstart & w_mask] = head[ins_h]; head[ins_h] = (short)strstart; } } while (--prev_length != 0); match_available = 0; match_length = 2; strstart++; if (flag) { flush_block_only(eof: false); if (strm.avail_out == 0) { return 0; } } } else if (match_available != 0) { if (_tr_tally(0, window[strstart - 1] & 0xFF)) { flush_block_only(eof: false); } strstart++; lookahead--; if (strm.avail_out == 0) { return 0; } } else { match_available = 1; strstart++; lookahead--; } } if (match_available != 0) { bool flag = _tr_tally(0, window[strstart - 1] & 0xFF); match_available = 0; } flush_block_only(flush == 4); if (strm.avail_out == 0) { if (flush == 4) { return 2; } return 0; } if (flush != 4) { return 1; } return 3; } internal int longest_match(int cur_match) { int num = max_chain_length; int num2 = strstart; int num3 = prev_length; int num4 = ((strstart > w_size - MIN_LOOKAHEAD) ? (strstart - (w_size - MIN_LOOKAHEAD)) : 0); int num5 = nice_match; int num6 = w_mask; int num7 = strstart + 258; byte b = window[num2 + num3 - 1]; byte b2 = window[num2 + num3]; if (prev_length >= good_match) { num >>= 2; } if (num5 > lookahead) { num5 = lookahead; } do { int num8 = cur_match; if (window[num8 + num3] != b2 || window[num8 + num3 - 1] != b || window[num8] != window[num2] || window[++num8] != window[num2 + 1]) { continue; } num2 += 2; num8++; while (window[++num2] == window[++num8] && window[++num2] == window[++num8] && window[++num2] == window[++num8] && window[++num2] == window[++num8] && window[++num2] == window[++num8] && window[++num2] == window[++num8] && window[++num2] == window[++num8] && window[++num2] == window[++num8] && num2 < num7) { } int num9 = 258 - (num7 - num2); num2 = num7 - 258; if (num9 > num3) { match_start = cur_match; num3 = num9; if (num9 >= num5) { break; } b = window[num2 + num3 - 1]; b2 = window[num2 + num3]; } } while ((cur_match = prev[cur_match & num6] & 0xFFFF) > num4 && --num != 0); if (num3 <= lookahead) { return num3; } return lookahead; } internal int deflateInit(ZStream strm, int level, int bits) { return deflateInit2(strm, level, 8, bits, 8, 0); } internal int deflateInit(ZStream strm, int level) { return deflateInit(strm, level, 15); } internal int deflateInit2(ZStream strm, int level, int method, int windowBits, int memLevel, int strategy) { int num = 0; strm.msg = null; if (level == -1) { level = 6; } if (windowBits < 0) { num = 1; windowBits = -windowBits; } if (memLevel < 1 || memLevel > 9 || method != 8 || windowBits < 9 || windowBits > 15 || level < 0 || level > 9 || strategy < 0 || strategy > 2) { return -2; } strm.dstate = this; noheader = num; w_bits = windowBits; w_size = 1 << w_bits; w_mask = w_size - 1; hash_bits = memLevel + 7; hash_size = 1 << hash_bits; hash_mask = hash_size - 1; hash_shift = (hash_bits + 3 - 1) / 3; window = new byte[w_size * 2]; prev = new short[w_size]; head = new short[hash_size]; lit_bufsize = 1 << memLevel + 6; pending_buf = new byte[lit_bufsize * 4]; pending_buf_size = lit_bufsize * 4; d_buf = lit_bufsize; l_buf = 3 * lit_bufsize; this.level = level; this.strategy = strategy; this.method = (byte)method; return deflateReset(strm); } internal int deflateReset(ZStream strm) { strm.total_in = (strm.total_out = 0L); strm.msg = null; strm.data_type = 2; pending = 0; pending_out = 0; if (noheader < 0) { noheader = 0; } status = ((noheader != 0) ? 113 : 42); strm.adler = strm._adler.adler32(0L, null, 0, 0); last_flush = 0; tr_init(); lm_init(); return 0; } internal int deflateEnd() { if (status != 42 && status != 113 && status != 666) { return -2; } pending_buf = null; head = null; prev = null; window = null; if (status != 113) { return 0; } return -3; } internal int deflateParams(ZStream strm, int _level, int _strategy) { int result = 0; if (_level == -1) { _level = 6; } if (_level < 0 || _level > 9 || _strategy < 0 || _strategy > 2) { return -2; } if (config_table[level].func != config_table[_level].func && strm.total_in != 0L) { result = strm.deflate(1); } if (level != _level) { level = _level; max_lazy_match = config_table[level].max_lazy; good_match = config_table[level].good_length; nice_match = config_table[level].nice_length; max_chain_length = config_table[level].max_chain; } strategy = _strategy; return result; } internal int deflateSetDictionary(ZStream strm, byte[] dictionary, int dictLength) { int num = dictLength; int sourceIndex = 0; if (dictionary == null || status != 42) { return -2; } strm.adler = strm._adler.adler32(strm.adler, dictionary, 0, dictLength); if (num < 3) { return 0; } if (num > w_size - MIN_LOOKAHEAD) { num = w_size - MIN_LOOKAHEAD; sourceIndex = dictLength - num; } Array.Copy(dictionary, sourceIndex, window, 0, num); strstart = num; block_start = num; ins_h = window[0] & 0xFF; ins_h = ((ins_h << hash_shift) ^ (window[1] & 0xFF)) & hash_mask; for (int i = 0; i <= num - 3; i++) { ins_h = ((ins_h << hash_shift) ^ (window[i + 2] & 0xFF)) & hash_mask; prev[i & w_mask] = head[ins_h]; head[ins_h] = (short)i; } return 0; } internal int deflate(ZStream strm, int flush) { if (flush > 4 || flush < 0) { return -2; } if (strm.next_out == null || (strm.next_in == null && strm.avail_in != 0) || (status == 666 && flush != 4)) { strm.msg = z_errmsg[4]; return -2; } if (strm.avail_out == 0) { strm.msg = z_errmsg[7]; return -5; } this.strm = strm; int num = last_flush; last_flush = flush; if (status == 42) { int num2 = 8 + (w_bits - 8 << 4) << 8; int num3 = ((level - 1) & 0xFF) >> 1; if (num3 > 3) { num3 = 3; } num2 |= num3 << 6; if (strstart != 0) { num2 |= 0x20; } num2 += 31 - num2 % 31; status = 113; putShortMSB(num2); if (strstart != 0) { putShortMSB((int)SupportClass.URShift(strm.adler, 16)); putShortMSB((int)(strm.adler & 0xFFFF)); } strm.adler = strm._adler.adler32(0L, null, 0, 0); } if (pending != 0) { strm.flush_pending(); if (strm.avail_out == 0) { last_flush = -1; return 0; } } else if (strm.avail_in == 0 && flush <= num && flush != 4) { strm.msg = z_errmsg[7]; return -5; } if (status == 666 && strm.avail_in != 0) { strm.msg = z_errmsg[7]; return -5; } if (strm.avail_in != 0 || lookahead != 0 || (flush != 0 && status != 666)) { int num4 = -1; switch (config_table[level].func) { case 0: num4 = deflate_stored(flush); break; case 1: num4 = deflate_fast(flush); break; case 2: num4 = deflate_slow(flush); break; } if (num4 == 2 || num4 == 3) { status = 666; } switch (num4) { case 0: case 2: if (strm.avail_out == 0) { last_flush = -1; } return 0; case 1: if (flush == 1) { _tr_align(); } else { _tr_stored_block(0, 0, eof: false); if (flush == 3) { for (int i = 0; i < hash_size; i++) { head[i] = 0; } } } strm.flush_pending(); if (strm.avail_out == 0) { last_flush = -1; return 0; } break; } } if (flush != 4) { return 0; } if (noheader != 0) { return 1; } putShortMSB((int)SupportClass.URShift(strm.adler, 16)); putShortMSB((int)(strm.adler & 0xFFFF)); strm.flush_pending(); noheader = -1; if (pending == 0) { return 1; } return 0; } static Deflate() { z_errmsg = new string[10] { "need dictionary", "stream end", "", "file error", "stream error", "data error", "insufficient memory", "buffer error", "incompatible version", "" }; MIN_LOOKAHEAD = 262; L_CODES = 286; HEAP_SIZE = 2 * L_CODES + 1; config_table = new Config[10]; config_table[0] = new Config(0, 0, 0, 0, 0); config_table[1] = new Config(4, 4, 8, 4, 1); config_table[2] = new Config(4, 5, 16, 8, 1); config_table[3] = new Config(4, 6, 32, 32, 1); config_table[4] = new Config(4, 4, 16, 16, 2); config_table[5] = new Config(8, 16, 32, 32, 2); config_table[6] = new Config(8, 16, 128, 128, 2); config_table[7] = new Config(8, 32, 128, 256, 2); config_table[8] = new Config(32, 128, 258, 1024, 2); config_table[9] = new Config(32, 258, 258, 4096, 2); } } }