예제 #1
0
파일: Inflater.cs 프로젝트: bininc/CommLiby
 private bool HandleBlocksState(CompressionStream stream, out ErrorCode result)
 {
     result     = ErrorCode.Ok;
     this.error = (ErrorCode)this.blocks.Process(stream, (int)this.error);
     if (this.error == ErrorCode.DataError)
     {
         this.state  = InflaterState.Error;
         this.marker = 0;
         return(true);
     }
     if (this.error == ErrorCode.Ok)
     {
         this.error = this.startError;
     }
     if (this.error != ErrorCode.StreamEnd)
     {
         result = this.error;
         return(false);
     }
     this.error = this.startError;
     this.blocks.Reset(stream, this.was);
     if (this.nowrap != 0)
     {
         this.state = InflaterState.Done;
         return(true);
     }
     this.state = InflaterState.CheckFour;
     return(true);
 }
예제 #2
0
파일: Inflater.cs 프로젝트: bininc/CommLiby
        private bool HandleFlagState(CompressionStream stream, out ErrorCode result)
        {
            result = ErrorCode.Ok;
            if (stream.InputCount == 0)
            {
                result = this.error;
                return(false);
            }
            this.error = this.startError;
            --stream.InputCount;
            ++stream.InputTotal;
            int num = (int)stream.Input[stream.InputIndex++] & (int)byte.MaxValue;

            if (((this.method << 8) + num) % 31 != 0)
            {
                this.state          = InflaterState.Error;
                stream.ErrorMessage = "incorrect header check";
                this.marker         = 5;
                return(true);
            }
            if ((num & 32) == 0)
            {
                this.state = InflaterState.Blocks;
                return(true);
            }
            this.state = InflaterState.DictionaryFour;
            return(true);
        }
예제 #3
0
        public void Recycle()
        {
            output.Recycle();
            input.Recycle();
            literalLengthTree = null;
            distanceTree      = null;

            Array.Clear(codeList, 0, codeList.Length);
            Array.Clear(codeLengthTreeCodeLength, 0, codeLengthTreeCodeLength.Length);

            state = InflaterState.ReadingHeader;
            // hasFormatReader = false;
            bfinal    = 0;
            blockType = BlockType.Uncompressed;

            Array.Clear(blockLengthBuffer, 0, blockLengthBuffer.Length);
            blockLength = 0;

            length       = 0;
            distanceCode = 0;
            extraBits    = 0;

            loopCounter            = 0;
            literalLengthCodeCount = 0;
            distanceCodeCount      = 0;
            codeLengthCodeCount    = 0;
            codeArraySize          = 0;
            lengthCode             = 0;

            codeLengthTree = null;
            Reset();
        }
예제 #4
0
파일: Inflater.cs 프로젝트: bininc/CommLiby
 private bool HandleMethodState(CompressionStream stream, out ErrorCode result)
 {
     result = ErrorCode.Ok;
     if (stream.InputCount == 0)
     {
         result = this.error;
         return(false);
     }
     this.error = this.startError;
     --stream.InputCount;
     ++stream.InputTotal;
     if (((this.method = (int)stream.Input[stream.InputIndex++]) & 15) != 8)
     {
         this.state          = InflaterState.Error;
         stream.ErrorMessage = "unknown compression method";
         this.marker         = 5;
         return(true);
     }
     if ((this.method >> 4) + 8 > this.wbits)
     {
         this.state          = InflaterState.Error;
         stream.ErrorMessage = "invalid window size";
         this.marker         = 5;
         return(true);
     }
     this.state = InflaterState.Flag;
     return(true);
 }
예제 #5
0
        public int Inflate(byte[] bytes, int offset, int length)
        {
            // copy bytes from output to outputbytes if we have available bytes
            // if buffer is not filled up. keep decoding until no input are available
            // if decodeBlock returns false. Throw an exception.
            int count = 0;

            do
            {
                int copied = 0;
                if (_uncompressedSize == -1)
                {
                    copied = _output.CopyTo(bytes, offset, length);
                }
                else
                {
                    if (_uncompressedSize > _currentInflatedCount)
                    {
                        length = (int)Math.Min(length, _uncompressedSize - _currentInflatedCount);
                        copied = _output.CopyTo(bytes, offset, length);
                        _currentInflatedCount += copied;
                    }
                    else
                    {
                        _state = InflaterState.Done;
                        _output.ClearBytesUsed();
                    }
                }
                if (copied > 0)
                {
                    if (_hasFormatReader)
                    {
                        _formatReader.UpdateWithBytesRead(bytes, offset, copied);
                    }

                    offset += copied;
                    count  += copied;
                    length -= copied;
                }

                if (length == 0)
                {   // filled in the bytes array
                    break;
                }
                // Decode will return false when more input is needed
            } while (!Finished() && Decode());

            if (_state == InflaterState.VerifyingFooter)
            {  // finished reading CRC
                // In this case finished is true and output window has all the data.
                // But some data in output window might not be copied out.
                if (_output.AvailableBytes == 0)
                {
                    _formatReader.Validate();
                }
            }

            return(count);
        }
