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>
ZLibException(int errorCode, string msg)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>
ZLibException(int errorCode)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>
Reset()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>
Update(byte[] data)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>
Update(byte[] data, int offset, int count)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>
Update(string data)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>
Update(string data, Encoding encoding)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>
DataAvailableHandler(byte[] data, int startIndex, int count)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>
Add(byte[] data)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>
Add(byte[] data, int offset, int count)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>
Finish()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)]
zlibCompileFlags()220         private static extern uint zlibCompileFlags();
221 
222         [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)]
zlibVersion()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
bitSize(uint bits)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>
Info()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 }
289