/// <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 (_lzma_stream.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
                    _lzma_stream.next_in = _inbuf;
                    _lzma_stream.avail_in = (UIntPtr)bytesRead;
                    Marshal.Copy(data, 0, _inbuf, bytesRead);
                }

                // try to read from existing outbuf
                int cReadable = BUFSIZE - (int)(uint)_lzma_stream.avail_out - read_pos;
                if (cReadable > 0)
                {
                    var cCopy = Math.Min(cReadable, count - cTotalRead);
                    var p = Native.Is64Bit ? 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 (_lzma_stream.avail_out == UIntPtr.Zero && read_pos + (uint)_lzma_stream.avail_out == BUFSIZE)
                {
                    _lzma_stream.next_out = _outbuf;
                    _lzma_stream.avail_out = (UIntPtr)BUFSIZE;
                    read_pos = 0;
                }

                // do decompress
                ret = Native.lzma_code(_lzma_stream, action);
                if (ret != lzma_ret.LZMA_OK && ret != lzma_ret.LZMA_STREAM_END)
                    throw new Exception($"lzma_code returns {ret}");
            }
        }
Exemple #2
0
        /// <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 (_lzma_stream.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 == 0)
                    {
                        action = lzma_action.LZMA_FINISH;                 // source stream has no more data
                    }
                    _lzma_stream.next_in  = _inbuf;
                    _lzma_stream.avail_in = (UIntPtr)bytesRead;
                    Marshal.Copy(data, 0, _inbuf, bytesRead);
                }

                // try to read from existing outbuf
                int cReadable = BUFSIZE - (int)(uint)_lzma_stream.avail_out - read_pos;
                if (cReadable > 0)
                {
                    var cCopy = Math.Min(cReadable, count - cTotalRead);
                    var p     = Native.Is64Bit ? 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 (_lzma_stream.avail_out == UIntPtr.Zero && read_pos + (uint)_lzma_stream.avail_out == BUFSIZE)
                {
                    _lzma_stream.next_out  = _outbuf;
                    _lzma_stream.avail_out = (UIntPtr)BUFSIZE;
                    read_pos = 0;
                }

                // do decompress
                ret = Native.lzma_code(_lzma_stream, action);
                if (ret != lzma_ret.LZMA_OK && ret != lzma_ret.LZMA_STREAM_END)
                {
                    throw new Exception($"lzma_code returns {ret}");
                }
            }
        }
Exemple #3
0
 public static extern lzma_ret lzma_code(lzma_stream *strm, lzma_action action);