1275793eaSopenharmony_ci// 2275793eaSopenharmony_ci// � Copyright Henrik Ravn 2004 3275793eaSopenharmony_ci// 4275793eaSopenharmony_ci// Use, modification and distribution are subject to the Boost Software License, Version 1.0. 5275793eaSopenharmony_ci// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6275793eaSopenharmony_ci// 7275793eaSopenharmony_ci 8275793eaSopenharmony_ciusing System; 9275793eaSopenharmony_ciusing System.Runtime.InteropServices; 10275793eaSopenharmony_ci 11275793eaSopenharmony_cinamespace DotZLib 12275793eaSopenharmony_ci{ 13275793eaSopenharmony_ci /// <summary> 14275793eaSopenharmony_ci /// Implements the common functionality needed for all <see cref="Codec"/>s 15275793eaSopenharmony_ci /// </summary> 16275793eaSopenharmony_ci public abstract class CodecBase : Codec, IDisposable 17275793eaSopenharmony_ci { 18275793eaSopenharmony_ci 19275793eaSopenharmony_ci #region Data members 20275793eaSopenharmony_ci 21275793eaSopenharmony_ci /// <summary> 22275793eaSopenharmony_ci /// Instance of the internal zlib buffer structure that is 23275793eaSopenharmony_ci /// passed to all functions in the zlib dll 24275793eaSopenharmony_ci /// </summary> 25275793eaSopenharmony_ci internal ZStream _ztream = new ZStream(); 26275793eaSopenharmony_ci 27275793eaSopenharmony_ci /// <summary> 28275793eaSopenharmony_ci /// True if the object instance has been disposed, false otherwise 29275793eaSopenharmony_ci /// </summary> 30275793eaSopenharmony_ci protected bool _isDisposed = false; 31275793eaSopenharmony_ci 32275793eaSopenharmony_ci /// <summary> 33275793eaSopenharmony_ci /// The size of the internal buffers 34275793eaSopenharmony_ci /// </summary> 35275793eaSopenharmony_ci protected const int kBufferSize = 16384; 36275793eaSopenharmony_ci 37275793eaSopenharmony_ci private byte[] _outBuffer = new byte[kBufferSize]; 38275793eaSopenharmony_ci private byte[] _inBuffer = new byte[kBufferSize]; 39275793eaSopenharmony_ci 40275793eaSopenharmony_ci private GCHandle _hInput; 41275793eaSopenharmony_ci private GCHandle _hOutput; 42275793eaSopenharmony_ci 43275793eaSopenharmony_ci private uint _checksum = 0; 44275793eaSopenharmony_ci 45275793eaSopenharmony_ci #endregion 46275793eaSopenharmony_ci 47275793eaSopenharmony_ci /// <summary> 48275793eaSopenharmony_ci /// Initializes a new instance of the <c>CodeBase</c> class. 49275793eaSopenharmony_ci /// </summary> 50275793eaSopenharmony_ci public CodecBase() 51275793eaSopenharmony_ci { 52275793eaSopenharmony_ci try 53275793eaSopenharmony_ci { 54275793eaSopenharmony_ci _hInput = GCHandle.Alloc(_inBuffer, GCHandleType.Pinned); 55275793eaSopenharmony_ci _hOutput = GCHandle.Alloc(_outBuffer, GCHandleType.Pinned); 56275793eaSopenharmony_ci } 57275793eaSopenharmony_ci catch (Exception) 58275793eaSopenharmony_ci { 59275793eaSopenharmony_ci CleanUp(false); 60275793eaSopenharmony_ci throw; 61275793eaSopenharmony_ci } 62275793eaSopenharmony_ci } 63275793eaSopenharmony_ci 64275793eaSopenharmony_ci 65275793eaSopenharmony_ci #region Codec Members 66275793eaSopenharmony_ci 67275793eaSopenharmony_ci /// <summary> 68275793eaSopenharmony_ci /// Occurs when more processed data are available. 69275793eaSopenharmony_ci /// </summary> 70275793eaSopenharmony_ci public event DataAvailableHandler DataAvailable; 71275793eaSopenharmony_ci 72275793eaSopenharmony_ci /// <summary> 73275793eaSopenharmony_ci /// Fires the <see cref="DataAvailable"/> event 74275793eaSopenharmony_ci /// </summary> 75275793eaSopenharmony_ci protected void OnDataAvailable() 76275793eaSopenharmony_ci { 77275793eaSopenharmony_ci if (_ztream.total_out > 0) 78275793eaSopenharmony_ci { 79275793eaSopenharmony_ci if (DataAvailable != null) 80275793eaSopenharmony_ci DataAvailable( _outBuffer, 0, (int)_ztream.total_out); 81275793eaSopenharmony_ci resetOutput(); 82275793eaSopenharmony_ci } 83275793eaSopenharmony_ci } 84275793eaSopenharmony_ci 85275793eaSopenharmony_ci /// <summary> 86275793eaSopenharmony_ci /// Adds more data to the codec to be processed. 87275793eaSopenharmony_ci /// </summary> 88275793eaSopenharmony_ci /// <param name="data">Byte array containing the data to be added to the codec</param> 89275793eaSopenharmony_ci /// <remarks>Adding data may, or may not, raise the <c>DataAvailable</c> event</remarks> 90275793eaSopenharmony_ci public void Add(byte[] data) 91275793eaSopenharmony_ci { 92275793eaSopenharmony_ci Add(data,0,data.Length); 93275793eaSopenharmony_ci } 94275793eaSopenharmony_ci 95275793eaSopenharmony_ci /// <summary> 96275793eaSopenharmony_ci /// Adds more data to the codec to be processed. 97275793eaSopenharmony_ci /// </summary> 98275793eaSopenharmony_ci /// <param name="data">Byte array containing the data to be added to the codec</param> 99275793eaSopenharmony_ci /// <param name="offset">The index of the first byte to add from <c>data</c></param> 100275793eaSopenharmony_ci /// <param name="count">The number of bytes to add</param> 101275793eaSopenharmony_ci /// <remarks>Adding data may, or may not, raise the <c>DataAvailable</c> event</remarks> 102275793eaSopenharmony_ci /// <remarks>This must be implemented by a derived class</remarks> 103275793eaSopenharmony_ci public abstract void Add(byte[] data, int offset, int count); 104275793eaSopenharmony_ci 105275793eaSopenharmony_ci /// <summary> 106275793eaSopenharmony_ci /// Finishes up any pending data that needs to be processed and handled. 107275793eaSopenharmony_ci /// </summary> 108275793eaSopenharmony_ci /// <remarks>This must be implemented by a derived class</remarks> 109275793eaSopenharmony_ci public abstract void Finish(); 110275793eaSopenharmony_ci 111275793eaSopenharmony_ci /// <summary> 112275793eaSopenharmony_ci /// Gets the checksum of the data that has been added so far 113275793eaSopenharmony_ci /// </summary> 114275793eaSopenharmony_ci public uint Checksum { get { return _checksum; } } 115275793eaSopenharmony_ci 116275793eaSopenharmony_ci #endregion 117275793eaSopenharmony_ci 118275793eaSopenharmony_ci #region Destructor & IDisposable stuff 119275793eaSopenharmony_ci 120275793eaSopenharmony_ci /// <summary> 121275793eaSopenharmony_ci /// Destroys this instance 122275793eaSopenharmony_ci /// </summary> 123275793eaSopenharmony_ci ~CodecBase() 124275793eaSopenharmony_ci { 125275793eaSopenharmony_ci CleanUp(false); 126275793eaSopenharmony_ci } 127275793eaSopenharmony_ci 128275793eaSopenharmony_ci /// <summary> 129275793eaSopenharmony_ci /// Releases any unmanaged resources and calls the <see cref="CleanUp()"/> method of the derived class 130275793eaSopenharmony_ci /// </summary> 131275793eaSopenharmony_ci public void Dispose() 132275793eaSopenharmony_ci { 133275793eaSopenharmony_ci CleanUp(true); 134275793eaSopenharmony_ci } 135275793eaSopenharmony_ci 136275793eaSopenharmony_ci /// <summary> 137275793eaSopenharmony_ci /// Performs any codec specific cleanup 138275793eaSopenharmony_ci /// </summary> 139275793eaSopenharmony_ci /// <remarks>This must be implemented by a derived class</remarks> 140275793eaSopenharmony_ci protected abstract void CleanUp(); 141275793eaSopenharmony_ci 142275793eaSopenharmony_ci // performs the release of the handles and calls the derived CleanUp() 143275793eaSopenharmony_ci private void CleanUp(bool isDisposing) 144275793eaSopenharmony_ci { 145275793eaSopenharmony_ci if (!_isDisposed) 146275793eaSopenharmony_ci { 147275793eaSopenharmony_ci CleanUp(); 148275793eaSopenharmony_ci if (_hInput.IsAllocated) 149275793eaSopenharmony_ci _hInput.Free(); 150275793eaSopenharmony_ci if (_hOutput.IsAllocated) 151275793eaSopenharmony_ci _hOutput.Free(); 152275793eaSopenharmony_ci 153275793eaSopenharmony_ci _isDisposed = true; 154275793eaSopenharmony_ci } 155275793eaSopenharmony_ci } 156275793eaSopenharmony_ci 157275793eaSopenharmony_ci 158275793eaSopenharmony_ci #endregion 159275793eaSopenharmony_ci 160275793eaSopenharmony_ci #region Helper methods 161275793eaSopenharmony_ci 162275793eaSopenharmony_ci /// <summary> 163275793eaSopenharmony_ci /// Copies a number of bytes to the internal codec buffer - ready for processing 164275793eaSopenharmony_ci /// </summary> 165275793eaSopenharmony_ci /// <param name="data">The byte array that contains the data to copy</param> 166275793eaSopenharmony_ci /// <param name="startIndex">The index of the first byte to copy</param> 167275793eaSopenharmony_ci /// <param name="count">The number of bytes to copy from <c>data</c></param> 168275793eaSopenharmony_ci protected void copyInput(byte[] data, int startIndex, int count) 169275793eaSopenharmony_ci { 170275793eaSopenharmony_ci Array.Copy(data, startIndex, _inBuffer,0, count); 171275793eaSopenharmony_ci _ztream.next_in = _hInput.AddrOfPinnedObject(); 172275793eaSopenharmony_ci _ztream.total_in = 0; 173275793eaSopenharmony_ci _ztream.avail_in = (uint)count; 174275793eaSopenharmony_ci 175275793eaSopenharmony_ci } 176275793eaSopenharmony_ci 177275793eaSopenharmony_ci /// <summary> 178275793eaSopenharmony_ci /// Resets the internal output buffers to a known state - ready for processing 179275793eaSopenharmony_ci /// </summary> 180275793eaSopenharmony_ci protected void resetOutput() 181275793eaSopenharmony_ci { 182275793eaSopenharmony_ci _ztream.total_out = 0; 183275793eaSopenharmony_ci _ztream.avail_out = kBufferSize; 184275793eaSopenharmony_ci _ztream.next_out = _hOutput.AddrOfPinnedObject(); 185275793eaSopenharmony_ci } 186275793eaSopenharmony_ci 187275793eaSopenharmony_ci /// <summary> 188275793eaSopenharmony_ci /// Updates the running checksum property 189275793eaSopenharmony_ci /// </summary> 190275793eaSopenharmony_ci /// <param name="newSum">The new checksum value</param> 191275793eaSopenharmony_ci protected void setChecksum(uint newSum) 192275793eaSopenharmony_ci { 193275793eaSopenharmony_ci _checksum = newSum; 194275793eaSopenharmony_ci } 195275793eaSopenharmony_ci #endregion 196275793eaSopenharmony_ci 197275793eaSopenharmony_ci } 198275793eaSopenharmony_ci} 199