예제 #1
0
        // Calculate the huffman code for each character based on the code length for each character.
        // This algorithm is described in standard RFC 1951
        private uint[] CalculateHuffmanCode()
        {
            uint[] bitLengthCount = new uint[17];
            foreach (int codeLength in _codeLengthArray)
            {
                bitLengthCount[codeLength]++;
            }
            bitLengthCount[0] = 0; // clear count for length 0

            uint[] nextCode = new uint[17];
            uint   tempCode = 0;

            for (int bits = 1; bits <= 16; bits++)
            {
                tempCode       = (tempCode + bitLengthCount[bits - 1]) << 1;
                nextCode[bits] = tempCode;
            }

            uint[] code = new uint[MaxLiteralTreeElements];
            for (int i = 0; i < _codeLengthArray.Length; i++)
            {
                int len = _codeLengthArray[i];

                if (len > 0)
                {
                    code[i] = DecodeHelper.BitReverse(nextCode[len], len);
                    nextCode[len]++;
                }
            }
            return(code);
        }
예제 #2
0
        public int Inflate(byte[] bytes, int offset, int length)
        {
            // copy bytes from output to outputbytes if we have aviable 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 = _output.CopyTo(bytes, offset, length);
                if (copied > 0)
                {
                    if (_usingGzip)
                    {
                        _crc32 = DecodeHelper.UpdateCrc32(_crc32, bytes, offset, copied);
                        uint n = _streamSize + (uint) copied;
                        if (n < _streamSize)
                        {
                            // overflow, the gzip stream is probably malicious.
                            throw new InvalidDataException("SR.StreamSizeOverflow");
                        }
                        _streamSize = n;
                    }

                    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.VerifyingGZIPFooter)
            {
                // 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)
                {
                    if (_crc32 != _gZipDecoder.Crc32)
                    {
                        throw new InvalidDataException("SR.InvalidCRC");
                    }

                    if (_streamSize != _gZipDecoder.StreamSize)
                    {
                        throw new InvalidDataException("SR.InvalidStreamSize");
                    }
                }
            }

            return count;
        }
예제 #3
0
        //
        // Copy the compressed byte to outputBuffer
        // Returns the bytes we have copied. The caller needs to provide the buffer
        // to avoid extra coping.
        //
        public int GetCompressedOutput(byte[] outputBuffer)
        {
            Debug.Assert(!NeedsInput(), "call SetInput before trying to compress!");

            _output.UpdateBuffer(outputBuffer);
            if (_usingGzip && !_hasGzipHeader)
            {
                // Write the GZIP header only once
                _output.WriteGzipHeader(3);
                _hasGzipHeader = true;
            }

            if (!_hasBlockHeader)
            {
                // Output dynamic block header only once
                _hasBlockHeader = true;
                _output.WritePreamble();
            }

            do
            {
                // read more input data into the window if there is space available
                int bytesToCopy = (_inputBuffer.Count < _inputWindow.FreeWindowSpace) ?
                                  _inputBuffer.Count : _inputWindow.FreeWindowSpace;
                if (bytesToCopy > 0)
                {
                    // copy data into history window
                    _inputWindow.CopyBytes(_inputBuffer.Buffer, _inputBuffer.StartIndex, bytesToCopy);

                    if (_usingGzip)
                    {
                        // update CRC for gzip stream
                        _gzipCrc32 = DecodeHelper.UpdateCrc32(_gzipCrc32, _inputBuffer.Buffer, _inputBuffer.StartIndex, bytesToCopy);

                        uint n = _inputStreamSize + (uint)bytesToCopy;
                        if (n < _inputStreamSize)
                        {  // overflow, gzip doesn't support compressing more than Int32.Maxvalue bytes.
                            throw new InvalidDataException("SR.StreamSizeOverflow");
                        }
                        _inputStreamSize = n;
                    }

                    _inputBuffer.ConsumeBytes(bytesToCopy);
                }

                // compress the bytes in input history window
                while (_inputWindow.BytesAvailable > 0 && _output.SafeToWriteTo())
                {
                    // Find next match. A match can be a symbol,
                    // a distance/length pair, a symbol followed by a distance/Length pair

                    _inputWindow.GetNextSymbolOrMatch(_currentMatch);

                    if (_currentMatch.State == MatchState.HasSymbol)
                    {
                        _output.WriteChar(_currentMatch.Symbol);
                    }
                    else if (_currentMatch.State == MatchState.HasMatch)
                    {
                        _output.WriteMatch(_currentMatch.Length, _currentMatch.Position);
                    }
                    else
                    {
                        _output.WriteChar(_currentMatch.Symbol);
                        _output.WriteMatch(_currentMatch.Length, _currentMatch.Position);
                    }
                }
            } while (_output.SafeToWriteTo() && !NeedsInput());

            // update book keeping needed to write end of block data
            _needsEob = true;

            return(_output.BytesWritten); // number of bytes we have written
        }