예제 #6
0
        private bool DecodeUncompressedBlock(out bool end_of_block)
        {
            end_of_block = false;
            while (true)
            {
                switch (this.state)
                {
                case InflaterState.UncompressedAligning:
                    this.input.SkipToByteBoundary();
                    this.state = InflaterState.UncompressedByte1;
                    goto case InflaterState.UncompressedByte1;

                case InflaterState.UncompressedByte1:
                case InflaterState.UncompressedByte2:
                case InflaterState.UncompressedByte3:
                case InflaterState.UncompressedByte4:
                    int bits = this.input.GetBits(8);
                    if (bits >= 0)
                    {
                        this.blockLengthBuffer[(int)(this.state - 16)] = (byte)bits;
                        if (this.state == InflaterState.UncompressedByte4)
                        {
                            this.blockLength = (int)this.blockLengthBuffer[0] + (int)this.blockLengthBuffer[1] * 256;
                            if ((int)(ushort)this.blockLength != (int)(ushort)~((int)this.blockLengthBuffer[2] + (int)this.blockLengthBuffer[3] * 256))
                            {
                                goto label_6;
                            }
                        }
                        ++this.state;
                        continue;
                    }
                    goto label_3;

                case InflaterState.DecodingUncompressed:
                    goto label_8;

                default:
                    goto label_13;
                }
            }
label_3:
            return(false);

label_6:
            throw new InvalidDataException(SR.GetString("Invalid block length"));
label_8:
            this.blockLength -= this.output.CopyFrom(this.input, this.blockLength);
            if (this.blockLength == 0)
            {
                this.state   = InflaterState.ReadingBFinal;
                end_of_block = true;
                return(true);
            }
            return(this.output.FreeBytes == 0);

label_13:
            Debug.Assert(false, "check why we are here!");
            throw new InvalidDataException(SR.GetString("Unknown state"));
        }
예제 #7
0
파일: Inflater.cs 프로젝트: bininc/CommLiby
 private bool HandleDictionaryZeroState(CompressionStream stream, out ErrorCode result)
 {
     this.state          = InflaterState.Error;
     stream.ErrorMessage = "need dictionary";
     this.marker         = 0;
     result = ErrorCode.StreamError;
     return(false);
 }
예제 #8
0
 private void Reset()
 {
     if (this.hasFormatReader)
     {
         this.state = InflaterState.ReadingHeader;
         return;
     }
     this.state = InflaterState.ReadingBFinal;
 }
예제 #9
0
        private bool DecodeUncompressedBlock(out bool end_of_block)
        {
            end_of_block = false;
            while (true)
            {
                switch (this.state)
                {
                case InflaterState.UncompressedAligning:
                    this.input.SkipToByteBoundary();
                    this.state = InflaterState.UncompressedByte1;
                    goto IL_43;

                case InflaterState.UncompressedByte1:
                case InflaterState.UncompressedByte2:
                case InflaterState.UncompressedByte3:
                case InflaterState.UncompressedByte4:
                    goto IL_43;

                case InflaterState.DecodingUncompressed:
                    goto IL_D6;
                }
                break;
IL_43:
                int bits = this.input.GetBits(8);
                if (bits < 0)
                {
                    return(false);
                }
                this.blockLengthBuffer[this.state - InflaterState.UncompressedByte1] = (byte)bits;
                if (this.state == InflaterState.UncompressedByte4)
                {
                    this.blockLength = (int)this.blockLengthBuffer[0] + (int)this.blockLengthBuffer[1] * 256;
                    int num = (int)this.blockLengthBuffer[2] + (int)this.blockLengthBuffer[3] * 256;
                    if ((ushort)this.blockLength != (ushort)(~(ushort)num))
                    {
                        goto Block_4;
                    }
                }
                this.state++;
            }
            throw new InvalidDataException(SR.GetString("Unknown state"));
Block_4:
            throw new InvalidDataException(SR.GetString("Invalid block length"));
IL_D6:
            int num2 = this.output.CopyFrom(this.input, this.blockLength);

            this.blockLength -= num2;
            if (this.blockLength == 0)
            {
                this.state   = InflaterState.ReadingBFinal;
                end_of_block = true;
                return(true);
            }
            return(this.output.FreeBytes == 0);
        }
예제 #10
0
 private void Reset()
 {
     if (_hasFormatReader)
     {
         _state = InflaterState.ReadingHeader;     // start by reading Header info
     }
     else
     {
         _state = InflaterState.ReadingBFinal;     // start by reading BFinal bit
     }
 }
예제 #11
0
        internal InflaterManaged(bool deflate64, long uncompressedSize)
        {
            _output = new OutputWindow();
            _input  = new InputBuffer();

            _codeList = new byte[HuffmanTree.MaxLiteralTreeElements + HuffmanTree.MaxDistTreeElements];
            _codeLengthTreeCodeLength = new byte[HuffmanTree.NumberOfCodeLengthTreeElements];
            _deflate64        = deflate64;
            _uncompressedSize = uncompressedSize;
            _state            = InflaterState.ReadingBFinal; // start by reading BFinal bit
        }
예제 #12
0
        private bool DecodeUncompressedBlock(out bool end_of_block)
        {
            end_of_block = false;
            while (true)
            {
                switch (this.state)
                {
                case InflaterState.UncompressedAligning:
                    this.input.SkipToByteBoundary();
                    this.state = InflaterState.UncompressedByte1;
                    break;

                case InflaterState.UncompressedByte1:
                case InflaterState.UncompressedByte2:
                case InflaterState.UncompressedByte3:
                case InflaterState.UncompressedByte4:
                    break;

                case InflaterState.DecodingUncompressed:
                {
                    int num3 = this.output.CopyFrom(this.input, this.blockLength);
                    this.blockLength -= num3;
                    if (this.blockLength != 0)
                    {
                        return(this.output.FreeBytes == 0);
                    }
                    this.state   = InflaterState.ReadingBFinal;
                    end_of_block = true;
                    return(true);
                }

                default:
                    throw new InvalidDataException(SR.GetString("UnknownState"));
                }
                int bits = this.input.GetBits(8);
                if (bits < 0)
                {
                    return(false);
                }
                this.blockLengthBuffer[((int)this.state) - 0x10] = (byte)bits;
                if (this.state == InflaterState.UncompressedByte4)
                {
                    this.blockLength = this.blockLengthBuffer[0] + (this.blockLengthBuffer[1] * 0x100);
                    int num2 = this.blockLengthBuffer[2] + (this.blockLengthBuffer[3] * 0x100);
                    if (((ushort)this.blockLength) != ((ushort)~num2))
                    {
                        throw new InvalidDataException(SR.GetString("InvalidBlockLength"));
                    }
                }
                this.state += 1;
            }
        }
