public override int Read(byte[] buffer, int offset, int count) { if (_mode != CompressionMode.Decompress) { throw new BrotliException("Can't read on this stream"); } int bytesRead = (int)(_intermediateStream.Length - _readOffset); uint totalCount = 0; Boolean endOfStream = false; Boolean errorDetected = false; while (bytesRead < count) { while (true) { if (_lastDecodeResult == BrotliDecoderResult.NeedsMoreInput) { _availableIn = (UInt32)_stream.Read(_managedBuffer, 0, (int)BufferSize); _ptrNextInput = _ptrInputBuffer; if (_availableIn <= 0) { endOfStream = true; break; } Marshal.Copy(_managedBuffer, 0, _ptrInputBuffer, (int)_availableIn); } else if (_lastDecodeResult == BrotliDecoderResult.NeedsMoreOutput) { Marshal.Copy(_ptrOutputBuffer, _managedBuffer, 0, BufferSize); _intermediateStream.Write(_managedBuffer, 0, BufferSize); bytesRead += BufferSize; _availableOut = BufferSize; _ptrNextOutput = _ptrOutputBuffer; } else { //Error or OK endOfStream = true; break; } _lastDecodeResult = Brolib.BrotliDecoderDecompressStream(_state, ref _availableIn, ref _ptrNextInput, ref _availableOut, ref _ptrNextOutput, out totalCount); if (bytesRead >= count) { break; } } if (endOfStream && !Brolib.BrotliDecoderIsFinished(_state)) { errorDetected = true; } if (_lastDecodeResult == BrotliDecoderResult.Error || errorDetected) { var error = Brolib.BrotliDecoderGetErrorCode(_state); var text = Brolib.BrotliDecoderErrorString(error); throw new BrotliDecodeException(String.Format("Unable to decode stream,possibly corrupt data.Code={0}({1})", error, text), error, text); } if (endOfStream && !Brolib.BrotliDecoderIsFinished(_state) && _lastDecodeResult == BrotliDecoderResult.NeedsMoreInput) { throw new BrotliException("Unable to decode stream,unexpected EOF"); } if (endOfStream && _ptrNextOutput != _ptrOutputBuffer) { int remainBytes = (int)(_ptrNextOutput.ToInt64() - _ptrOutputBuffer.ToInt64()); bytesRead += remainBytes; Marshal.Copy(_ptrOutputBuffer, _managedBuffer, 0, remainBytes); _intermediateStream.Write(_managedBuffer, 0, remainBytes); _ptrNextOutput = _ptrOutputBuffer; } if (endOfStream) { break; } } if (_intermediateStream.Length - _readOffset >= count || endOfStream) { _intermediateStream.Seek(_readOffset, SeekOrigin.Begin); var bytesToRead = (int)(_intermediateStream.Length - _readOffset); if (bytesToRead > count) { bytesToRead = count; } _intermediateStream.Read(buffer, offset, bytesToRead); TruncateBeginning(_intermediateStream, _readOffset + bytesToRead); _readOffset = 0; return(bytesToRead); } return(0); }
private static TransformationStatus GetTransformationStatusFromBrotliDecoderResult(BrotliDecoderResult result) { if (result == BrotliDecoderResult.Success) { return(TransformationStatus.Done); } if (result == BrotliDecoderResult.NeedsMoreOutput) { return(TransformationStatus.DestinationTooSmall); } if (result == BrotliDecoderResult.NeedsMoreInput) { return(TransformationStatus.NeedMoreSourceData); } return(TransformationStatus.InvalidData); }
public int Decompress(byte[] source, int offset, int count, byte[] destination) { if (mCompressionMode != CompressionMode.Decompress) { throw new BrotliException( "The BrotliStream instance can not decompress the buffer."); } BrotliDecoderResult lastDecodeResult = BrotliDecoderResult.NeedsMoreInput; int bytesProcessed = 0; bool endOfSource = false; bool errorDetected = false; int destinationLength = 0; while (bytesProcessed < count) { while (true) { if (lastDecodeResult == BrotliDecoderResult.NeedsMoreInput) { mAvailableIn = (count - bytesProcessed) > BUFFER_SIZE ? BUFFER_SIZE : (uint)(count - bytesProcessed); mPtrNextInput = mPtrInputBuffer; if (mAvailableIn <= 0) { endOfSource = true; break; } Marshal.Copy( source, offset + bytesProcessed, mPtrInputBuffer, (int)mAvailableIn); } else if (lastDecodeResult == BrotliDecoderResult.NeedsMoreOutput) { Marshal.Copy( mPtrOutputBuffer, destination, destinationLength, BUFFER_SIZE); destinationLength += BUFFER_SIZE; bytesProcessed += BUFFER_SIZE; mAvailableOut = BUFFER_SIZE; mPtrNextOutput = mPtrOutputBuffer; } else { // Error or OK endOfSource = true; break; } uint totalCount = 0; lastDecodeResult = Brolib.BrotliDecoderDecompressStream( mPtrState, ref mAvailableIn, ref mPtrNextInput, ref mAvailableOut, ref mPtrNextOutput, out totalCount); if (bytesProcessed >= destination.Length) { break; } } if (endOfSource && !Brolib.BrotliDecoderIsFinished(mPtrState)) { errorDetected = true; } if (lastDecodeResult == BrotliDecoderResult.Error || errorDetected) { int errorCode = Brolib.BrotliDecoderGetErrorCode(mPtrState); string errorMessage = Brolib.BrotliDecoderErrorString(errorCode); throw new BrotliException(string.Format( "Unable to decompress the buffer. Error {0} - {1}", errorCode, errorMessage)); } if (endOfSource && Brolib.BrotliDecoderIsFinished(mPtrState) && lastDecodeResult == BrotliDecoderResult.NeedsMoreInput) { throw new Exception("Unable to decompress the buffer. Unexpected EOF."); } if (endOfSource && mPtrNextOutput != mPtrOutputBuffer) { int remainingBytes = (int)(mPtrNextOutput.ToInt64() - mPtrOutputBuffer.ToInt64()); bytesProcessed += remainingBytes; if (destinationLength + remainingBytes > destination.Length) { throw new BrotliException( "The destination buffer is smaller than the decompressed source buffer"); } Marshal.Copy(mPtrOutputBuffer, destination, destinationLength, remainingBytes); destinationLength += remainingBytes; mPtrNextOutput = mPtrOutputBuffer; } if (endOfSource) { break; } } return(destinationLength); }