Example #1
0
        //Each block of compressed data begins with 3 header bits
        // containing the following data:
        //    first bit       BFINAL
        //    next 2 bits     BTYPE
        // Note that the header bits do not necessarily begin on a byte
        // boundary, since a block does not necessarily occupy an integral
        // number of bytes.
        // BFINAL is set if and only if this is the last block of the data
        // set.
        // BTYPE specifies how the data are compressed, as follows:
        //    00 - no compression
        //    01 - compressed with fixed Huffman codes
        //    10 - compressed with dynamic Huffman codes
        //    11 - reserved (error)
        // The only difference between the two compressed cases is how the
        // Huffman codes for the literal/length and distance alphabets are
        // defined.
        //
        // This function returns true for success (end of block or output window is full,) 
        // false if we are short of input
        //
        private bool Decode()
        {
            bool eob = false;
            bool result = false;

            if (Finished())
            {
                return true;
            }

            if (_hasFormatReader)
            {
                if (_state == InflaterState.ReadingHeader)
                {
                    if (!_formatReader.ReadHeader(_input))
                    {
                        return false;
                    }
                    _state = InflaterState.ReadingBFinal;
                }
                else if (_state == InflaterState.StartReadingFooter || _state == InflaterState.ReadingFooter)
                {
                    if (!_formatReader.ReadFooter(_input))
                        return false;

                    _state = InflaterState.VerifyingFooter;
                    return true;
                }
            }

            if (_state == InflaterState.ReadingBFinal)
            {   // reading bfinal bit
                // Need 1 bit
                if (!_input.EnsureBitsAvailable(1))
                    return false;

                _bfinal = _input.GetBits(1);
                _state = InflaterState.ReadingBType;
            }

            if (_state == InflaterState.ReadingBType)
            {
                // Need 2 bits
                if (!_input.EnsureBitsAvailable(2))
                {
                    _state = InflaterState.ReadingBType;
                    return false;
                }

                _blockType = (BlockType)_input.GetBits(2);
                if (_blockType == BlockType.Dynamic)
                {
                    _state = InflaterState.ReadingNumLitCodes;
                }
                else if (_blockType == BlockType.Static)
                {
                    _literalLengthTree = HuffmanTree.StaticLiteralLengthTree;
                    _distanceTree = HuffmanTree.StaticDistanceTree;
                    _state = InflaterState.DecodeTop;
                }
                else if (_blockType == BlockType.Uncompressed)
                {
                    _state = InflaterState.UncompressedAligning;
                }
                else
                {
                    throw new InvalidDataException(SR.UnknownBlockType);
                }
            }

            if (_blockType == BlockType.Dynamic)
            {
                if (_state < InflaterState.DecodeTop)
                {   // we are reading the header
                    result = DecodeDynamicBlockHeader();
                }
                else
                {
                    result = DecodeBlock(out eob);  // this can returns true when output is full
                }
            }
            else if (_blockType == BlockType.Static)
            {
                result = DecodeBlock(out eob);
            }
            else if (_blockType == BlockType.Uncompressed)
            {
                result = DecodeUncompressedBlock(out eob);
            }
            else
            {
                throw new InvalidDataException(SR.UnknownBlockType);
            }

            //
            // If we reached the end of the block and the block we were decoding had
            // bfinal=1 (final block)
            //
            if (eob && (_bfinal != 0))
            {
                if (_hasFormatReader)
                    _state = InflaterState.StartReadingFooter;
                else
                    _state = InflaterState.Done;
            }
            return result;
        }
Example #2
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;
        }
