Beispiel #1
0
        /// <summary>
        /// Reads a number of decompressed bytes into the specified byte array.
        /// </summary>
        /// <param name="buffer">The array to store decompressed bytes.</param>
        /// <param name="offset">The byte offset in <paramref name="buffer"/> at which the read bytes will be placed.</param>
        /// <param name="count">The maximum number of decompressed bytes to read.</param>
        /// <returns>The number of bytes that were read into the byte array.</returns>
        public override int Read(byte[] buffer, int offset, int count) {
            if (_mode != CompressionMode.Decompress)
                throw new InvalidOperationException("Read is only supported in Decompress mode");

            EnsureNotDisposed();
            ValidateParameters(buffer, offset, count);

            int totalWritten = 0;
            while (offset < buffer.Length && _lastDecoderState != Brotli.BrotliDecoderResult.BROTLI_DECODER_RESULT_SUCCESS) {
                if (_lastDecoderState == Brotli.BrotliDecoderResult.BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT) {
                    if (_bufferCount > 0 && _bufferOffset != 0) {
                        Array.Copy(_buffer, _bufferOffset, _buffer, 0, _bufferCount);
                    }
                    _bufferOffset = 0;

                    int numRead = 0;
                    while (_bufferCount < _buffer.Length && ((numRead = _stream.Read(_buffer, _bufferCount, _buffer.Length - _bufferCount)) > 0)) {
                        _bufferCount += numRead;
                        if (_bufferCount > _buffer.Length)
                            throw new InvalidDataException("Invalid input stream detected, more bytes supplied than expected.");
                    }

                    if (_bufferCount <= 0)
                        break;
                }

                size_t available_in = _bufferCount;
                size_t available_in_old = available_in;
                size_t available_out = count;
                size_t available_out_old = available_out;

                fixed (byte* out_buf_ptr = buffer)
                fixed (byte* in_buf_ptr = _buffer) {
                    byte* in_buf = in_buf_ptr + _bufferOffset;
                    byte* out_buf = out_buf_ptr + offset;
                    _lastDecoderState = Brotli.BrotliDecoderDecompressStream(ref _decoderState, &available_in, &in_buf,
                        &available_out, &out_buf, null);
                }

                if (_lastDecoderState == Brotli.BrotliDecoderResult.BROTLI_DECODER_RESULT_ERROR)
                    throw new InvalidDataException("Decompression failed with error code: " + _decoderState.error_code);

                size_t bytesConsumed = available_in_old - available_in;
                size_t bytesWritten = available_out_old - available_out;

                if (bytesConsumed > 0) {
                    _bufferOffset += (int) bytesConsumed;
                    _bufferCount -= (int) bytesConsumed;
                }

                if (bytesWritten > 0) {
                    totalWritten += (int)bytesWritten;
                    offset += (int)bytesWritten;
                    count -= (int)bytesWritten;
                }
            }

            return totalWritten;
        }
Beispiel #2
0
        /// <summary>
        /// Reads a number of decompressed bytes into the specified byte array.
        /// </summary>
        /// <param name="buffer">The array to store decompressed bytes.</param>
        /// <param name="offset">The byte offset in <paramref name="buffer"/> at which the read bytes will be placed.</param>
        /// <param name="count">The maximum number of decompressed bytes to read.</param>
        /// <returns>The number of bytes that were read into the byte array.</returns>
        public override int Read(byte[] buffer, int offset, int count)
        {
            if (_mode != CompressionMode.Decompress)
            {
                throw new InvalidOperationException("Read is only supported in Decompress mode");
            }

            EnsureNotDisposed();
            ValidateParameters(buffer, offset, count);

            bool endOfStream = false;

            byte[] in_buf = new byte[0xffff];
            size_t available_in = 0, available_out = count;

            fixed(byte *in_buf_ptr = in_buf)
            fixed(byte *buf_ptr = buffer)
            {
                byte *next_in  = in_buf_ptr;
                byte *next_out = buf_ptr + offset;
                int   total    = 0;

                while (true)
                {
                    if (_lastDecoderState == Brotli.BrotliDecoderResult.BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT)
                    {
                        int len = _stream.Read(in_buf, 0, in_buf.Length);
                        if (len <= 0)
                        {
                            endOfStream = true;
                            break;
                        }
                        available_in = len;
                        next_in      = in_buf_ptr;
                    }
                    else if (_lastDecoderState == Brotli.BrotliDecoderResult.BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT)
                    {
                        /* Ignore */
                    }
                    else
                    {
                        endOfStream = true;
                        break;
                    }

                    size_t available_out_old = available_out;
                    _lastDecoderState = Brotli.BrotliDecoderDecompressStream(ref _decoderState, &available_in,
                                                                             &next_in, &available_out, &next_out, null);

                    total += (int)(available_out_old - available_out);
                    if (total >= count)
                    {
                        break;
                    }
                }

                if (endOfStream && _lastDecoderState != Brotli.BrotliDecoderResult.BROTLI_DECODER_RESULT_SUCCESS)
                {
                    throw new InvalidDataException("Decompression failed with error code: " + _decoderState.error_code);
                }

                return(total);
            }
        }