Ejemplo n.º 1
0
        public static TransformationStatus Decompress(ReadOnlySpan <byte> source, Span <byte> destination, out int bytesConsumed, out int bytesWritten, ref State state)
        {
            EnsureInitialized(ref state, false);
            bytesConsumed = source.Length;
            bytesWritten  = destination.Length;
            if (BrotliNative.BrotliDecoderIsFinished(state.BrotliNativeState))
            {
                return(TransformationStatus.Done);
            }
            unsafe
            {
                IntPtr bufIn, bufOut;
                fixed(byte *inBytes = &source.DangerousGetPinnableReference())
                fixed(byte *outBytes = &destination.DangerousGetPinnableReference())
                {
                    bufIn  = new IntPtr(inBytes);
                    bufOut = new IntPtr(outBytes);
                    nuint availableOutput = (nuint)bytesWritten;
                    nuint consumed        = (nuint)bytesConsumed;

                    state.LastDecoderResult = BrotliNative.BrotliDecoderDecompressStream(state.BrotliNativeState, ref consumed, ref bufIn, ref availableOutput, ref bufOut, out nuint totalOut);
                    bytesWritten            = destination.Length - (int)availableOutput;
                    bytesConsumed           = (int)consumed;
                }
                if (state.LastDecoderResult == BrotliDecoderResult.NeedsMoreInput)
                {
                    return(TransformationStatus.NeedMoreSourceData);
                }
                else if (state.LastDecoderResult == BrotliDecoderResult.NeedsMoreOutput)
                {
                    return(TransformationStatus.DestinationTooSmall);
                }

                if (state.LastDecoderResult == BrotliDecoderResult.Error || !BrotliNative.BrotliDecoderIsFinished(state.BrotliNativeState))
                {
                    var error = BrotliNative.BrotliDecoderGetErrorCode(state.BrotliNativeState);
                    var text  = BrotliNative.BrotliDecoderErrorString(error);
                    throw new System.IO.IOException(text + BrotliEx.unableDecode);
                }
                if (state.LastDecoderResult == BrotliDecoderResult.NeedsMoreInput)
                {
                    throw new System.IO.IOException(BrotliEx.FinishDecompress);
                }
                return(GetTransformationStatusFromBrotliDecoderResult(state.LastDecoderResult));
            }
        }
Ejemplo n.º 2
0
        public override int Read(byte[] buffer, int offset, int count)
        {
            EnsureDecompressionMode();
            ValidateParameters(buffer, offset, count);
            EnsureNotDisposed();

            int     bytesRead     = (int)(_decoder.BufferStream.Length - _readOffset);
            uint    totalCount    = 0;
            Boolean endOfStream   = false;
            Boolean errorDetected = false;

            Byte[] buf = new Byte[BufferSize];
            while (bytesRead < count)
            {
                while (true)
                {
                    if (_decoder.LastDecoderResult == BrotliNative.BrotliDecoderResult.NeedsMoreInput)
                    {
                        AvailIn = (IntPtr)_stream.Read(buf, 0, (int)BufferSize);
                        NextIn  = BufferIn;
                        if ((int)AvailIn <= 0)
                        {
                            endOfStream = true;
                            break;
                        }
                        Marshal.Copy(buf, 0, BufferIn, (int)AvailIn);
                    }
                    else if (_decoder.LastDecoderResult == BrotliNative.BrotliDecoderResult.NeedsMoreOutput)
                    {
                        Marshal.Copy(BufferOut, buf, 0, BufferSize);
                        _decoder.BufferStream.Write(buf, 0, BufferSize);
                        bytesRead += BufferSize;
                        AvailOut   = new IntPtr((uint)BufferSize);
                        NextOut    = BufferOut;
                    }
                    else
                    {
                        //Error or OK
                        endOfStream = true;
                        break;
                    }
                    _decoder.LastDecoderResult = BrotliNative.BrotliDecoderDecompressStream(_decoder.State, ref AvailIn, ref NextIn,
                                                                                            ref AvailOut, ref NextOut, out totalCount);
                    if (bytesRead >= count)
                    {
                        break;
                    }
                }
                if (endOfStream && !BrotliNative.BrotliDecoderIsFinished(_decoder.State))
                {
                    errorDetected = true;
                }
                if (_decoder.LastDecoderResult == BrotliNative.BrotliDecoderResult.Error || errorDetected)
                {
                    var error = BrotliNative.BrotliDecoderGetErrorCode(_decoder.State);
                    var text  = BrotliNative.BrotliDecoderErrorString(error);
                    throw new System.IO.IOException(text + "- unable to decode stream");
                }
                if (endOfStream && !BrotliNative.BrotliDecoderIsFinished(_decoder.State) && _decoder.LastDecoderResult == BrotliNative.BrotliDecoderResult.NeedsMoreInput)
                {
                    throw new System.IO.IOException("Bad finish");
                }
                if (endOfStream && NextOut != BufferOut)
                {
                    int remainBytes = (int)(NextOut.ToInt64() - BufferOut.ToInt64());
                    bytesRead += remainBytes;
                    Marshal.Copy(BufferOut, buf, 0, remainBytes);
                    _decoder.BufferStream.Write(buf, 0, remainBytes);
                    NextOut = BufferOut;
                }
                if (endOfStream)
                {
                    break;
                }
            }
            if (_decoder.BufferStream.Length - _readOffset >= count || endOfStream)
            {
                _decoder.BufferStream.Seek(_readOffset, SeekOrigin.Begin);
                var bytesToRead = (int)(_decoder.BufferStream.Length - _readOffset);
                if (bytesToRead > count)
                {
                    bytesToRead = count;
                }
                _decoder.BufferStream.Read(buffer, offset, bytesToRead);
                _decoder.RemoveBytes(_readOffset + bytesToRead);
                _readOffset = 0;
                return(bytesToRead);
            }
            return(0);
        }