예제 #13
0
파일: Inflater.cs 프로젝트: bininc/CommLiby
 private int Reset(CompressionStream stream)
 {
     if (stream == null)
     {
         return(-2);
     }
     stream.InputTotal   = 0L;
     stream.OutputTotal  = 0L;
     stream.ErrorMessage = (string)null;
     this.state          = this.nowrap != 0 ? InflaterState.Blocks : InflaterState.Method;
     this.blocks.Reset(stream, (long[])null);
     return(0);
 }
예제 #14
0
 public void Reset()
 {
     if (this.using_gzip)
     {
         this.gZipDecoder.Reset();
         this.state      = InflaterState.ReadingGZIPHeader;
         this.streamSize = 0;
         this.crc32      = 0;
     }
     else
     {
         this.state = InflaterState.ReadingBFinal;
     }
 }
예제 #15
0
 public void Reset()
 {
     if (using_gzip)
     {
         gZipDecoder.Reset();
         state      = InflaterState.ReadingGZIPHeader; // start by reading GZip Header info
         streamSize = 0;
         crc32      = 0;
     }
     else
     {
         state = InflaterState.ReadingBFinal;       // start by reading BFinal bit
     }
 }
예제 #16
0
 public void Reset()
 {
     if (_usingGzip)
     {
         _gZipDecoder.Reset();
         _state = InflaterState.ReadingGZIPHeader; // start by reading GZip Header info 
         _streamSize = 0;
         _crc32 = 0;
     }
     else
     {
         _state = InflaterState.ReadingBFinal; // start by reading BFinal bit
     }
 }
예제 #17
0
파일: Inflater.cs 프로젝트: bininc/CommLiby
        public int Sync(CompressionStream stream)
        {
            if (stream == null)
            {
                return(-2);
            }
            if (this.state != InflaterState.Error)
            {
                this.state  = InflaterState.Error;
                this.marker = 0;
            }
            int inputCount = stream.InputCount;

            if (inputCount == 0)
            {
                return(-5);
            }
            int inputIndex = stream.InputIndex;
            int index;

            for (index = this.marker; inputCount != 0 && index < 4; --inputCount)
            {
                if ((int)stream.Input[inputIndex] == (int)Inflater.mark[index])
                {
                    ++index;
                }
                else
                {
                    index = stream.Input[inputIndex] == (byte)0 ? 4 - index : 0;
                }
                ++inputIndex;
            }
            stream.InputTotal += (long)(inputIndex - stream.InputIndex);
            stream.InputIndex  = inputIndex;
            stream.InputCount  = inputCount;
            this.marker        = index;
            if (index != 4)
            {
                return(-3);
            }
            long inputTotal  = stream.InputTotal;
            long outputTotal = stream.OutputTotal;

            this.Reset(stream);
            stream.InputTotal  = inputTotal;
            stream.OutputTotal = outputTotal;
            this.state         = InflaterState.Blocks;
            return(0);
        }
예제 #18
0
파일: Inflater.cs 프로젝트: bininc/CommLiby
 private bool HandleCheckTwoState(CompressionStream stream, out ErrorCode result)
 {
     result = ErrorCode.Ok;
     if (stream.InputCount == 0)
     {
         result = this.error;
         return(false);
     }
     this.error = this.startError;
     --stream.InputCount;
     ++stream.InputTotal;
     this.need += (uint)((ulong)(((int)stream.Input[stream.InputIndex++] & (int)byte.MaxValue) << 8) & 65280UL);
     this.state = InflaterState.CheckOne;
     return(true);
 }
예제 #19
0
파일: Inflater.cs 프로젝트: bininc/CommLiby
 private bool HandleCheckFourState(CompressionStream stream, out ErrorCode result)
 {
     result = ErrorCode.Ok;
     if (stream.InputCount == 0)
     {
         result = this.error;
         return(false);
     }
     this.error = this.startError;
     --stream.InputCount;
     ++stream.InputTotal;
     this.need  = (uint)(((int)stream.Input[stream.InputIndex++] & (int)byte.MaxValue) << 24 & -16777216);
     this.state = InflaterState.CheckThree;
     return(true);
 }
예제 #20
0
파일: Inflater.cs 프로젝트: bininc/CommLiby
 private bool HandleDictionaryThreeState(CompressionStream stream, out ErrorCode result)
 {
     result = ErrorCode.Ok;
     if (stream.InputCount == 0)
     {
         result = this.error;
         return(false);
     }
     this.error = this.startError;
     --stream.InputCount;
     ++stream.InputTotal;
     this.need += (uint)((ulong)(((int)stream.Input[stream.InputIndex++] & (int)byte.MaxValue) << 16) & 16711680UL);
     this.state = InflaterState.DictionaryTwo;
     return(true);
 }
예제 #21
0
파일: Inflater.cs 프로젝트: bininc/CommLiby
 private bool HandleDictionaryOneState(CompressionStream stream, out ErrorCode result)
 {
     result = ErrorCode.Ok;
     if (stream.InputCount == 0)
     {
         result = this.error;
         return(false);
     }
     this.error = this.startError;
     --stream.InputCount;
     ++stream.InputTotal;
     this.need      += (uint)((ulong)stream.Input[stream.InputIndex++] & (ulong)byte.MaxValue);
     stream.Checksum = new Adler32(this.need);
     this.state      = InflaterState.DictionaryZero;
     result          = ErrorCode.NeedsDictionary;
     return(false);
 }
