/// <summary> /// Create multi-threaded compressing XZStream. Requires more memory than single-threaded mode. /// </summary> public unsafe XZStream(Stream baseStream, XZCompressOptions compOpts, XZThreadedCompressOptions threadOpts) { XZInit.Manager.EnsureLoaded(); BaseStream = baseStream ?? throw new ArgumentNullException(nameof(baseStream)); _mode = Mode.Compress; _disposed = false; // Check and set XZStreamOptions _leaveOpen = compOpts.LeaveOpen; _bufferSize = CheckBufferSize(compOpts.BufferSize); _workBuf = new byte[_bufferSize]; // Prepare LzmaStream and buffers _lzmaStream = new LzmaStream(); _lzmaStreamPin = GCHandle.Alloc(_lzmaStream, GCHandleType.Pinned); // Check LzmaMt instance LzmaMt mt = compOpts.ToLzmaMt(threadOpts); CheckPreset(mt.Preset); // Initialize the encoder LzmaRet ret = XZInit.Lib.LzmaStreamEncoderMt(_lzmaStream, mt); XZException.CheckReturnValue(ret); // Set possible max memory usage. MaxMemUsage = XZInit.Lib.LzmaStreamEncoderMtMemUsage(mt); }
/// <summary> /// Create single-threaded compressing XZStream. /// </summary> public unsafe XZStream(Stream baseStream, XZCompressOptions compOpts) { XZInit.Manager.EnsureLoaded(); BaseStream = baseStream ?? throw new ArgumentNullException(nameof(baseStream)); _mode = Mode.Compress; _disposed = false; // Check and set compress options _leaveOpen = compOpts.LeaveOpen; _bufferSize = CheckBufferSize(compOpts.BufferSize); _workBuf = new byte[_bufferSize]; // Prepare LzmaStream _lzmaStream = new LzmaStream(); _lzmaStreamPin = GCHandle.Alloc(_lzmaStream, GCHandleType.Pinned); // Check preset uint preset = compOpts.Preset; CheckPreset(preset); // Initialize the encoder LzmaRet ret = XZInit.Lib.LzmaEasyEncoder(_lzmaStream, preset, compOpts.Check); XZException.CheckReturnValue(ret); // Set possible max memory usage. MaxMemUsage = XZInit.Lib.LzmaEasyEncoderMemUsage(preset); }
public unsafe void Write(ReadOnlySpan <byte> span) #endif { // For Compress if (_mode != Mode.Compress) { throw new NotSupportedException("Write() not supported on decompression"); } TotalIn += span.Length; fixed(byte *readPtr = span) fixed(byte *writePtr = _workBuf) { _lzmaStream.NextIn = readPtr; _lzmaStream.AvailIn = (uint)span.Length; _lzmaStream.NextOut = writePtr + _workBufPos; _lzmaStream.AvailOut = (uint)(_workBuf.Length - _workBufPos); // Return condition : _lzmaStream.AvailIn == 0 while (_lzmaStream.AvailIn != 0) { LzmaRet ret = XZInit.Lib.LzmaCode(_lzmaStream, LzmaAction.Run); _workBufPos = (int)((ulong)_workBuf.Length - _lzmaStream.AvailOut); // If the output buffer is full, write the data from the output bufffer to the output file. if (_lzmaStream.AvailOut == 0) { // Write to _baseStream BaseStream.Write(_workBuf, 0, _workBuf.Length); TotalOut += _workBuf.Length; // Reset NextOut and AvailOut _workBufPos = 0; _lzmaStream.NextOut = writePtr; _lzmaStream.AvailOut = (uint)_workBuf.Length; } // Normally the return value of lzma_code() will be LZMA_OK until everything has been encoded. XZException.CheckReturnValue(ret); } } }
private unsafe void FinishWrite() { Debug.Assert(_mode == Mode.Compress, "FinishWrite() must not be called in decompression"); fixed(byte *writePtr = _workBuf) { _lzmaStream.NextIn = (byte *)0; _lzmaStream.AvailIn = 0; _lzmaStream.NextOut = writePtr + _workBufPos; _lzmaStream.AvailOut = (uint)(_workBuf.Length - _workBufPos); LzmaRet ret = LzmaRet.Ok; while (ret != LzmaRet.StreamEnd) { ulong bakAvailOut = _lzmaStream.AvailOut; ret = XZInit.Lib.LzmaCode(_lzmaStream, LzmaAction.Finish); _workBufPos = (int)(bakAvailOut - _lzmaStream.AvailOut); // If the compression finished successfully, // write the data from the output buffer to the output file. if (_lzmaStream.AvailOut == 0 || ret == LzmaRet.StreamEnd) { // Write to _baseStream // When lzma_code() has returned LZMA_STREAM_END, the output buffer is likely to be only partially // full. Calculate how much new data there is to be written to the output file. BaseStream.Write(_workBuf, 0, _workBufPos); TotalOut += _workBufPos; // Reset NextOut and AvailOut _workBufPos = 0; _lzmaStream.NextOut = writePtr; _lzmaStream.AvailOut = (uint)_workBuf.Length; } else { // Once everything has been encoded successfully, the return value of lzma_code() will be LZMA_STREAM_END. XZException.CheckReturnValue(ret); } } } }
/// <summary> /// Create decompressing XZStream /// </summary> public unsafe XZStream(Stream baseStream, XZDecompressOptions decompOpts) { XZInit.Manager.EnsureLoaded(); BaseStream = baseStream ?? throw new ArgumentNullException(nameof(baseStream)); _mode = Mode.Decompress; _disposed = false; // Check and set decompress options _leaveOpen = decompOpts.LeaveOpen; _bufferSize = CheckBufferSize(decompOpts.BufferSize); _workBuf = new byte[_bufferSize]; // Prepare LzmaStream and buffers _lzmaStream = new LzmaStream(); _lzmaStreamPin = GCHandle.Alloc(_lzmaStream, GCHandleType.Pinned); // Initialize the decoder LzmaRet ret = XZInit.Lib.LzmaStreamDecoder(_lzmaStream, decompOpts.MemLimit, decompOpts.DecodeFlags); XZException.CheckReturnValue(ret); }
public unsafe int Read(Span <byte> span) #endif { // For Decompress if (_mode != Mode.Decompress) { throw new NotSupportedException("Read() not supported on compression"); } if (_workBufPos == ReadDone) { return(0); } int readSize = 0; LzmaAction action = LzmaAction.Run; fixed(byte *readPtr = _workBuf) fixed(byte *writePtr = span) { _lzmaStream.NextIn = readPtr + _workBufPos; _lzmaStream.NextOut = writePtr; _lzmaStream.AvailOut = (uint)span.Length; while (_lzmaStream.AvailOut != 0) { if (_lzmaStream.AvailIn == 0) { // Read from _baseStream int baseReadSize = BaseStream.Read(_workBuf, 0, _workBuf.Length); TotalIn += baseReadSize; _workBufPos = 0; _lzmaStream.NextIn = readPtr; _lzmaStream.AvailIn = (uint)baseReadSize; if (baseReadSize == 0) // End of stream { action = LzmaAction.Finish; } } ulong bakAvailIn = _lzmaStream.AvailIn; ulong bakAvailOut = _lzmaStream.AvailOut; LzmaRet ret = XZInit.Lib.LzmaCode(_lzmaStream, action); _workBufPos += (int)(bakAvailIn - _lzmaStream.AvailIn); readSize += (int)(bakAvailOut - _lzmaStream.AvailOut); // Once everything has been decoded successfully, the return value of lzma_code() will be LZMA_STREAM_END. if (ret == LzmaRet.StreamEnd) { _workBufPos = ReadDone; break; } // Normally the return value of lzma_code() will be LZMA_OK until everything has been encoded. XZException.CheckReturnValue(ret); } } TotalOut += readSize; return(readSize); }