Ejemplo n.º 1
0
        public static TransformationStatus Compress(ReadOnlySpan <byte> source, Span <byte> destination, out int bytesConsumed, out int bytesWritten, int quality = DefaultQuality, int windowSize = DefaultWindowSize, BrotliEncoderMode encMode = BrotliEncoderMode.Generic)
        {
            if (quality > DefaultQuality || quality <= 0)
            {
                throw new System.ArgumentOutOfRangeException(BrotliEx.WrongQuality);
            }
            if (windowSize > DefaultWindowSize || windowSize <= 0)
            {
                throw new System.ArgumentOutOfRangeException(BrotliEx.WrongWindowSize);
            }
            bytesConsumed = bytesWritten = 0;
            unsafe
            {
                IntPtr bufIn, bufOut;
                fixed(byte *inBytes = &source.DangerousGetPinnableReference())
                fixed(byte *outBytes = &destination.DangerousGetPinnableReference())
                {
                    bufIn  = new IntPtr(inBytes);
                    bufOut = new IntPtr(outBytes);
                    nuint written  = (nuint)destination.Length;
                    nuint consumed = (nuint)source.Length;

                    if (!BrotliNative.BrotliEncoderCompress(quality, windowSize, encMode, consumed, bufIn, ref written, bufOut))
                    {
                        return(TransformationStatus.InvalidData);
                    }
                    ;
                    bytesConsumed = (int)consumed;
                    bytesWritten  = (int)written;
                    return(TransformationStatus.Done);
                }
            }
        }
Ejemplo n.º 2
0
        public static OperationStatus Compress(ReadOnlySpan <byte> source, Span <byte> destination, out int bytesConsumed, out int bytesWritten, ref State state)
        {
            EnsureInitialized(ref state, true);
            bytesWritten  = destination.Length;
            bytesConsumed = source.Length;
            unsafe
            {
                IntPtr bufIn, bufOut;
                while (bytesConsumed > 0)
                {
                    fixed(byte *inBytes = &MemoryMarshal.GetReference(source))
                    fixed(byte *outBytes = &MemoryMarshal.GetReference(destination))
                    {
                        bufIn  = new IntPtr(inBytes);
                        bufOut = new IntPtr(outBytes);
                        nuint availableOutput = (nuint)bytesWritten;
                        nuint consumed        = (nuint)bytesConsumed;

                        if (!BrotliNative.BrotliEncoderCompressStream(state.BrotliNativeState, BrotliEncoderOperation.Process, ref consumed, ref bufIn, ref availableOutput, ref bufOut, out nuint totalOut))
                        {
                            return(OperationStatus.InvalidData);
                        }
                        ;
                        bytesConsumed = (int)consumed;
                        bytesWritten  = destination.Length - (int)availableOutput;
                        if (availableOutput != (nuint)destination.Length)
                        {
                            return(OperationStatus.DestinationTooSmall);
                        }
                    }
                }
                return(OperationStatus.Done);
            }
        }
Ejemplo n.º 3
0
 internal void Dispose()
 {
     if (!_isDisposed && State != IntPtr.Zero)
     {
         BrotliNative.BrotliEncoderDestroyInstance(State);
     }
     _isDisposed = true;
 }
Ejemplo n.º 4
0
 private void InitializeEncoder()
 {
     State = BrotliNative.BrotliEncoderCreateInstance();
     if (State == IntPtr.Zero)
     {
         throw new System.IO.IOException(BrotliEx.EncoderInstanceCreate);
     }
 }
Ejemplo n.º 5
0
 public void SetWindow(uint window)
 {
     if (window < MinWindowBits || window > MaxWindowBits)
     {
         throw new ArgumentException(BrotliEx.WrongWindowSize);
     }
     BrotliNative.BrotliEncoderSetParameter(State, BrotliEncoderParameter.LGWin, window);
 }
Ejemplo n.º 6
0
 public void SetQuality(uint quality)
 {
     if (quality < MinQuality || quality > MaxQuality)
     {
         throw new ArgumentException(BrotliEx.WrongQuality);
     }
     BrotliNative.BrotliEncoderSetParameter(State, BrotliEncoderParameter.Quality, quality);
 }
