// 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<>8); s.bi_buf=(ushort)(val>>(Buf_size-s.bi_valid)); s.bi_valid+=len-Buf_size; } else { s.bi_buf|=(ushort)(value<> 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<>8); s.bi_buf=(ushort)(val>>(Buf_size-s.bi_valid)); s.bi_valid+=len-Buf_size; } else { s.bi_buf|=(ushort)(value<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<=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=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; rank0) { // 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>=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++]; } } } }