protected override void Dispose(bool disposing) { if (_stream == null) { return; } var _lzma_stream = new lzma_stream(); _lzma_stream.next_in = next_in; _lzma_stream.next_out = next_out; _lzma_stream.avail_in = avail_in; _lzma_stream.avail_out = avail_out; _lzma_stream.allocator = allocator; _lzma_stream._internal = _internal; _lzma_stream.total_in = total_in; _lzma_stream.total_out = total_out; ManagedXZPInvoke.lzma_end(&_lzma_stream); Marshal.FreeHGlobal(_inbuf); Marshal.FreeHGlobal(_outbuf); //_stream.Close(); _stream.Dispose(); _stream = null; }
private void Init() { _inbuf = Marshal.AllocHGlobal(BUFSIZE); _outbuf = Marshal.AllocHGlobal(BUFSIZE); var _lzma_stream = new lzma_stream(); var r = ManagedXZPInvoke.lzma_auto_decoder(&_lzma_stream, ulong.MaxValue, LZMA_CONCATENATED); if (r != lzma_ret.LZMA_OK) { throw new Exception($"Can not create lzma stream: {r}"); } // init lzma_stream next_in = _inbuf; next_out = _outbuf; avail_in = UIntPtr.Zero; avail_out = (UIntPtr)BUFSIZE; allocator = _lzma_stream.allocator; _internal = _lzma_stream._internal; total_in = _lzma_stream.total_in; total_out = _lzma_stream.total_out; }
/// <summary> /// learn from 02_decompress.c /// </summary> /// <param name="buffer"></param> /// <param name="offset"></param> /// <param name="count"></param> /// <returns></returns> public override int Read(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(0); } int cTotalRead = 0; while (true) { // read from underlying stream if (avail_in == UIntPtr.Zero && action == lzma_action.LZMA_RUN) { // read more data from underlying stream var data = new byte[BUFSIZE]; var bytesRead = _stream.Read(data, 0, BUFSIZE); if (bytesRead < BUFSIZE) { action = lzma_action.LZMA_FINISH; // source stream has no more data } next_in = _inbuf; avail_in = (UIntPtr)bytesRead; Marshal.Copy(data, 0, _inbuf, bytesRead); } // try to read from existing outbuf int cReadable = BUFSIZE - (int)(uint)avail_out - read_pos; if (cReadable > 0) { var cCopy = Math.Min(cReadable, count - cTotalRead); var p = (IntPtr.Size == 8) ? new IntPtr(_outbuf.ToInt64() + read_pos) : new IntPtr(_outbuf.ToInt32() + read_pos); Marshal.Copy(p, buffer, offset + cTotalRead, cCopy); cTotalRead += cCopy; read_pos += cCopy; //Trace.Assert(cTotalRead <= count); if (cTotalRead == count) { return(cTotalRead); } } // need to read more data from outbuf // if previous decode returns LZMA_STREAM_END, there will be no more data if (ret == lzma_ret.LZMA_STREAM_END) { return(cTotalRead); } // otherwise, reset outbuf to recv more decompressed data from liblzma, or decompress is finished //Trace.Assert(read_pos + (uint)_lzma_stream.avail_out <= BUFSIZE); if (avail_out == UIntPtr.Zero && read_pos + (uint)avail_out == BUFSIZE) { next_out = _outbuf; avail_out = (UIntPtr)BUFSIZE; read_pos = 0; } var _lzma_stream = new lzma_stream(); _lzma_stream.next_in = next_in; _lzma_stream.next_out = next_out; _lzma_stream.avail_in = avail_in; _lzma_stream.avail_out = avail_out; _lzma_stream.allocator = allocator; _lzma_stream._internal = _internal; _lzma_stream.total_in = total_in; _lzma_stream.total_out = total_out; // do decompress ret = ManagedXZPInvoke.lzma_code(&_lzma_stream, action); if (ret != lzma_ret.LZMA_OK && ret != lzma_ret.LZMA_STREAM_END) { throw new Exception($"lzma_code returns {ret}"); } next_in = _lzma_stream.next_in; next_out = _lzma_stream.next_out; avail_in = _lzma_stream.avail_in; avail_out = _lzma_stream.avail_out; allocator = _lzma_stream.allocator; _internal = _lzma_stream._internal; total_in = _lzma_stream.total_in; total_out = _lzma_stream.total_out; } }