PageRenderTime 25ms CodeModel.GetById 1ms RepoModel.GetById 0ms app.codeStats 0ms

/Utilities/Compression/Inflaters/InflaterHuffmanTree.cs

#
C# | 259 lines | 191 code | 19 blank | 49 comment | 23 complexity | eff5f103efb7fcdcb2f38cdff32faaaa MD5 | raw file
Possible License(s): Apache-2.0
  1. // Based on Mike Krueger's SharpZipLib, Copyright (C) 2001 (GNU license).
  2. // Authors of the original java version: Jochen Hoenicke, John Leuner
  3. // See http://www.ISeeSharpCode.com for more information.
  4. using System;
  5. using Delta.Utilities.Compression.Deflaters;
  6. using Delta.Utilities.Compression.Streams;
  7. namespace Delta.Utilities.Compression.Inflaters
  8. {
  9. /// <summary>
  10. /// Huffman tree used for inflation
  11. /// </summary>
  12. public class InflaterHuffmanTree
  13. {
  14. #region Constants
  15. /// <summary>
  16. /// Maximum bit length
  17. /// </summary>
  18. private const int MaximumBitLength = 15;
  19. #endregion
  20. #region defLitLenTree (Static)
  21. /// <summary>
  22. /// Literal length tree
  23. /// </summary>
  24. public static InflaterHuffmanTree defLitLenTree;
  25. #endregion
  26. #region defDistTree (Static)
  27. /// <summary>
  28. /// Distance tree
  29. /// </summary>
  30. public static InflaterHuffmanTree defDistTree;
  31. #endregion
  32. #region Private
  33. #region tree (Private)
  34. /// <summary>
  35. /// Tree
  36. /// </summary>
  37. private short[] tree;
  38. #endregion
  39. #endregion
  40. #region Constructors
  41. /// <summary>
  42. /// Create inflater huffman tree
  43. /// </summary>
  44. static InflaterHuffmanTree()
  45. {
  46. try
  47. {
  48. byte[] codeLengths = new byte[288];
  49. int i = 0;
  50. while (i < 144)
  51. {
  52. codeLengths[i++] = 8;
  53. } // while (i)
  54. while (i < 256)
  55. {
  56. codeLengths[i++] = 9;
  57. } // while (i)
  58. while (i < 280)
  59. {
  60. codeLengths[i++] = 7;
  61. } // while (i)
  62. while (i < 288)
  63. {
  64. codeLengths[i++] = 8;
  65. } // while (i)
  66. defLitLenTree = new InflaterHuffmanTree(codeLengths);
  67. codeLengths = new byte[32];
  68. i = 0;
  69. while (i < 32)
  70. {
  71. codeLengths[i++] = 5;
  72. } // while (i)
  73. defDistTree = new InflaterHuffmanTree(codeLengths);
  74. } // try
  75. catch (Exception)
  76. {
  77. throw new CompressionException(
  78. "InflaterHuffmanTree: static tree length illegal");
  79. } // catch (Exception)
  80. }
  81. /// <summary>
  82. /// Constructs a Huffman tree from the array of code lengths.
  83. /// </summary>
  84. /// <param name = "codeLengths">
  85. /// the array of code lengths
  86. /// </param>
  87. public InflaterHuffmanTree(byte[] codeLengths)
  88. {
  89. BuildTree(codeLengths);
  90. }
  91. #endregion
  92. #region GetSymbol (Public)
  93. /// <summary>
  94. /// Reads the next symbol from input. The symbol is encoded using the
  95. /// huffman tree.
  96. /// </summary>
  97. /// <param name="input">
  98. /// input the input source.
  99. /// </param>
  100. /// <returns>
  101. /// the next symbol, or -1 if not enough input is available.
  102. /// </returns>
  103. public int GetSymbol(StreamManipulator input)
  104. {
  105. int lookahead, symbol;
  106. if ((lookahead = input.PeekBits(9)) >= 0)
  107. {
  108. if ((symbol = tree[lookahead]) >= 0)
  109. {
  110. input.DropBits(symbol & 15);
  111. return symbol >> 4;
  112. } // if (symbol)
  113. int subtree = -(symbol >> 4);
  114. int bitlen = symbol & 15;
  115. if ((lookahead = input.PeekBits(bitlen)) >= 0)
  116. {
  117. symbol = tree[subtree | (lookahead >> 9)];
  118. input.DropBits(symbol & 15);
  119. return symbol >> 4;
  120. } // if (lookahead)
  121. else
  122. {
  123. int bits = input.AvailableBits;
  124. lookahead = input.PeekBits(bits);
  125. symbol = tree[subtree | (lookahead >> 9)];
  126. if ((symbol & 15) <= bits)
  127. {
  128. input.DropBits(symbol & 15);
  129. return symbol >> 4;
  130. } // if (symbol)
  131. else
  132. {
  133. return -1;
  134. } // else
  135. } // else
  136. } // if (lookahead)
  137. else
  138. {
  139. int bits = input.AvailableBits;
  140. lookahead = input.PeekBits(bits);
  141. symbol = tree[lookahead];
  142. if (symbol >= 0 && (symbol & 15) <= bits)
  143. {
  144. input.DropBits(symbol & 15);
  145. return symbol >> 4;
  146. } // if (symbol)
  147. else
  148. {
  149. return -1;
  150. } // else
  151. } // else
  152. }
  153. #endregion
  154. #region Methods (Private)
  155. #region BuildTree
  156. /// <summary>
  157. /// Build tree
  158. /// </summary>
  159. /// <param name="codeLengths">Code lengths</param>
  160. private void BuildTree(byte[] codeLengths)
  161. {
  162. int[] blCount = new int[MaximumBitLength + 1];
  163. int[] nextCode = new int[MaximumBitLength + 1];
  164. for (int i = 0; i < codeLengths.Length; i++)
  165. {
  166. int bits = codeLengths[i];
  167. if (bits > 0)
  168. {
  169. blCount[bits]++;
  170. } // if (bits)
  171. } // for (int)
  172. int code = 0;
  173. int treeSize = 512;
  174. for (int bits = 1; bits <= MaximumBitLength; bits++)
  175. {
  176. nextCode[bits] = code;
  177. code += blCount[bits] << (16 - bits);
  178. if (bits >= 10)
  179. {
  180. /* We need an extra table for bit lengths >= 10. */
  181. int start = nextCode[bits] & 0x1ff80;
  182. int end = code & 0x1ff80;
  183. treeSize += (end - start) >> (16 - bits);
  184. } // if (bits)
  185. } // for (bits)
  186. // -jr comment this out! doesnt work for dynamic trees and pkzip 2.04g
  187. //if (code != 65536)
  188. //{
  189. // throw new CompressionException("Code lengths don't add up properly.");
  190. //}
  191. // Now create and fill the extra tables from longest to shortest
  192. // bit len. This way the sub trees will be aligned.
  193. tree = new short[treeSize];
  194. int treePtr = 512;
  195. for (int bits = MaximumBitLength; bits >= 10; bits--)
  196. {
  197. int end = code & 0x1ff80;
  198. code -= blCount[bits] << (16 - bits);
  199. int start = code & 0x1ff80;
  200. for (int i = start; i < end; i += 1 << 7)
  201. {
  202. tree[DeflaterHuffman.BitReverse(i)] = (short)((-treePtr << 4) | bits);
  203. treePtr += 1 << (bits - 9);
  204. } // for (int)
  205. } // for (bits)
  206. for (int i = 0; i < codeLengths.Length; i++)
  207. {
  208. int bits = codeLengths[i];
  209. if (bits == 0)
  210. {
  211. continue;
  212. } // if (bits)
  213. code = nextCode[bits];
  214. int revcode = DeflaterHuffman.BitReverse(code);
  215. if (bits <= 9)
  216. {
  217. do
  218. {
  219. tree[revcode] = (short)((i << 4) | bits);
  220. revcode += 1 << bits;
  221. } while (revcode < 512);
  222. } // if (bits)
  223. else
  224. {
  225. int subTree = tree[revcode & 511];
  226. int treeLen = 1 << (subTree & 15);
  227. subTree = -(subTree >> 4);
  228. do
  229. {
  230. tree[subTree | (revcode >> 9)] = (short)((i << 4) | bits);
  231. revcode += 1 << bits;
  232. } while (revcode < treeLen);
  233. } // else
  234. nextCode[bits] = code + (1 << (16 - bits));
  235. } // for (int)
  236. }
  237. #endregion
  238. #endregion
  239. }
  240. }