public override void Write(byte[] buffer, int offset, int count) { if (_mode != CompressionMode.Compress) { throw new BrotliException("Can't write on this stream"); } _written = true; totalWrote += count; //Console.WriteLine(String.Format("Write {0} bytes,total={1} bytes.", count, totalWrote)); UInt32 totalOut = 0; int bytesRemain = count; int currentOffset = offset; Boolean compressOK = true; while (bytesRemain > 0) { int copyLen = bytesRemain > BufferSize ? BufferSize : bytesRemain; Marshal.Copy(buffer, currentOffset, _ptrInputBuffer, copyLen); bytesRemain -= copyLen; currentOffset += copyLen; _availableIn = (UInt32)copyLen; _ptrNextInput = _ptrInputBuffer; while (_availableIn > 0) { compressOK = Brolib.BrotliEncoderCompressStream(_state, BrotliEncoderOperation.Process, ref _availableIn, ref _ptrNextInput, ref _availableOut, ref _ptrNextOutput, out totalOut); if (!compressOK) { throw new BrotliException("Unable to compress stream"); } if (_availableOut != BufferSize) { var bytesWrote = (int)(BufferSize - _availableOut); //Byte[] localBuffer = new Byte[bytesWrote]; Marshal.Copy(_ptrOutputBuffer, _managedBuffer, 0, bytesWrote); _stream.Write(_managedBuffer, 0, bytesWrote); _availableOut = BufferSize; _ptrNextOutput = _ptrOutputBuffer; } } if (Brolib.BrotliEncoderIsFinished(_state)) { break; } } }
protected virtual void FlushBrotliStream(Boolean finished) { //test if the resource has been freed if (_state == IntPtr.Zero) { return; } if (Brolib.BrotliEncoderIsFinished(_state)) { return; } BrotliEncoderOperation op = finished ? BrotliEncoderOperation.Finish : BrotliEncoderOperation.Flush; UInt32 totalOut = 0; while (true) { var compressOK = Brolib.BrotliEncoderCompressStream(_state, op, ref _availableIn, ref _ptrNextInput, ref _availableOut, ref _ptrNextOutput, out totalOut); if (!compressOK) { throw new BrotliException("Unable to finish encode stream"); } var extraData = _availableOut != BufferSize; if (extraData) { var bytesWrote = (int)(BufferSize - _availableOut); if (_written) { Marshal.Copy(_ptrOutputBuffer, _managedBuffer, 0, bytesWrote); _stream.Write(_managedBuffer, 0, bytesWrote); } _availableOut = BufferSize; _ptrNextOutput = _ptrOutputBuffer; } if (Brolib.BrotliEncoderIsFinished(_state)) { break; } if (!extraData) { break; } } }
public int Compress(byte[] source, int offset, int count, byte[] destination) { if (mCompressionMode != CompressionMode.Compress) { throw new BrotliException( "The BrotliStream instance can not compress the buffer."); } int destinationLength = 0; int remainingBytes = count; int currentOffset = offset; #region Process while (remainingBytes > 0) { int bytesToCopy = remainingBytes > BUFFER_SIZE ? BUFFER_SIZE : remainingBytes; Marshal.Copy(source, currentOffset, mPtrInputBuffer, bytesToCopy); remainingBytes -= bytesToCopy; currentOffset += bytesToCopy; mAvailableIn = (UInt32)bytesToCopy; mPtrNextInput = mPtrInputBuffer; while (mAvailableIn > 0) { uint totalOut = 0; bool processedOk = Brolib.BrotliEncoderCompressStream( mPtrState, BrotliEncoderOperation.Process, ref mAvailableIn, ref mPtrNextInput, ref mAvailableOut, ref mPtrNextOutput, out totalOut); if (!processedOk) { throw new BrotliException("Could not compress the buffer."); } if (mAvailableOut == BUFFER_SIZE) { continue; } int bytesProcessed = (int)(BUFFER_SIZE - mAvailableOut); Marshal.Copy( mPtrOutputBuffer, destination, destinationLength, bytesProcessed); destinationLength += bytesProcessed; mAvailableOut = BUFFER_SIZE; mPtrNextOutput = mPtrOutputBuffer; } if (Brolib.BrotliEncoderIsFinished(mPtrState)) { break; } } #endregion #region Finish while (true) { UInt32 totalOut = 0; bool compressedOk = Brolib.BrotliEncoderCompressStream( mPtrState, BrotliEncoderOperation.Finish, ref mAvailableIn, ref mPtrNextInput, ref mAvailableOut, ref mPtrNextOutput, out totalOut); if (!compressedOk) { throw new BrotliException("Unable to correctly compress the buffer"); } bool extraData = mAvailableOut != BUFFER_SIZE; if (extraData) { int bytesWritten = (int)(BUFFER_SIZE - mAvailableOut); Marshal.Copy(mPtrOutputBuffer, destination, destinationLength, bytesWritten); destinationLength += bytesWritten; mAvailableOut = BUFFER_SIZE; mPtrNextOutput = mPtrOutputBuffer; } if (Brolib.BrotliEncoderIsFinished(mPtrState) || !extraData) { break; } } #endregion return(destinationLength); }