예제 #22
0
        public int Inflate(byte[] bytes, int offset, int length)
        {
            // copy bytes from output to outputbytes if we have available bytes
            // if buffer is not filled up. keep decoding until no input are available
            // if decodeBlock returns false. Throw an exception.
            int count = 0;

            do
            {
                int copied = 0;
                if (_uncompressedSize == -1)
                {
                    copied = _output.CopyTo(bytes, offset, length);
                }
                else
                {
                    if (_uncompressedSize > _currentInflatedCount)
                    {
                        length = (int)Math.Min(length, _uncompressedSize - _currentInflatedCount);
                        copied = _output.CopyTo(bytes, offset, length);
                        _currentInflatedCount += copied;
                    }
                    else
                    {
                        _state = InflaterState.Done;
                        _output.ClearBytesUsed();
                    }
                }
                if (copied > 0)
                {
                    offset += copied;
                    count  += copied;
                    length -= copied;
                }

                if (length == 0)
                {   // filled in the bytes array
                    break;
                }
                // Decode will return false when more input is needed
            } while (!Finished() && Decode());

            return(count);
        }
예제 #23
0
        public int Inflate(Span <byte> bytes)
        {
            // copy bytes from output to outputbytes if we have available bytes
            // if buffer is not filled up. keep decoding until no input are available
            // if decodeBlock returns false. Throw an exception.
            int count = 0;

            do
            {
                int copied = 0;
                if (_uncompressedSize == -1)
                {
                    copied = _output.CopyTo(bytes);
                }
                else
                {
                    if (_uncompressedSize > _currentInflatedCount)
                    {
                        bytes  = bytes.Slice(0, (int)Math.Min(bytes.Length, _uncompressedSize - _currentInflatedCount));
                        copied = _output.CopyTo(bytes);
                        _currentInflatedCount += copied;
                    }
                    else
                    {
                        _state = InflaterState.Done;
                        _output.ClearBytesUsed();
                    }
                }
                if (copied > 0)
                {
                    bytes  = bytes.Slice(copied, bytes.Length - copied);
                    count += copied;
                }

                if (bytes.IsEmpty)
                {
                    // filled in the bytes buffer
                    break;
                }
                // Decode will return false when more input is needed
            } while (!Finished() && Decode());

            return(count);
        }
예제 #24
0
파일: Inflater.cs 프로젝트: bininc/CommLiby
 private bool HandleCheckOneState(CompressionStream stream, out ErrorCode result)
 {
     result = ErrorCode.Ok;
     if (stream.InputCount == 0)
     {
         result = this.error;
         return(false);
     }
     this.error = this.startError;
     --stream.InputCount;
     ++stream.InputTotal;
     this.need += (uint)((ulong)stream.Input[stream.InputIndex++] & (ulong)byte.MaxValue);
     if ((int)this.was[0] != (int)this.need)
     {
         this.state          = InflaterState.Error;
         stream.ErrorMessage = "incorrect data check";
         this.marker         = 5;
         return(true);
     }
     this.state = InflaterState.Done;
     return(true);
 }
예제 #25
0
파일: Inflater.cs 프로젝트: bininc/CommLiby
        public int SetDictionary(CompressionStream stream, byte[] dictionary, int dictLength)
        {
            int start = 0;
            int n     = dictLength;

            if (stream == null || this.state != InflaterState.DictionaryZero)
            {
                return(-2);
            }
            if (Adler32.Get(dictionary, 0, dictLength) != stream.Checksum.Get())
            {
                return(-3);
            }
            stream.Checksum = new Adler32();
            if (n >= 1 << this.wbits)
            {
                n     = (1 << this.wbits) - 1;
                start = dictLength - n;
            }
            this.blocks.SetDictionary(dictionary, start, n);
            this.state = InflaterState.Blocks;
            return(0);
        }
예제 #26
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("Deflate64: unknown block type");
                }
            }

            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("Deflate64: unknown block type");
            }

            //
            // 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);
        }
예제 #27
0
 private void Reset()
 {
     _state =                              //_hasFormatReader ?
                                           //InflaterState.ReadingHeader :   // start by reading Header info
              InflaterState.ReadingBFinal; // start by reading BFinal bit
 }
예제 #28
0
파일: Inflater.cs 프로젝트: neatstudio/oh
        private bool DecodeBlock(out bool end_of_block_code_seen)
        {
            end_of_block_code_seen = false;
            int freeBytes = this.output.FreeBytes;
            while (freeBytes > 0x102) {
                int nextSymbol;
                int num4;
                switch (this.state) {
                    case InflaterState.DecodeTop:
                        nextSymbol = this.literalLengthTree.GetNextSymbol(this.input);
                        if (nextSymbol >= 0) {
                            break;
                        }
                        return false;

                    case InflaterState.HaveInitialLength:
                        goto Label_00C6;

                    case InflaterState.HaveFullLength:
                        goto Label_010B;

                    case InflaterState.HaveDistCode:
                        goto Label_016D;

                    default:
                        throw new InvalidDataException("Decoder is in some unknown state. This might be caused by corrupted data.");
                }
                if (nextSymbol < 0x100) {
                    this.output.Write((byte)nextSymbol);
                    freeBytes--;
                    continue;
                }
                if (nextSymbol == 0x100) {
                    end_of_block_code_seen = true;
                    this.state = InflaterState.ReadingBFinal;
                    return true;
                }
                nextSymbol -= 0x101;
                if (nextSymbol < 8) {
                    nextSymbol += 3;
                    this.extraBits = 0;
                }
                else if (nextSymbol == 0x1c) {
                    nextSymbol = 0x102;
                    this.extraBits = 0;
                }
                else {
                    this.extraBits = extraLengthBits[nextSymbol];
                }
                this.length = nextSymbol;
            Label_00C6:
                if (this.extraBits > 0) {
                    this.state = InflaterState.HaveInitialLength;
                    int bits = this.input.GetBits(this.extraBits);
                    if (bits < 0) {
                        return false;
                    }
                    this.length = lengthBase[this.length] + bits;
                }
                this.state = InflaterState.HaveFullLength;
            Label_010B:
                if (this.blockType == BlockType.Dynamic) {
                    this.distanceCode = this.distanceTree.GetNextSymbol(this.input);
                }
                else {
                    this.distanceCode = this.input.GetBits(5);
                    if (this.distanceCode >= 0) {
                        this.distanceCode = staticDistanceTreeTable[this.distanceCode];
                    }
                }
                if (this.distanceCode < 0) {
                    return false;
                }
                this.state = InflaterState.HaveDistCode;
            Label_016D:
                if (this.distanceCode > 3) {
                    this.extraBits = (this.distanceCode - 2) >> 1;
                    int num5 = this.input.GetBits(this.extraBits);
                    if (num5 < 0) {
                        return false;
                    }
                    num4 = distanceBasePosition[this.distanceCode] + num5;
                }
                else {
                    num4 = this.distanceCode + 1;
                }
                this.output.WriteLengthDistance(this.length, num4);
                freeBytes -= this.length;
                this.state = InflaterState.DecodeTop;
            }
            return true;
        }
