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