/* This file is part of SevenZipSharp. SevenZipSharp is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. SevenZipSharp is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SevenZipSharp. If not, see . */ #define DOTNET20 #define UNMANAGED #define COMPRESS using System; using System.IO; using SevenZip.Sdk.Compression.Lzma; namespace SevenZip { #if LZMA_STREAM /// /// The stream which decompresses data with LZMA on the fly. /// public class LzmaDecodeStream : Stream { private readonly MemoryStream _buffer = new MemoryStream(); private readonly Decoder _decoder = new Decoder(); private readonly Stream _input; private byte[] _commonProperties; private bool _error; private bool _firstChunkRead; /// /// Initializes a new instance of the LzmaDecodeStream class. /// /// A compressed stream. public LzmaDecodeStream(Stream encodedStream) { if (!encodedStream.CanRead) { throw new ArgumentException("The specified stream can not read.", "encodedStream"); } _input = encodedStream; } /// /// Gets the chunk size. /// public int ChunkSize { get { return (int) _buffer.Length; } } /// /// Gets a value indicating whether the current stream supports reading. /// public override bool CanRead { get { return true; } } /// /// Gets a value indicating whether the current stream supports seeking. /// public override bool CanSeek { get { return false; } } /// /// Gets a value indicating whether the current stream supports writing. /// public override bool CanWrite { get { return false; } } /// /// Gets the length in bytes of the output stream. /// public override long Length { get { if (_input.CanSeek) { return _input.Length; } return _buffer.Length; } } /// /// Gets or sets the position within the output stream. /// public override long Position { get { if (_input.CanSeek) { return _input.Position; } return _buffer.Position; } set { throw new NotSupportedException(); } } private void ReadChunk() { long size; byte[] properties; try { properties = SevenZipExtractor.GetLzmaProperties(_input, out size); } catch (LzmaException) { _error = true; return; } if (!_firstChunkRead) { _commonProperties = properties; } if (_commonProperties[0] != properties[0] || _commonProperties[1] != properties[1] || _commonProperties[2] != properties[2] || _commonProperties[3] != properties[3] || _commonProperties[4] != properties[4]) { _error = true; return; } if (_buffer.Capacity < (int) size) { _buffer.Capacity = (int) size; } _buffer.SetLength(size); _decoder.SetDecoderProperties(properties); _buffer.Position = 0; _decoder.Code( _input, _buffer, 0, size, null); _buffer.Position = 0; } /// /// Does nothing. /// public override void Flush() {} /// /// Reads a sequence of bytes from the current stream and decompresses data if necessary. /// /// An array of bytes. /// The zero-based byte offset in buffer at which to begin storing the data read from the current stream. /// The maximum number of bytes to be read from the current stream. /// The total number of bytes read into the buffer. public override int Read(byte[] buffer, int offset, int count) { if (_error) { return 0; } if (!_firstChunkRead) { ReadChunk(); _firstChunkRead = true; } int readCount = 0; while (count > _buffer.Length - _buffer.Position && !_error) { var buf = new byte[_buffer.Length - _buffer.Position]; _buffer.Read(buf, 0, buf.Length); buf.CopyTo(buffer, offset); offset += buf.Length; count -= buf.Length; readCount += buf.Length; ReadChunk(); } if (!_error) { _buffer.Read(buffer, offset, count); readCount += count; } return readCount; } /// /// Sets the position within the current stream. /// /// A byte offset relative to the origin parameter. /// A value of type System.IO.SeekOrigin indicating the reference point used to obtain the new position. /// The new position within the current stream. public override long Seek(long offset, SeekOrigin origin) { throw new NotSupportedException(); } /// /// Sets the length of the current stream. /// /// The desired length of the current stream in bytes. public override void SetLength(long value) { throw new NotSupportedException(); } /// /// Writes a sequence of bytes to the current stream. /// /// An array of bytes. /// The zero-based byte offset in buffer at which to begin storing the data read from the current stream. /// The maximum number of bytes to be read from the current stream. public override void Write(byte[] buffer, int offset, int count) { throw new NotSupportedException(); } } #endif }