예제 #1
0
        /// <summary>
        /// Initializes a new instance of the <see cref="XZInputStream"/> class.
        /// </summary>
        /// <param name="stream">
        /// The underlying <see cref="Stream"/> from which to decompress the data.
        /// </param>
        /// <param name="format">
        /// The lzma formats which are supported.
        /// </param>
        /// <param name="ownership">
        /// Determines whether the underlying stream should be disposed of, or not.
        /// </param>
        public XZInputStream(Stream stream, LzmaFormat format = LzmaFormat.Auto, Ownership ownership = Ownership.None)
        {
            this.innerStream = stream ?? throw new ArgumentNullException(nameof(stream));
            this.ownership   = ownership;

            LzmaResult ret;

            switch (format)
            {
            case LzmaFormat.Lzma:
                ret = NativeMethods.lzma_alone_decoder(ref this.lzmaStream, ulong.MaxValue);
                break;

            case LzmaFormat.Xz:
                ret = NativeMethods.lzma_stream_decoder(ref this.lzmaStream, ulong.MaxValue, LzmaDecodeFlags.Concatenated);
                break;

            default:
            case LzmaFormat.Auto:
                ret = NativeMethods.lzma_auto_decoder(ref this.lzmaStream, ulong.MaxValue, LzmaDecodeFlags.Concatenated);
                break;
            }

            this.inbuf  = Marshal.AllocHGlobal(BufSize);
            this.outbuf = Marshal.AllocHGlobal(BufSize);

            this.lzmaStream.AvailIn  = 0;
            this.lzmaStream.NextIn   = (byte *)this.inbuf;
            this.lzmaStream.NextOut  = (byte *)this.outbuf;
            this.lzmaStream.AvailOut = BufSize;

            LzmaException.ThrowOnError(ret);
        }
예제 #2
0
        /// <summary>
        /// Reads bytes from stream.
        /// </summary>
        /// <param name="buffer">
        /// The buffer into which to read the data.
        /// </param>
        /// <param name="offset">
        /// The offset at which to start writing the data.
        /// </param>
        /// <param name="count">
        /// The number of bytes to read.
        /// </param>
        /// <returns>byte read or -1 on end of stream.</returns>
        public unsafe override int Read(byte[] buffer, int offset, int count)
        {
            Verify.NotDisposed(this);

            // Make sure data is available in the output buffer.
            while ((int)this.lzmaStream.AvailOut == BufSize - this.outbufProcessed)
            {
                LzmaAction action = LzmaAction.Run;

                if (this.lzmaStream.AvailOut == 0)
                {
                    this.lzmaStream.AvailOut = BufSize;
                    this.lzmaStream.NextOut  = (byte *)this.outbuf;
                    this.outbufProcessed     = 0;
                }

                if (this.lzmaStream.AvailIn == 0)
                {
                    Span <byte> inputBuffer = new Span <byte>((void *)this.inbuf, BufSize);
                    this.lzmaStream.AvailIn = (uint)this.innerStream.Read(inputBuffer);
                    this.lzmaStream.NextIn  = (byte *)this.inbuf;

                    if (this.lzmaStream.AvailIn == 0)
                    {
                        action = LzmaAction.Finish;
                    }
                }

                // Decode the data.
                var ret = NativeMethods.lzma_code(ref this.lzmaStream, action);

                if (ret == LzmaResult.StreamEnd)
                {
                    break;
                }
                else if (ret != LzmaResult.OK)
                {
                    NativeMethods.lzma_end(ref this.lzmaStream);
                    LzmaException.ThrowOnError(ret);
                }
            }

            // Get the amount of data which can be copied
            var canRead = Math.Min(
                BufSize - (int)this.lzmaStream.AvailOut - this.outbufProcessed,
                count);

            var source = new Span <byte>((byte *)this.outbuf + this.outbufProcessed, canRead);
            var target = new Span <byte>(buffer, offset, canRead);

            source.CopyTo(target);

            this.outbufProcessed += canRead;
            this.position        += canRead;

            return(canRead);
        }
예제 #3
0
        public XZOutputStream(Stream stream, int threads, uint preset, bool leaveOpen)
        {
            if (stream == null)
            {
                throw new ArgumentNullException(nameof(stream));
            }

            this.innerStream = stream;
            this.leaveOpen   = leaveOpen;

            LzmaResult ret;

            if (threads == 1 || !NativeMethods.SupportsMultiThreading)
            {
                ret = NativeMethods.lzma_easy_encoder(ref this.lzmaStream, preset, LzmaCheck.Crc64);
            }
            else
            {
                if (threads <= 0)
                {
                    throw new ArgumentOutOfRangeException(nameof(threads));
                }

                if (threads > Environment.ProcessorCount)
                {
                    Trace.TraceWarning("{0} threads required, but only {1} processors available", threads, Environment.ProcessorCount);
                    threads = Environment.ProcessorCount;
                }

                var mt = new LzmaMT()
                {
                    preset  = preset,
                    check   = LzmaCheck.Crc64,
                    threads = (uint)threads,
                };
                ret = NativeMethods.lzma_stream_encoder_mt(ref this.lzmaStream, ref mt);
            }

            if (ret == LzmaResult.OK)
            {
                this.outbuf = new byte[BufSize];
                this.lzmaStream.AvailOut = BufSize;
                return;
            }

            GC.SuppressFinalize(this);
            LzmaException.ThrowOnError(ret);
        }
