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