public override void Write(byte[] buffer, int offset, int count)
{
if (buffer == null) throw new ArgumentNullException(nameof(buffer));
if (offset < 0) throw new ArgumentOutOfRangeException(nameof(offset));
if (count < 0) throw new ArgumentOutOfRangeException(nameof(count));
if (count + offset > buffer.Length) throw new ArgumentOutOfRangeException(nameof(count), "offset+count > buffer.length");
if (count == 0) return;
int bytesProcessed = 0;
while (true)
{
// Fill the input buffer if it is empty.
if (_lzma_stream.avail_in == UIntPtr.Zero)
{
int bytesToProcess = Math.Min(count - bytesProcessed, BUFSIZE);
if (bytesToProcess == 0) break; // no more data to compress
_lzma_stream.next_in = _inbuf;
_lzma_stream.avail_in = (UIntPtr)bytesToProcess;
Marshal.Copy(buffer, offset + bytesProcessed, _inbuf, bytesToProcess);
bytesProcessed += bytesToProcess;
}
// do compress, RUN action should return LZMA_OK on success
var ret = Native.lzma_code(_lzma_stream, lzma_action.LZMA_RUN);
if (ret != lzma_ret.LZMA_OK)
throw new Exception($"lzma_code returns {ret}");
// check output buffer
if (_lzma_stream.avail_out == UIntPtr.Zero)
{
byte[] data = new byte[BUFSIZE];
Marshal.Copy(_outbuf, data, 0, data.Length);
_stream.Write(data, 0, data.Length);
// Reset next_out and avail_out.
_lzma_stream.next_out = _outbuf;
_lzma_stream.avail_out = (UIntPtr)BUFSIZE;
}
}
}