Example #3
0
        //Each block of compressed data begins with 3 header bits
        // containing the following data:
        //    first bit       BFINAL
        //    next 2 bits     BTYPE
        // Note that the header bits do not necessarily begin on a byte
        // boundary, since a block does not necessarily occupy an integral
        // number of bytes.
        // BFINAL is set if and only if this is the last block of the data
        // set.
        // BTYPE specifies how the data are compressed, as follows:
        //    00 - no compression
        //    01 - compressed with fixed Huffman codes
        //    10 - compressed with dynamic Huffman codes
        //    11 - reserved (error)
        // The only difference between the two compressed cases is how the
        // Huffman codes for the literal/length and distance alphabets are
        // defined.
        //
        // This function returns true for success (end of block or output window is full,)
        // false if we are short of input
        //
        private bool Decode()
        {
            bool eob    = false;
            bool result = false;

            if (Finished())
            {
                return(true);
            }

            if (using_gzip)
            {
                if (state == InflaterState.ReadingGZIPHeader)
                {
                    if (!gZipDecoder.ReadGzipHeader())
                    {
                        return(false);
                    }
                    state = InflaterState.ReadingBFinal;
                }
                else if (state == InflaterState.StartReadingGZIPFooter || state == InflaterState.ReadingGZIPFooter)
                {
                    if (!gZipDecoder.ReadGzipFooter())
                    {
                        return(false);
                    }

                    state = InflaterState.VerifyingGZIPFooter;
                    return(true);
                }
            }

            if (state == InflaterState.ReadingBFinal)     // reading bfinal bit
            // Need 1 bit
            {
                if (!input.EnsureBitsAvailable(1))
                {
                    return(false);
                }

                bfinal = input.GetBits(1);
                state  = InflaterState.ReadingBType;
            }

            if (state == InflaterState.ReadingBType)
            {
                // Need 2 bits
                if (!input.EnsureBitsAvailable(2))
                {
                    state = InflaterState.ReadingBType;
                    return(false);
                }

                blockType = (BlockType)input.GetBits(2);
                if (blockType == BlockType.Dynamic)
                {
                    Debug.WriteLineIf(CompressionTracingSwitch.Informational, "Decoding Dynamic Block", "Compression");
                    state = InflaterState.ReadingNumLitCodes;
                }
                else if (blockType == BlockType.Static)
                {
                    Debug.WriteLineIf(CompressionTracingSwitch.Informational, "Decoding Static Block", "Compression");
                    literalLengthTree = HuffmanTree.StaticLiteralLengthTree;
                    distanceTree      = HuffmanTree.StaticDistanceTree;
                    state             = InflaterState.DecodeTop;
                }
                else if (blockType == BlockType.Uncompressed)
                {
                    Debug.WriteLineIf(CompressionTracingSwitch.Informational, "Decoding UnCompressed Block", "Compression");
                    state = InflaterState.UncompressedAligning;
                }
                else
                {
                    throw new InvalidDataException(SR.GetString(SR.UnknownBlockType));
                }
            }

            if (blockType == BlockType.Dynamic)
            {
                if (state < InflaterState.DecodeTop)     // we are reading the header
                {
                    result = DecodeDynamicBlockHeader();
                }
                else
                {
                    result = DecodeBlock(out eob);  // this can returns true when output is full
                }
            }
            else if (blockType == BlockType.Static)
            {
                result = DecodeBlock(out eob);
            }
            else if (blockType == BlockType.Uncompressed)
            {
                result = DecodeUncompressedBlock(out eob);
            }
            else
            {
                throw new InvalidDataException(SR.GetString(SR.UnknownBlockType));
            }

            //
            // If we reached the end of the block and the block we were decoding had
            // bfinal=1 (final block)
            //
            if (eob && (bfinal != 0))
            {
                if (using_gzip)
                {
                    state = InflaterState.StartReadingGZIPFooter;
                }
                else
                {
                    state = InflaterState.Done;
                }
            }
            return(result);
        }
