3 // Copyright (C) 2001 Mike Krueger
4 // Copyright (C) 2004 John Reilly
6 // This file was translated from java, it was part of the GNU Classpath
7 // Copyright (C) 2001 Free Software Foundation, Inc.
9 // This program is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU General Public License
11 // as published by the Free Software Foundation; either version 2
12 // of the License, or (at your option) any later version.
14 // This program is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 // GNU General Public License for more details.
19 // You should have received a copy of the GNU General Public License
20 // along with this program; if not, write to the Free Software
21 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 // Linking this library statically or dynamically with other modules is
24 // making a combined work based on this library. Thus, the terms and
25 // conditions of the GNU General Public License cover the whole
28 // As a special exception, the copyright holders of this library give you
29 // permission to link this library with independent modules to produce an
30 // executable, regardless of the license terms of these independent
31 // modules, and to copy and distribute the resulting executable under
32 // terms of your choice, provided that you also meet, for each linked
33 // independent module, the terms and conditions of the license of that
34 // module. An independent module is a module which is not derived from
35 // or based on this library. If you modify this library, you may extend
36 // this exception to your version of the library, but you are not
37 // obligated to do so. If you do not wish to do so, delete this
38 // exception statement from your version.
41 using ICSharpCode.SharpZipLib.Silverlight.Zip.Compression;
43 namespace ICSharpCode.SharpZipLib.Silverlight.Zip.Compression
46 /// This is the DeflaterHuffman class.
48 /// This class is <i>not</i> thread safe. This is inherent in the API, due
49 /// to the split of Deflate and SetInput.
51 /// author of the original java version : Jochen Hoenicke
53 public class DeflaterHuffman
55 const int BUFSIZE = 1 << (DeflaterConstants.DEFAULT_MEM_LEVEL + 6);
56 const int LITERAL_NUM = 286;
58 // Number of distance codes
59 const int DIST_NUM = 30;
60 // Number of codes used to transfer bit lengths
61 const int BITLEN_NUM = 19;
63 // repeat previous bit length 3-6 times (2 bits of repeat count)
64 const int REP_3_6 = 16;
65 // repeat a zero length 3-10 times (3 bits of repeat count)
66 const int REP_3_10 = 17;
67 // repeat a zero length 11-138 times (7 bits of repeat count)
68 const int REP_11_138 = 18;
70 const int EOF_SYMBOL = 256;
72 // The lengths of the bit length codes are sent in order of decreasing
73 // probability, to avoid transmitting the lengths for unused bit length codes.
74 static readonly int[] BL_ORDER = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
76 static readonly byte[] bit4Reverse = {
95 static readonly short[] staticLCodes;
96 static readonly byte[] staticLLength;
97 static readonly short[] staticDCodes;
98 static readonly byte[] staticDLength;
102 #region Instance Fields
103 public readonly short[] freqs;
105 public byte[] length;
107 public readonly int minNumCodes;
112 readonly int[] bl_counts;
113 readonly int maxLength;
114 readonly DeflaterHuffman dh;
118 public Tree(DeflaterHuffman dh, int elems, int minCodes, int maxLength)
121 minNumCodes = minCodes;
122 this.maxLength = maxLength;
123 freqs = new short[elems];
124 bl_counts = new int[maxLength];
130 /// Resets the internal state of the tree
134 for (int i = 0; i < freqs.Length; i++) {
141 public void WriteSymbol(int code)
143 // if (DeflaterConstants.DEBUGGING) {
145 // // Console.Write("writeSymbol("+freqs.length+","+code+"): ");
147 dh.pending.WriteBits(codes[code] & 0xffff, length[code]);
151 /// Set static codes and length
153 /// <param name="staticCodes">new codes</param>
154 /// <param name="staticLengths">length for new codes</param>
155 public void SetStaticCodes(short[] staticCodes, byte[] staticLengths)
158 length = staticLengths;
162 /// Build dynamic codes and lengths
164 public void BuildCodes()
166 var nextCode = new int[maxLength];
169 codes = new short[freqs.Length];
171 // if (DeflaterConstants.DEBUGGING) {
172 // //Console.WriteLine("buildCodes: "+freqs.Length);
175 for (int bits = 0; bits < maxLength; bits++) {
176 nextCode[bits] = code;
177 code += bl_counts[bits] << (15 - bits);
179 // if (DeflaterConstants.DEBUGGING) {
180 // //Console.WriteLine("bits: " + ( bits + 1) + " count: " + bl_counts[bits]
181 // +" nextCode: "+code);
184 for (int i=0; i < numCodes; i++) {
185 int bits = length[i];
188 // if (DeflaterConstants.DEBUGGING) {
189 // //Console.WriteLine("codes["+i+"] = rev(" + nextCode[bits-1]+"),
193 codes[i] = BitReverse(nextCode[bits-1]);
194 nextCode[bits-1] += 1 << (16 - bits);
199 public void BuildTree()
201 int numSymbols = freqs.Length;
203 /* heap is a priority queue, sorted by frequency, least frequent
204 * nodes first. The heap is a binary tree, with the property, that
205 * the parent node is smaller than both child nodes. This assures
206 * that the smallest node is the first parent.
208 * The binary tree is encoded in an array: 0 is root node and
209 * the nodes 2*n+1, 2*n+2 are the child nodes of node n.
211 var heap = new int[numSymbols];
214 for (var n = 0; n < numSymbols; n++) {
221 // Insert n into heap
224 while (pos > 0 && freqs[heap[ppos = (pos - 1) / 2]] > freq) {
225 heap[pos] = heap[ppos];
233 /* We could encode a single literal with 0 bits but then we
234 * don't see the literals. Therefore we force at least two
235 * literals to avoid this case. We don't care about order in
236 * this case, both literals get a 1 bit code.
238 while (heapLen < 2) {
239 int node = maxCode < 2 ? ++maxCode : 0;
240 heap[heapLen++] = node;
243 numCodes = Math.Max(maxCode + 1, minNumCodes);
245 var numLeafs = heapLen;
246 var childs = new int[4 * heapLen - 2];
247 var values = new int[2 * heapLen - 1];
248 var numNodes = numLeafs;
249 for (var i = 0; i < heapLen; i++) {
251 childs[2 * i] = node;
252 childs[2 * i + 1] = -1;
253 values[i] = freqs[node] << 8;
257 /* Construct the Huffman tree by repeatedly combining the least two
262 int last = heap[--heapLen];
264 // Propagate the hole to the leafs of the heap
268 while (path < heapLen) {
269 if (path + 1 < heapLen && values[heap[path]] > values[heap[path+1]]) {
273 heap[ppos] = heap[path];
278 /* Now propagate the last element down along path. Normally
279 * it shouldn't go too deep.
281 int lastVal = values[last];
282 while ((path = ppos) > 0 && values[heap[ppos = (path - 1)/2]] > lastVal) {
283 heap[path] = heap[ppos];
288 int second = heap[0];
290 // Create a new node father of first and second
292 childs[2 * last] = first;
293 childs[2 * last + 1] = second;
294 int mindepth = Math.Min(values[first] & 0xff, values[second] & 0xff);
295 values[last] = lastVal = values[first] + values[second] - mindepth + 1;
297 // Again, propagate the hole to the leafs
301 while (path < heapLen) {
302 if (path + 1 < heapLen && values[heap[path]] > values[heap[path+1]]) {
306 heap[ppos] = heap[path];
311 // Now propagate the new element down along path
312 while ((path = ppos) > 0 && values[heap[ppos = (path - 1)/2]] > lastVal) {
313 heap[path] = heap[ppos];
316 } while (heapLen > 1);
318 if (heap[0] != childs.Length / 2 - 1) {
319 throw new SharpZipBaseException("Heap invariant violated");
326 /// Get encoded length
328 /// <returns>Encoded length, the sum of frequencies * lengths</returns>
329 public int GetEncodedLength()
332 for (int i = 0; i < freqs.Length; i++) {
333 len += freqs[i] * length[i];
339 /// Scan a literal or distance tree to determine the frequencies of the codes
340 /// in the bit length tree.
342 public void CalcBLFreq(Tree blTree)
344 var curlen = -1; /* length of current code */
347 while (i < numCodes) {
348 var count = 1; /* repeat count of the current code */
349 int nextlen = length[i];
350 int max_count; /* max repeat count */
351 int min_count; /* min repeat count */
358 if (curlen != nextlen) {
359 blTree.freqs[nextlen]++;
366 while (i < numCodes && curlen == length[i]) {
368 if (++count >= max_count) {
373 if (count < min_count) {
374 blTree.freqs[curlen] += (short)count;
375 } else if (curlen != 0) {
376 blTree.freqs[REP_3_6]++;
377 } else if (count <= 10) {
378 blTree.freqs[REP_3_10]++;
380 blTree.freqs[REP_11_138]++;
386 /// Write tree values
388 /// <param name="blTree">Tree to write</param>
389 public void WriteTree(Tree blTree)
391 var curlen = -1; // length of current code
394 while (i < numCodes) {
395 var count = 1; // repeat count of the current code
396 int nextlen = length[i];
397 int max_count; // max repeat count
398 int min_count; // min repeat count
405 if (curlen != nextlen) {
406 blTree.WriteSymbol(nextlen);
413 while (i < numCodes && curlen == length[i]) {
415 if (++count >= max_count) {
420 if (count < min_count) {
421 while (count-- > 0) {
422 blTree.WriteSymbol(curlen);
424 } else if (curlen != 0) {
425 blTree.WriteSymbol(REP_3_6);
426 dh.pending.WriteBits(count - 3, 2);
427 } else if (count <= 10) {
428 blTree.WriteSymbol(REP_3_10);
429 dh.pending.WriteBits(count - 3, 3);
431 blTree.WriteSymbol(REP_11_138);
432 dh.pending.WriteBits(count - 11, 7);
437 void BuildLength(int[] childs)
439 length = new byte [freqs.Length];
440 var numNodes = childs.Length / 2;
441 var numLeafs = (numNodes + 1) / 2;
444 for (var i = 0; i < maxLength; i++) {
448 // First calculate optimal bit lengths
449 var lengths = new int[numNodes];
450 lengths[numNodes-1] = 0;
452 for (int i = numNodes - 1; i >= 0; i--) {
453 if (childs[2 * i + 1] != -1) {
454 int bitLength = lengths[i] + 1;
455 if (bitLength > maxLength) {
456 bitLength = maxLength;
459 lengths[childs[2 * i]] = lengths[childs[2 * i + 1]] = bitLength;
462 var bitLength = lengths[i];
463 bl_counts[bitLength - 1]++;
464 length[childs[2*i]] = (byte) lengths[i];
468 // if (DeflaterConstants.DEBUGGING) {
469 // //Console.WriteLine("Tree "+freqs.Length+" lengths:");
470 // for (int i=0; i < numLeafs; i++) {
471 // //Console.WriteLine("Node "+childs[2*i]+" freq: "+freqs[childs[2*i]]
472 // + " len: "+length[childs[2*i]]);
480 int incrBitLen = maxLength - 1;
482 // Find the first bit length which could increase:
483 while (bl_counts[--incrBitLen] == 0)
488 // Move this node one down and remove a corresponding
489 // number of overflow nodes.
491 bl_counts[incrBitLen]--;
492 bl_counts[++incrBitLen]++;
493 overflow -= 1 << (maxLength - 1 - incrBitLen);
494 } while (overflow > 0 && incrBitLen < maxLength - 1);
495 } while (overflow > 0);
497 /* We may have overshot above. Move some nodes from maxLength to
498 * maxLength-1 in that case.
500 bl_counts[maxLength-1] += overflow;
501 bl_counts[maxLength-2] -= overflow;
503 /* Now recompute all bit lengths, scanning in increasing
504 * frequency. It is simpler to reconstruct all lengths instead of
505 * fixing only the wrong ones. This idea is taken from 'ar'
506 * written by Haruhiko Okumura.
508 * The nodes were inserted with decreasing frequency into the childs
511 int nodePtr = 2 * numLeafs;
512 for (int bits = maxLength; bits != 0; bits--) {
513 int n = bl_counts[bits-1];
515 int childPtr = 2*childs[nodePtr++];
516 if (childs[childPtr + 1] == -1) {
517 // We found another leaf
518 length[childs[childPtr]] = (byte) bits;
523 // if (DeflaterConstants.DEBUGGING) {
524 // //Console.WriteLine("*** After overflow elimination. ***");
525 // for (int i=0; i < numLeafs; i++) {
526 // //Console.WriteLine("Node "+childs[2*i]+" freq: "+freqs[childs[2*i]]
527 // + " len: "+length[childs[2*i]]);
534 #region Instance Fields
536 /// Pending buffer to use
538 public DeflaterPending pending;
540 readonly Tree literalTree;
541 readonly Tree distTree;
542 readonly Tree blTree;
544 // Buffer for distances
545 readonly short[] d_buf;
546 readonly byte[] l_buf;
551 static DeflaterHuffman()
553 // See RFC 1951 3.2.6
555 staticLCodes = new short[LITERAL_NUM];
556 staticLLength = new byte[LITERAL_NUM];
560 staticLCodes[i] = BitReverse((0x030 + i) << 8);
561 staticLLength[i++] = 8;
565 staticLCodes[i] = BitReverse((0x190 - 144 + i) << 7);
566 staticLLength[i++] = 9;
570 staticLCodes[i] = BitReverse((0x000 - 256 + i) << 9);
571 staticLLength[i++] = 7;
574 while (i < LITERAL_NUM) {
575 staticLCodes[i] = BitReverse((0x0c0 - 280 + i) << 8);
576 staticLLength[i++] = 8;
580 staticDCodes = new short[DIST_NUM];
581 staticDLength = new byte[DIST_NUM];
582 for (i = 0; i < DIST_NUM; i++) {
583 staticDCodes[i] = BitReverse(i << 11);
584 staticDLength[i] = 5;
589 /// Construct instance with pending buffer
591 /// <param name="pending">Pending buffer to use</param>
592 public DeflaterHuffman(DeflaterPending pending)
594 this.pending = pending;
596 literalTree = new Tree(this, LITERAL_NUM, 257, 15);
597 distTree = new Tree(this, DIST_NUM, 1, 15);
598 blTree = new Tree(this, BITLEN_NUM, 4, 7);
600 d_buf = new short[BUFSIZE];
601 l_buf = new byte [BUFSIZE];
605 /// Reset internal state
617 /// Write all trees to pending buffer
619 /// <param name="blTreeCodes">The number/rank of treecodes to send.</param>
620 public void SendAllTrees(int blTreeCodes)
623 literalTree.BuildCodes();
624 distTree.BuildCodes();
625 pending.WriteBits(literalTree.numCodes - 257, 5);
626 pending.WriteBits(distTree.numCodes - 1, 5);
627 pending.WriteBits(blTreeCodes - 4, 4);
628 for (int rank = 0; rank < blTreeCodes; rank++) {
629 pending.WriteBits(blTree.length[BL_ORDER[rank]], 3);
631 literalTree.WriteTree(blTree);
632 distTree.WriteTree(blTree);
636 /// Compress current buffer writing data to pending buffer
638 public void CompressBlock()
640 for (int i = 0; i < last_lit; i++) {
641 int litlen = l_buf[i] & 0xff;
644 // if (DeflaterConstants.DEBUGGING) {
645 // Console.Write("["+(dist+1)+","+(litlen+3)+"]: ");
648 int lc = Lcode(litlen);
649 literalTree.WriteSymbol(lc);
651 int bits = (lc - 261) / 4;
652 if (bits > 0 && bits <= 5) {
653 pending.WriteBits(litlen & ((1 << bits) - 1), bits);
656 int dc = Dcode(dist);
657 distTree.WriteSymbol(dc);
661 pending.WriteBits(dist & ((1 << bits) - 1), bits);
664 // if (DeflaterConstants.DEBUGGING) {
665 // if (litlen > 32 && litlen < 127) {
666 // Console.Write("("+(char)litlen+"): ");
668 // Console.Write("{"+litlen+"}: ");
671 literalTree.WriteSymbol(litlen);
674 literalTree.WriteSymbol(EOF_SYMBOL);
678 /// Flush block to output with no compression
680 /// <param name="stored">Data to write</param>
681 /// <param name="storedOffset">Index of first byte to write</param>
682 /// <param name="storedLength">Count of bytes to write</param>
683 /// <param name="lastBlock">True if this is the last block</param>
684 public void FlushStoredBlock(byte[] stored, int storedOffset, int storedLength, bool lastBlock)
686 pending.WriteBits((DeflaterConstants.STORED_BLOCK << 1) + (lastBlock ? 1 : 0), 3);
687 pending.AlignToByte();
688 pending.WriteShort(storedLength);
689 pending.WriteShort(~storedLength);
690 pending.WriteBlock(stored, storedOffset, storedLength);
695 /// Flush block to output with compression
697 /// <param name="stored">Data to flush</param>
698 /// <param name="storedOffset">Index of first byte to flush</param>
699 /// <param name="storedLength">Count of bytes to flush</param>
700 /// <param name="lastBlock">True if this is the last block</param>
701 public void FlushBlock(byte[] stored, int storedOffset, int storedLength, bool lastBlock)
703 literalTree.freqs[EOF_SYMBOL]++;
706 literalTree.BuildTree();
707 distTree.BuildTree();
709 // Calculate bitlen frequency
710 literalTree.CalcBLFreq(blTree);
711 distTree.CalcBLFreq(blTree);
717 for (int i = 18; i > blTreeCodes; i--) {
718 if (blTree.length[BL_ORDER[i]] > 0) {
722 int opt_len = 14 + blTreeCodes * 3 + blTree.GetEncodedLength() +
723 literalTree.GetEncodedLength() + distTree.GetEncodedLength() +
726 int static_len = extra_bits;
727 for (int i = 0; i < LITERAL_NUM; i++) {
728 static_len += literalTree.freqs[i] * staticLLength[i];
730 for (int i = 0; i < DIST_NUM; i++) {
731 static_len += distTree.freqs[i] * staticDLength[i];
733 if (opt_len >= static_len) {
734 // Force static trees
735 opt_len = static_len;
738 if (storedOffset >= 0 && storedLength + 4 < opt_len >> 3) {
741 // if (DeflaterConstants.DEBUGGING) {
742 // //Console.WriteLine("Storing, since " + storedLength + " < " + opt_len
743 // + " <= " + static_len);
745 FlushStoredBlock(stored, storedOffset, storedLength, lastBlock);
746 } else if (opt_len == static_len) {
747 // Encode with static tree
748 pending.WriteBits((DeflaterConstants.STATIC_TREES << 1) + (lastBlock ? 1 : 0), 3);
749 literalTree.SetStaticCodes(staticLCodes, staticLLength);
750 distTree.SetStaticCodes(staticDCodes, staticDLength);
754 // Encode with dynamic tree
755 pending.WriteBits((DeflaterConstants.DYN_TREES << 1) + (lastBlock ? 1 : 0), 3);
756 SendAllTrees(blTreeCodes);
763 /// Get value indicating if internal buffer is full
765 /// <returns>true if buffer is full</returns>
768 return last_lit >= BUFSIZE;
772 /// Add literal to buffer
774 /// <param name="literal">Literal value to add to buffer.</param>
775 /// <returns>Value indicating internal buffer is full</returns>
776 public bool TallyLit(int literal)
778 // if (DeflaterConstants.DEBUGGING) {
779 // if (lit > 32 && lit < 127) {
780 // //Console.WriteLine("("+(char)lit+")");
782 // //Console.WriteLine("{"+lit+"}");
786 l_buf[last_lit++] = (byte)literal;
787 literalTree.freqs[literal]++;
792 /// Add distance code and length to literal and distance trees
794 /// <param name="distance">Distance code</param>
795 /// <param name="length">Length</param>
796 /// <returns>Value indicating if internal buffer is full</returns>
797 public bool TallyDist(int distance, int length)
799 // if (DeflaterConstants.DEBUGGING) {
800 // //Console.WriteLine("[" + distance + "," + length + "]");
803 d_buf[last_lit] = (short)distance;
804 l_buf[last_lit++] = (byte)(length - 3);
806 int lc = Lcode(length - 3);
807 literalTree.freqs[lc]++;
808 if (lc >= 265 && lc < 285) {
809 extra_bits += (lc - 261) / 4;
812 int dc = Dcode(distance - 1);
813 distTree.freqs[dc]++;
815 extra_bits += dc / 2 - 1;
822 /// Reverse the bits of a 16 bit value.
824 /// <param name="toReverse">Value to reverse bits</param>
825 /// <returns>Value with bits reversed</returns>
826 public static short BitReverse(int toReverse)
828 return (short) (bit4Reverse[toReverse & 0xF] << 12 |
829 bit4Reverse[(toReverse >> 4) & 0xF] << 8 |
830 bit4Reverse[(toReverse >> 8) & 0xF] << 4 |
831 bit4Reverse[toReverse >> 12]);
834 static int Lcode(int length)
841 while (length >= 8) {
845 return code + length;
848 static int Dcode(int distance)
851 while (distance >= 4) {
855 return code + distance;