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)); } }
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); }
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); }