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