/// <summary>
        /// Writes a number of bytes to the stream
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="length"></param>
        /// <param name="offset"></param>
        /// <param name="count"></param>
        /// <exception cref="ArgumentNullException">If <c>buffer</c> is null</exception>
        /// <exception cref="ArgumentOutOfRangeException">If <c>count</c> or <c>offset</c> are negative</exception>
        /// <exception cref="ArgumentException">If <c>offset</c>  + <c>count</c> is &gt; buffer.Length</exception>
        /// <exception cref="NotSupportedException">If this stream is not writeable.</exception>
        /// <exception cref="ObjectDisposedException">If this stream has been disposed.</exception>
        public unsafe void Write(byte *buffer, int length, int offset, int count)
        {
            if (!CanWrite)
            {
                throw new NotSupportedException();
            }
            if (buffer == null)
            {
                throw new ArgumentNullException();
            }
            if (offset < 0 || count < 0)
            {
                throw new ArgumentOutOfRangeException();
            }
            if ((offset + count) > length)
            {
                throw new ArgumentException();
            }
            if (_isDisposed)
            {
                throw new ObjectDisposedException("GZipStream");
            }

            var result = ZLibNative.gzwrite(_gzFile, buffer + offset, count);

            if (result < 0)
            {
                throw new IOException();
            }
        }
        /// <summary>Closes the current stream and releases any resources (such as sockets and file handles) associated with the current stream.</summary>
        public unsafe override void Close()
        {
            if (_isClosed)
            {
                return;
            }
            _isClosed = true;
            if (_mode == CompressionMode.Compress)
            {
                if (_writeAfterReset)
                {
                    Write(null, 0, ZLibFlush.Finish);
                }
                ZLibNative.deflateEnd(ref _zstream);
            }
            else
            {
                ZLibNative.inflateEnd(ref _zstream);
            }

            if (CloseUnderlyingStream)
            {
                _stream.Close();
            }

            _tmpBufferHandle.Free();
            base.Close();
        }
 // Does the actual closing of the file handle.
 void CleanUp(bool isDisposing)
 {
     if (_isDisposed)
     {
         return;
     }
     ZLibNative.gzclose(_gzFile);
     _isDisposed = true;
 }
 /// <summary>
 /// Attempts to read a single byte from the stream.
 /// </summary>
 /// <returns>The byte that was read, or -1 in case of error or End-Of-File</returns>
 public override int ReadByte()
 {
     if (!CanRead)
     {
         throw new NotSupportedException();
     }
     if (_isDisposed)
     {
         throw new ObjectDisposedException("GZipStream");
     }
     return(ZLibNative.gzgetc(_gzFile));
 }
        /// <exception cref="NotSupportedException">The stream must be in decompress mode to read from.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="p"/> is <see langword="null" />.</exception>
        /// <exception cref="ArgumentOutOfRangeException">length cannot be negative.</exception>
        /// <exception cref="ObjectDisposedException">The method cannot be called after the object has been disposed.</exception>
        public unsafe int Read(byte *p, int length)
        {
            if (!CanRead)
            {
                throw new NotSupportedException($"{nameof(GZipStream)} must be in decompress mode to read from");
            }
            if (p == null)
            {
                throw new ArgumentNullException(nameof(p));
            }
            if (length < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(length), "length cannot be negative");
            }
            if (_isDisposed)
            {
                throw new ObjectDisposedException(nameof(GZipStream));
            }
            Contract.EndContractBlock();

            var exitLoop = false;

            _zstream.next_out  = p;
            _zstream.avail_out = (uint)length;

            while (_zstream.avail_out > 0 && exitLoop == false)
            {
                if (_zstream.avail_in == 0)
                {
                    var readLength = _stream.Read(_tmpBuffer, 0, _tmpBuffer.Length);
                    _zstream.avail_in = (uint)readLength;
                    _zstream.next_in  = (byte *)_tmpBufferPtr;
                }
                var result = ZLibNative.inflate(ref _zstream, ZLibFlush.NoFlush);
                switch (result)
                {
                case ZLibReturnCode.StreamEnd:
                    exitLoop = true;
                    break;

                case ZLibReturnCode.Ok:
                    break;

                case ZLibReturnCode.MemError:
                    throw new OutOfMemoryException($"ZLib return code: {result}");

                default:
                    throw new Exception($"ZLib return code: {result}");
                }
            }

            return(length - (int)_zstream.avail_out);
        }
        unsafe void Write(byte *buffer, int count, ZLibFlush flush)
        {
            if (_mode == CompressionMode.Decompress)
            {
                throw new NotSupportedException("Can't write on a decompress stream!");
            }

            // This indicates that we need to go through a "Finish" write when closing/reseting
            _writeAfterReset = true;

            _zstream.avail_in = (uint)count;
            _zstream.next_in  = buffer;
            uint availOut;

            do
            {
                var result = ZLibNative.deflate(ref _zstream, flush);
                availOut = _zstream.avail_out;
                if (availOut < BufferSize)
                {
                    var outSize = BufferSize - availOut;
                    _stream.Write(_tmpBuffer, 0, (int)outSize);
                    _zstream.next_out  = (byte *)_tmpBufferPtr;
                    _zstream.avail_out = BufferSize;
                }
                // Translate erros into specific exceptions
                switch (result)
                {
                case ZLibReturnCode.Ok:
                    continue;

                case ZLibReturnCode.StreamEnd:
                    return;

                case ZLibReturnCode.MemError:
                    throw new OutOfMemoryException("zlib return code: " + result);

                default:
                    throw new Exception("zlib return code: " + result);
                }
                // We go one for two reasons:
                // 1. There's still more input available
                // 2. We're in some FLUSH/FINISH scenario
                //    and the output buffer has no sufficient space left
            } while ((_zstream.avail_in > 0) ||
                     (flush != ZLibFlush.NoFlush && availOut == 0));
        }
        /// <summary>Initializes a new instance of the GZipStream class using the specified stream and BZip2CompressionMode value.</summary>
        /// <param name="stream">The stream to compress or decompress.</param>
        /// <param name="mode">One of the BZip2CompressionMode values that indicates the action to take.</param>
        /// <param name="options">The Gzip Options</param>ll
        public unsafe GZipStream(Stream stream, CompressionMode mode, GZipOptions options)
        {
            if (stream == null)
            {
                throw new ArgumentNullException("stream");
            }

            _stream = stream;
            _mode   = mode;

            _zstream.zalloc = null;
            _zstream.zfree  = null;
            _zstream.opaque = null;

            _tmpBuffer       = new byte[BufferSize];
            _tmpBufferHandle = GCHandle.Alloc(_tmpBuffer, GCHandleType.Pinned);
            _tmpBufferPtr    = _tmpBufferHandle.AddrOfPinnedObject().ToPointer();
            ZLibReturnCode ret;

            switch (mode)
            {
            case CompressionMode.Compress:
                ret = ZLibNative.deflateInit2_(ref _zstream,
                                               options.Level, options.Method, options.WindowBits,
                                               options.MemoryLevel, (int)options.Strategy,
                                               ZLibVersion, Marshal.SizeOf(typeof(ZStream)));

                if (ret != ZLibReturnCode.Ok)
                {
                    throw new ArgumentException("Unable to init ZLib. Return code: " + ret);
                }

                _zstream.next_out  = (byte *)_tmpBufferPtr;
                _zstream.avail_out = (uint)_tmpBuffer.Length;
                break;

            case CompressionMode.Decompress:
                ret = ZLibNative.inflateInit2_(ref _zstream, options.WindowBits, ZLibVersion, Marshal.SizeOf(typeof(ZStream)));

                if (ret != ZLibReturnCode.Ok)
                {
                    throw new ArgumentException("Unable to init ZLib. Return code: " + ret);
                }
                break;
            }
        }
 /// <summary>Closes the current stream and releases any resources (such as sockets and file handles) associated with the current stream.</summary>
 public unsafe void Reset()
 {
     if (_isClosed)
     {
         return;
     }
     if (_mode == CompressionMode.Compress)
     {
         if (_writeAfterReset)
         {
             Write(null, 0, ZLibFlush.Finish);
         }
         _writeAfterReset = false;
         ZLibNative.deflateReset(ref _zstream);
     }
     else
     {
         ZLibNative.inflateReset(ref _zstream);
     }
 }
        /// <summary>
        /// Opens an existing file as a readable GZipFileStream
        /// </summary>
        /// <param name="fileName">The name of the file to open</param>
        /// <param name="access">The file access pattern</param>
        /// <param name="level">The compression level to use</param>
        /// <exception cref="ZLibException">If an error occurred in the internal zlib function</exception>
        public GZipFileStream(string fileName, FileAccess access, CompressLevel level)
        {
            switch (access)
            {
            case FileAccess.Read:
                _isWriting = false;
                _gzFile    = ZLibNative.gzopen(fileName, "rb");
                break;

            case FileAccess.Write:
                _isWriting = true;
                _gzFile    = ZLibNative.gzopen(fileName, String.Format("wb{0}", (int)level));
                break;

            case FileAccess.ReadWrite:
                throw new ArgumentException(String.Format("{0} cannot be used with {1}", access, GetType().FullName), "access");
            }
            if (_gzFile == IntPtr.Zero)
            {
                throw new ZLibException(-1, "Could not open " + fileName);
            }
        }
Esempio n. 10
0
 /// <summary>
 /// Constructs an instance of the <c>ZLibInfo</c> class.
 /// </summary>
 public ZLibInfo()
 {
     _flags = ZLibNative.zlibCompileFlags();
 }