AxibugEmuOnline/OtherCore/MyNes.Standard2/MyNes.Core/ComponentAce.Compression.Libs.zlib/Deflate.cs

1413 lines
32 KiB
C#
Raw Normal View History

2024-07-24 15:03:33 +08:00
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);
}
}
}