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