+++ /dev/null
-//\r
-// © Copyright Henrik Ravn 2004\r
-//\r
-// Use, modification and distribution are subject to the Boost Software License, Version 1.0.\r
-// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
-//\r
-\r
-using System;\r
-using System.IO;\r
-using System.Runtime.InteropServices;\r
-\r
-namespace DotZLib\r
-{\r
- /// <summary>\r
- /// Implements a compressed <see cref="Stream"/>, in GZip (.gz) format.\r
- /// </summary>\r
- public class GZipStream : Stream, IDisposable\r
- {\r
- #region Dll Imports\r
- [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl, CharSet=CharSet.Ansi)]\r
- private static extern IntPtr gzopen(string name, string mode);\r
-\r
- [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)]\r
- private static extern int gzclose(IntPtr gzFile);\r
-\r
- [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)]\r
- private static extern int gzwrite(IntPtr gzFile, int data, int length);\r
-\r
- [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)]\r
- private static extern int gzread(IntPtr gzFile, int data, int length);\r
-\r
- [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)]\r
- private static extern int gzgetc(IntPtr gzFile);\r
-\r
- [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)]\r
- private static extern int gzputc(IntPtr gzFile, int c);\r
-\r
- #endregion\r
-\r
- #region Private data\r
- private IntPtr _gzFile;\r
- private bool _isDisposed = false;\r
- private bool _isWriting;\r
- #endregion\r
-\r
- #region Constructors\r
- /// <summary>\r
- /// Creates a new file as a writeable GZipStream\r
- /// </summary>\r
- /// <param name="fileName">The name of the compressed file to create</param>\r
- /// <param name="level">The compression level to use when adding data</param>\r
- /// <exception cref="ZLibException">If an error occurred in the internal zlib function</exception>\r
- public GZipStream(string fileName, CompressLevel level)\r
- {\r
- _isWriting = true;\r
- _gzFile = gzopen(fileName, String.Format("wb{0}", (int)level));\r
- if (_gzFile == IntPtr.Zero)\r
- throw new ZLibException(-1, "Could not open " + fileName);\r
- }\r
-\r
- /// <summary>\r
- /// Opens an existing file as a readable GZipStream\r
- /// </summary>\r
- /// <param name="fileName">The name of the file to open</param>\r
- /// <exception cref="ZLibException">If an error occurred in the internal zlib function</exception>\r
- public GZipStream(string fileName)\r
- {\r
- _isWriting = false;\r
- _gzFile = gzopen(fileName, "rb");\r
- if (_gzFile == IntPtr.Zero)\r
- throw new ZLibException(-1, "Could not open " + fileName);\r
-\r
- }\r
- #endregion\r
-\r
- #region Access properties\r
- /// <summary>\r
- /// Returns true of this stream can be read from, false otherwise\r
- /// </summary>\r
- public override bool CanRead\r
- {\r
- get\r
- {\r
- return !_isWriting;\r
- }\r
- }\r
-\r
-\r
- /// <summary>\r
- /// Returns false.\r
- /// </summary>\r
- public override bool CanSeek\r
- {\r
- get\r
- {\r
- return false;\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// Returns true if this tsream is writeable, false otherwise\r
- /// </summary>\r
- public override bool CanWrite\r
- {\r
- get\r
- {\r
- return _isWriting;\r
- }\r
- }\r
- #endregion\r
-\r
- #region Destructor & IDispose stuff\r
-\r
- /// <summary>\r
- /// Destroys this instance\r
- /// </summary>\r
- ~GZipStream()\r
- {\r
- cleanUp(false);\r
- }\r
-\r
- /// <summary>\r
- /// Closes the external file handle\r
- /// </summary>\r
- public void Dispose()\r
- {\r
- cleanUp(true);\r
- }\r
-\r
- // Does the actual closing of the file handle.\r
- private void cleanUp(bool isDisposing)\r
- {\r
- if (!_isDisposed)\r
- {\r
- gzclose(_gzFile);\r
- _isDisposed = true;\r
- }\r
- }\r
- #endregion\r
-\r
- #region Basic reading and writing\r
- /// <summary>\r
- /// Attempts to read a number of bytes from the stream.\r
- /// </summary>\r
- /// <param name="buffer">The destination data buffer</param>\r
- /// <param name="offset">The index of the first destination byte in <c>buffer</c></param>\r
- /// <param name="count">The number of bytes requested</param>\r
- /// <returns>The number of bytes read</returns>\r
- /// <exception cref="ArgumentNullException">If <c>buffer</c> is null</exception>\r
- /// <exception cref="ArgumentOutOfRangeException">If <c>count</c> or <c>offset</c> are negative</exception>\r
- /// <exception cref="ArgumentException">If <c>offset</c> + <c>count</c> is > buffer.Length</exception>\r
- /// <exception cref="NotSupportedException">If this stream is not readable.</exception>\r
- /// <exception cref="ObjectDisposedException">If this stream has been disposed.</exception>\r
- public override int Read(byte[] buffer, int offset, int count)\r
- {\r
- if (!CanRead) throw new NotSupportedException();\r
- if (buffer == null) throw new ArgumentNullException();\r
- if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException();\r
- if ((offset+count) > buffer.Length) throw new ArgumentException();\r
- if (_isDisposed) throw new ObjectDisposedException("GZipStream");\r
-\r
- GCHandle h = GCHandle.Alloc(buffer, GCHandleType.Pinned);\r
- int result;\r
- try\r
- {\r
- result = gzread(_gzFile, h.AddrOfPinnedObject().ToInt32() + offset, count);\r
- if (result < 0)\r
- throw new IOException();\r
- }\r
- finally\r
- {\r
- h.Free();\r
- }\r
- return result;\r
- }\r
-\r
- /// <summary>\r
- /// Attempts to read a single byte from the stream.\r
- /// </summary>\r
- /// <returns>The byte that was read, or -1 in case of error or End-Of-File</returns>\r
- public override int ReadByte()\r
- {\r
- if (!CanRead) throw new NotSupportedException();\r
- if (_isDisposed) throw new ObjectDisposedException("GZipStream");\r
- return gzgetc(_gzFile);\r
- }\r
-\r
- /// <summary>\r
- /// Writes a number of bytes to the stream\r
- /// </summary>\r
- /// <param name="buffer"></param>\r
- /// <param name="offset"></param>\r
- /// <param name="count"></param>\r
- /// <exception cref="ArgumentNullException">If <c>buffer</c> is null</exception>\r
- /// <exception cref="ArgumentOutOfRangeException">If <c>count</c> or <c>offset</c> are negative</exception>\r
- /// <exception cref="ArgumentException">If <c>offset</c> + <c>count</c> is > buffer.Length</exception>\r
- /// <exception cref="NotSupportedException">If this stream is not writeable.</exception>\r
- /// <exception cref="ObjectDisposedException">If this stream has been disposed.</exception>\r
- public override void Write(byte[] buffer, int offset, int count)\r
- {\r
- if (!CanWrite) throw new NotSupportedException();\r
- if (buffer == null) throw new ArgumentNullException();\r
- if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException();\r
- if ((offset+count) > buffer.Length) throw new ArgumentException();\r
- if (_isDisposed) throw new ObjectDisposedException("GZipStream");\r
-\r
- GCHandle h = GCHandle.Alloc(buffer, GCHandleType.Pinned);\r
- try\r
- {\r
- int result = gzwrite(_gzFile, h.AddrOfPinnedObject().ToInt32() + offset, count);\r
- if (result < 0)\r
- throw new IOException();\r
- }\r
- finally\r
- {\r
- h.Free();\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// Writes a single byte to the stream\r
- /// </summary>\r
- /// <param name="value">The byte to add to the stream.</param>\r
- /// <exception cref="NotSupportedException">If this stream is not writeable.</exception>\r
- /// <exception cref="ObjectDisposedException">If this stream has been disposed.</exception>\r
- public override void WriteByte(byte value)\r
- {\r
- if (!CanWrite) throw new NotSupportedException();\r
- if (_isDisposed) throw new ObjectDisposedException("GZipStream");\r
-\r
- int result = gzputc(_gzFile, (int)value);\r
- if (result < 0)\r
- throw new IOException();\r
- }\r
- #endregion\r
-\r
- #region Position & length stuff\r
- /// <summary>\r
- /// Not supported.\r
- /// </summary>\r
- /// <param name="value"></param>\r
- /// <exception cref="NotSupportedException">Always thrown</exception>\r
- public override void SetLength(long value)\r
- {\r
- throw new NotSupportedException();\r
- }\r
-\r
- /// <summary>\r
- /// Not suppported.\r
- /// </summary>\r
- /// <param name="offset"></param>\r
- /// <param name="origin"></param>\r
- /// <returns></returns>\r
- /// <exception cref="NotSupportedException">Always thrown</exception>\r
- public override long Seek(long offset, SeekOrigin origin)\r
- {\r
- throw new NotSupportedException();\r
- }\r
-\r
- /// <summary>\r
- /// Flushes the <c>GZipStream</c>.\r
- /// </summary>\r
- /// <remarks>In this implementation, this method does nothing. This is because excessive\r
- /// flushing may degrade the achievable compression rates.</remarks>\r
- public override void Flush()\r
- {\r
- // left empty on purpose\r
- }\r
-\r
- /// <summary>\r
- /// Gets/sets the current position in the <c>GZipStream</c>. Not suppported.\r
- /// </summary>\r
- /// <remarks>In this implementation this property is not supported</remarks>\r
- /// <exception cref="NotSupportedException">Always thrown</exception>\r
- public override long Position\r
- {\r
- get\r
- {\r
- throw new NotSupportedException();\r
- }\r
- set\r
- {\r
- throw new NotSupportedException();\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// Gets the size of the stream. Not suppported.\r
- /// </summary>\r
- /// <remarks>In this implementation this property is not supported</remarks>\r
- /// <exception cref="NotSupportedException">Always thrown</exception>\r
- public override long Length\r
- {\r
- get\r
- {\r
- throw new NotSupportedException();\r
- }\r
- }\r
- #endregion\r
- }\r
-}\r