Summary

Class:ICSharpCode.SharpZipLib.Zip.Compression.InflaterHuffmanTree
Assembly:ICSharpCode.SharpZipLib
File(s):C:\Users\Neil\Documents\Visual Studio 2015\Projects\icsharpcode\SZL_master\ICSharpCode.SharpZipLib\Zip\Compression\InflaterHuffmanTree.cs
Covered lines:65
Uncovered lines:23
Coverable lines:88
Total lines:193
Line coverage:73.8%
Branch coverage:75%

Metrics

MethodCyclomatic ComplexitySequence CoverageBranch Coverage
.cctor()690100
.ctor(...)1100100
BuildTree(...)1282.6982.61
GetSymbol(...)741.6746.15

File(s)

C:\Users\Neil\Documents\Visual Studio 2015\Projects\icsharpcode\SZL_master\ICSharpCode.SharpZipLib\Zip\Compression\InflaterHuffmanTree.cs

#LineLine coverage
 1using System;
 2using ICSharpCode.SharpZipLib.Zip.Compression.Streams;
 3
 4namespace ICSharpCode.SharpZipLib.Zip.Compression
 5{
 6  /// <summary>
 7  /// Huffman tree used for inflation
 8  /// </summary>
 9  public class InflaterHuffmanTree
 10  {
 11    #region Constants
 12    const int MAX_BITLEN = 15;
 13    #endregion
 14
 15    #region Instance Fields
 16    short[] tree;
 17    #endregion
 18
 19    /// <summary>
 20    /// Literal length tree
 21    /// </summary>
 22    public static InflaterHuffmanTree defLitLenTree;
 23
 24    /// <summary>
 25    /// Distance tree
 26    /// </summary>
 27    public static InflaterHuffmanTree defDistTree;
 28
 29    static InflaterHuffmanTree()
 30    {
 31      try {
 132        byte[] codeLengths = new byte[288];
 133        int i = 0;
 14534         while (i < 144) {
 14435          codeLengths[i++] = 8;
 36        }
 11337         while (i < 256) {
 11238          codeLengths[i++] = 9;
 39        }
 2540         while (i < 280) {
 2441          codeLengths[i++] = 7;
 42        }
 943         while (i < 288) {
 844          codeLengths[i++] = 8;
 45        }
 146        defLitLenTree = new InflaterHuffmanTree(codeLengths);
 47
 148        codeLengths = new byte[32];
 149        i = 0;
 3350         while (i < 32) {
 3251          codeLengths[i++] = 5;
 52        }
 153        defDistTree = new InflaterHuffmanTree(codeLengths);
 154      } catch (Exception) {
 055        throw new SharpZipBaseException("InflaterHuffmanTree: static tree length illegal");
 56      }
 157    }
 58
 59    #region Constructors
 60    /// <summary>
 61    /// Constructs a Huffman tree from the array of code lengths.
 62    /// </summary>
 63    /// <param name = "codeLengths">
 64    /// the array of code lengths
 65    /// </param>
 566    public InflaterHuffmanTree(byte[] codeLengths)
 67    {
 568      BuildTree(codeLengths);
 569    }
 70    #endregion
 71
 72    void BuildTree(byte[] codeLengths)
 73    {
 574      int[] blCount = new int[MAX_BITLEN + 1];
 575      int[] nextCode = new int[MAX_BITLEN + 1];
 76
 122077       for (int i = 0; i < codeLengths.Length; i++) {
 60578        int bits = codeLengths[i];
 60579         if (bits > 0) {
 35880          blCount[bits]++;
 81        }
 82      }
 83
 584      int code = 0;
 585      int treeSize = 512;
 16086       for (int bits = 1; bits <= MAX_BITLEN; bits++) {
 7587        nextCode[bits] = code;
 7588        code += blCount[bits] << (16 - bits);
 7589         if (bits >= 10) {
 90          /* We need an extra table for bit lengths >= 10. */
 3091          int start = nextCode[bits] & 0x1ff80;
 3092          int end = code & 0x1ff80;
 3093          treeSize += (end - start) >> (16 - bits);
 94        }
 95      }
 96
 97      /* -jr comment this out! doesnt work for dynamic trees and pkzip 2.04g
 98            if (code != 65536)
 99            {
 100              throw new SharpZipBaseException("Code lengths don't add up properly.");
 101            }
 102      */
 103      /* Now create and fill the extra tables from longest to shortest
 104      * bit len.  This way the sub trees will be aligned.
 105      */
 5106      tree = new short[treeSize];
 5107      int treePtr = 512;
 70108       for (int bits = MAX_BITLEN; bits >= 10; bits--) {
 30109        int end = code & 0x1ff80;
 30110        code -= blCount[bits] << (16 - bits);
 30111        int start = code & 0x1ff80;
 60112         for (int i = start; i < end; i += 1 << 7) {
 0113          tree[DeflaterHuffman.BitReverse(i)] = (short)((-treePtr << 4) | bits);
 0114          treePtr += 1 << (bits - 9);
 115        }
 116      }
 117
 1220118       for (int i = 0; i < codeLengths.Length; i++) {
 605119        int bits = codeLengths[i];
 605120         if (bits == 0) {
 121          continue;
 122        }
 358123        code = nextCode[bits];
 358124        int revcode = DeflaterHuffman.BitReverse(code);
 358125         if (bits <= 9) {
 126          do {
 2560127            tree[revcode] = (short)((i << 4) | bits);
 2560128            revcode += 1 << bits;
 2560129           } while (revcode < 512);
 358130        } else {
 0131          int subTree = tree[revcode & 511];
 0132          int treeLen = 1 << (subTree & 15);
 0133          subTree = -(subTree >> 4);
 134          do {
 0135            tree[subTree | (revcode >> 9)] = (short)((i << 4) | bits);
 0136            revcode += 1 << bits;
 0137           } while (revcode < treeLen);
 138        }
 358139        nextCode[bits] = code + (1 << (16 - bits));
 140      }
 141
 5142    }
 143
 144    /// <summary>
 145    /// Reads the next symbol from input.  The symbol is encoded using the
 146    /// huffman tree.
 147    /// </summary>
 148    /// <param name="input">
 149    /// input the input source.
 150    /// </param>
 151    /// <returns>
 152    /// the next symbol, or -1 if not enough input is available.
 153    /// </returns>
 154    public int GetSymbol(StreamManipulator input)
 155    {
 156      int lookahead, symbol;
 9839157       if ((lookahead = input.PeekBits(9)) >= 0) {
 9816158         if ((symbol = tree[lookahead]) >= 0) {
 9816159          input.DropBits(symbol & 15);
 9816160          return symbol >> 4;
 161        }
 0162        int subtree = -(symbol >> 4);
 0163        int bitlen = symbol & 15;
 0164         if ((lookahead = input.PeekBits(bitlen)) >= 0) {
 0165          symbol = tree[subtree | (lookahead >> 9)];
 0166          input.DropBits(symbol & 15);
 0167          return symbol >> 4;
 168        } else {
 0169          int bits = input.AvailableBits;
 0170          lookahead = input.PeekBits(bits);
 0171          symbol = tree[subtree | (lookahead >> 9)];
 0172           if ((symbol & 15) <= bits) {
 0173            input.DropBits(symbol & 15);
 0174            return symbol >> 4;
 175          } else {
 0176            return -1;
 177          }
 178        }
 179      } else {
 23180        int bits = input.AvailableBits;
 23181        lookahead = input.PeekBits(bits);
 23182        symbol = tree[lookahead];
 23183         if (symbol >= 0 && (symbol & 15) <= bits) {
 23184          input.DropBits(symbol & 15);
 23185          return symbol >> 4;
 186        } else {
 0187          return -1;
 188        }
 189      }
 190    }
 191  }
 192}
 193