xref: /minix3/common/dist/zlib/contrib/dotzlib/DotZLib/CodecBase.cs (revision 44bedb31d842b4b0444105519bcf929a69fe2dc1)
1*44bedb31SLionel Sambuc //
2*44bedb31SLionel Sambuc // � Copyright Henrik Ravn 2004
3*44bedb31SLionel Sambuc //
4*44bedb31SLionel Sambuc // Use, modification and distribution are subject to the Boost Software License, Version 1.0.
5*44bedb31SLionel Sambuc // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6*44bedb31SLionel Sambuc //
7*44bedb31SLionel Sambuc 
8*44bedb31SLionel Sambuc using System;
9*44bedb31SLionel Sambuc using System.Runtime.InteropServices;
10*44bedb31SLionel Sambuc 
11*44bedb31SLionel Sambuc namespace DotZLib
12*44bedb31SLionel Sambuc {
13*44bedb31SLionel Sambuc 	/// <summary>
14*44bedb31SLionel Sambuc 	/// Implements the common functionality needed for all <see cref="Codec"/>s
15*44bedb31SLionel Sambuc 	/// </summary>
16*44bedb31SLionel Sambuc 	public abstract class CodecBase : Codec, IDisposable
17*44bedb31SLionel Sambuc 	{
18*44bedb31SLionel Sambuc 
19*44bedb31SLionel Sambuc         #region Data members
20*44bedb31SLionel Sambuc 
21*44bedb31SLionel Sambuc         /// <summary>
22*44bedb31SLionel Sambuc         /// Instance of the internal zlib buffer structure that is
23*44bedb31SLionel Sambuc         /// passed to all functions in the zlib dll
24*44bedb31SLionel Sambuc         /// </summary>
25*44bedb31SLionel Sambuc         internal ZStream _ztream = new ZStream();
26*44bedb31SLionel Sambuc 
27*44bedb31SLionel Sambuc         /// <summary>
28*44bedb31SLionel Sambuc         /// True if the object instance has been disposed, false otherwise
29*44bedb31SLionel Sambuc         /// </summary>
30*44bedb31SLionel Sambuc         protected bool _isDisposed = false;
31*44bedb31SLionel Sambuc 
32*44bedb31SLionel Sambuc         /// <summary>
33*44bedb31SLionel Sambuc         /// The size of the internal buffers
34*44bedb31SLionel Sambuc         /// </summary>
35*44bedb31SLionel Sambuc         protected const int kBufferSize = 16384;
36*44bedb31SLionel Sambuc 
37*44bedb31SLionel Sambuc         private byte[] _outBuffer = new byte[kBufferSize];
38*44bedb31SLionel Sambuc         private byte[] _inBuffer = new byte[kBufferSize];
39*44bedb31SLionel Sambuc 
40*44bedb31SLionel Sambuc         private GCHandle _hInput;
41*44bedb31SLionel Sambuc         private GCHandle _hOutput;
42*44bedb31SLionel Sambuc 
43*44bedb31SLionel Sambuc         private uint _checksum = 0;
44*44bedb31SLionel Sambuc 
45*44bedb31SLionel Sambuc         #endregion
46*44bedb31SLionel Sambuc 
47*44bedb31SLionel Sambuc         /// <summary>
48*44bedb31SLionel Sambuc         /// Initializes a new instance of the <c>CodeBase</c> class.
49*44bedb31SLionel Sambuc         /// </summary>
CodecBase()50*44bedb31SLionel Sambuc 		public CodecBase()
51*44bedb31SLionel Sambuc 		{
52*44bedb31SLionel Sambuc             try
53*44bedb31SLionel Sambuc             {
54*44bedb31SLionel Sambuc                 _hInput = GCHandle.Alloc(_inBuffer, GCHandleType.Pinned);
55*44bedb31SLionel Sambuc                 _hOutput = GCHandle.Alloc(_outBuffer, GCHandleType.Pinned);
56*44bedb31SLionel Sambuc             }
57*44bedb31SLionel Sambuc             catch (Exception)
58*44bedb31SLionel Sambuc             {
59*44bedb31SLionel Sambuc                 CleanUp(false);
60*44bedb31SLionel Sambuc                 throw;
61*44bedb31SLionel Sambuc             }
62*44bedb31SLionel Sambuc         }
63*44bedb31SLionel Sambuc 
64*44bedb31SLionel Sambuc 
65*44bedb31SLionel Sambuc         #region Codec Members
66*44bedb31SLionel Sambuc 
67*44bedb31SLionel Sambuc         /// <summary>
68*44bedb31SLionel Sambuc         /// Occurs when more processed data are available.
69*44bedb31SLionel Sambuc         /// </summary>
70*44bedb31SLionel Sambuc         public event DataAvailableHandler DataAvailable;
71*44bedb31SLionel Sambuc 
72*44bedb31SLionel Sambuc         /// <summary>
73*44bedb31SLionel Sambuc         /// Fires the <see cref="DataAvailable"/> event
74*44bedb31SLionel Sambuc         /// </summary>
OnDataAvailable()75*44bedb31SLionel Sambuc         protected void OnDataAvailable()
76*44bedb31SLionel Sambuc         {
77*44bedb31SLionel Sambuc             if (_ztream.total_out > 0)
78*44bedb31SLionel Sambuc             {
79*44bedb31SLionel Sambuc                 if (DataAvailable != null)
80*44bedb31SLionel Sambuc                     DataAvailable( _outBuffer, 0, (int)_ztream.total_out);
81*44bedb31SLionel Sambuc                 resetOutput();
82*44bedb31SLionel Sambuc             }
83*44bedb31SLionel Sambuc         }
84*44bedb31SLionel Sambuc 
85*44bedb31SLionel Sambuc         /// <summary>
86*44bedb31SLionel Sambuc         /// Adds more data to the codec to be processed.
87*44bedb31SLionel Sambuc         /// </summary>
88*44bedb31SLionel Sambuc         /// <param name="data">Byte array containing the data to be added to the codec</param>
89*44bedb31SLionel Sambuc         /// <remarks>Adding data may, or may not, raise the <c>DataAvailable</c> event</remarks>
Add(byte[] data)90*44bedb31SLionel Sambuc         public void Add(byte[] data)
91*44bedb31SLionel Sambuc         {
92*44bedb31SLionel Sambuc             Add(data,0,data.Length);
93*44bedb31SLionel Sambuc         }
94*44bedb31SLionel Sambuc 
95*44bedb31SLionel Sambuc         /// <summary>
96*44bedb31SLionel Sambuc         /// Adds more data to the codec to be processed.
97*44bedb31SLionel Sambuc         /// </summary>
98*44bedb31SLionel Sambuc         /// <param name="data">Byte array containing the data to be added to the codec</param>
99*44bedb31SLionel Sambuc         /// <param name="offset">The index of the first byte to add from <c>data</c></param>
100*44bedb31SLionel Sambuc         /// <param name="count">The number of bytes to add</param>
101*44bedb31SLionel Sambuc         /// <remarks>Adding data may, or may not, raise the <c>DataAvailable</c> event</remarks>
102*44bedb31SLionel Sambuc         /// <remarks>This must be implemented by a derived class</remarks>
Add(byte[] data, int offset, int count)103*44bedb31SLionel Sambuc         public abstract void Add(byte[] data, int offset, int count);
104*44bedb31SLionel Sambuc 
105*44bedb31SLionel Sambuc         /// <summary>
106*44bedb31SLionel Sambuc         /// Finishes up any pending data that needs to be processed and handled.
107*44bedb31SLionel Sambuc         /// </summary>
108*44bedb31SLionel Sambuc         /// <remarks>This must be implemented by a derived class</remarks>
Finish()109*44bedb31SLionel Sambuc         public abstract void Finish();
110*44bedb31SLionel Sambuc 
111*44bedb31SLionel Sambuc         /// <summary>
112*44bedb31SLionel Sambuc         /// Gets the checksum of the data that has been added so far
113*44bedb31SLionel Sambuc         /// </summary>
114*44bedb31SLionel Sambuc         public uint Checksum { get { return _checksum; } }
115*44bedb31SLionel Sambuc 
116*44bedb31SLionel Sambuc         #endregion
117*44bedb31SLionel Sambuc 
118*44bedb31SLionel Sambuc         #region Destructor & IDisposable stuff
119*44bedb31SLionel Sambuc 
120*44bedb31SLionel Sambuc         /// <summary>
121*44bedb31SLionel Sambuc         /// Destroys this instance
122*44bedb31SLionel Sambuc         /// </summary>
~CodecBase()123*44bedb31SLionel Sambuc         ~CodecBase()
124*44bedb31SLionel Sambuc         {
125*44bedb31SLionel Sambuc             CleanUp(false);
126*44bedb31SLionel Sambuc         }
127*44bedb31SLionel Sambuc 
128*44bedb31SLionel Sambuc         /// <summary>
129*44bedb31SLionel Sambuc         /// Releases any unmanaged resources and calls the <see cref="CleanUp()"/> method of the derived class
130*44bedb31SLionel Sambuc         /// </summary>
Dispose()131*44bedb31SLionel Sambuc         public void Dispose()
132*44bedb31SLionel Sambuc         {
133*44bedb31SLionel Sambuc             CleanUp(true);
134*44bedb31SLionel Sambuc         }
135*44bedb31SLionel Sambuc 
136*44bedb31SLionel Sambuc         /// <summary>
137*44bedb31SLionel Sambuc         /// Performs any codec specific cleanup
138*44bedb31SLionel Sambuc         /// </summary>
139*44bedb31SLionel Sambuc         /// <remarks>This must be implemented by a derived class</remarks>
CleanUp()140*44bedb31SLionel Sambuc         protected abstract void CleanUp();
141*44bedb31SLionel Sambuc 
142*44bedb31SLionel Sambuc         // performs the release of the handles and calls the dereived CleanUp()
CleanUp(bool isDisposing)143*44bedb31SLionel Sambuc         private void CleanUp(bool isDisposing)
144*44bedb31SLionel Sambuc         {
145*44bedb31SLionel Sambuc             if (!_isDisposed)
146*44bedb31SLionel Sambuc             {
147*44bedb31SLionel Sambuc                 CleanUp();
148*44bedb31SLionel Sambuc                 if (_hInput.IsAllocated)
149*44bedb31SLionel Sambuc                     _hInput.Free();
150*44bedb31SLionel Sambuc                 if (_hOutput.IsAllocated)
151*44bedb31SLionel Sambuc                     _hOutput.Free();
152*44bedb31SLionel Sambuc 
153*44bedb31SLionel Sambuc                 _isDisposed = true;
154*44bedb31SLionel Sambuc             }
155*44bedb31SLionel Sambuc         }
156*44bedb31SLionel Sambuc 
157*44bedb31SLionel Sambuc 
158*44bedb31SLionel Sambuc         #endregion
159*44bedb31SLionel Sambuc 
160*44bedb31SLionel Sambuc         #region Helper methods
161*44bedb31SLionel Sambuc 
162*44bedb31SLionel Sambuc         /// <summary>
163*44bedb31SLionel Sambuc         /// Copies a number of bytes to the internal codec buffer - ready for proccesing
164*44bedb31SLionel Sambuc         /// </summary>
165*44bedb31SLionel Sambuc         /// <param name="data">The byte array that contains the data to copy</param>
166*44bedb31SLionel Sambuc         /// <param name="startIndex">The index of the first byte to copy</param>
167*44bedb31SLionel Sambuc         /// <param name="count">The number of bytes to copy from <c>data</c></param>
copyInput(byte[] data, int startIndex, int count)168*44bedb31SLionel Sambuc         protected void copyInput(byte[] data, int startIndex, int count)
169*44bedb31SLionel Sambuc         {
170*44bedb31SLionel Sambuc             Array.Copy(data, startIndex, _inBuffer,0, count);
171*44bedb31SLionel Sambuc             _ztream.next_in = _hInput.AddrOfPinnedObject();
172*44bedb31SLionel Sambuc             _ztream.total_in = 0;
173*44bedb31SLionel Sambuc             _ztream.avail_in = (uint)count;
174*44bedb31SLionel Sambuc 
175*44bedb31SLionel Sambuc         }
176*44bedb31SLionel Sambuc 
177*44bedb31SLionel Sambuc         /// <summary>
178*44bedb31SLionel Sambuc         /// Resets the internal output buffers to a known state - ready for processing
179*44bedb31SLionel Sambuc         /// </summary>
resetOutput()180*44bedb31SLionel Sambuc         protected void resetOutput()
181*44bedb31SLionel Sambuc         {
182*44bedb31SLionel Sambuc             _ztream.total_out = 0;
183*44bedb31SLionel Sambuc             _ztream.avail_out = kBufferSize;
184*44bedb31SLionel Sambuc             _ztream.next_out = _hOutput.AddrOfPinnedObject();
185*44bedb31SLionel Sambuc         }
186*44bedb31SLionel Sambuc 
187*44bedb31SLionel Sambuc         /// <summary>
188*44bedb31SLionel Sambuc         /// Updates the running checksum property
189*44bedb31SLionel Sambuc         /// </summary>
190*44bedb31SLionel Sambuc         /// <param name="newSum">The new checksum value</param>
setChecksum(uint newSum)191*44bedb31SLionel Sambuc         protected void setChecksum(uint newSum)
192*44bedb31SLionel Sambuc         {
193*44bedb31SLionel Sambuc             _checksum = newSum;
194*44bedb31SLionel Sambuc         }
195*44bedb31SLionel Sambuc         #endregion
196*44bedb31SLionel Sambuc 
197*44bedb31SLionel Sambuc     }
198*44bedb31SLionel Sambuc }
199