예제 #29
0
        bool DecodeBlock(out bool end_of_block_code_seen) {
            end_of_block_code_seen = false;

            int freeBytes = output.FreeBytes;   // it is a little bit faster than frequently accessing the property 
            while(freeBytes > 258) { 
                // 258 means we can safely do decoding since maximum repeat length is 258

                int symbol;
                switch (state) {
                case InflaterState.DecodeTop:

                    symbol = literalLengthTree.GetNextSymbol(input);
                    if( symbol < 0) {          // running out of input
                        return false;
                    }

                    if (symbol < 256) {        // literal
                        output.Write((byte)symbol);
                        --freeBytes;
                    } 
                    else if( symbol == 256) { // end of block
                        end_of_block_code_seen = true;
                        Debug.WriteLineIf(CompressionTracingSwitch.Informational, "End of Block", "Compression");                                                                                        
                        // Reset state
                        state = InflaterState.ReadingBFinal;                                      
                        return true;           // ***********
                    }
                    else {                 // length/distance pair
                        symbol -= 257;     // length code started at 257
                        if( symbol < 8) {
                            symbol += 3;   // match length = 3,4,5,6,7,8,9,10
                            extraBits = 0;
                        }
                        else if( symbol == 28) { // extra bits for code 285 is 0 
                            symbol = 258;             // code 285 means length 258    
                            extraBits = 0;                            
                        }
                        else {
                            extraBits = extraLengthBits[symbol];
                            Debug.Assert(extraBits != 0, "We handle other cases seperately!"); 
                        }
                        length = symbol;
                        goto case InflaterState.HaveInitialLength;
                    }
                    break;

                case InflaterState.HaveInitialLength:
                    if( extraBits > 0) {
                        state = InflaterState.HaveInitialLength;
                        int bits = input.GetBits(extraBits);
                        if( bits < 0) {
                            return false;
                        }
                        length = lengthBase[length] + bits;
                    }
                    state = InflaterState.HaveFullLength;                
                    goto case InflaterState.HaveFullLength;

                case InflaterState.HaveFullLength:
                    if( blockType == BlockType.Dynamic) {
                        distanceCode = distanceTree.GetNextSymbol(input);   
                    }
                    else {   // get distance code directly for static block
                        distanceCode = input.GetBits(5);   
                        if( distanceCode >= 0 ) {
                            distanceCode = staticDistanceTreeTable[distanceCode];
                        }                        
                    }

                    if( distanceCode < 0) { // running out input                    
                        return false;
                    }

                    state = InflaterState.HaveDistCode;
                    goto case InflaterState.HaveDistCode;

                case InflaterState.HaveDistCode:
                    // To avoid a table lookup we note that for distanceCode >= 2,
                    // extra_bits = (distanceCode-2) >> 1
                    int offset;
                    if( distanceCode > 3) {
                        extraBits = (distanceCode-2) >> 1;
                        int bits = input.GetBits(extraBits);
                        if( bits < 0 ) {
                            return false;
                        }
                        offset = distanceBasePosition[distanceCode] + bits;
                    }
                    else {
                        offset = distanceCode + 1;
                    }

                    Debug.Assert(freeBytes>= 258, "following operation is not safe!");
                    output.WriteLengthDistance(length, offset);
                    freeBytes -= length;
                    state = InflaterState.DecodeTop;
                    break;

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

            return true;
        }
예제 #30
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;
        }
예제 #31
0
 public void Reset() {
     if ( using_gzip) {
         gZipDecoder.Reset();
         state   = InflaterState.ReadingGZIPHeader; // start by reading GZip Header info
         streamSize = 0;
         crc32 = 0;
     } 
     else {
         state   = InflaterState.ReadingBFinal;     // start by reading BFinal bit 
     }
 }
예제 #32
0
파일: Inflater.cs 프로젝트: neatstudio/oh
        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;
        }
예제 #33
0
파일: Inflater.cs 프로젝트: neatstudio/oh
        private bool DecodeUncompressedBlock(out bool end_of_block)
        {
            end_of_block = false;
            while (true) {
                switch (this.state) {
                    case InflaterState.UncompressedAligning:
                        this.input.SkipToByteBoundary();
                        this.state = InflaterState.UncompressedByte1;
                        break;

                    case InflaterState.UncompressedByte1:
                    case InflaterState.UncompressedByte2:
                    case InflaterState.UncompressedByte3:
                    case InflaterState.UncompressedByte4:
                        break;

                    case InflaterState.DecodingUncompressed: {
                            int num3 = this.output.CopyFrom(this.input, this.blockLength);
                            this.blockLength -= num3;
                            if (this.blockLength != 0) {
                                return (this.output.FreeBytes == 0);
                            }
                            this.state = InflaterState.ReadingBFinal;
                            end_of_block = true;
                            return true;
                        }
                    default:
                        throw new InvalidDataException("Decoder is in some unknown state. This might be caused by corrupted data.");
                }
                int bits = this.input.GetBits(8);
                if (bits < 0) {
                    return false;
                }
                this.blockLengthBuffer[((int)this.state) - 0x10] = (byte)bits;
                if (this.state == InflaterState.UncompressedByte4) {
                    this.blockLength = this.blockLengthBuffer[0] + (this.blockLengthBuffer[1] * 0x100);
                    int num2 = this.blockLengthBuffer[2] + (this.blockLengthBuffer[3] * 0x100);
                    if (((ushort)this.blockLength) != ((ushort)~num2)) {
                        throw new InvalidDataException("Block length does not match with its complement.");
                    }
                }
                this.state += 1;
            }
        }
