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