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