예제 #34
0
파일: Inflater.cs 프로젝트: neatstudio/oh
 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;
 }
예제 #35
0
        private bool DecodeBlock(out bool end_of_block_code_seen)
        {
            end_of_block_code_seen = false;

            int freeBytes = _output.FreeBytes;   // it is a little bit faster than frequently accessing the property 
            while (freeBytes > 258)
            {
                // 258 means we can safely do decoding since maximum repeat length is 258

                int symbol;
                switch (_state)
                {
                    case InflaterState.DecodeTop:
                        // decode an element from the literal tree

                        // TODO: optimize this!!!
                        symbol = _literalLengthTree.GetNextSymbol(_input);
                        if (symbol < 0)
                        {          // running out of input
                            return false;
                        }

                        if (symbol < 256)
                        {        // literal
                            _output.Write((byte)symbol);
                            --freeBytes;
                        }
                        else if (symbol == 256)
                        { // end of block
                            end_of_block_code_seen = true;
                            // Reset state
                            _state = InflaterState.ReadingBFinal;
                            return true;           // ***********
                        }
                        else
                        {                 // length/distance pair
                            symbol -= 257;     // length code started at 257
                            if (symbol < 8)
                            {
                                symbol += 3;   // match length = 3,4,5,6,7,8,9,10
                                _extraBits = 0;
                            }
                            else if (!_deflate64 && symbol == 28)
                            { // extra bits for code 285 is 0 
                                symbol = 258;             // code 285 means length 258
                                _extraBits = 0;
                            }
                            else
                            {
                                if (symbol < 0 || symbol >= s_extraLengthBits.Length)
                                {
                                    throw new InvalidDataException(SR.GenericInvalidData);
                                }
                                _extraBits = s_extraLengthBits[symbol];
                                Debug.Assert(_extraBits != 0, "We handle other cases seperately!");
                            }
                            _length = symbol;
                            goto case InflaterState.HaveInitialLength;
                        }
                        break;

                    case InflaterState.HaveInitialLength:
                        if (_extraBits > 0)
                        {
                            _state = InflaterState.HaveInitialLength;
                            int bits = _input.GetBits(_extraBits);
                            if (bits < 0)
                            {
                                return false;
                            }

                            if (_length < 0 || _length >= s_lengthBase.Length)
                            {
                                throw new InvalidDataException(SR.GenericInvalidData);
                            }
                            _length = s_lengthBase[_length] + bits;
                        }
                        _state = InflaterState.HaveFullLength;
                        goto case InflaterState.HaveFullLength;

                    case InflaterState.HaveFullLength:
                        if (_blockType == BlockType.Dynamic)
                        {
                            _distanceCode = _distanceTree.GetNextSymbol(_input);
                        }
                        else
                        {   // get distance code directly for static block
                            _distanceCode = _input.GetBits(5);
                            if (_distanceCode >= 0)
                            {
                                _distanceCode = s_staticDistanceTreeTable[_distanceCode];
                            }
                        }

                        if (_distanceCode < 0)
                        { // running out input                    
                            return false;
                        }

                        _state = InflaterState.HaveDistCode;
                        goto case InflaterState.HaveDistCode;

                    case InflaterState.HaveDistCode:
                        // To avoid a table lookup we note that for distanceCode >= 2,
                        // extra_bits = (distanceCode-2) >> 1
                        int offset;
                        if (_distanceCode > 3)
                        {
                            _extraBits = (_distanceCode - 2) >> 1;
                            int bits = _input.GetBits(_extraBits);
                            if (bits < 0)
                            {
                                return false;
                            }
                            offset = s_distanceBasePosition[_distanceCode] + bits;
                        }
                        else
                        {
                            offset = _distanceCode + 1;
                        }

                        Debug.Assert(freeBytes >= 258, "following operation is not safe!");
                        _output.WriteLengthDistance(_length, offset);
                        freeBytes -= _length;
                        _state = InflaterState.DecodeTop;
                        break;

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

            return true;
        }
예제 #36
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;
        }
예제 #37
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_CODE_ORDER[_loopCounter]] = (byte)bits;
                    ++_loopCounter;
                }

                for (int i = _codeLengthCodeCount; i < S_CODE_ORDER.Length; i++)
                {
                    _codeLengthTreeCodeLength[S_CODE_ORDER[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*/ Assert(false, "check why we are here!");
                throw new InvalidDataException("Deflate64: unknown state");
            }

            byte[] literalTreeCodeLength  = new byte[HuffmanTree.MAX_LITERAL_TREE_ELEMENTS];
            byte[] distanceTreeCodeLength = new byte[HuffmanTree.MAX_DIST_TREE_ELEMENTS];

            // 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.END_OF_BLOCK_CODE] == 0)
            {
                throw new InvalidDataException();
            }

            _literalLengthTree = new HuffmanTree(literalTreeCodeLength);
            _distanceTree      = new HuffmanTree(distanceTreeCodeLength);
            _state             = InflaterState.DecodeTop;
            return(true);
        }
예제 #38
0
        // Format of Non-compressed blocks (BTYPE=00):
        //
        // Any bits of input up to the next byte boundary are ignored.
        // The rest of the block consists of the following information:
        //
        //     0   1   2   3   4...
        //   +---+---+---+---+================================+
        //   |  LEN  | NLEN  |... LEN bytes of literal data...|
        //   +---+---+---+---+================================+
        //
        // LEN is the number of data bytes in the block.  NLEN is the
        // one's complement of LEN.
        private bool DecodeUncompressedBlock(out bool endOfBlock)
        {
            endOfBlock = false;
            while (true)
            {
                switch (_state)
                {
                case InflaterState.UncompressedAligning:     // initial state when calling this function
                                                             // we must skip to a byte boundary
                    _input.SkipToByteBoundary();
                    _state = InflaterState.UncompressedByte1;
                    goto case InflaterState.UncompressedByte1;

                case InflaterState.UncompressedByte1:       // decoding block length
                case InflaterState.UncompressedByte2:
                case InflaterState.UncompressedByte3:
                case InflaterState.UncompressedByte4:
                    int bits = _input.GetBits(8);
                    if (bits < 0)
                    {
                        return(false);
                    }

                    _blockLengthBuffer[_state - InflaterState.UncompressedByte1] = (byte)bits;
                    if (_state == InflaterState.UncompressedByte4)
                    {
                        _blockLength = _blockLengthBuffer[0] + ((int)_blockLengthBuffer[1]) * 256;
                        int blockLengthComplement = _blockLengthBuffer[2] + ((int)_blockLengthBuffer[3]) * 256;

                        // make sure complement matches
                        if ((ushort)_blockLength != (ushort)(~blockLengthComplement))
                        {
                            throw new InvalidDataException("Deflate64: invalid block length");
                        }
                    }

                    _state += 1;
                    break;

                case InflaterState.DecodingUncompressed:     // copying block data

                    // Directly copy bytes from input to output.
                    int bytesCopied = _output.CopyFrom(_input, _blockLength);
                    _blockLength -= bytesCopied;

                    if (_blockLength == 0)
                    {
                        // Done with this block, need to re-init bit buffer for next block
                        _state     = InflaterState.ReadingBFinal;
                        endOfBlock = true;
                        return(true);
                    }

                    // We can fail to copy all bytes for two reasons:
                    //    Running out of Input
                    //    running out of free space in output window
                    if (_output.FreeBytes == 0)
                    {
                        return(true);
                    }

                    return(false);

                default:
                    Debug./*Fail*/ Assert(false, "check why we are here!");
                    throw new InvalidDataException("Deflate64: unknown state");
                }
            }
        }
예제 #39
0
        private bool DecodeBlock(out bool endOfBlockCodeSeen)
        {
            endOfBlockCodeSeen = false;

            int freeBytes = _output.FreeBytes;   // it is a little bit faster than frequently accessing the property

            while (freeBytes > 65536)
            {
                // With Deflate64 we can have up to a 64kb length, so we ensure at least that much space is available
                // in the OutputWindow to avoid overwriting previous unflushed output data.

                int symbol;
                switch (_state)
                {
                case InflaterState.DecodeTop:
                    // decode an element from the literal tree

                    // TODO: optimize this!!!
                    symbol = _literalLengthTree.GetNextSymbol(_input);
                    if (symbol < 0)
                    {
                        // running out of input
                        return(false);
                    }

                    if (symbol < 256)
                    {
                        // literal
                        _output.Write((byte)symbol);
                        --freeBytes;
                    }
                    else if (symbol == 256)
                    {
                        // end of block
                        endOfBlockCodeSeen = true;
                        // Reset state
                        _state = InflaterState.ReadingBFinal;
                        return(true);
                    }
                    else
                    {
                        // length/distance pair
                        symbol -= 257;         // length code started at 257
                        if (symbol < 8)
                        {
                            symbol    += 3;    // match length = 3,4,5,6,7,8,9,10
                            _extraBits = 0;
                        }
                        else if (!_deflate64 && symbol == 28)
                        {
                            // extra bits for code 285 is 0
                            symbol     = 258;             // code 285 means length 258
                            _extraBits = 0;
                        }
                        else
                        {
                            if (symbol < 0 || symbol >= S_EXTRA_LENGTH_BITS.Length)
                            {
                                throw new InvalidDataException("Deflate64: invalid data");
                            }
                            _extraBits = S_EXTRA_LENGTH_BITS[symbol];
                            Debug.Assert(_extraBits != 0, "We handle other cases separately!");
                        }
                        _length = symbol;
                        goto case InflaterState.HaveInitialLength;
                    }
                    break;

                case InflaterState.HaveInitialLength:
                    if (_extraBits > 0)
                    {
                        _state = InflaterState.HaveInitialLength;
                        int bits = _input.GetBits(_extraBits);
                        if (bits < 0)
                        {
                            return(false);
                        }

                        if (_length < 0 || _length >= S_LENGTH_BASE.Length)
                        {
                            throw new InvalidDataException("Deflate64: invalid data");
                        }
                        _length = S_LENGTH_BASE[_length] + bits;
                    }
                    _state = InflaterState.HaveFullLength;
                    goto case InflaterState.HaveFullLength;

                case InflaterState.HaveFullLength:
                    if (_blockType == BlockType.Dynamic)
                    {
                        _distanceCode = _distanceTree.GetNextSymbol(_input);
                    }
                    else
                    {
                        // get distance code directly for static block
                        _distanceCode = _input.GetBits(5);
                        if (_distanceCode >= 0)
                        {
                            _distanceCode = S_STATIC_DISTANCE_TREE_TABLE[_distanceCode];
                        }
                    }

                    if (_distanceCode < 0)
                    {
                        // running out input
                        return(false);
                    }

                    _state = InflaterState.HaveDistCode;
                    goto case InflaterState.HaveDistCode;

                case InflaterState.HaveDistCode:
                    // To avoid a table lookup we note that for distanceCode > 3,
                    // extra_bits = (distanceCode-2) >> 1
                    int offset;
                    if (_distanceCode > 3)
                    {
                        _extraBits = (_distanceCode - 2) >> 1;
                        int bits = _input.GetBits(_extraBits);
                        if (bits < 0)
                        {
                            return(false);
                        }
                        offset = S_DISTANCE_BASE_POSITION[_distanceCode] + bits;
                    }
                    else
                    {
                        offset = _distanceCode + 1;
                    }

                    _output.WriteLengthDistance(_length, offset);
                    freeBytes -= _length;
                    _state     = InflaterState.DecodeTop;
                    break;

                default:
                    Debug./*Fail*/ Assert(false, "check why we are here!");
                    throw new InvalidDataException("Deflate64: unknown state");
                }
            }

            return(true);
        }
 private void Reset()
 {
     if (this.hasFormatReader)
     {
         this.state = InflaterState.ReadingHeader;
     }
     else
     {
         this.state = InflaterState.ReadingBFinal;
     }
 }
예제 #41
0
 private void Reset()
 {
     if (_hasFormatReader)
     {
         _state = InflaterState.ReadingHeader;     // start by reading Header info
     }
     else
     {
         _state = InflaterState.ReadingBFinal;     // start by reading BFinal bit 
     }
 }
예제 #42
0
 private void Reset()
 {
     _state = _hasFormatReader ? InflaterState.ReadingHeader : InflaterState.ReadingBFinal;
 }
예제 #43
0
        // Format of Non-compressed blocks (BTYPE=00):
        //
        // Any bits of input up to the next byte boundary are ignored.
        // The rest of the block consists of the following information:
        //
        //     0   1   2   3   4...
        //   +---+---+---+---+================================+
        //   |  LEN  | NLEN  |... LEN bytes of literal data...|
        //   +---+---+---+---+================================+
        // 
        // LEN is the number of data bytes in the block.  NLEN is the
        // one's complement of LEN.

        private bool DecodeUncompressedBlock(out bool end_of_block)
        {
            end_of_block = false;
            while (true)
            {
                switch (_state)
                {
                    case InflaterState.UncompressedAligning: // intial state when calling this function
                                                             // we must skip to a byte boundary
                        _input.SkipToByteBoundary();
                        _state = InflaterState.UncompressedByte1;
                        goto case InflaterState.UncompressedByte1;

                    case InflaterState.UncompressedByte1:   // decoding block length 
                    case InflaterState.UncompressedByte2:
                    case InflaterState.UncompressedByte3:
                    case InflaterState.UncompressedByte4:
                        int bits = _input.GetBits(8);
                        if (bits < 0)
                        {
                            return false;
                        }

                        _blockLengthBuffer[_state - InflaterState.UncompressedByte1] = (byte)bits;
                        if (_state == InflaterState.UncompressedByte4)
                        {
                            _blockLength = _blockLengthBuffer[0] + ((int)_blockLengthBuffer[1]) * 256;
                            int blockLengthComplement = _blockLengthBuffer[2] + ((int)_blockLengthBuffer[3]) * 256;

                            // make sure complement matches
                            if ((ushort)_blockLength != (ushort)(~blockLengthComplement))
                            {
                                throw new InvalidDataException(SR.InvalidBlockLength);
                            }
                        }

                        _state += 1;
                        break;

                    case InflaterState.DecodingUncompressed: // copying block data 

                        // Directly copy bytes from input to output. 
                        int bytesCopied = _output.CopyFrom(_input, _blockLength);
                        _blockLength -= bytesCopied;

                        if (_blockLength == 0)
                        {
                            // Done with this block, need to re-init bit buffer for next block
                            _state = InflaterState.ReadingBFinal;
                            end_of_block = true;
                            return true;
                        }

                        // We can fail to copy all bytes for two reasons:
                        //    Running out of Input 
                        //    running out of free space in output window
                        if (_output.FreeBytes == 0)
                        {
                            return true;
                        }

                        return false;

                    default:
                        Debug.Assert(false, "check why we are here!");
                        throw new InvalidDataException(SR.UnknownState);
                }
            }
        }
예제 #44
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()
        {
            var eob = false;
            var result = false;

            if (Finished())
            {
                return true;
            }

            if (_hasFormatReader)
            {
                switch (_state)
                {
                    case InflaterState.ReadingHeader:
                        if (!_formatReader.ReadHeader(_input))
                        {
                            return false;
                        }
                        _state = InflaterState.ReadingBFinal;
                        break;

                    case InflaterState.ReadingFooter:
                    case InflaterState.StartReadingFooter:
                        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);
                switch (_blockType)
                {
                    case BlockType.Dynamic:
                        _state = InflaterState.ReadingNumLitCodes;
                        break;
                    case BlockType.Static:
                        _literalLengthTree = HuffmanTree.StaticLiteralLengthTree;
                        _distanceTree = HuffmanTree.StaticDistanceTree;
                        _state = InflaterState.DecodeTop;
                        break;
                    case BlockType.Uncompressed:
                        _state = InflaterState.UncompressedAligning;
                        break;
                    default:
                        throw new InvalidDataContractException("Unknown block type.");
                }
            }

            switch (_blockType)
            {
                case BlockType.Dynamic:
                    result = _state < InflaterState.DecodeTop ? DecodeDynamicBlockHeader() : DecodeBlock(out eob);
                    break;
                case BlockType.Static:
                    result = DecodeBlock(out eob);
                    break;
                case BlockType.Uncompressed:
                    result = DecodeUncompressedBlock(out eob);
                    break;
                default:
                    throw new InvalidDataContractException("Unknown block type.");
            }

            //
            // If we reached the end of the block and the block we were decoding had
            // bfinal=1 (final block)
            //
            if (!eob || (_bfinal == 0))
                return result;
            _state = _hasFormatReader ? InflaterState.StartReadingFooter : InflaterState.Done;
            return result;
        }
예제 #45
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;
        }
예제 #46
0
파일: Inflater.cs 프로젝트: neatstudio/oh
 public void Reset()
 {
     if (this.using_gzip) {
         this.gZipDecoder.Reset();
         this.state = InflaterState.ReadingGZIPHeader;
         this.streamSize = 0;
         this.crc32 = 0;
     }
     else {
         this.state = InflaterState.ReadingBFinal;
     }
 }