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