Example #4
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.
        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[codeOrder[loopCounter]] = (byte)bits;
                    ++loopCounter;
                }

                for (int i = codeLengthCodeCount; i < codeOrder.Length; i++)
                {
                    codeLengthTreeCodeLength[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
                    {
                        if (!input.EnsureBitsAvailable(7))   // it doesn't matter if we require more bits here
                        {
                            state = InflaterState.ReadingTreeCodesAfter;
                            return(false);
                        }

                        int repeatCount;
                        if (lengthCode == 16)
                        {
                            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)
                        {
                            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
                        {
                            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.GetString(SR.UnknownState));
            }

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

            // Create literal and distance tables
            Array.Copy(codeList, literalTreeCodeLength, 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);
        }
 static HuffmanTree()
 {
     // construct the static literal tree and distance tree
     staticLiteralLengthTree = new HuffmanTree(GetStaticLiteralTreeLength());
     staticDistanceTree      = new HuffmanTree(GetStaticDistanceTreeLength());
 }
        //Each block of compressed data begins with 3 header bits
        // containing the following data:
        //    first bit       BFINAL
        //    next 2 bits     BTYPE
        // Note that the header bits do not necessarily begin on a byte
        // boundary, since a block does not necessarily occupy an integral
        // number of bytes.
        // BFINAL is set if and only if this is the last block of the data
        // set.
        // BTYPE specifies how the data are compressed, as follows:
        //    00 - no compression
        //    01 - compressed with fixed Huffman codes
        //    10 - compressed with dynamic Huffman codes
        //    11 - reserved (error)
        // The only difference between the two compressed cases is how the
        // Huffman codes for the literal/length and distance alphabets are
        // defined.
        //
        // This function returns true for success (end of block or output window is full,) 
        // false if we are short of input
        //
        private bool Decode() {
            bool eob = false;
            bool result = false;

            if( Finished()) {
                return true;
            }

            if (using_gzip) {
                if (state == InflaterState.ReadingGZIPHeader) {
                    if (!gZipDecoder.ReadGzipHeader()) {
                        return false;
                    }
                    state = InflaterState.ReadingBFinal;              
                }
                else if (state == InflaterState.StartReadingGZIPFooter || state == InflaterState.ReadingGZIPFooter) {
                    if (!gZipDecoder.ReadGzipFooter())
                        return false;

                    state = InflaterState.VerifyingGZIPFooter;
                    return true;
                }
            }

            if( state == InflaterState.ReadingBFinal) {   // reading bfinal bit
                // Need 1 bit
                if (!input.EnsureBitsAvailable(1))
                    return false;

                bfinal = input.GetBits(1);
                state = InflaterState.ReadingBType;
            }
            
            if( state == InflaterState.ReadingBType) {
                // Need 2 bits
                if (!input.EnsureBitsAvailable(2)) {
                    state = InflaterState.ReadingBType;
                    return false;
                }

                blockType = (BlockType)input.GetBits(2);
                if (blockType == BlockType.Dynamic) {
                    Debug.WriteLineIf(CompressionTracingSwitch.Informational, "Decoding Dynamic Block", "Compression");                                                                
                    state = InflaterState.ReadingNumLitCodes;
                } 
                else if (blockType == BlockType.Static) {
                    Debug.WriteLineIf(CompressionTracingSwitch.Informational, "Decoding Static Block", "Compression");                                                                                    
                    literalLengthTree = HuffmanTree.StaticLiteralLengthTree;
                    distanceTree = HuffmanTree.StaticDistanceTree;
                    state = InflaterState.DecodeTop;
                } 
                else if (blockType == BlockType.Uncompressed) {
                    Debug.WriteLineIf(CompressionTracingSwitch.Informational, "Decoding UnCompressed Block", "Compression");                                                                                    
                    state = InflaterState.UncompressedAligning;
                } 
                else {
                    throw new InvalidDataException(SR.GetString(SR.UnknownBlockType));
                }
            }

            if (blockType == BlockType.Dynamic) {
                if (state < InflaterState.DecodeTop) {   // we are reading the header
                    result = DecodeDynamicBlockHeader();
                }
                else {                    
                    result = DecodeBlock(out eob);  // this can returns true when output is full
                }
            } 
            else if (blockType == BlockType.Static) {
                result = DecodeBlock(out eob);
            } 
            else if (blockType == BlockType.Uncompressed) {
                result = DecodeUncompressedBlock(out eob);
            } 
            else {
                throw new InvalidDataException(SR.GetString(SR.UnknownBlockType));
            }

            //
            // If we reached the end of the block and the block we were decoding had
            // bfinal=1 (final block)
            //
            if (eob && (bfinal != 0)) {
                if (using_gzip)
                    state = InflaterState.StartReadingGZIPFooter;
                else
                    state = InflaterState.Done;
            }
            return result;
        }
Example #7
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.Fail("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);
        }
        //Each block of compressed data begins with 3 header bits
        // containing the following data:
        //    first bit       BFINAL
        //    next 2 bits     BTYPE
        // Note that the header bits do not necessarily begin on a byte
        // boundary, since a block does not necessarily occupy an integral
        // number of bytes.
        // BFINAL is set if and only if this is the last block of the data
        // set.
        // BTYPE specifies how the data are compressed, as follows:
        //    00 - no compression
        //    01 - compressed with fixed Huffman codes
        //    10 - compressed with dynamic Huffman codes
        //    11 - reserved (error)
        // The only difference between the two compressed cases is how the
        // Huffman codes for the literal/length and distance alphabets are
        // defined.
        //
        // This function returns true for success (end of block or output window is full,)
        // false if we are short of input
        //
        private bool Decode()
        {
            bool eob    = false;
            bool result = false;

            if (Finished())
            {
                return(true);
            }

            if (_hasFormatReader)
            {
                if (_state == InflaterState.ReadingHeader)
                {
                    if (!_formatReader.ReadHeader(_input))
                    {
                        return(false);
                    }
                    _state = InflaterState.ReadingBFinal;
                }
                else if (_state == InflaterState.StartReadingFooter || _state == InflaterState.ReadingFooter)
                {
                    if (!_formatReader.ReadFooter(_input))
                    {
                        return(false);
                    }

                    _state = InflaterState.VerifyingFooter;
                    return(true);
                }
            }

            if (_state == InflaterState.ReadingBFinal)
            {   // reading bfinal bit
                // Need 1 bit
                if (!_input.EnsureBitsAvailable(1))
                {
                    return(false);
                }

                _bfinal = _input.GetBits(1);
                _state  = InflaterState.ReadingBType;
            }

            if (_state == InflaterState.ReadingBType)
            {
                // Need 2 bits
                if (!_input.EnsureBitsAvailable(2))
                {
                    _state = InflaterState.ReadingBType;
                    return(false);
                }

                _blockType = (BlockType)_input.GetBits(2);
                if (_blockType == BlockType.Dynamic)
                {
                    _state = InflaterState.ReadingNumLitCodes;
                }
                else if (_blockType == BlockType.Static)
                {
                    _literalLengthTree = HuffmanTree.StaticLiteralLengthTree;
                    _distanceTree      = HuffmanTree.StaticDistanceTree;
                    _state             = InflaterState.DecodeTop;
                }
                else if (_blockType == BlockType.Uncompressed)
                {
                    _state = InflaterState.UncompressedAligning;
                }
                else
                {
                    throw new InvalidDataException(SR.UnknownBlockType);
                }
            }

            if (_blockType == BlockType.Dynamic)
            {
                if (_state < InflaterState.DecodeTop)
                {   // we are reading the header
                    result = DecodeDynamicBlockHeader();
                }
                else
                {
                    result = DecodeBlock(out eob);  // this can returns true when output is full
                }
            }
            else if (_blockType == BlockType.Static)
            {
                result = DecodeBlock(out eob);
            }
            else if (_blockType == BlockType.Uncompressed)
            {
                result = DecodeUncompressedBlock(out eob);
            }
            else
            {
                throw new InvalidDataException(SR.UnknownBlockType);
            }

            //
            // If we reached the end of the block and the block we were decoding had
            // bfinal=1 (final block)
            //
            if (eob && (_bfinal != 0))
            {
                if (_hasFormatReader)
                {
                    _state = InflaterState.StartReadingFooter;
                }
                else
                {
                    _state = InflaterState.Done;
                }
            }
            return(result);
        }
Example #9
0
 static HuffmanTree()
 {
     // construct the static literal tree and distance tree
     s_staticLiteralLengthTree = new HuffmanTree(GetStaticLiteralTreeLength());
     s_staticDistanceTree = new HuffmanTree(GetStaticDistanceTreeLength());
 }
Example #10
0
        private bool DecodeDynamicBlockHeader()
        {
            switch (this.state) {
                case InflaterState.ReadingNumLitCodes:
                    this.literalLengthCodeCount = this.input.GetBits(5);
                    if (this.literalLengthCodeCount >= 0) {
                        this.literalLengthCodeCount += 0x101;
                        this.state = InflaterState.ReadingNumDistCodes;
                        break;
                    }
                    return false;

                case InflaterState.ReadingNumDistCodes:
                    break;

                case InflaterState.ReadingNumCodeLengthCodes:
                    goto Label_0096;

                case InflaterState.ReadingCodeLengthCodes:
                    goto Label_0107;

                case InflaterState.ReadingTreeCodesBefore:
                case InflaterState.ReadingTreeCodesAfter:
                    goto Label_0315;

                default:
                    throw new InvalidDataException("Decoder is in some unknown state. This might be caused by corrupted data.");
            }
            this.distanceCodeCount = this.input.GetBits(5);
            if (this.distanceCodeCount < 0) {
                return false;
            }
            this.distanceCodeCount++;
            this.state = InflaterState.ReadingNumCodeLengthCodes;
            Label_0096:
            this.codeLengthCodeCount = this.input.GetBits(4);
            if (this.codeLengthCodeCount < 0) {
                return false;
            }
            this.codeLengthCodeCount += 4;
            this.loopCounter = 0;
            this.state = InflaterState.ReadingCodeLengthCodes;
            Label_0107:
            while (this.loopCounter < this.codeLengthCodeCount) {
                int bits = this.input.GetBits(3);
                if (bits < 0) {
                    return false;
                }
                this.codeLengthTreeCodeLength[codeOrder[this.loopCounter]] = (byte)bits;
                this.loopCounter++;
            }
            for (int i = this.codeLengthCodeCount; i < codeOrder.Length; i++) {
                this.codeLengthTreeCodeLength[codeOrder[i]] = 0;
            }
            this.codeLengthTree = new HuffmanTree(this.codeLengthTreeCodeLength);
            this.codeArraySize = this.literalLengthCodeCount + this.distanceCodeCount;
            this.loopCounter = 0;
            this.state = InflaterState.ReadingTreeCodesBefore;
            Label_0315:
            while (this.loopCounter < this.codeArraySize) {
                if ((this.state == InflaterState.ReadingTreeCodesBefore) && ((this.lengthCode = this.codeLengthTree.GetNextSymbol(this.input)) < 0)) {
                    return false;
                }
                if (this.lengthCode <= 15) {
                    this.codeList[this.loopCounter++] = (byte)this.lengthCode;
                }
                else {
                    int num3;
                    if (!this.input.EnsureBitsAvailable(7)) {
                        this.state = InflaterState.ReadingTreeCodesAfter;
                        return false;
                    }
                    if (this.lengthCode == 0x10) {
                        if (this.loopCounter == 0) {
                            throw new InvalidDataException();
                        }
                        byte num4 = this.codeList[this.loopCounter - 1];
                        num3 = this.input.GetBits(2) + 3;
                        if ((this.loopCounter + num3) > this.codeArraySize) {
                            throw new InvalidDataException();
                        }
                        for (int j = 0; j < num3; j++) {
                            this.codeList[this.loopCounter++] = num4;
                        }
                    }
                    else if (this.lengthCode == 0x11) {
                        num3 = this.input.GetBits(3) + 3;
                        if ((this.loopCounter + num3) > this.codeArraySize) {
                            throw new InvalidDataException();
                        }
                        for (int k = 0; k < num3; k++) {
                            this.codeList[this.loopCounter++] = 0;
                        }
                    }
                    else {
                        num3 = this.input.GetBits(7) + 11;
                        if ((this.loopCounter + num3) > this.codeArraySize) {
                            throw new InvalidDataException();
                        }
                        for (int m = 0; m < num3; m++) {
                            this.codeList[this.loopCounter++] = 0;
                        }
                    }
                }
                this.state = InflaterState.ReadingTreeCodesBefore;
            }
            byte[] destinationArray = new byte[0x120];
            byte[] buffer2 = new byte[0x20];
            Array.Copy(this.codeList, 0, destinationArray, 0, this.literalLengthCodeCount);
            Array.Copy(this.codeList, this.literalLengthCodeCount, buffer2, 0, this.distanceCodeCount);
            if (destinationArray[0x100] == 0) {
                throw new InvalidDataException();
            }
            this.literalLengthTree = new HuffmanTree(destinationArray);
            this.distanceTree = new HuffmanTree(buffer2);
            this.state = InflaterState.DecodeTop;
            return true;
        }
Example #11
0
 private bool Decode()
 {
     bool flag = false;
     bool flag2 = false;
     if (this.Finished()) {
         return true;
     }
     if (this.using_gzip) {
         if (this.state == InflaterState.ReadingGZIPHeader) {
             if (!this.gZipDecoder.ReadGzipHeader()) {
                 return false;
             }
             this.state = InflaterState.ReadingBFinal;
         }
         else if ((this.state == InflaterState.StartReadingGZIPFooter) || (this.state == InflaterState.ReadingGZIPFooter)) {
             if (!this.gZipDecoder.ReadGzipFooter()) {
                 return false;
             }
             this.state = InflaterState.VerifyingGZIPFooter;
             return true;
         }
     }
     if (this.state == InflaterState.ReadingBFinal) {
         if (!this.input.EnsureBitsAvailable(1)) {
             return false;
         }
         this.bfinal = this.input.GetBits(1);
         this.state = InflaterState.ReadingBType;
     }
     if (this.state == InflaterState.ReadingBType) {
         if (!this.input.EnsureBitsAvailable(2)) {
             this.state = InflaterState.ReadingBType;
             return false;
         }
         this.blockType = (BlockType)this.input.GetBits(2);
         if (this.blockType != BlockType.Dynamic) {
             if (this.blockType != BlockType.Static) {
                 if (this.blockType != BlockType.Uncompressed) {
                     throw new InvalidDataException("Unknown block type. Stream might be corrupted.");
                 }
                 this.state = InflaterState.UncompressedAligning;
             }
             else {
                 this.literalLengthTree = HuffmanTree.StaticLiteralLengthTree;
                 this.distanceTree = HuffmanTree.StaticDistanceTree;
                 this.state = InflaterState.DecodeTop;
             }
         }
         else {
             this.state = InflaterState.ReadingNumLitCodes;
         }
     }
     if (this.blockType == BlockType.Dynamic) {
         if (this.state < InflaterState.DecodeTop) {
             flag2 = this.DecodeDynamicBlockHeader();
         }
         else {
             flag2 = this.DecodeBlock(out flag);
         }
     }
     else if (this.blockType == BlockType.Static) {
         flag2 = this.DecodeBlock(out flag);
     }
     else {
         if (this.blockType != BlockType.Uncompressed) {
             throw new InvalidDataException("Unknown block type. Stream might be corrupted.");
         }
         flag2 = this.DecodeUncompressedBlock(out flag);
     }
     if (flag && (this.bfinal != 0)) {
         if (this.using_gzip) {
             this.state = InflaterState.StartReadingGZIPFooter;
             return flag2;
         }
         this.state = InflaterState.Done;
     }
     return flag2;
 }
Example #12
0
        private bool Decode()
        {
            bool flag  = false;
            bool flag2 = false;

            if (this.Finished())
            {
                return(true);
            }
            if (this.using_gzip)
            {
                if (this.state == InflaterState.ReadingGZIPHeader)
                {
                    if (!this.gZipDecoder.ReadGzipHeader())
                    {
                        return(false);
                    }
                    this.state = InflaterState.ReadingBFinal;
                }
                else if ((this.state == InflaterState.StartReadingGZIPFooter) || (this.state == InflaterState.ReadingGZIPFooter))
                {
                    if (!this.gZipDecoder.ReadGzipFooter())
                    {
                        return(false);
                    }
                    this.state = InflaterState.VerifyingGZIPFooter;
                    return(true);
                }
            }
            if (this.state == InflaterState.ReadingBFinal)
            {
                if (!this.input.EnsureBitsAvailable(1))
                {
                    return(false);
                }
                this.bfinal = this.input.GetBits(1);
                this.state  = InflaterState.ReadingBType;
            }
            if (this.state == InflaterState.ReadingBType)
            {
                if (!this.input.EnsureBitsAvailable(2))
                {
                    this.state = InflaterState.ReadingBType;
                    return(false);
                }
                this.blockType = (BlockType)this.input.GetBits(2);
                if (this.blockType != BlockType.Dynamic)
                {
                    if (this.blockType != BlockType.Static)
                    {
                        if (this.blockType != BlockType.Uncompressed)
                        {
                            throw new InvalidDataException("Unknown block type. Stream might be corrupted.");
                        }
                        this.state = InflaterState.UncompressedAligning;
                    }
                    else
                    {
                        this.literalLengthTree = HuffmanTree.StaticLiteralLengthTree;
                        this.distanceTree      = HuffmanTree.StaticDistanceTree;
                        this.state             = InflaterState.DecodeTop;
                    }
                }
                else
                {
                    this.state = InflaterState.ReadingNumLitCodes;
                }
            }
            if (this.blockType == BlockType.Dynamic)
            {
                if (this.state < InflaterState.DecodeTop)
                {
                    flag2 = this.DecodeDynamicBlockHeader();
                }
                else
                {
                    flag2 = this.DecodeBlock(out flag);
                }
            }
            else if (this.blockType == BlockType.Static)
            {
                flag2 = this.DecodeBlock(out flag);
            }
            else
            {
                if (this.blockType != BlockType.Uncompressed)
                {
                    throw new InvalidDataException("Unknown block type. Stream might be corrupted.");
                }
                flag2 = this.DecodeUncompressedBlock(out flag);
            }
            if (flag && (this.bfinal != 0))
            {
                if (this.using_gzip)
                {
                    this.state = InflaterState.StartReadingGZIPFooter;
                    return(flag2);
                }
                this.state = InflaterState.Done;
            }
            return(flag2);
        }
Example #13
0
        private bool DecodeDynamicBlockHeader()
        {
            switch (this.state)
            {
            case InflaterState.ReadingNumLitCodes:
                this.literalLengthCodeCount = this.input.GetBits(5);
                if (this.literalLengthCodeCount >= 0)
                {
                    this.literalLengthCodeCount += 0x101;
                    this.state = InflaterState.ReadingNumDistCodes;
                    break;
                }
                return(false);

            case InflaterState.ReadingNumDistCodes:
                break;

            case InflaterState.ReadingNumCodeLengthCodes:
                goto Label_0096;

            case InflaterState.ReadingCodeLengthCodes:
                goto Label_0107;

            case InflaterState.ReadingTreeCodesBefore:
            case InflaterState.ReadingTreeCodesAfter:
                goto Label_0315;

            default:
                throw new InvalidDataException("Decoder is in some unknown state. This might be caused by corrupted data.");
            }
            this.distanceCodeCount = this.input.GetBits(5);
            if (this.distanceCodeCount < 0)
            {
                return(false);
            }
            this.distanceCodeCount++;
            this.state = InflaterState.ReadingNumCodeLengthCodes;
Label_0096:
            this.codeLengthCodeCount = this.input.GetBits(4);
            if (this.codeLengthCodeCount < 0)
            {
                return(false);
            }
            this.codeLengthCodeCount += 4;
            this.loopCounter          = 0;
            this.state = InflaterState.ReadingCodeLengthCodes;
Label_0107:
            while (this.loopCounter < this.codeLengthCodeCount)
            {
                int bits = this.input.GetBits(3);
                if (bits < 0)
                {
                    return(false);
                }
                this.codeLengthTreeCodeLength[codeOrder[this.loopCounter]] = (byte)bits;
                this.loopCounter++;
            }
            for (int i = this.codeLengthCodeCount; i < codeOrder.Length; i++)
            {
                this.codeLengthTreeCodeLength[codeOrder[i]] = 0;
            }
            this.codeLengthTree = new HuffmanTree(this.codeLengthTreeCodeLength);
            this.codeArraySize  = this.literalLengthCodeCount + this.distanceCodeCount;
            this.loopCounter    = 0;
            this.state          = InflaterState.ReadingTreeCodesBefore;
Label_0315:
            while (this.loopCounter < this.codeArraySize)
            {
                if ((this.state == InflaterState.ReadingTreeCodesBefore) && ((this.lengthCode = this.codeLengthTree.GetNextSymbol(this.input)) < 0))
                {
                    return(false);
                }
                if (this.lengthCode <= 15)
                {
                    this.codeList[this.loopCounter++] = (byte)this.lengthCode;
                }
                else
                {
                    int num3;
                    if (!this.input.EnsureBitsAvailable(7))
                    {
                        this.state = InflaterState.ReadingTreeCodesAfter;
                        return(false);
                    }
                    if (this.lengthCode == 0x10)
                    {
                        if (this.loopCounter == 0)
                        {
                            throw new InvalidDataException();
                        }
                        byte num4 = this.codeList[this.loopCounter - 1];
                        num3 = this.input.GetBits(2) + 3;
                        if ((this.loopCounter + num3) > this.codeArraySize)
                        {
                            throw new InvalidDataException();
                        }
                        for (int j = 0; j < num3; j++)
                        {
                            this.codeList[this.loopCounter++] = num4;
                        }
                    }
                    else if (this.lengthCode == 0x11)
                    {
                        num3 = this.input.GetBits(3) + 3;
                        if ((this.loopCounter + num3) > this.codeArraySize)
                        {
                            throw new InvalidDataException();
                        }
                        for (int k = 0; k < num3; k++)
                        {
                            this.codeList[this.loopCounter++] = 0;
                        }
                    }
                    else
                    {
                        num3 = this.input.GetBits(7) + 11;
                        if ((this.loopCounter + num3) > this.codeArraySize)
                        {
                            throw new InvalidDataException();
                        }
                        for (int m = 0; m < num3; m++)
                        {
                            this.codeList[this.loopCounter++] = 0;
                        }
                    }
                }
                this.state = InflaterState.ReadingTreeCodesBefore;
            }
            byte[] destinationArray = new byte[0x120];
            byte[] buffer2          = new byte[0x20];
            Array.Copy(this.codeList, 0, destinationArray, 0, this.literalLengthCodeCount);
            Array.Copy(this.codeList, this.literalLengthCodeCount, buffer2, 0, this.distanceCodeCount);
            if (destinationArray[0x100] == 0)
            {
                throw new InvalidDataException();
            }
            this.literalLengthTree = new HuffmanTree(destinationArray);
            this.distanceTree      = new HuffmanTree(buffer2);
            this.state             = InflaterState.DecodeTop;
            return(true);
        }