Ejemplo n.º 7
0
 private void InitializeEncoder()
 {
     State = BrotliNative.BrotliEncoderCreateInstance();
     if (State == IntPtr.Zero)
     {
         throw new Exception();//TODO Create exception
     }
 }
Ejemplo n.º 8
0
 internal void InitializeEncoder()
 {
     BrotliNativeState = BrotliNative.BrotliEncoderCreateInstance();
     if (BrotliNativeState == IntPtr.Zero)
     {
         throw new System.Exception(BrotliEx.EncoderInstanceCreate);
     }
     CompressMode = true;
 }
Ejemplo n.º 9
0
 private void InitializeDecoder()
 {
     State = BrotliNative.BrotliDecoderCreateInstance();
     if (State == IntPtr.Zero)
     {
         throw new System.IO.IOException(BrotliEx.DecoderInstanceCreate);//TODO Create exception
     }
     BufferStream = new MemoryStream();
 }
Ejemplo n.º 10
0
 private void InitializeDecoder()
 {
     State = BrotliNative.BrotliDecoderCreateInstance();
     if (State == IntPtr.Zero)
     {
         throw new System.IO.IOException(BrotliEx.DecoderInstanceCreate);
     }
     LastDecoderResult = BrotliDecoderResult.NeedsMoreInput;
     _bufferStream     = new MemoryStream();
 }
Ejemplo n.º 11
0
 internal void InitializeDecoder()
 {
     BrotliNativeState = BrotliNative.BrotliDecoderCreateInstance();
     LastDecoderResult = BrotliDecoderResult.NeedsMoreInput;
     if (BrotliNativeState == IntPtr.Zero)
     {
         throw new System.Exception(BrotliEx.DecoderInstanceCreate);
     }
     CompressMode = false;
 }
Ejemplo n.º 12
0
 public void Dispose()
 {
     if (CompressMode)
     {
         BrotliNative.BrotliEncoderDestroyInstance(BrotliNativeState);
     }
     else
     {
         BrotliNative.BrotliDecoderDestroyInstance(BrotliNativeState);
     }
 }
Ejemplo n.º 13
0
 internal void InitializeEncoder()
 {
     BrotliNativeState = BrotliNative.BrotliEncoderCreateInstance();
     if (BrotliNativeState == IntPtr.Zero)
     {
         throw new System.Exception(BrotliEx.EncoderInstanceCreate);
     }
     CompressMode = true;
     SetQuality((uint)GetQualityFromCompressionLevel(CompressionLevel.Optimal));
     SetWindow(MaxWindowBits);
 }
Ejemplo n.º 14
0
 public void SetWindow(uint window)
 {
     if (BrotliNativeState == IntPtr.Zero)
     {
         InitializeEncoder();
     }
     if (window - MinWindowBits > MaxWindowBits - MinWindowBits)
     {
         throw new ArgumentOutOfRangeException(BrotliEx.WrongWindowSize);
     }
     BrotliNative.BrotliEncoderSetParameter(BrotliNativeState, BrotliEncoderParameter.LGWin, window);
 }
Ejemplo n.º 15
0
 public void SetQuality(uint quality)
 {
     if (BrotliNativeState == IntPtr.Zero)
     {
         InitializeEncoder();
     }
     if (quality > MaxQuality)
     {
         throw new ArgumentOutOfRangeException(BrotliEx.WrongQuality);
     }
     BrotliNative.BrotliEncoderSetParameter(BrotliNativeState, BrotliEncoderParameter.Quality, quality);
 }
