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 }