Exemplo n.º 1
0
        /// <summary>
        /// learn from 01_compress_easy.c
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="offset"></param>
        /// <param name="count"></param>
        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)
                {
                    var data = ArrayPool <byte> .Shared.Rent(BUFSIZE);

                    Marshal.Copy(_outbuf, data, 0, BUFSIZE);
                    _stream.Write(data, 0, BUFSIZE);
                    ArrayPool <byte> .Shared.Return(data);

                    // Reset next_out and avail_out.
                    _lzma_stream.next_out  = _outbuf;
                    _lzma_stream.avail_out = (UIntPtr)BUFSIZE;
                }
            }
        }