1 //
   2 // © Copyright Henrik Ravn 2004
   3 //
   4 // Use, modification and distribution are subject to the Boost Software License, Version 1.0.
   5 // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
   6 //
   7 
   8 using System;
   9 using System.IO;
  10 using System.Runtime.InteropServices;
  11 using System.Text;
  12 
  13 
  14 namespace DotZLib
  15 {
  16 
  17     #region Internal types
  18 
  19     /// <summary>
  20     /// Defines constants for the various flush types used with zlib
  21     /// </summary>
  22     internal enum FlushTypes
  23     {
  24         None,  Partial,  Sync,  Full,  Finish,  Block
  25     }
  26 
  27     #region ZStream structure
  28     // internal mapping of the zlib zstream structure for marshalling
  29     [StructLayoutAttribute(LayoutKind.Sequential, Pack=4, Size=0, CharSet=CharSet.Ansi)]
  30     internal struct ZStream
  31     {
  32         public IntPtr next_in;
  33         public uint avail_in;
  34         public uint total_in;
  35 
  36         public IntPtr next_out;
  37         public uint avail_out;
  38         public uint total_out;
  39 
  40         [MarshalAs(UnmanagedType.LPStr)]
  41         string msg;
  42         uint state;
  43 
  44         uint zalloc;
  45         uint zfree;
  46         uint opaque;
  47 
  48         int data_type;
  49         public uint adler;
  50         uint reserved;
  51     }
  52 
  53     #endregion
  54 
  55     #endregion
  56 
  57     #region Public enums
  58     /// <summary>
  59     /// Defines constants for the available compression levels in zlib
  60     /// </summary>
  61     public enum CompressLevel : int
  62     {
  63         /// <summary>
  64         /// The default compression level with a reasonable compromise between compression and speed
  65         /// </summary>
  66         Default = -1,
  67         /// <summary>
  68         /// No compression at all. The data are passed straight through.
  69         /// </summary>
  70         None = 0,
  71         /// <summary>
  72         /// The maximum compression rate available.
  73         /// </summary>
  74         Best = 9,
  75         /// <summary>
  76         /// The fastest available compression level.
  77         /// </summary>
  78         Fastest = 1
  79     }
  80     #endregion
  81 
  82     #region Exception classes
  83     /// <summary>
  84     /// The exception that is thrown when an error occurs on the zlib dll
  85     /// </summary>
  86     public class ZLibException : ApplicationException
  87     {
  88         /// <summary>
  89         /// Initializes a new instance of the <see cref="ZLibException"/> class with a specified
  90         /// error message and error code
  91         /// </summary>
  92         /// <param name="errorCode">The zlib error code that caused the exception</param>
  93         /// <param name="msg">A message that (hopefully) describes the error</param>
  94         public ZLibException(int errorCode, string msg) : base(String.Format("ZLib error {0} {1}", errorCode, msg))
  95         {
  96         }
  97 
  98         /// <summary>
  99         /// Initializes a new instance of the <see cref="ZLibException"/> class with a specified
 100         /// error code
 101         /// </summary>
 102         /// <param name="errorCode">The zlib error code that caused the exception</param>
 103         public ZLibException(int errorCode) : base(String.Format("ZLib error {0}", errorCode))
 104         {
 105         }
 106     }
 107     #endregion
 108 
 109     #region Interfaces
 110 
 111     /// <summary>
 112     /// Declares methods and properties that enables a running checksum to be calculated
 113     /// </summary>
 114     public interface ChecksumGenerator
 115     {
 116         /// <summary>
 117         /// Gets the current value of the checksum
 118         /// </summary>
 119         uint Value { get; }
 120 
 121         /// <summary>
 122         /// Clears the current checksum to 0
 123         /// </summary>
 124         void Reset();
 125 
 126         /// <summary>
 127         /// Updates the current checksum with an array of bytes
 128         /// </summary>
 129         /// <param name="data">The data to update the checksum with</param>
 130         void Update(byte[] data);
 131 
 132         /// <summary>
 133         /// Updates the current checksum with part of an array of bytes
 134         /// </summary>
 135         /// <param name="data">The data to update the checksum with</param>
 136         /// <param name="offset">Where in <c>data</c> to start updating</param>
 137         /// <param name="count">The number of bytes from <c>data</c> to use</param>
 138         /// <exception cref="ArgumentException">The sum of offset and count is larger than the length of <c>data</c></exception>
 139         /// <exception cref="ArgumentNullException"><c>data</c> is a null reference</exception>
 140         /// <exception cref="ArgumentOutOfRangeException">Offset or count is negative.</exception>
 141         void Update(byte[] data, int offset, int count);
 142 
 143         /// <summary>
 144         /// Updates the current checksum with the data from a string
 145         /// </summary>
 146         /// <param name="data">The string to update the checksum with</param>
 147         /// <remarks>The characters in the string are converted by the UTF-8 encoding</remarks>
 148         void Update(string data);
 149 
 150         /// <summary>
 151         /// Updates the current checksum with the data from a string, using a specific encoding
 152         /// </summary>
 153         /// <param name="data">The string to update the checksum with</param>
 154         /// <param name="encoding">The encoding to use</param>
 155         void Update(string data, Encoding encoding);
 156     }
 157 
 158 
 159     /// <summary>
 160     /// Represents the method that will be called from a codec when new data
 161     /// are available.
 162     /// </summary>
 163     /// <paramref name="data">The byte array containing the processed data</paramref>
 164     /// <paramref name="startIndex">The index of the first processed byte in <c>data</c></paramref>
 165     /// <paramref name="count">The number of processed bytes available</paramref>
 166     /// <remarks>On return from this method, the data may be overwritten, so grab it while you can.
 167     /// You cannot assume that startIndex will be zero.
 168     /// </remarks>
 169     public delegate void DataAvailableHandler(byte[] data, int startIndex, int count);
 170 
 171     /// <summary>
 172     /// Declares methods and events for implementing compressors/decompressors
 173     /// </summary>
 174     public interface Codec
 175     {
 176         /// <summary>
 177         /// Occurs when more processed data are available.
 178         /// </summary>
 179         event DataAvailableHandler DataAvailable;
 180 
 181         /// <summary>
 182         /// Adds more data to the codec to be processed.
 183         /// </summary>
 184         /// <param name="data">Byte array containing the data to be added to the codec</param>
 185         /// <remarks>Adding data may, or may not, raise the <c>DataAvailable</c> event</remarks>
 186         void Add(byte[] data);
 187 
 188         /// <summary>
 189         /// Adds more data to the codec to be processed.
 190         /// </summary>
 191         /// <param name="data">Byte array containing the data to be added to the codec</param>
 192         /// <param name="offset">The index of the first byte to add from <c>data</c></param>
 193         /// <param name="count">The number of bytes to add</param>
 194         /// <remarks>Adding data may, or may not, raise the <c>DataAvailable</c> event</remarks>
 195         void Add(byte[] data, int offset, int count);
 196 
 197         /// <summary>
 198         /// Finishes up any pending data that needs to be processed and handled.
 199         /// </summary>
 200         void Finish();
 201 
 202         /// <summary>
 203         /// Gets the checksum of the data that has been added so far
 204         /// </summary>
 205         uint Checksum { get; }
 206 
 207 
 208     }
 209 
 210     #endregion
 211 
 212     #region Classes
 213     /// <summary>
 214     /// Encapsulates general information about the ZLib library
 215     /// </summary>
 216     public class Info
 217     {
 218         #region DLL imports
 219         [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)]
 220         private static extern uint zlibCompileFlags();
 221 
 222         [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)]
 223         private static extern string zlibVersion();
 224         #endregion
 225 
 226         #region Private stuff
 227         private uint _flags;
 228 
 229         // helper function that unpacks a bitsize mask
 230         private static int bitSize(uint bits)
 231         {
 232             switch (bits)
 233             {
 234                 case 0: return 16;
 235                 case 1: return 32;
 236                 case 2: return 64;
 237             }
 238             return -1;
 239         }
 240         #endregion
 241 
 242         /// <summary>
 243         /// Constructs an instance of the <c>Info</c> class.
 244         /// </summary>
 245         public Info()
 246         {
 247             _flags = zlibCompileFlags();
 248         }
 249 
 250         /// <summary>
 251         /// True if the library is compiled with debug info
 252         /// </summary>
 253         public bool HasDebugInfo { get { return 0 != (_flags & 0x100); } }
 254 
 255         /// <summary>
 256         /// True if the library is compiled with assembly optimizations
 257         /// </summary>
 258         public bool UsesAssemblyCode { get { return 0 != (_flags & 0x200); } }
 259 
 260         /// <summary>
 261         /// Gets the size of the unsigned int that was compiled into Zlib
 262         /// </summary>
 263         public int SizeOfUInt { get { return bitSize(_flags & 3); } }
 264 
 265         /// <summary>
 266         /// Gets the size of the unsigned long that was compiled into Zlib
 267         /// </summary>
 268         public int SizeOfULong { get { return bitSize((_flags >> 2) & 3); } }
 269 
 270         /// <summary>
 271         /// Gets the size of the pointers that were compiled into Zlib
 272         /// </summary>
 273         public int SizeOfPointer { get { return bitSize((_flags >> 4) & 3); } }
 274 
 275         /// <summary>
 276         /// Gets the size of the z_off_t type that was compiled into Zlib
 277         /// </summary>
 278         public int SizeOfOffset { get { return bitSize((_flags >> 6) & 3); } }
 279 
 280         /// <summary>
 281         /// Gets the version of ZLib as a string, e.g. "1.2.1"
 282         /// </summary>
 283         public static string Version { get { return zlibVersion(); } }
 284     }
 285 
 286     #endregion
 287 
 288 }