Ejemplo n.º 3
0
        public override int Read(byte[] buffer, int offset, int count)
        {
            EnsureDecompressionMode();
            ValidateParameters(buffer, offset, count);
            EnsureNotDisposed();
            DateTime begin         = DateTime.Now;
            int      bytesRead     = (int)(_decoder.BufferStream.Length - _readOffset);
            nuint    totalCount    = 0;
            bool     endOfStream   = false;
            bool     errorDetected = false;

            Byte[] buf = new Byte[_bufferSize];
            while (bytesRead < count)
            {
                TimeSpan ExecutionTime = DateTime.Now - begin;
                if (ReadTimeout > 0 && ExecutionTime.TotalMilliseconds >= ReadTimeout)
                {
                    throw new TimeoutException(BrotliEx.TimeoutRead);
                }
                while (true)
                {
                    if (_decoder.LastDecoderResult == BrotliDecoderResult.NeedsMoreInput)
                    {
                        _availableInput = (nuint)_stream.Read(buf, 0, (int)_bufferSize);
                        _nextInput      = _bufferInput;
                        if ((int)_availableInput <= 0)
                        {
                            endOfStream = true;
                            break;
                        }
                        Marshal.Copy(buf, 0, _bufferInput, (int)_availableInput);
                    }
                    else if (_decoder.LastDecoderResult == BrotliDecoderResult.NeedsMoreOutput)
                    {
                        Marshal.Copy(_bufferOutput, buf, 0, _bufferSize);
                        _decoder.BufferStream.Write(buf, 0, _bufferSize);
                        bytesRead       += _bufferSize;
                        _availableOutput = (nuint)_bufferSize;
                        _nextOutput      = _bufferOutput;
                    }
                    else
                    {
                        //Error or OK
                        endOfStream = true;
                        break;
                    }
                    _decoder.LastDecoderResult = BrotliNative.BrotliDecoderDecompressStream(_decoder.State, ref _availableInput, ref _nextInput,
                                                                                            ref _availableOutput, ref _nextOutput, out totalCount);
                    if (bytesRead >= count)
                    {
                        break;
                    }
                }
                if (endOfStream && !BrotliNative.BrotliDecoderIsFinished(_decoder.State))
                {
                    errorDetected = true;
                }
                if (_decoder.LastDecoderResult == BrotliDecoderResult.Error || errorDetected)
                {
                    var error = BrotliNative.BrotliDecoderGetErrorCode(_decoder.State);
                    var text  = BrotliNative.BrotliDecoderErrorString(error);
                    throw new System.IO.IOException(text + BrotliEx.unableDecode);
                }
                if (endOfStream && !BrotliNative.BrotliDecoderIsFinished(_decoder.State) && _decoder.LastDecoderResult == BrotliDecoderResult.NeedsMoreInput)
                {
                    throw new System.IO.IOException(BrotliEx.FinishDecompress);
                }
                if (endOfStream && _nextOutput != _bufferOutput)
                {
                    int remainBytes = (int)(_nextOutput.ToInt64() - _bufferOutput.ToInt64());
                    bytesRead += remainBytes;
                    Marshal.Copy(_bufferOutput, buf, 0, remainBytes);
                    _decoder.BufferStream.Write(buf, 0, remainBytes);
                    _nextOutput = _bufferOutput;
                }
                if (endOfStream)
                {
                    break;
                }
            }
            if (_decoder.BufferStream.Length - _readOffset >= count || endOfStream)
            {
                _decoder.BufferStream.Seek(_readOffset, SeekOrigin.Begin);
                var bytesToRead = (int)(_decoder.BufferStream.Length - _readOffset);
                if (bytesToRead > count)
                {
                    bytesToRead = count;
                }
                _decoder.BufferStream.Read(buffer, offset, bytesToRead);
                _decoder.RemoveBytes(_readOffset + bytesToRead);
                _readOffset = 0;
                return(bytesToRead);
            }
            return(0);
        }