Ejemplo n.º 16
0
        public override void Write(byte[] buffer, int offset, int count)
        {
            EnsureCompressionMode();
            ValidateParameters(buffer, offset, count);
            EnsureNotDisposed();
            if (_mode != CompressionMode.Compress)
            {
                totalWrote += count;
            }
            DateTime begin         = DateTime.Now;
            nuint    totalOut      = 0;
            int      bytesRemain   = count;
            int      currentOffset = offset;
            int      copyLen;

            while (bytesRemain > 0)
            {
                TimeSpan ExecutionTime = DateTime.Now - begin;
                if (WriteTimeout > 0 && ExecutionTime.TotalMilliseconds >= WriteTimeout)
                {
                    throw new TimeoutException(BrotliEx.TimeoutWrite);
                }
                copyLen = bytesRemain > _bufferSize ? _bufferSize : bytesRemain;
                Marshal.Copy(buffer, currentOffset, _bufferInput, copyLen);
                bytesRemain    -= copyLen;
                currentOffset  += copyLen;
                _availableInput = (nuint)copyLen;
                _nextInput      = _bufferInput;
                while ((int)_availableInput > 0)
                {
                    if (!BrotliNative.BrotliEncoderCompressStream(_encoder.State, BrotliEncoderOperation.Process, ref _availableInput, ref _nextInput, ref _availableOutput,
                                                                  ref _nextOutput, out totalOut))
                    {
                        throw new System.IO.IOException(BrotliEx.unableEncode);
                    }

                    if (_availableOutput != (nuint)_bufferSize)
                    {
                        var    bytesWrote = (int)((nuint)_bufferSize - _availableOutput);
                        Byte[] buf        = new Byte[bytesWrote];
                        Marshal.Copy(_bufferOutput, buf, 0, bytesWrote);
                        _stream.Write(buf, 0, bytesWrote);
                        _availableOutput = (nuint)_bufferSize;
                        _nextOutput      = _bufferOutput;
                    }
                }
                if (BrotliNative.BrotliEncoderIsFinished(_encoder.State))
                {
                    break;
                }
            }
        }
Ejemplo n.º 17
0
        public static OperationStatus FlushEncoder(ReadOnlySpan <byte> source, Span <byte> destination, out int bytesConsumed, out int bytesWritten, ref State state, bool isFinished = true)
        {
            EnsureInitialized(ref state, true);
            BrotliEncoderOperation operation = isFinished ? BrotliEncoderOperation.Finish : BrotliEncoderOperation.Flush;

            bytesWritten  = destination.Length;
            bytesConsumed = 0;
            if (state.BrotliNativeState == IntPtr.Zero)
            {
                return(OperationStatus.InvalidData);
            }
            if (BrotliNative.BrotliEncoderIsFinished(state.BrotliNativeState))
            {
                return(OperationStatus.Done);
            }
            unsafe
            {
                IntPtr bufIn, bufOut;
                fixed(byte *inBytes = &MemoryMarshal.GetReference(source))
                fixed(byte *outBytes = &MemoryMarshal.GetReference(destination))
                {
                    bufIn  = new IntPtr(inBytes);
                    bufOut = new IntPtr(outBytes);
                    nuint availableOutput = (nuint)destination.Length;
                    nuint consumed        = (nuint)source.Length;

                    if (!BrotliNative.BrotliEncoderCompressStream(state.BrotliNativeState, operation, ref consumed, ref bufIn, ref availableOutput, ref bufOut, out nuint totalOut))
                    {
                        return(OperationStatus.InvalidData);
                    }
                    bytesConsumed = (int)consumed;
                    bytesWritten  = (int)availableOutput;
                }
                bytesWritten = destination.Length - bytesWritten;
                if (bytesWritten > 0)
                {
                    if (BrotliNative.BrotliEncoderIsFinished(state.BrotliNativeState))
                    {
                        return(OperationStatus.Done);
                    }
                    else
                    {
                        return(OperationStatus.DestinationTooSmall);
                    }
                }
            }
            return(OperationStatus.Done);
        }
Ejemplo n.º 18
0
 public static bool Compress(ReadOnlySpan <byte> source, Span <byte> destination, out nuint bytesConsumed, out nuint bytesWritten, int quality, int lgwin)
 {
     unsafe
     {
         bytesConsumed = (nuint)source.Length;
         bytesWritten  = (nuint)0;
         IntPtr bufIn, bufOut;
         fixed(byte *inBytes = &source.DangerousGetPinnableReference())
         fixed(byte *outBytes = &destination.DangerousGetPinnableReference())
         {
             bufIn  = new IntPtr(inBytes);
             bufOut = new IntPtr(outBytes);
             return(BrotliNative.BrotliEncoderCompress(quality, lgwin, BrotliNative.BrotliEncoderMode.Generic, bytesConsumed, bufIn, ref bytesWritten, bufOut));
         }
     }
 }
