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