annotate src/zlib-1.2.8/contrib/dotzlib/DotZLib/GZipStream.cs @ 83:ae30d91d2ffe

Replace these with versions built using an older toolset (so as to avoid ABI compatibilities when linking on Ubuntu 14.04 for packaging purposes)
author Chris Cannam
date Fri, 07 Feb 2020 11:51:13 +0000
parents 5ea0608b923f
children
rev   line source
Chris@43 1 //
Chris@43 2 // © Copyright Henrik Ravn 2004
Chris@43 3 //
Chris@43 4 // Use, modification and distribution are subject to the Boost Software License, Version 1.0.
Chris@43 5 // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Chris@43 6 //
Chris@43 7
Chris@43 8 using System;
Chris@43 9 using System.IO;
Chris@43 10 using System.Runtime.InteropServices;
Chris@43 11
Chris@43 12 namespace DotZLib
Chris@43 13 {
Chris@43 14 /// <summary>
Chris@43 15 /// Implements a compressed <see cref="Stream"/>, in GZip (.gz) format.
Chris@43 16 /// </summary>
Chris@43 17 public class GZipStream : Stream, IDisposable
Chris@43 18 {
Chris@43 19 #region Dll Imports
Chris@43 20 [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl, CharSet=CharSet.Ansi)]
Chris@43 21 private static extern IntPtr gzopen(string name, string mode);
Chris@43 22
Chris@43 23 [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)]
Chris@43 24 private static extern int gzclose(IntPtr gzFile);
Chris@43 25
Chris@43 26 [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)]
Chris@43 27 private static extern int gzwrite(IntPtr gzFile, int data, int length);
Chris@43 28
Chris@43 29 [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)]
Chris@43 30 private static extern int gzread(IntPtr gzFile, int data, int length);
Chris@43 31
Chris@43 32 [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)]
Chris@43 33 private static extern int gzgetc(IntPtr gzFile);
Chris@43 34
Chris@43 35 [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)]
Chris@43 36 private static extern int gzputc(IntPtr gzFile, int c);
Chris@43 37
Chris@43 38 #endregion
Chris@43 39
Chris@43 40 #region Private data
Chris@43 41 private IntPtr _gzFile;
Chris@43 42 private bool _isDisposed = false;
Chris@43 43 private bool _isWriting;
Chris@43 44 #endregion
Chris@43 45
Chris@43 46 #region Constructors
Chris@43 47 /// <summary>
Chris@43 48 /// Creates a new file as a writeable GZipStream
Chris@43 49 /// </summary>
Chris@43 50 /// <param name="fileName">The name of the compressed file to create</param>
Chris@43 51 /// <param name="level">The compression level to use when adding data</param>
Chris@43 52 /// <exception cref="ZLibException">If an error occurred in the internal zlib function</exception>
Chris@43 53 public GZipStream(string fileName, CompressLevel level)
Chris@43 54 {
Chris@43 55 _isWriting = true;
Chris@43 56 _gzFile = gzopen(fileName, String.Format("wb{0}", (int)level));
Chris@43 57 if (_gzFile == IntPtr.Zero)
Chris@43 58 throw new ZLibException(-1, "Could not open " + fileName);
Chris@43 59 }
Chris@43 60
Chris@43 61 /// <summary>
Chris@43 62 /// Opens an existing file as a readable GZipStream
Chris@43 63 /// </summary>
Chris@43 64 /// <param name="fileName">The name of the file to open</param>
Chris@43 65 /// <exception cref="ZLibException">If an error occurred in the internal zlib function</exception>
Chris@43 66 public GZipStream(string fileName)
Chris@43 67 {
Chris@43 68 _isWriting = false;
Chris@43 69 _gzFile = gzopen(fileName, "rb");
Chris@43 70 if (_gzFile == IntPtr.Zero)
Chris@43 71 throw new ZLibException(-1, "Could not open " + fileName);
Chris@43 72
Chris@43 73 }
Chris@43 74 #endregion
Chris@43 75
Chris@43 76 #region Access properties
Chris@43 77 /// <summary>
Chris@43 78 /// Returns true of this stream can be read from, false otherwise
Chris@43 79 /// </summary>
Chris@43 80 public override bool CanRead
Chris@43 81 {
Chris@43 82 get
Chris@43 83 {
Chris@43 84 return !_isWriting;
Chris@43 85 }
Chris@43 86 }
Chris@43 87
Chris@43 88
Chris@43 89 /// <summary>
Chris@43 90 /// Returns false.
Chris@43 91 /// </summary>
Chris@43 92 public override bool CanSeek
Chris@43 93 {
Chris@43 94 get
Chris@43 95 {
Chris@43 96 return false;
Chris@43 97 }
Chris@43 98 }
Chris@43 99
Chris@43 100 /// <summary>
Chris@43 101 /// Returns true if this tsream is writeable, false otherwise
Chris@43 102 /// </summary>
Chris@43 103 public override bool CanWrite
Chris@43 104 {
Chris@43 105 get
Chris@43 106 {
Chris@43 107 return _isWriting;
Chris@43 108 }
Chris@43 109 }
Chris@43 110 #endregion
Chris@43 111
Chris@43 112 #region Destructor & IDispose stuff
Chris@43 113
Chris@43 114 /// <summary>
Chris@43 115 /// Destroys this instance
Chris@43 116 /// </summary>
Chris@43 117 ~GZipStream()
Chris@43 118 {
Chris@43 119 cleanUp(false);
Chris@43 120 }
Chris@43 121
Chris@43 122 /// <summary>
Chris@43 123 /// Closes the external file handle
Chris@43 124 /// </summary>
Chris@43 125 public void Dispose()
Chris@43 126 {
Chris@43 127 cleanUp(true);
Chris@43 128 }
Chris@43 129
Chris@43 130 // Does the actual closing of the file handle.
Chris@43 131 private void cleanUp(bool isDisposing)
Chris@43 132 {
Chris@43 133 if (!_isDisposed)
Chris@43 134 {
Chris@43 135 gzclose(_gzFile);
Chris@43 136 _isDisposed = true;
Chris@43 137 }
Chris@43 138 }
Chris@43 139 #endregion
Chris@43 140
Chris@43 141 #region Basic reading and writing
Chris@43 142 /// <summary>
Chris@43 143 /// Attempts to read a number of bytes from the stream.
Chris@43 144 /// </summary>
Chris@43 145 /// <param name="buffer">The destination data buffer</param>
Chris@43 146 /// <param name="offset">The index of the first destination byte in <c>buffer</c></param>
Chris@43 147 /// <param name="count">The number of bytes requested</param>
Chris@43 148 /// <returns>The number of bytes read</returns>
Chris@43 149 /// <exception cref="ArgumentNullException">If <c>buffer</c> is null</exception>
Chris@43 150 /// <exception cref="ArgumentOutOfRangeException">If <c>count</c> or <c>offset</c> are negative</exception>
Chris@43 151 /// <exception cref="ArgumentException">If <c>offset</c> + <c>count</c> is &gt; buffer.Length</exception>
Chris@43 152 /// <exception cref="NotSupportedException">If this stream is not readable.</exception>
Chris@43 153 /// <exception cref="ObjectDisposedException">If this stream has been disposed.</exception>
Chris@43 154 public override int Read(byte[] buffer, int offset, int count)
Chris@43 155 {
Chris@43 156 if (!CanRead) throw new NotSupportedException();
Chris@43 157 if (buffer == null) throw new ArgumentNullException();
Chris@43 158 if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException();
Chris@43 159 if ((offset+count) > buffer.Length) throw new ArgumentException();
Chris@43 160 if (_isDisposed) throw new ObjectDisposedException("GZipStream");
Chris@43 161
Chris@43 162 GCHandle h = GCHandle.Alloc(buffer, GCHandleType.Pinned);
Chris@43 163 int result;
Chris@43 164 try
Chris@43 165 {
Chris@43 166 result = gzread(_gzFile, h.AddrOfPinnedObject().ToInt32() + offset, count);
Chris@43 167 if (result < 0)
Chris@43 168 throw new IOException();
Chris@43 169 }
Chris@43 170 finally
Chris@43 171 {
Chris@43 172 h.Free();
Chris@43 173 }
Chris@43 174 return result;
Chris@43 175 }
Chris@43 176
Chris@43 177 /// <summary>
Chris@43 178 /// Attempts to read a single byte from the stream.
Chris@43 179 /// </summary>
Chris@43 180 /// <returns>The byte that was read, or -1 in case of error or End-Of-File</returns>
Chris@43 181 public override int ReadByte()
Chris@43 182 {
Chris@43 183 if (!CanRead) throw new NotSupportedException();
Chris@43 184 if (_isDisposed) throw new ObjectDisposedException("GZipStream");
Chris@43 185 return gzgetc(_gzFile);
Chris@43 186 }
Chris@43 187
Chris@43 188 /// <summary>
Chris@43 189 /// Writes a number of bytes to the stream
Chris@43 190 /// </summary>
Chris@43 191 /// <param name="buffer"></param>
Chris@43 192 /// <param name="offset"></param>
Chris@43 193 /// <param name="count"></param>
Chris@43 194 /// <exception cref="ArgumentNullException">If <c>buffer</c> is null</exception>
Chris@43 195 /// <exception cref="ArgumentOutOfRangeException">If <c>count</c> or <c>offset</c> are negative</exception>
Chris@43 196 /// <exception cref="ArgumentException">If <c>offset</c> + <c>count</c> is &gt; buffer.Length</exception>
Chris@43 197 /// <exception cref="NotSupportedException">If this stream is not writeable.</exception>
Chris@43 198 /// <exception cref="ObjectDisposedException">If this stream has been disposed.</exception>
Chris@43 199 public override void Write(byte[] buffer, int offset, int count)
Chris@43 200 {
Chris@43 201 if (!CanWrite) throw new NotSupportedException();
Chris@43 202 if (buffer == null) throw new ArgumentNullException();
Chris@43 203 if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException();
Chris@43 204 if ((offset+count) > buffer.Length) throw new ArgumentException();
Chris@43 205 if (_isDisposed) throw new ObjectDisposedException("GZipStream");
Chris@43 206
Chris@43 207 GCHandle h = GCHandle.Alloc(buffer, GCHandleType.Pinned);
Chris@43 208 try
Chris@43 209 {
Chris@43 210 int result = gzwrite(_gzFile, h.AddrOfPinnedObject().ToInt32() + offset, count);
Chris@43 211 if (result < 0)
Chris@43 212 throw new IOException();
Chris@43 213 }
Chris@43 214 finally
Chris@43 215 {
Chris@43 216 h.Free();
Chris@43 217 }
Chris@43 218 }
Chris@43 219
Chris@43 220 /// <summary>
Chris@43 221 /// Writes a single byte to the stream
Chris@43 222 /// </summary>
Chris@43 223 /// <param name="value">The byte to add to the stream.</param>
Chris@43 224 /// <exception cref="NotSupportedException">If this stream is not writeable.</exception>
Chris@43 225 /// <exception cref="ObjectDisposedException">If this stream has been disposed.</exception>
Chris@43 226 public override void WriteByte(byte value)
Chris@43 227 {
Chris@43 228 if (!CanWrite) throw new NotSupportedException();
Chris@43 229 if (_isDisposed) throw new ObjectDisposedException("GZipStream");
Chris@43 230
Chris@43 231 int result = gzputc(_gzFile, (int)value);
Chris@43 232 if (result < 0)
Chris@43 233 throw new IOException();
Chris@43 234 }
Chris@43 235 #endregion
Chris@43 236
Chris@43 237 #region Position & length stuff
Chris@43 238 /// <summary>
Chris@43 239 /// Not supported.
Chris@43 240 /// </summary>
Chris@43 241 /// <param name="value"></param>
Chris@43 242 /// <exception cref="NotSupportedException">Always thrown</exception>
Chris@43 243 public override void SetLength(long value)
Chris@43 244 {
Chris@43 245 throw new NotSupportedException();
Chris@43 246 }
Chris@43 247
Chris@43 248 /// <summary>
Chris@43 249 /// Not suppported.
Chris@43 250 /// </summary>
Chris@43 251 /// <param name="offset"></param>
Chris@43 252 /// <param name="origin"></param>
Chris@43 253 /// <returns></returns>
Chris@43 254 /// <exception cref="NotSupportedException">Always thrown</exception>
Chris@43 255 public override long Seek(long offset, SeekOrigin origin)
Chris@43 256 {
Chris@43 257 throw new NotSupportedException();
Chris@43 258 }
Chris@43 259
Chris@43 260 /// <summary>
Chris@43 261 /// Flushes the <c>GZipStream</c>.
Chris@43 262 /// </summary>
Chris@43 263 /// <remarks>In this implementation, this method does nothing. This is because excessive
Chris@43 264 /// flushing may degrade the achievable compression rates.</remarks>
Chris@43 265 public override void Flush()
Chris@43 266 {
Chris@43 267 // left empty on purpose
Chris@43 268 }
Chris@43 269
Chris@43 270 /// <summary>
Chris@43 271 /// Gets/sets the current position in the <c>GZipStream</c>. Not suppported.
Chris@43 272 /// </summary>
Chris@43 273 /// <remarks>In this implementation this property is not supported</remarks>
Chris@43 274 /// <exception cref="NotSupportedException">Always thrown</exception>
Chris@43 275 public override long Position
Chris@43 276 {
Chris@43 277 get
Chris@43 278 {
Chris@43 279 throw new NotSupportedException();
Chris@43 280 }
Chris@43 281 set
Chris@43 282 {
Chris@43 283 throw new NotSupportedException();
Chris@43 284 }
Chris@43 285 }
Chris@43 286
Chris@43 287 /// <summary>
Chris@43 288 /// Gets the size of the stream. Not suppported.
Chris@43 289 /// </summary>
Chris@43 290 /// <remarks>In this implementation this property is not supported</remarks>
Chris@43 291 /// <exception cref="NotSupportedException">Always thrown</exception>
Chris@43 292 public override long Length
Chris@43 293 {
Chris@43 294 get
Chris@43 295 {
Chris@43 296 throw new NotSupportedException();
Chris@43 297 }
Chris@43 298 }
Chris@43 299 #endregion
Chris@43 300 }
Chris@43 301 }