Ejemplo n.º 19
0
 public static BrotliNative.BrotliDecoderResult Decompress(ReadOnlySpan <byte> source, Span <byte> destination, out nuint bytesConsumed, out nuint bytesWritten)
 {
     unsafe
     {
         bytesConsumed = (nuint)source.Length;
         bytesWritten  = (nuint)0;
         IntPtr bufIn, bufOut;
         fixed(byte *inBytes = &source.DangerousGetPinnableReference())
         fixed(byte *outBytes = &destination.DangerousGetPinnableReference())
         {
             bufIn  = new IntPtr(inBytes);
             bufOut = new IntPtr(outBytes);
             return(BrotliNative.BrotliDecoderDecompress(ref bytesConsumed, bufIn, ref bytesWritten, bufOut));
         }
     }
 }
Ejemplo n.º 20
0
 public void Dispose()
 {
     if (BrotliNativeState == IntPtr.Zero)
     {
         return;
     }
     if (CompressMode)
     {
         BrotliNative.BrotliEncoderDestroyInstance(BrotliNativeState);
     }
     else
     {
         BrotliNative.BrotliDecoderDestroyInstance(BrotliNativeState);
     }
     BrotliNativeState = IntPtr.Zero;
 }
Ejemplo n.º 21
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.º 22
0
        public override void Write(byte[] buffer, int offset, int count)
        {
            EnsureCompressionMode();
            ValidateParameters(buffer, offset, count);
            EnsureNotDisposed();
            if (_mode != CompressionMode.Compress)
            {
                totalWrote += count;
            }
            nuint totalOut      = 0;
            int   bytesRemain   = count;
            int   currentOffset = offset;
            int   copyLen;

            while (bytesRemain > 0)
            {
                copyLen = bytesRemain > BufferSize ? BufferSize : bytesRemain;
                Marshal.Copy(buffer, currentOffset, BufferIn, copyLen);
                bytesRemain   -= copyLen;
                currentOffset += copyLen;
                AvailIn        = (IntPtr)copyLen;
                NextIn         = BufferIn;
                while ((int)AvailIn > 0)
                {
                    if (!BrotliNative.BrotliEncoderCompressStream(_encoder.State, BrotliNative.BrotliEncoderOperation.Process, ref AvailIn, ref NextIn, ref AvailOut,
                                                                  ref NextOut, out totalOut))
                    {
                        throw new System.IO.IOException("Unable compress stream");
                    }
                    if ((nuint)AvailOut != BufferSize)
                    {
                        var    bytesWrote = (int)(BufferSize - (nuint)AvailOut);
                        Byte[] buf        = new Byte[bytesWrote];
                        Marshal.Copy(BufferOut, buf, 0, bytesWrote);
                        _stream.Write(buf, 0, bytesWrote);
                        AvailOut = new IntPtr((uint)BufferSize);
                        NextOut  = BufferOut;
                    }
                }
                if (BrotliNative.BrotliEncoderIsFinished(_encoder.State))
                {
                    break;
                }
            }
        }
Ejemplo n.º 23
0
        protected virtual void FlushEncoder(bool finished)
        {
            if (_encoder.State == IntPtr.Zero)
            {
                return;
            }
            if (BrotliNative.BrotliEncoderIsFinished(_encoder.State))
            {
                return;
            }
            BrotliEncoderOperation op = finished ? BrotliEncoderOperation.Finish : BrotliEncoderOperation.Flush;
            nuint totalOut            = 0;

            while (true)
            {
                if (!BrotliNative.BrotliEncoderCompressStream(_encoder.State, op, ref _availableInput, ref _nextInput, ref _availableOutput, ref _nextOutput, out totalOut))
                {
                    throw new System.IO.IOException(BrotliEx.unableEncode);
                }
                var extraData = (nuint)_availableOutput != (nuint)_bufferSize;
                if (extraData)
                {
                    var    bytesWrote = (int)((nuint)_bufferSize - (nuint)_availableOutput);
                    Byte[] buf        = new Byte[bytesWrote];
                    Marshal.Copy(_bufferOutput, buf, 0, bytesWrote);
                    _stream.Write(buf, 0, bytesWrote);
                    _availableOutput = (nuint)_bufferSize;
                    _nextOutput      = _bufferOutput;
                }
                if (BrotliNative.BrotliEncoderIsFinished(_encoder.State))
                {
                    break;
                }
                if (!extraData)
                {
                    break;
                }
            }
        }
