342 lines
9.7 KiB
C#
342 lines
9.7 KiB
C#
using System;
|
|
|
|
namespace ComponentAce.Compression.Libs.zlib
|
|
{
|
|
internal sealed class Tree
|
|
{
|
|
private const int MAX_BITS = 15;
|
|
|
|
private const int BL_CODES = 19;
|
|
|
|
private const int D_CODES = 30;
|
|
|
|
private const int LITERALS = 256;
|
|
|
|
private const int LENGTH_CODES = 29;
|
|
|
|
private static readonly int L_CODES = 286;
|
|
|
|
private static readonly int HEAP_SIZE = 2 * L_CODES + 1;
|
|
|
|
internal const int MAX_BL_BITS = 7;
|
|
|
|
internal const int END_BLOCK = 256;
|
|
|
|
internal const int REP_3_6 = 16;
|
|
|
|
internal const int REPZ_3_10 = 17;
|
|
|
|
internal const int REPZ_11_138 = 18;
|
|
|
|
internal static readonly int[] extra_lbits = new int[29]
|
|
{
|
|
0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
|
|
1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
|
|
4, 4, 4, 4, 5, 5, 5, 5, 0
|
|
};
|
|
|
|
internal static readonly int[] extra_dbits = new int[30]
|
|
{
|
|
0, 0, 0, 0, 1, 1, 2, 2, 3, 3,
|
|
4, 4, 5, 5, 6, 6, 7, 7, 8, 8,
|
|
9, 9, 10, 10, 11, 11, 12, 12, 13, 13
|
|
};
|
|
|
|
internal static readonly int[] extra_blbits = new int[19]
|
|
{
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 2, 3, 7
|
|
};
|
|
|
|
internal static readonly byte[] bl_order = new byte[19]
|
|
{
|
|
16, 17, 18, 0, 8, 7, 9, 6, 10, 5,
|
|
11, 4, 12, 3, 13, 2, 14, 1, 15
|
|
};
|
|
|
|
internal const int Buf_size = 16;
|
|
|
|
internal const int DIST_CODE_LEN = 512;
|
|
|
|
internal static readonly byte[] _dist_code = new byte[512]
|
|
{
|
|
0, 1, 2, 3, 4, 4, 5, 5, 6, 6,
|
|
6, 6, 7, 7, 7, 7, 8, 8, 8, 8,
|
|
8, 8, 8, 8, 9, 9, 9, 9, 9, 9,
|
|
9, 9, 10, 10, 10, 10, 10, 10, 10, 10,
|
|
10, 10, 10, 10, 10, 10, 10, 10, 11, 11,
|
|
11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
|
|
11, 11, 11, 11, 12, 12, 12, 12, 12, 12,
|
|
12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
|
|
12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
|
|
12, 12, 12, 12, 12, 12, 13, 13, 13, 13,
|
|
13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
|
|
13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
|
|
13, 13, 13, 13, 13, 13, 13, 13, 14, 14,
|
|
14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
|
|
14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
|
|
14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
|
|
14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
|
|
14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
|
|
14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
|
|
14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
|
|
15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
|
15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
|
15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
|
15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
|
15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
|
15, 15, 15, 15, 15, 15, 0, 0, 16, 17,
|
|
18, 18, 19, 19, 20, 20, 20, 20, 21, 21,
|
|
21, 21, 22, 22, 22, 22, 22, 22, 22, 22,
|
|
23, 23, 23, 23, 23, 23, 23, 23, 24, 24,
|
|
24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
|
24, 24, 24, 24, 25, 25, 25, 25, 25, 25,
|
|
25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
|
|
26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
|
|
26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
|
|
26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
|
|
26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
|
|
27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
|
|
27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
|
|
27, 27, 27, 27, 28, 28, 28, 28, 28, 28,
|
|
28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
|
|
28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
|
|
28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
|
|
28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
|
|
28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
|
|
28, 28, 28, 28, 28, 28, 28, 28, 29, 29,
|
|
29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
|
|
29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
|
|
29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
|
|
29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
|
|
29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
|
|
29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
|
|
29, 29
|
|
};
|
|
|
|
internal static readonly byte[] _length_code = new byte[256]
|
|
{
|
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 8,
|
|
9, 9, 10, 10, 11, 11, 12, 12, 12, 12,
|
|
13, 13, 13, 13, 14, 14, 14, 14, 15, 15,
|
|
15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
|
|
17, 17, 17, 17, 17, 17, 17, 17, 18, 18,
|
|
18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
|
|
19, 19, 19, 19, 20, 20, 20, 20, 20, 20,
|
|
20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
|
|
21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
|
|
21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
|
|
22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
|
|
22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
|
|
23, 23, 23, 23, 23, 23, 23, 23, 24, 24,
|
|
24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
|
24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
|
24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
|
25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
|
|
25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
|
|
25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
|
|
25, 25, 26, 26, 26, 26, 26, 26, 26, 26,
|
|
26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
|
|
26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
|
|
26, 26, 26, 26, 27, 27, 27, 27, 27, 27,
|
|
27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
|
|
27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
|
|
27, 27, 27, 27, 27, 28
|
|
};
|
|
|
|
internal static readonly int[] base_length = new int[29]
|
|
{
|
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 10,
|
|
12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
|
|
64, 80, 96, 112, 128, 160, 192, 224, 0
|
|
};
|
|
|
|
internal static readonly int[] base_dist = new int[30]
|
|
{
|
|
0, 1, 2, 3, 4, 6, 8, 12, 16, 24,
|
|
32, 48, 64, 96, 128, 192, 256, 384, 512, 768,
|
|
1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576
|
|
};
|
|
|
|
internal short[] dyn_tree;
|
|
|
|
internal int max_code;
|
|
|
|
internal StaticTree stat_desc;
|
|
|
|
internal static int d_code(int dist)
|
|
{
|
|
if (dist >= 256)
|
|
{
|
|
return _dist_code[256 + SupportClass.URShift(dist, 7)];
|
|
}
|
|
return _dist_code[dist];
|
|
}
|
|
|
|
internal void gen_bitlen(Deflate s)
|
|
{
|
|
short[] array = dyn_tree;
|
|
short[] static_tree = stat_desc.static_tree;
|
|
int[] extra_bits = stat_desc.extra_bits;
|
|
int extra_base = stat_desc.extra_base;
|
|
int max_length = stat_desc.max_length;
|
|
int num = 0;
|
|
for (int i = 0; i <= 15; i++)
|
|
{
|
|
s.bl_count[i] = 0;
|
|
}
|
|
array[s.heap[s.heap_max] * 2 + 1] = 0;
|
|
int j;
|
|
for (j = s.heap_max + 1; j < HEAP_SIZE; j++)
|
|
{
|
|
int num2 = s.heap[j];
|
|
int i = array[array[num2 * 2 + 1] * 2 + 1] + 1;
|
|
if (i > max_length)
|
|
{
|
|
i = max_length;
|
|
num++;
|
|
}
|
|
array[num2 * 2 + 1] = (short)i;
|
|
if (num2 <= max_code)
|
|
{
|
|
s.bl_count[i]++;
|
|
int num3 = 0;
|
|
if (num2 >= extra_base)
|
|
{
|
|
num3 = extra_bits[num2 - extra_base];
|
|
}
|
|
short num4 = array[num2 * 2];
|
|
s.opt_len += num4 * (i + num3);
|
|
if (static_tree != null)
|
|
{
|
|
s.static_len += num4 * (static_tree[num2 * 2 + 1] + num3);
|
|
}
|
|
}
|
|
}
|
|
if (num == 0)
|
|
{
|
|
return;
|
|
}
|
|
do
|
|
{
|
|
int i = max_length - 1;
|
|
while (s.bl_count[i] == 0)
|
|
{
|
|
i--;
|
|
}
|
|
s.bl_count[i]--;
|
|
s.bl_count[i + 1] = (short)(s.bl_count[i + 1] + 2);
|
|
s.bl_count[max_length]--;
|
|
num -= 2;
|
|
}
|
|
while (num > 0);
|
|
for (int i = max_length; i != 0; i--)
|
|
{
|
|
int num2 = s.bl_count[i];
|
|
while (num2 != 0)
|
|
{
|
|
int num5 = s.heap[--j];
|
|
if (num5 <= max_code)
|
|
{
|
|
if (array[num5 * 2 + 1] != i)
|
|
{
|
|
s.opt_len = (int)(s.opt_len + ((long)i - (long)array[num5 * 2 + 1]) * array[num5 * 2]);
|
|
array[num5 * 2 + 1] = (short)i;
|
|
}
|
|
num2--;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
internal void build_tree(Deflate s)
|
|
{
|
|
short[] array = dyn_tree;
|
|
short[] static_tree = stat_desc.static_tree;
|
|
int elems = stat_desc.elems;
|
|
int num = -1;
|
|
s.heap_len = 0;
|
|
s.heap_max = HEAP_SIZE;
|
|
for (int i = 0; i < elems; i++)
|
|
{
|
|
if (array[i * 2] != 0)
|
|
{
|
|
num = (s.heap[++s.heap_len] = i);
|
|
s.depth[i] = 0;
|
|
}
|
|
else
|
|
{
|
|
array[i * 2 + 1] = 0;
|
|
}
|
|
}
|
|
int num2;
|
|
while (s.heap_len < 2)
|
|
{
|
|
num2 = (s.heap[++s.heap_len] = ((num < 2) ? (++num) : 0));
|
|
array[num2 * 2] = 1;
|
|
s.depth[num2] = 0;
|
|
s.opt_len--;
|
|
if (static_tree != null)
|
|
{
|
|
s.static_len -= static_tree[num2 * 2 + 1];
|
|
}
|
|
}
|
|
max_code = num;
|
|
for (int i = s.heap_len / 2; i >= 1; i--)
|
|
{
|
|
s.pqdownheap(array, i);
|
|
}
|
|
num2 = elems;
|
|
do
|
|
{
|
|
int i = s.heap[1];
|
|
s.heap[1] = s.heap[s.heap_len--];
|
|
s.pqdownheap(array, 1);
|
|
int num3 = s.heap[1];
|
|
s.heap[--s.heap_max] = i;
|
|
s.heap[--s.heap_max] = num3;
|
|
array[num2 * 2] = (short)(array[i * 2] + array[num3 * 2]);
|
|
s.depth[num2] = (byte)(Math.Max(s.depth[i], s.depth[num3]) + 1);
|
|
array[i * 2 + 1] = (array[num3 * 2 + 1] = (short)num2);
|
|
s.heap[1] = num2++;
|
|
s.pqdownheap(array, 1);
|
|
}
|
|
while (s.heap_len >= 2);
|
|
s.heap[--s.heap_max] = s.heap[1];
|
|
gen_bitlen(s);
|
|
gen_codes(array, num, s.bl_count);
|
|
}
|
|
|
|
internal static void gen_codes(short[] tree, int max_code, short[] bl_count)
|
|
{
|
|
short[] array = new short[16];
|
|
short num = 0;
|
|
for (int i = 1; i <= 15; i++)
|
|
{
|
|
num = (array[i] = (short)(num + bl_count[i - 1] << 1));
|
|
}
|
|
for (int j = 0; j <= max_code; j++)
|
|
{
|
|
int num2 = tree[j * 2 + 1];
|
|
if (num2 != 0)
|
|
{
|
|
tree[j * 2] = (short)bi_reverse(array[num2]++, num2);
|
|
}
|
|
}
|
|
}
|
|
|
|
internal static int bi_reverse(int code, int len)
|
|
{
|
|
int num = 0;
|
|
do
|
|
{
|
|
num |= code & 1;
|
|
code = SupportClass.URShift(code, 1);
|
|
num <<= 1;
|
|
}
|
|
while (--len > 0);
|
|
return SupportClass.URShift(num, 1);
|
|
}
|
|
}
|
|
}
|