/// <summary> /// Initializes static members of the <see cref="Deflate" /> class. /// </summary> static Deflate() { var llcodelens = new int[288]; Arrays.Fill(llcodelens, 0, 144, 8); Arrays.Fill(llcodelens, 144, 256, 9); Arrays.Fill(llcodelens, 256, 280, 7); Arrays.Fill(llcodelens, 280, 288, 8); FixedLiteralLengthCode = new CanonicalCode(llcodelens).ToCodeTree(); var distcodelens = new int[32]; Arrays.Fill(distcodelens, 0, 32, 5); FixedDistanceCode = new CanonicalCode(distcodelens).ToCodeTree(); }
/// <summary> /// Decompresses a Huffman block. /// </summary> /// <param name="litLenCode">The litLen code.</param> /// <param name="distCode">The distance code.</param> private void DecompressHuffmanBlock(CodeTree litLenCode, CodeTree distCode) { if (litLenCode == null) { throw new InvalidOperationException(); } while (true) { var sym = this.DecodeSymbol(litLenCode); if (sym == 256) { // End of block break; } if (sym < 256) { // Literal byte this.output.Write((byte)sym); this.dictionary.Append(sym); } else { // Length and distance for copying var len = this.DecodeRunLength(sym); if (distCode == null) { throw new FormatException("Length symbol encountered with empty distance code"); } var distSym = this.DecodeSymbol(distCode); var dist = this.DecodeDistance(distSym); this.dictionary.Copy(dist, len, this.output); } } }
/// <summary> /// Decodes the specified symbol. /// </summary> /// <param name="code">The code.</param> /// <returns>The <see cref="int" />.</returns> private int DecodeSymbol(CodeTree code) { var currentNode = code.Root; while (true) { var temp = this.input.ReadNoEof(); Node nextNode; if (temp == 0) { nextNode = currentNode.LeftChild; } else if (temp == 1) { nextNode = currentNode.RightChild; } else { throw new Exception(); } if (nextNode is Leaf) { return(((Leaf)nextNode).Symbol); } if (nextNode is InternalNode) { currentNode = (InternalNode)nextNode; } else { throw new InvalidOperationException(); } } }
/// <summary> /// Decodes the specified symbol. /// </summary> /// <param name="code">The code.</param> /// <returns>The <see cref="int" />.</returns> private int DecodeSymbol(CodeTree code) { var currentNode = code.Root; while (true) { var temp = this.input.ReadNoEof(); Node nextNode; if (temp == 0) { nextNode = currentNode.LeftChild; } else if (temp == 1) { nextNode = currentNode.RightChild; } else { throw new Exception(); } if (nextNode is Leaf) { return ((Leaf)nextNode).Symbol; } if (nextNode is InternalNode) { currentNode = (InternalNode)nextNode; } else { throw new InvalidOperationException(); } } }
/// <summary> /// Initializes a new instance of the <see cref="CanonicalCode" /> class based on the given code tree. /// </summary> /// <param name="tree">The tree.</param> /// <param name="symbolLimit">The symbol limit.</param> public CanonicalCode(CodeTree tree, int symbolLimit) { this.codeLengths = new int[symbolLimit]; this.BuildCodeLengths(tree.Root, 0); }