Ejemplo n.º 24
0
        protected virtual void FlushEncoder(Boolean finished)
        {
            if (_encoder.State == IntPtr.Zero)
            {
                return;
            }
            if (BrotliNative.BrotliEncoderIsFinished(_encoder.State))
            {
                return;
            }
            BrotliNative.BrotliEncoderOperation op = finished ? BrotliNative.BrotliEncoderOperation.Finish : BrotliNative.BrotliEncoderOperation.Flush;
            UInt32 totalOut = 0;

            while (true)
            {
                if (!BrotliNative.BrotliEncoderCompressStream(_encoder.State, op, ref AvailIn, ref NextIn, ref AvailOut, ref NextOut, out totalOut))
                {
                    throw new Exception();                                                                                                                                 // unable encode
                }
                var extraData = (nuint)AvailOut != BufferSize;
                if (extraData)
                {
                    var    bytesWrote = (int)(BufferSize - (nuint)AvailOut);
                    Byte[] buf        = new Byte[bytesWrote];
                    Marshal.Copy(BufferOut, buf, 0, bytesWrote);
                    _stream.Write(buf, 0, bytesWrote);
                    AvailOut = (IntPtr)BufferSize;
                    NextOut  = BufferOut;
                }
                if (BrotliNative.BrotliEncoderIsFinished(_encoder.State))
                {
                    break;
                }
                if (!extraData)
                {
                    break;
                }
            }
        }
Ejemplo n.º 25
0
        public static TransformationStatus Decompress(ReadOnlySpan <byte> source, Span <byte> destination, out int bytesConsumed, out int bytesWritten)
        {
            bytesConsumed = bytesWritten = 0;
            unsafe
            {
                IntPtr bufIn, bufOut;
                fixed(byte *inBytes = &source.DangerousGetPinnableReference())
                fixed(byte *outBytes = &destination.DangerousGetPinnableReference())
                {
                    bufIn  = new IntPtr(inBytes);
                    bufOut = new IntPtr(outBytes);
                    nuint written           = (nuint)destination.Length;
                    nuint consumed          = (nuint)source.Length;
                    BrotliDecoderResult res = BrotliNative.BrotliDecoderDecompress(ref consumed, bufIn, ref written, bufOut);

                    if (res == BrotliDecoderResult.Success)
                    {
                        bytesWritten  = (int)written;
                        bytesConsumed = (int)consumed;
                    }
                    return(GetTransformationStatusFromBrotliDecoderResult(res));
                }
            }
        }
Ejemplo n.º 26
0
        protected virtual void FlushEncoder(bool finished)
        {
            if (_state.BrotliNativeState == IntPtr.Zero)
            {
                return;
            }
            if (BrotliNative.BrotliEncoderIsFinished(_state.BrotliNativeState))
            {
                return;
            }
            TransformationStatus flushStatus = TransformationStatus.DestinationTooSmall;

            while (flushStatus == TransformationStatus.DestinationTooSmall)
            {
                flushStatus = Brotli.FlushEncoder(Array.Empty <byte>(), _buffer, out _availableInput, out _availableOutput, ref _state, finished);
                _stream.Write(_buffer, 0, _availableOutput);
                _availableOutput = _bufferSize;

                if (BrotliNative.BrotliEncoderIsFinished(_state.BrotliNativeState))
                {
                    break;
                }
            }
        }
Ejemplo n.º 27
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);
        }
Ejemplo n.º 28
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);
        }