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