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