Files
CypherCore/Source/Framework/IO/Zlib/Trees.cs
T
2021-11-15 16:11:20 -05:00

1069 lines
43 KiB
C#

// trees.cs -- output deflated data using Huffman coding
// Copyright (C) 1995-2010 Jean-loup Gailly
// Copyright (C) 2007-2011 by the Authors
// For conditions of distribution and use, see copyright notice in License.txt
// ALGORITHM
//
// The "deflation" process uses several Huffman trees. The more
// common source values are represented by shorter bit sequences.
//
// Each code tree is stored in a compressed form which is itself
// a Huffman encoding of the lengths of all the code strings (in
// ascending order by source values). The actual code strings are
// reconstructed from the lengths in the inflate process, as described
// in the deflate specification.
//
// REFERENCES
//
// Deutsch, L.P.,"'Deflate' Compressed Data Format Specification".
// Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc
//
// Storer, James A.
// Data Compression: Methods and Theory, pp. 49-50.
// Computer Science Press, 1988. ISBN 0-7167-8156-5.
//
// Sedgewick, R.
// Algorithms, p290.
// Addison-Wesley, 1983. ISBN 0-201-06672-6.
namespace Framework.IO
{
public static partial class ZLib
{
// ===========================================================================
// Constants
//
// Bit length codes must not exceed MAX_BL_BITS bits
private const int MAX_BL_BITS=7;
// end of block literal code
private const int END_BLOCK=256;
// repeat previous bit length 3-6 times (2 bits of repeat count)
private const int REP_3_6=16;
// repeat a zero length 3-10 times (3 bits of repeat count)
private const int REPZ_3_10=17;
// repeat a zero length 11-138 times (7 bits of repeat count)
private const int REPZ_11_138=18;
// extra bits for each length code
private static readonly int[] extra_lbits=new int[LENGTH_CODES] { 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 };
// extra bits for each distance code
private static readonly int[] extra_dbits=new int[D_CODES] { 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 };
// extra bits for each bit length code
private static readonly int[] extra_blbits=new int[BL_CODES] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7 };
// The lengths of the bit length codes are sent in order of decreasing
// probability, to avoid transmitting the lengths for unused bit length codes.
private static readonly byte[] bl_order=new byte[BL_CODES] { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
// Number of bits used within bi_buf. (bi_buf might be implemented on
// more than 16 bits on some systems.)
private const int Buf_size=8*2*sizeof(byte);
// ===========================================================================
// Local data. These are initialized only once.
// see definition of array dist_code below
private const int DIST_CODE_LEN=512;
#region Tables
private static readonly ct_data[] static_ltree=new ct_data[L_CODES+2]
{
new ct_data( 12, 8), new ct_data(140, 8), new ct_data( 76, 8), new ct_data(204, 8),
new ct_data( 44, 8), new ct_data(172, 8), new ct_data(108, 8), new ct_data(236, 8),
new ct_data( 28, 8), new ct_data(156, 8), new ct_data( 92, 8), new ct_data(220, 8),
new ct_data( 60, 8), new ct_data(188, 8), new ct_data(124, 8), new ct_data(252, 8),
new ct_data( 2, 8), new ct_data(130, 8), new ct_data( 66, 8), new ct_data(194, 8),
new ct_data( 34, 8), new ct_data(162, 8), new ct_data( 98, 8), new ct_data(226, 8),
new ct_data( 18, 8), new ct_data(146, 8), new ct_data( 82, 8), new ct_data(210, 8),
new ct_data( 50, 8), new ct_data(178, 8), new ct_data(114, 8), new ct_data(242, 8),
new ct_data( 10, 8), new ct_data(138, 8), new ct_data( 74, 8), new ct_data(202, 8),
new ct_data( 42, 8), new ct_data(170, 8), new ct_data(106, 8), new ct_data(234, 8),
new ct_data( 26, 8), new ct_data(154, 8), new ct_data( 90, 8), new ct_data(218, 8),
new ct_data( 58, 8), new ct_data(186, 8), new ct_data(122, 8), new ct_data(250, 8),
new ct_data( 6, 8), new ct_data(134, 8), new ct_data( 70, 8), new ct_data(198, 8),
new ct_data( 38, 8), new ct_data(166, 8), new ct_data(102, 8), new ct_data(230, 8),
new ct_data( 22, 8), new ct_data(150, 8), new ct_data( 86, 8), new ct_data(214, 8),
new ct_data( 54, 8), new ct_data(182, 8), new ct_data(118, 8), new ct_data(246, 8),
new ct_data( 14, 8), new ct_data(142, 8), new ct_data( 78, 8), new ct_data(206, 8),
new ct_data( 46, 8), new ct_data(174, 8), new ct_data(110, 8), new ct_data(238, 8),
new ct_data( 30, 8), new ct_data(158, 8), new ct_data( 94, 8), new ct_data(222, 8),
new ct_data( 62, 8), new ct_data(190, 8), new ct_data(126, 8), new ct_data(254, 8),
new ct_data( 1, 8), new ct_data(129, 8), new ct_data( 65, 8), new ct_data(193, 8),
new ct_data( 33, 8), new ct_data(161, 8), new ct_data( 97, 8), new ct_data(225, 8),
new ct_data( 17, 8), new ct_data(145, 8), new ct_data( 81, 8), new ct_data(209, 8),
new ct_data( 49, 8), new ct_data(177, 8), new ct_data(113, 8), new ct_data(241, 8),
new ct_data( 9, 8), new ct_data(137, 8), new ct_data( 73, 8), new ct_data(201, 8),
new ct_data( 41, 8), new ct_data(169, 8), new ct_data(105, 8), new ct_data(233, 8),
new ct_data( 25, 8), new ct_data(153, 8), new ct_data( 89, 8), new ct_data(217, 8),
new ct_data( 57, 8), new ct_data(185, 8), new ct_data(121, 8), new ct_data(249, 8),
new ct_data( 5, 8), new ct_data(133, 8), new ct_data( 69, 8), new ct_data(197, 8),
new ct_data( 37, 8), new ct_data(165, 8), new ct_data(101, 8), new ct_data(229, 8),
new ct_data( 21, 8), new ct_data(149, 8), new ct_data( 85, 8), new ct_data(213, 8),
new ct_data( 53, 8), new ct_data(181, 8), new ct_data(117, 8), new ct_data(245, 8),
new ct_data( 13, 8), new ct_data(141, 8), new ct_data( 77, 8), new ct_data(205, 8),
new ct_data( 45, 8), new ct_data(173, 8), new ct_data(109, 8), new ct_data(237, 8),
new ct_data( 29, 8), new ct_data(157, 8), new ct_data( 93, 8), new ct_data(221, 8),
new ct_data( 61, 8), new ct_data(189, 8), new ct_data(125, 8), new ct_data(253, 8),
new ct_data( 19, 9), new ct_data(275, 9), new ct_data(147, 9), new ct_data(403, 9),
new ct_data( 83, 9), new ct_data(339, 9), new ct_data(211, 9), new ct_data(467, 9),
new ct_data( 51, 9), new ct_data(307, 9), new ct_data(179, 9), new ct_data(435, 9),
new ct_data(115, 9), new ct_data(371, 9), new ct_data(243, 9), new ct_data(499, 9),
new ct_data( 11, 9), new ct_data(267, 9), new ct_data(139, 9), new ct_data(395, 9),
new ct_data( 75, 9), new ct_data(331, 9), new ct_data(203, 9), new ct_data(459, 9),
new ct_data( 43, 9), new ct_data(299, 9), new ct_data(171, 9), new ct_data(427, 9),
new ct_data(107, 9), new ct_data(363, 9), new ct_data(235, 9), new ct_data(491, 9),
new ct_data( 27, 9), new ct_data(283, 9), new ct_data(155, 9), new ct_data(411, 9),
new ct_data( 91, 9), new ct_data(347, 9), new ct_data(219, 9), new ct_data(475, 9),
new ct_data( 59, 9), new ct_data(315, 9), new ct_data(187, 9), new ct_data(443, 9),
new ct_data(123, 9), new ct_data(379, 9), new ct_data(251, 9), new ct_data(507, 9),
new ct_data( 7, 9), new ct_data(263, 9), new ct_data(135, 9), new ct_data(391, 9),
new ct_data( 71, 9), new ct_data(327, 9), new ct_data(199, 9), new ct_data(455, 9),
new ct_data( 39, 9), new ct_data(295, 9), new ct_data(167, 9), new ct_data(423, 9),
new ct_data(103, 9), new ct_data(359, 9), new ct_data(231, 9), new ct_data(487, 9),
new ct_data( 23, 9), new ct_data(279, 9), new ct_data(151, 9), new ct_data(407, 9),
new ct_data( 87, 9), new ct_data(343, 9), new ct_data(215, 9), new ct_data(471, 9),
new ct_data( 55, 9), new ct_data(311, 9), new ct_data(183, 9), new ct_data(439, 9),
new ct_data(119, 9), new ct_data(375, 9), new ct_data(247, 9), new ct_data(503, 9),
new ct_data( 15, 9), new ct_data(271, 9), new ct_data(143, 9), new ct_data(399, 9),
new ct_data( 79, 9), new ct_data(335, 9), new ct_data(207, 9), new ct_data(463, 9),
new ct_data( 47, 9), new ct_data(303, 9), new ct_data(175, 9), new ct_data(431, 9),
new ct_data(111, 9), new ct_data(367, 9), new ct_data(239, 9), new ct_data(495, 9),
new ct_data( 31, 9), new ct_data(287, 9), new ct_data(159, 9), new ct_data(415, 9),
new ct_data( 95, 9), new ct_data(351, 9), new ct_data(223, 9), new ct_data(479, 9),
new ct_data( 63, 9), new ct_data(319, 9), new ct_data(191, 9), new ct_data(447, 9),
new ct_data(127, 9), new ct_data(383, 9), new ct_data(255, 9), new ct_data(511, 9),
new ct_data( 0, 7), new ct_data( 64, 7), new ct_data( 32, 7), new ct_data( 96, 7),
new ct_data( 16, 7), new ct_data( 80, 7), new ct_data( 48, 7), new ct_data(112, 7),
new ct_data( 8, 7), new ct_data( 72, 7), new ct_data( 40, 7), new ct_data(104, 7),
new ct_data( 24, 7), new ct_data( 88, 7), new ct_data( 56, 7), new ct_data(120, 7),
new ct_data( 4, 7), new ct_data( 68, 7), new ct_data( 36, 7), new ct_data(100, 7),
new ct_data( 20, 7), new ct_data( 84, 7), new ct_data( 52, 7), new ct_data(116, 7),
new ct_data( 3, 8), new ct_data(131, 8), new ct_data( 67, 8), new ct_data(195, 8),
new ct_data( 35, 8), new ct_data(163, 8), new ct_data( 99, 8), new ct_data(227, 8)
};
private static readonly ct_data[] static_dtree=new ct_data[D_CODES]
{
new ct_data( 0, 5), new ct_data(16, 5), new ct_data( 8, 5), new ct_data(24, 5), new ct_data( 4, 5),
new ct_data(20, 5), new ct_data(12, 5), new ct_data(28, 5), new ct_data( 2, 5), new ct_data(18, 5),
new ct_data(10, 5), new ct_data(26, 5), new ct_data( 6, 5), new ct_data(22, 5), new ct_data(14, 5),
new ct_data(30, 5), new ct_data( 1, 5), new ct_data(17, 5), new ct_data( 9, 5), new ct_data(25, 5),
new ct_data( 5, 5), new ct_data(21, 5), new ct_data(13, 5), new ct_data(29, 5), new ct_data( 3, 5),
new ct_data(19, 5), new ct_data(11, 5), new ct_data(27, 5), new ct_data( 7, 5), new ct_data(23, 5)
};
private static readonly byte[] _dist_code=new byte[DIST_CODE_LEN]
{
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
};
private static readonly byte[] _length_code=new byte[MAX_MATCH-MIN_MATCH+1]
{
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
};
private static readonly int[] base_length=new int[LENGTH_CODES]
{
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
};
private static readonly int[] base_dist=new int[D_CODES]
{
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
};
#endregion
class static_tree_desc
{
public readonly ct_data[] static_tree; // static tree or NULL
public readonly int[] extra_bits; // extra bits for each code or NULL
public int extra_base; // base index for extra_bits
public int elems; // max number of elements in the tree
public int max_length; // max bit length for the codes
public static_tree_desc(ct_data[] static_tree, int[] extra_bits, int extra_base, int elems, int max_length)
{
this.static_tree=static_tree;
this.extra_bits=extra_bits;
this.extra_base=extra_base;
this.elems=elems;
this.max_length=max_length;
}
}
private static readonly static_tree_desc static_l_desc=new(static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS);
private static readonly static_tree_desc static_d_desc=new(static_dtree, extra_dbits, 0, D_CODES, MAX_BITS);
private static readonly static_tree_desc static_bl_desc=new(null, extra_blbits, 0, BL_CODES, MAX_BL_BITS);
// ===========================================================================
// Local (static) routines in this file.
//
// Send a code of the given tree. c and tree must not have side effects
//#define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len)
static void send_code(deflate_state s, int c, ct_data[] tree)
{
ushort value=tree[c].Code;
ushort len=tree[c].Len;
if(s.bi_valid>(int)Buf_size-len)
{
int val=value;
s.bi_buf|=(ushort)(val<<s.bi_valid);
//was put_short(s, s.bi_buf);
s.pending_buf[s.pending++]=(byte)(s.bi_buf&0xff);
s.pending_buf[s.pending++]=(byte)((ushort)s.bi_buf>>8);
s.bi_buf=(ushort)(val>>(Buf_size-s.bi_valid));
s.bi_valid+=len-Buf_size;
}
else
{
s.bi_buf|=(ushort)(value<<s.bi_valid);
s.bi_valid+=len;
}
}
// ===========================================================================
// Output a short LSB first on the stream.
// IN assertion: there is enough room in pendingBuf.
//#define put_short(s, w) { \
// put_byte(s, (unsigned char)((w) & 0xff)); \
// put_byte(s, (unsigned char)((unsigned short)(w) >> 8)); \
//}
// ===========================================================================
// Send a value on a given number of bits.
// IN assertion: length <= 16 and value fits in length bits.
//#define send_bits(s, value, length) { \
// int len = length; \
// if(s.bi_valid > (int)Buf_size - len) { \
// int val = value; \
// s.bi_buf |= (val << s.bi_valid); \
// // put_short(s, s.bi_buf); \
// s.pending_buf[s.pending++] = (unsigned char)(s.bi_buf & 0xff);\
// s.pending_buf[s.pending++] = (unsigned char)((unsigned short)s.bi_buf >> 8);\
// s.bi_buf = (unsigned short)val >> (Buf_size - s.bi_valid); \
// s.bi_valid += len - Buf_size; \
// } else { \
// s.bi_buf |= (value) << s.bi_valid; \
// s.bi_valid += len; \
// } \
// }
static void send_bits(deflate_state s, int value, int length)
{
int len=length;
if(s.bi_valid>(int)Buf_size-len)
{
int val=value;
s.bi_buf|=(ushort)(val<<s.bi_valid);
//was put_short(s, s.bi_buf);
s.pending_buf[s.pending++]=(byte)(s.bi_buf&0xff);
s.pending_buf[s.pending++]=(byte)((ushort)s.bi_buf>>8);
s.bi_buf=(ushort)(val>>(Buf_size-s.bi_valid));
s.bi_valid+=len-Buf_size;
}
else
{
s.bi_buf|=(ushort)(value<<s.bi_valid);
s.bi_valid+=len;
}
}
// the arguments must not have side effects
// ===========================================================================
// Initialize the tree data structures for a new zlib stream.
static void _tr_init(deflate_state s)
{
s.l_desc.dyn_tree=s.dyn_ltree;
s.l_desc.stat_desc=static_l_desc;
s.d_desc.dyn_tree=s.dyn_dtree;
s.d_desc.stat_desc=static_d_desc;
s.bl_desc.dyn_tree=s.bl_tree;
s.bl_desc.stat_desc=static_bl_desc;
s.bi_buf=0;
s.bi_valid=0;
s.last_eob_len=8; // enough lookahead for inflate
// Initialize the first block of the first file:
init_block(s);
}
// ===========================================================================
// Initialize a new block.
static void init_block(deflate_state s)
{
// Initialize the trees.
for(int n=0; n<L_CODES; n++) s.dyn_ltree[n].Freq=0;
for(int n=0; n<D_CODES; n++) s.dyn_dtree[n].Freq=0;
for(int n=0; n<BL_CODES; n++) s.bl_tree[n].Freq=0;
s.dyn_ltree[END_BLOCK].Freq=1;
s.opt_len=s.static_len=0;
s.last_lit=s.matches=0;
}
// Index within the heap array of least frequent node in the Huffman tree
private const int SMALLEST=1;
// ===========================================================================
// Remove the smallest element from the heap and recreate the heap with
// one less element. Updates heap and heap_len.
//#define pqremove(s, tree, top) \
// top = s.heap[SMALLEST]; \
// s.heap[SMALLEST] = s.heap[s.heap_len--]; \
// pqdownheap(s, tree, SMALLEST);
// ===========================================================================
// Compares to subtrees, using the tree depth as tie breaker when
// the subtrees have equal frequency. This minimizes the worst case length.
//#define smaller(tree, n, m, depth) \
// (tree[n].Freq < tree[m].Freq || \
// (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m]))
// ===========================================================================
// Restore the heap property by moving down the tree starting at node k,
// exchanging a node with the smallest of its two sons if necessary, stopping
// when the heap property is re-established (each father smaller than its
// two sons).
// tree: the tree to restore
// k: node to move down
static void pqdownheap(deflate_state s, ct_data[] tree, int k)
{
int v=s.heap[k];
int j=k<<1; // left son of k
while(j<=s.heap_len)
{
// Set j to the smallest of the two sons:
//was if (j < s.heap_len && smaller(tree, s.heap[j+1], s.heap[j], s.depth))
if(j<s.heap_len&&(tree[s.heap[j+1]].Freq<tree[s.heap[j]].Freq||
(tree[s.heap[j+1]].Freq==tree[s.heap[j]].Freq&&s.depth[s.heap[j+1]]<=s.depth[s.heap[j]]))) j++;
// Exit if v is smaller than both sons
//was if (smaller(tree, v, s.heap[j], s.depth)) break;
if(tree[v].Freq<tree[s.heap[j]].Freq||
(tree[v].Freq==tree[s.heap[j]].Freq&&s.depth[v]<=s.depth[s.heap[j]])) break;
// Exchange v with the smallest son
s.heap[k]=s.heap[j]; k=j;
// And continue down the tree, setting j to the left son of k
j<<=1;
}
s.heap[k]=v;
}
// ===========================================================================
// Compute the optimal bit lengths for a tree and update the total bit length
// for the current block.
// IN assertion: the fields freq and dad are set, heap[heap_max] and
// above are the tree nodes sorted by increasing frequency.
// OUT assertions: the field len is set to the optimal bit length, the
// array bl_count contains the frequencies for each bit length.
// The length opt_len is updated; static_len is also updated if stree is
// not null.
// desc: the tree descriptor
static void gen_bitlen(deflate_state s, ref tree_desc desc)
{
ct_data[] tree=desc.dyn_tree;
int max_code=desc.max_code;
ct_data[] stree=desc.stat_desc.static_tree;
int[] extra=desc.stat_desc.extra_bits;
int @base=desc.stat_desc.extra_base;
int max_length=desc.stat_desc.max_length;
int h; // heap index
int n, m; // iterate over the tree elements
int bits; // bit length
int xbits; // extra bits
ushort f; // frequency
int overflow=0; // number of elements with bit length too large
for(bits=0; bits<=MAX_BITS; bits++) s.bl_count[bits]=0;
// In a first pass, compute the optimal bit lengths (which may
// overflow in the case of the bit length tree).
tree[s.heap[s.heap_max]].Len=0; // root of the heap
for(h=s.heap_max+1; h<HEAP_SIZE; h++)
{
n=s.heap[h];
bits=tree[tree[n].Dad].Len+1;
if(bits>max_length) { bits=max_length; overflow++; }
tree[n].Len=(ushort)bits;
// We overwrite tree[n].Dad which is no longer needed
if(n>max_code) continue; // not a leaf node
s.bl_count[bits]++;
xbits=0;
if(n>=@base) xbits=extra[n-@base];
f=tree[n].Freq;
s.opt_len+=(uint)(f*(bits+xbits));
if(stree!=null) s.static_len+=(uint)(f*(stree[n].Len+xbits));
}
if(overflow==0) return;
//Trace((stderr,"\nbit length overflow\n"));
// This happens for example on obj2 and pic of the Calgary corpus
// Find the first bit length which could increase:
do
{
bits=max_length-1;
while(s.bl_count[bits]==0) bits--;
s.bl_count[bits]--; // move one leaf down the tree
s.bl_count[bits+1]+=2; // move one overflow item as its brother
s.bl_count[max_length]--;
// The brother of the overflow item also moves one step up,
// but this does not affect bl_count[max_length]
overflow-=2;
} while(overflow>0);
// Now recompute all bit lengths, scanning in increasing frequency.
// h is still equal to HEAP_SIZE. (It is simpler to reconstruct all
// lengths instead of fixing only the wrong ones. This idea is taken
// from 'ar' written by Haruhiko Okumura.)
for(bits=max_length; bits!=0; bits--)
{
n=s.bl_count[bits];
while(n!=0)
{
m=s.heap[--h];
if(m>max_code) continue;
if((uint)tree[m].Len!=(uint)bits)
{
//Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits));
s.opt_len+=((uint)bits-tree[m].Len)*tree[m].Freq;
tree[m].Len=(ushort)bits;
}
n--;
}
}
}
// ===========================================================================
// Generate the codes for a given tree and bit counts (which need not be
// optimal).
// IN assertion: the array bl_count contains the bit length statistics for
// the given tree and the field len is set for all tree elements.
// OUT assertion: the field code is set for all tree elements of non
// zero code length.
// tree: the tree to decorate
// max_code: largest code with non zero frequency
// bl_count: number of codes at each bit length
static void gen_codes(ct_data[] tree, int max_code, ushort[] bl_count)
{
ushort[] next_code=new ushort[MAX_BITS+1]; // next code value for each bit length
ushort code=0; // running code value
int bits; // bit index
int n; // code index
// The distribution counts are first used to generate the code values
// without bit reversal.
for(bits=1; bits<=MAX_BITS; bits++) next_code[bits]=code=(ushort)((code+bl_count[bits-1])<<1);
// Check that the bit counts in bl_count are consistent. The last code
// must be all ones.
//Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1, "inconsistent bit counts");
//Tracev((stderr, "\ngen_codes: max_code %d ", max_code));
for(n=0; n<=max_code; n++)
{
int len=tree[n].Len;
if(len==0) continue;
// Now reverse the bits
tree[n].Code=bi_reverse(next_code[len]++, len);
//Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ", n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1));
}
}
// ===========================================================================
// Construct one Huffman tree and assigns the code bit strings and lengths.
// Update the total bit length for the current block.
// IN assertion: the field freq is set for all tree elements.
// OUT assertions: the fields len and code are set to the optimal bit length
// and corresponding code. The length opt_len is updated; static_len is
// also updated if stree is not null. The field max_code is set.
// desc: the tree descriptor
static void build_tree(deflate_state s, ref tree_desc desc)
{
ct_data[] tree=desc.dyn_tree;
ct_data[] stree=desc.stat_desc.static_tree;
int elems=desc.stat_desc.elems;
int n, m; // iterate over heap elements
int max_code=-1; // largest code with non zero frequency
int node; // new node being created
// Construct the initial heap, with least frequent element in
// heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
// heap[0] is not used.
s.heap_len=0;
s.heap_max=HEAP_SIZE;
for(n=0; n<elems; n++)
{
if(tree[n].Freq!=0)
{
s.heap[++(s.heap_len)]=max_code=n;
s.depth[n]=0;
}
else tree[n].Len=0;
}
// The pkzip format requires that at least one distance code exists,
// and that at least one bit should be sent even if there is only one
// possible code. So to avoid special checks later on we force at least
// two codes of non zero frequency.
while(s.heap_len<2)
{
node=s.heap[++(s.heap_len)]=(max_code<2?++max_code:0);
tree[node].Freq=1;
s.depth[node]=0;
s.opt_len--; if(stree!=null) s.static_len-=stree[node].Len;
// node is 0 or 1 so it does not have extra bits
}
desc.max_code=max_code;
// The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
// establish sub-heaps of increasing lengths:
for(n=s.heap_len/2; n>=1; n--) pqdownheap(s, tree, n);
// Construct the Huffman tree by repeatedly combining the least two
// frequent nodes.
node=elems; // next internal node of the tree
do
{
//was pqremove(s, tree, n); // n = node of least frequency
n=s.heap[SMALLEST];
s.heap[SMALLEST]=s.heap[s.heap_len--];
pqdownheap(s, tree, SMALLEST);
m=s.heap[SMALLEST]; // m = node of next least frequency
s.heap[--(s.heap_max)]=n; // keep the nodes sorted by frequency
s.heap[--(s.heap_max)]=m;
// Create a new node father of n and m
tree[node].Freq=(ushort)(tree[n].Freq+tree[m].Freq);
s.depth[node]=(byte)((s.depth[n]>=s.depth[m]?s.depth[n]:s.depth[m])+1);
tree[n].Dad=tree[m].Dad=(ushort)node;
// and insert the new node in the heap
s.heap[SMALLEST]=node++;
pqdownheap(s, tree, SMALLEST);
} while(s.heap_len>=2);
s.heap[--(s.heap_max)]=s.heap[SMALLEST];
// At this point, the fields freq and dad are set. We can now
// generate the bit lengths.
gen_bitlen(s, ref desc);
// The field len is now set, we can generate the bit codes
gen_codes(tree, max_code, s.bl_count);
}
// ===========================================================================
// Scan a literal or distance tree to determine the frequencies of the codes
// in the bit length tree.
// tree: the tree to be scanned
// max_code: and its largest code of non zero frequency
static void scan_tree(deflate_state s, ct_data[] tree, int max_code)
{
int n; // iterates over all tree elements
int prevlen=-1; // last emitted length
int curlen; // length of current code
int nextlen=tree[0].Len; // length of next code
int count=0; // repeat count of the current code
int max_count=7; // max repeat count
int min_count=4; // min repeat count
if(nextlen==0) { max_count=138; min_count=3; }
tree[max_code+1].Len=(ushort)0xffff; // guard
for(n=0; n<=max_code; n++)
{
curlen=nextlen; nextlen=tree[n+1].Len;
if(++count<max_count&&curlen==nextlen) continue;
if(count<min_count) s.bl_tree[curlen].Freq+=(ushort)count;
else if(curlen!=0)
{
if(curlen!=prevlen) s.bl_tree[curlen].Freq++;
s.bl_tree[REP_3_6].Freq++;
}
else if(count<=10) s.bl_tree[REPZ_3_10].Freq++;
else s.bl_tree[REPZ_11_138].Freq++;
count=0; prevlen=curlen;
if(nextlen==0) { max_count=138; min_count=3; }
else if(curlen==nextlen) { max_count=6; min_count=3; }
else { max_count=7; min_count=4; }
}
}
// ===========================================================================
// Send a literal or distance tree in compressed form, using the codes in bl_tree.
// tree: the tree to be scanned
// max_code: and its largest code of non zero frequency
static void send_tree(deflate_state s, ct_data[] tree, int max_code)
{
int n; // iterates over all tree elements
int prevlen=-1; // last emitted length
int curlen; // length of current code
int nextlen=tree[0].Len; // length of next code
int count=0; // repeat count of the current code
int max_count=7; // max repeat count
int min_count=4; // min repeat count
// tree[max_code+1].Len = -1;
// guard already set
if(nextlen==0) { max_count=138; min_count=3; }
for(n=0; n<=max_code; n++)
{
curlen=nextlen; nextlen=tree[n+1].Len;
if(++count<max_count&&curlen==nextlen) continue;
if(count<min_count)
{
do { send_code(s, curlen, s.bl_tree); } while(--count!=0);
}
else if(curlen!=0)
{
if(curlen!=prevlen) { send_code(s, curlen, s.bl_tree); count--; }
//Assert(count>=3&&count<=6, " 3_6?");
send_code(s, REP_3_6, s.bl_tree); send_bits(s, count-3, 2);
}
else if(count<=10) { send_code(s, REPZ_3_10, s.bl_tree); send_bits(s, count-3, 3); }
else { send_code(s, REPZ_11_138, s.bl_tree); send_bits(s, count-11, 7); }
count=0; prevlen=curlen;
if(nextlen==0) { max_count=138; min_count=3; }
else if(curlen==nextlen) { max_count=6; min_count=3; }
else { max_count=7; min_count=4; }
}
}
// ===========================================================================
// Construct the Huffman tree for the bit lengths and return the index in
// bl_order of the last bit length code to send.
static int build_bl_tree(deflate_state s)
{
int max_blindex; // index of last bit length code of non zero freq
// Determine the bit length frequencies for literal and distance trees
scan_tree(s, s.dyn_ltree, s.l_desc.max_code);
scan_tree(s, s.dyn_dtree, s.d_desc.max_code);
// Build the bit length tree:
build_tree(s, ref s.bl_desc);
// opt_len now includes the length of the tree representations, except
// the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
// Determine the number of bit length codes to send. The pkzip format
// requires that at least 4 bit length codes be sent. (appnote.txt says
// 3 but the actual value used is 4.)
for(max_blindex=BL_CODES-1; max_blindex>=3; max_blindex--)
{
if(s.bl_tree[bl_order[max_blindex]].Len!=0) break;
}
// Update opt_len to include the bit length tree and counts
s.opt_len+=(uint)(3*(max_blindex+1)+5+5+4);
//Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", s.opt_len, s.static_len));
return max_blindex;
}
// ===========================================================================
// Send the header for a block using dynamic Huffman trees: the counts, the
// lengths of the bit length codes, the literal tree and the distance tree.
// IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
// lcodes, dcodes, blcodes: number of codes for each tree
static void send_all_trees(deflate_state s, int lcodes, int dcodes, int blcodes)
{
int rank; // index in bl_order
//Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes");
//Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, "too many codes");
//Tracev((stderr, "\nbl counts: "));
send_bits(s, lcodes-257, 5); // not +255 as stated in appnote.txt
send_bits(s, dcodes-1, 5);
send_bits(s, blcodes-4, 4); // not -3 as stated in appnote.txt
for(rank=0; rank<blcodes; rank++)
{
//Tracev((stderr, "\nbl code %2d ", bl_order[rank]));
send_bits(s, s.bl_tree[bl_order[rank]].Len, 3);
}
//Tracev((stderr, "\nbl tree: sent %ld", s.bits_sent));
send_tree(s, s.dyn_ltree, lcodes-1); // literal tree
//Tracev((stderr, "\nlit tree: sent %ld", s.bits_sent));
send_tree(s, s.dyn_dtree, dcodes-1); // distance tree
//Tracev((stderr, "\ndist tree: sent %ld", s.bits_sent));
}
// ===========================================================================
// Send a stored block
// buf: input block
// stored_len: length of input block
// last: one if this is the last block for a file
static void _tr_stored_block(deflate_state s, byte[] buf, uint stored_len, int last)
{
send_bits(s, (STORED_BLOCK<<1)+last, 3); // send block type
copy_block(s, buf, 0, stored_len, 1); // with header
}
static void _tr_stored_block(deflate_state s, byte[] buf, int buf_ind, uint stored_len, int last)
{
send_bits(s, (STORED_BLOCK<<1)+last, 3); // send block type
copy_block(s, buf, buf_ind, stored_len, 1); // with header
}
// ===========================================================================
// Send one empty static block to give enough lookahead for inflate.
// This takes 10 bits, of which 7 may remain in the bit buffer.
// The current inflate code requires 9 bits of lookahead. If the
// last two codes for the previous block (real code plus EOB) were coded
// on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode
// the last real code. In this case we send two empty static blocks instead
// of one. (There are no problems if the previous block is stored or fixed.)
// To simplify the code, we assume the worst case of last real code encoded
// on one bit only.
static void _tr_align(deflate_state s)
{
send_bits(s, STATIC_TREES<<1, 3);
send_code(s, END_BLOCK, static_ltree);
bi_flush(s);
// Of the 10 bits for the empty block, we have already sent
// (10 - bi_valid) bits. The lookahead for the last real code (before
// the EOB of the previous block) was thus at least one plus the length
// of the EOB plus what we have just sent of the empty static block.
if(1+s.last_eob_len+10-s.bi_valid<9)
{
send_bits(s, STATIC_TREES<<1, 3);
send_code(s, END_BLOCK, static_ltree);
bi_flush(s);
}
s.last_eob_len=7;
}
// ===========================================================================
// Determine the best encoding for the current block: dynamic trees, static
// trees or store, and output the encoded block to the zip file.
// buf: input block, or NULL if too old
// stored_len: length of input block
// last: one if this is the last block for a file
static void _tr_flush_block(deflate_state s, byte[] buf, int buf_ind, uint stored_len, int last)
{
uint opt_lenb, static_lenb; // opt_len and static_len in bytes
int max_blindex=0; // index of last bit length code of non zero freq
// Build the Huffman trees unless a stored block is forced
if(s.level>0)
{
// Construct the literal and distance trees
build_tree(s, ref s.l_desc);
//Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s.opt_len, s.static_len));
build_tree(s, ref s.d_desc);
//Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s.opt_len, s.static_len));
// At this point, opt_len and static_len are the total bit lengths of
// the compressed block data, excluding the tree representations.
// Build the bit length tree for the above two trees, and get the index
// in bl_order of the last bit length code to send.
max_blindex=build_bl_tree(s);
// Determine the best encoding. Compute the block lengths in bytes.
opt_lenb=(s.opt_len+3+7)>>3;
static_lenb=(s.static_len+3+7)>>3;
//Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", opt_lenb, s.opt_len, static_lenb, s.static_len, stored_len, s.last_lit));
if(static_lenb<=opt_lenb) opt_lenb=static_lenb;
}
else
{
//Assert(buf!=(char*)0, "lost buf");
opt_lenb=static_lenb=stored_len+5; // force a stored block
}
if(stored_len+4<=opt_lenb&&buf!=null)
{
// 4: two words for the lengths
// The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
// Otherwise we can't have processed more than WSIZE input bytes since
// the last block flush, because compression would have been
// successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
// transform a block into a stored block.
_tr_stored_block(s, buf, buf_ind, stored_len, last);
}
else if(s.strategy==Z_FIXED||static_lenb==opt_lenb)
{
send_bits(s, (STATIC_TREES<<1)+last, 3);
compress_block(s, static_ltree, static_dtree);
}
else
{
send_bits(s, (DYN_TREES<<1)+last, 3);
send_all_trees(s, s.l_desc.max_code+1, s.d_desc.max_code+1, max_blindex+1);
compress_block(s, s.dyn_ltree, s.dyn_dtree);
}
//Assert (s.compressed_len == s.bits_sent, "bad compressed size");
// The above check is made mod 2^32, for files larger than 512 MB
// and unsigned int implemented on 32 bits.
init_block(s);
if(last!=0) bi_windup(s);
//Tracev((stderr,"\ncomprlen %lu(%lu) ", s.compressed_len>>3, s.compressed_len-7*eof));
}
// ===========================================================================
// Save the match info and tally the frequency counts. Return true if
// the current block must be flushed.
// dist: distance of matched string
// lc: match length-MIN_MATCH or unmatched char (if dist==0)
static bool _tr_tally(deflate_state s, uint dist, uint lc)
{
s.d_buf[s.last_lit]=(ushort)dist;
s.l_buf[s.last_lit++]=(byte)lc;
if(dist==0)
{
// lc is the unmatched char
s.dyn_ltree[lc].Freq++;
}
else
{
s.matches++;
// Here, lc is the match length - MIN_MATCH
dist--; // dist = match distance - 1
//Assert((ushort)dist < (ushort)MAX_DIST(s) &&
// (ushort)lc <= (ushort)(MAX_MATCH-MIN_MATCH) &&
// (ushort)(dist < 256 ? _dist_code[dist] : _dist_code[256+(dist>>7)]) < (ushort)D_CODES,
// "_tr_tally: bad match");
s.dyn_ltree[_length_code[lc]+LITERALS+1].Freq++;
s.dyn_dtree[(dist<256?_dist_code[dist]:_dist_code[256+(dist>>7)])].Freq++;
}
return (s.last_lit==s.lit_bufsize-1);
// We avoid equality with lit_bufsize because of wraparound at 64K
// on 16 bit machines and because stored blocks are restricted to
// 64K-1 bytes.
}
// ===========================================================================
// Send the block data compressed using the given Huffman trees
// ltree: literal tree
// dtree: distance tree
static void compress_block(deflate_state s, ct_data[] ltree, ct_data[] dtree)
{
uint dist; // distance of matched string
int lc; // match length or unmatched char (if dist == 0)
uint lx=0; // running index in l_buf
uint code; // the code to send
int extra; // number of extra bits to send
if(s.last_lit!=0)
{
do
{
dist=s.d_buf[lx];
lc=s.l_buf[lx++];
if(dist==0)
{
send_code(s, lc, ltree); // send a literal byte
//Tracecv(isgraph(lc), (stderr," '%c' ", lc));
}
else
{
// Here, lc is the match length - MIN_MATCH
code=_length_code[lc];
send_code(s, (int)(code+LITERALS+1), ltree); // send the length code
extra=extra_lbits[code];
if(extra!=0)
{
lc-=base_length[code];
send_bits(s, lc, extra); // send the extra length bits
}
dist--; // dist is now the match distance - 1
code=(dist<256?_dist_code[dist]:_dist_code[256+(dist>>7)]);
//Assert (code < D_CODES, "bad d_code");
send_code(s, (int)code, dtree); // send the distance code
extra=extra_dbits[code];
if(extra!=0)
{
dist-=(uint)base_dist[code];
send_bits(s, (int)dist, extra); // send the extra distance bits
}
} // literal or match pair ?
} while(lx<s.last_lit);
}
send_code(s, END_BLOCK, ltree);
s.last_eob_len=ltree[END_BLOCK].Len;
}
// ===========================================================================
// Reverse the first len bits of a code, using straightforward code (a faster
// method would use a table)
// IN assertion: 1 <= len <= 15
// code: the value to invert
// len: its bit length
static ushort bi_reverse(ushort code, int len)
{
ushort res=0;
do
{
res|=(ushort)(code&1);
code>>=1;
res<<=1;
} while(--len>0);
return (ushort)(res>>1);
}
// ===========================================================================
// Flush the bit buffer, keeping at most 7 bits in it.
static void bi_flush(deflate_state s)
{
if(s.bi_valid==16)
{
//was put_short(s, s.bi_buf);
s.pending_buf[s.pending++]=(byte)(s.bi_buf&0xff);
s.pending_buf[s.pending++]=(byte)((ushort)s.bi_buf>>8);
s.bi_buf=0;
s.bi_valid=0;
}
else if(s.bi_valid>=8)
{
//was put_byte(s, (unsigned char)s.bi_buf);
s.pending_buf[s.pending++]=(byte)s.bi_buf;
s.bi_buf>>=8;
s.bi_valid-=8;
}
}
// ===========================================================================
// Flush the bit buffer and align the output on a byte boundary
static void bi_windup(deflate_state s)
{
if(s.bi_valid>8)
{
//was put_short(s, s.bi_buf);
s.pending_buf[s.pending++]=(byte)(s.bi_buf&0xff);
s.pending_buf[s.pending++]=(byte)((ushort)s.bi_buf>>8);
}
else if(s.bi_valid>0)
{
//was put_byte(s, (unsigned char)s.bi_buf);
s.pending_buf[s.pending++]=(byte)s.bi_buf;
}
s.bi_buf=0;
s.bi_valid=0;
}
// ===========================================================================
// Copy a stored block, storing first the length and its
// one's complement if requested.
// buf: the input data
// len: its length
// header: true if block header must be written
static void copy_block(deflate_state s, byte[] buf, int buf_ind, uint len, int header)
{
bi_windup(s); // align on byte boundary
s.last_eob_len=8; // enough lookahead for inflate
if(header!=0)
{
//was put_short(s, (unsigned short)len);
s.pending_buf[s.pending++]=(byte)(((ushort)len)&0xff);
s.pending_buf[s.pending++]=(byte)(((ushort)len)>>8);
//was put_short(s, (unsigned short)~len);
s.pending_buf[s.pending++]=(byte)(((ushort)~len)&0xff);
s.pending_buf[s.pending++]=(byte)(((ushort)~len)>>8);
}
while(len--!=0)
{
//was put_byte(s, *buf++);
s.pending_buf[s.pending++]=buf[buf_ind++];
}
}
}
}