예제 #4
0
        public static byte[] Encode(byte[] buffer, uint preset = DefaultPreset)
        {
            var res = new byte[(long)NativeMethods.lzma_stream_buffer_bound((UIntPtr)buffer.Length)];

            UIntPtr outPos;
            var     ret = NativeMethods.lzma_easy_buffer_encode(preset, LzmaCheck.Crc64, null, buffer, (UIntPtr)buffer.Length, res, &outPos, (UIntPtr)res.Length);

            LzmaException.ThrowOnError(ret);

            if ((long)outPos < res.Length)
            {
                Array.Resize(ref res, (int)(ulong)outPos);
            }

            return(res);
        }
예제 #5
0
        public override void Write(byte[] buffer, int offset, int count)
        {
            Verify.NotDisposed(this);

            if (count == 0)
            {
                return;
            }

            var guard = buffer[checked ((uint)offset + (uint)count) - 1];

            if (this.lzmaStream.AvailIn != 0)
            {
                throw new InvalidOperationException();
            }

            this.lzmaStream.AvailIn = (uint)count;
            do
            {
                LzmaResult ret;
                fixed(byte *inbuf = &buffer[offset])
                {
                    this.lzmaStream.NextIn = inbuf;
                    fixed(byte *outbuf = &this.outbuf[BufSize - this.lzmaStream.AvailOut])
                    {
                        this.lzmaStream.NextOut = outbuf;
                        ret = NativeMethods.lzma_code(ref this.lzmaStream, LzmaAction.Run);
                    }

                    offset += (int)((ulong)this.lzmaStream.NextIn - (ulong)(IntPtr)inbuf);
                }

                if (ret != LzmaResult.OK)
                {
                    NativeMethods.lzma_end(ref this.lzmaStream);
                    LzmaException.ThrowOnError(ret);
                }

                if (this.lzmaStream.AvailOut == 0)
                {
                    this.innerStream.Write(this.outbuf, 0, BufSize);
                    this.lzmaStream.AvailOut = BufSize;
                }
            }while (this.lzmaStream.AvailIn != 0);
        }
예제 #6
0
        protected override void Dispose(bool disposing)
        {
            // finish encoding only if all input has been successfully processed
            if (this.lzmaStream.InternalState != null && this.lzmaStream.AvailIn == 0)
            {
                LzmaResult ret;
                do
                {
                    fixed(byte *outbuf = &this.outbuf[BufSize - (int)this.lzmaStream.AvailOut])
                    {
                        this.lzmaStream.NextOut = outbuf;
                        ret = NativeMethods.lzma_code(ref this.lzmaStream, LzmaAction.Finish);
                    }

                    if (ret > LzmaResult.StreamEnd)
                    {
                        NativeMethods.lzma_end(ref this.lzmaStream);
                        LzmaException.ThrowOnError(ret);
                    }

                    var writeSize = BufSize - (int)this.lzmaStream.AvailOut;

                    if (writeSize != 0)
                    {
                        this.innerStream.Write(this.outbuf, 0, writeSize);
                        this.lzmaStream.AvailOut = BufSize;
                    }
                }while (ret != LzmaResult.StreamEnd);
            }

            NativeMethods.lzma_end(ref this.lzmaStream);

            if (disposing && !this.leaveOpen)
            {
                this.innerStream?.Dispose();
            }

            base.Dispose(disposing);

            this.IsDisposed = true;
        }
예제 #7
0
        /// <summary>
        /// Initializes a new instance of the <see cref="XZDecompressor" /> class.
        /// </summary>
        /// <param name="format">
        /// The format of the data to decompress.
        /// </param>
        public XZDecompressor(LzmaFormat format = LzmaFormat.Auto)
        {
            LzmaResult ret;

            switch (format)
            {
            case LzmaFormat.Lzma:
                ret = NativeMethods.lzma_alone_decoder(ref this.lzmaStream, ulong.MaxValue);
                break;

            case LzmaFormat.Xz:
                ret = NativeMethods.lzma_stream_decoder(ref this.lzmaStream, ulong.MaxValue, LzmaDecodeFlags.Concatenated);
                break;

            default:
            case LzmaFormat.Auto:
                ret = NativeMethods.lzma_auto_decoder(ref this.lzmaStream, ulong.MaxValue, LzmaDecodeFlags.Concatenated);
                break;
            }

            LzmaException.ThrowOnError(ret);
        }