System.IO.Compression.HuffmanTree.GetNextSymbol C# (CSharp) Method

GetNextSymbol() public method

public GetNextSymbol ( InputBuffer input ) : int
input InputBuffer
return int
        public int GetNextSymbol(InputBuffer input) {
            uint num = input.TryLoad16Bits();
            if (input.AvailableBits == 0) {
                return -1;
            }
            int index = this.table[(num & this.tableMask)];
            if (index < 0) {
                uint num3 = 1u << this.tableBits;
                do {
                    index = -index;
                    if ((num & num3) == 0u) {
                        index = this.left[index];
                    }
                    else {
                        index = this.right[index];
                    }
                    num3 <<= 1;
                }
                while (index < 0);
            }
            if (this.codeLengthArray[index] > input.AvailableBits) {
                return -1;
            }
            input.SkipBits(this.codeLengthArray[index]);
            return index;
        }

Usage Example

Example #1
0
        // Format of the dynamic block header:
        //      5 Bits: HLIT, # of Literal/Length codes - 257 (257 - 286)
        //      5 Bits: HDIST, # of Distance codes - 1        (1 - 32)
        //      4 Bits: HCLEN, # of Code Length codes - 4     (4 - 19)
        //
        //      (HCLEN + 4) x 3 bits: code lengths for the code length
        //          alphabet given just above, in the order: 16, 17, 18,
        //          0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
        //
        //          These code lengths are interpreted as 3-bit integers
        //          (0-7); as above, a code length of 0 means the
        //          corresponding symbol (literal/length or distance code
        //          length) is not used.
        //
        //      HLIT + 257 code lengths for the literal/length alphabet,
        //          encoded using the code length Huffman code
        //
        //       HDIST + 1 code lengths for the distance alphabet,
        //          encoded using the code length Huffman code
        //
        // The code length repeat codes can cross from HLIT + 257 to the
        // HDIST + 1 code lengths.  In other words, all code lengths form
        // a single sequence of HLIT + HDIST + 258 values.
        private bool DecodeDynamicBlockHeader()
        {
            switch (_state)
            {
                case InflaterState.ReadingNumLitCodes:
                    _literalLengthCodeCount = _input.GetBits(5);
                    if (_literalLengthCodeCount < 0)
                    {
                        return false;
                    }
                    _literalLengthCodeCount += 257;
                    _state = InflaterState.ReadingNumDistCodes;
                    goto case InflaterState.ReadingNumDistCodes;

                case InflaterState.ReadingNumDistCodes:
                    _distanceCodeCount = _input.GetBits(5);
                    if (_distanceCodeCount < 0)
                    {
                        return false;
                    }
                    _distanceCodeCount += 1;
                    _state = InflaterState.ReadingNumCodeLengthCodes;
                    goto case InflaterState.ReadingNumCodeLengthCodes;

                case InflaterState.ReadingNumCodeLengthCodes:
                    _codeLengthCodeCount = _input.GetBits(4);
                    if (_codeLengthCodeCount < 0)
                    {
                        return false;
                    }
                    _codeLengthCodeCount += 4;
                    _loopCounter = 0;
                    _state = InflaterState.ReadingCodeLengthCodes;
                    goto case InflaterState.ReadingCodeLengthCodes;

                case InflaterState.ReadingCodeLengthCodes:
                    while (_loopCounter < _codeLengthCodeCount)
                    {
                        int bits = _input.GetBits(3);
                        if (bits < 0)
                        {
                            return false;
                        }
                        _codeLengthTreeCodeLength[s_codeOrder[_loopCounter]] = (byte)bits;
                        ++_loopCounter;
                    }

                    for (int i = _codeLengthCodeCount; i < s_codeOrder.Length; i++)
                    {
                        _codeLengthTreeCodeLength[s_codeOrder[i]] = 0;
                    }

                    // create huffman tree for code length
                    _codeLengthTree = new HuffmanTree(_codeLengthTreeCodeLength);
                    _codeArraySize = _literalLengthCodeCount + _distanceCodeCount;
                    _loopCounter = 0;     // reset loop count

                    _state = InflaterState.ReadingTreeCodesBefore;
                    goto case InflaterState.ReadingTreeCodesBefore;

                case InflaterState.ReadingTreeCodesBefore:
                case InflaterState.ReadingTreeCodesAfter:
                    while (_loopCounter < _codeArraySize)
                    {
                        if (_state == InflaterState.ReadingTreeCodesBefore)
                        {
                            if ((_lengthCode = _codeLengthTree.GetNextSymbol(_input)) < 0)
                            {
                                return false;
                            }
                        }

                        // The alphabet for code lengths is as follows:
                        //  0 - 15: Represent code lengths of 0 - 15
                        //  16: Copy the previous code length 3 - 6 times.
                        //  The next 2 bits indicate repeat length
                        //         (0 = 3, ... , 3 = 6)
                        //      Example:  Codes 8, 16 (+2 bits 11),
                        //                16 (+2 bits 10) will expand to
                        //                12 code lengths of 8 (1 + 6 + 5)
                        //  17: Repeat a code length of 0 for 3 - 10 times.
                        //    (3 bits of length)
                        //  18: Repeat a code length of 0 for 11 - 138 times
                        //    (7 bits of length)
                        if (_lengthCode <= 15)
                        {
                            _codeList[_loopCounter++] = (byte)_lengthCode;
                        }
                        else
                        {
                            int repeatCount;
                            if (_lengthCode == 16)
                            {
                                if (!_input.EnsureBitsAvailable(2))
                                {
                                    _state = InflaterState.ReadingTreeCodesAfter;
                                    return false;
                                }

                                if (_loopCounter == 0)
                                {          // can't have "prev code" on first code
                                    throw new InvalidDataException();
                                }

                                byte previousCode = _codeList[_loopCounter - 1];
                                repeatCount = _input.GetBits(2) + 3;

                                if (_loopCounter + repeatCount > _codeArraySize)
                                {
                                    throw new InvalidDataException();
                                }

                                for (int j = 0; j < repeatCount; j++)
                                {
                                    _codeList[_loopCounter++] = previousCode;
                                }
                            }
                            else if (_lengthCode == 17)
                            {
                                if (!_input.EnsureBitsAvailable(3))
                                {
                                    _state = InflaterState.ReadingTreeCodesAfter;
                                    return false;
                                }

                                repeatCount = _input.GetBits(3) + 3;

                                if (_loopCounter + repeatCount > _codeArraySize)
                                {
                                    throw new InvalidDataException();
                                }

                                for (int j = 0; j < repeatCount; j++)
                                {
                                    _codeList[_loopCounter++] = 0;
                                }
                            }
                            else
                            { // code == 18
                                if (!_input.EnsureBitsAvailable(7))
                                {
                                    _state = InflaterState.ReadingTreeCodesAfter;
                                    return false;
                                }

                                repeatCount = _input.GetBits(7) + 11;

                                if (_loopCounter + repeatCount > _codeArraySize)
                                {
                                    throw new InvalidDataException();
                                }

                                for (int j = 0; j < repeatCount; j++)
                                {
                                    _codeList[_loopCounter++] = 0;
                                }
                            }
                        }
                        _state = InflaterState.ReadingTreeCodesBefore; // we want to read the next code.
                    }
                    break;

                default:
                    Debug.Assert(false, "check why we are here!");
                    throw new InvalidDataException(SR.UnknownState);
            }

            byte[] literalTreeCodeLength = new byte[HuffmanTree.MaxLiteralTreeElements];
            byte[] distanceTreeCodeLength = new byte[HuffmanTree.MaxDistTreeElements];

            // Create literal and distance tables
            Array.Copy(_codeList, 0, literalTreeCodeLength, 0, _literalLengthCodeCount);
            Array.Copy(_codeList, _literalLengthCodeCount, distanceTreeCodeLength, 0, _distanceCodeCount);

            // Make sure there is an end-of-block code, otherwise how could we ever end?
            if (literalTreeCodeLength[HuffmanTree.EndOfBlockCode] == 0)
            {
                throw new InvalidDataException();
            }

            _literalLengthTree = new HuffmanTree(literalTreeCodeLength);
            _distanceTree = new HuffmanTree(distanceTreeCodeLength);
            _state = InflaterState.DecodeTop;
            return true;
        }
All Usage Examples Of System.IO.Compression.HuffmanTree::GetNextSymbol