CodecBase.cs revision 9e38dfa2f95fce609707a0941f10af9a785288de
18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt// 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt// � Copyright Henrik Ravn 2004 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt// 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt// Use, modification and distribution are subject to the Boost Software License, Version 1.0. 58d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 68d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt// 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtusing System; 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtusing System.Runtime.InteropServices; 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtnamespace DotZLib 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// <summary> 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// Implements the common functionality needed for all <see cref="Codec"/>s 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// </summary> 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt public abstract class CodecBase : Codec, IDisposable 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt #region Data members 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// <summary> 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// Instance of the internal zlib buffer structure that is 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// passed to all functions in the zlib dll 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// </summary> 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt internal ZStream _ztream = new ZStream(); 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// <summary> 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// True if the object instance has been disposed, false otherwise 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// </summary> 301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt protected bool _isDisposed = false; 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// <summary> 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// The size of the internal buffers 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// </summary> 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt protected const int kBufferSize = 16384; 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt private byte[] _outBuffer = new byte[kBufferSize]; 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt private byte[] _inBuffer = new byte[kBufferSize]; 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt private GCHandle _hInput; 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt private GCHandle _hOutput; 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt private uint _checksum = 0; 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt #endregion 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// <summary> 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// Initializes a new instance of the <c>CodeBase</c> class. 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// </summary> 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt public CodecBase() 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt try 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _hInput = GCHandle.Alloc(_inBuffer, GCHandleType.Pinned); 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _hOutput = GCHandle.Alloc(_outBuffer, GCHandleType.Pinned); 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt catch (Exception) 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt CleanUp(false); 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt throw; 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt #region Codec Members 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// <summary> 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// Occurs when more processed data are available. 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// </summary> 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt public event DataAvailableHandler DataAvailable; 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// <summary> 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// Fires the <see cref="DataAvailable"/> event 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// </summary> 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt protected void OnDataAvailable() 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (_ztream.total_out > 0) 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (DataAvailable != null) 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt DataAvailable( _outBuffer, 0, (int)_ztream.total_out); 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resetOutput(); 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// <summary> 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// Adds more data to the codec to be processed. 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// </summary> 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// <param name="data">Byte array containing the data to be added to the codec</param> 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// <remarks>Adding data may, or may not, raise the <c>DataAvailable</c> event</remarks> 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt public void Add(byte[] data) 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt Add(data,0,data.Length); 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// <summary> 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// Adds more data to the codec to be processed. 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// </summary> 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// <param name="data">Byte array containing the data to be added to the codec</param> 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// <param name="offset">The index of the first byte to add from <c>data</c></param> 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// <param name="count">The number of bytes to add</param> 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// <remarks>Adding data may, or may not, raise the <c>DataAvailable</c> event</remarks> 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// <remarks>This must be implemented by a derived class</remarks> 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt public abstract void Add(byte[] data, int offset, int count); 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// <summary> 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// Finishes up any pending data that needs to be processed and handled. 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// </summary> 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// <remarks>This must be implemented by a derived class</remarks> 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt public abstract void Finish(); 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// <summary> 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// Gets the checksum of the data that has been added so far 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// </summary> 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt public uint Checksum { get { return _checksum; } } 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt #endregion 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt #region Destructor & IDisposable stuff 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// <summary> 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// Destroys this instance 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// </summary> 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ~CodecBase() 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt CleanUp(false); 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// <summary> 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// Releases any unmanaged resources and calls the <see cref="CleanUp()"/> method of the derived class 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// </summary> 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt public void Dispose() 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt CleanUp(true); 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// <summary> 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// Performs any codec specific cleanup 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// </summary> 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// <remarks>This must be implemented by a derived class</remarks> 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt protected abstract void CleanUp(); 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // performs the release of the handles and calls the dereived CleanUp() 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt private void CleanUp(bool isDisposing) 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!_isDisposed) 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt CleanUp(); 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (_hInput.IsAllocated) 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _hInput.Free(); 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (_hOutput.IsAllocated) 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _hOutput.Free(); 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _isDisposed = true; 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt #endregion 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt #region Helper methods 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// <summary> 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// Copies a number of bytes to the internal codec buffer - ready for proccesing 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// </summary> 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// <param name="data">The byte array that contains the data to copy</param> 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// <param name="startIndex">The index of the first byte to copy</param> 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// <param name="count">The number of bytes to copy from <c>data</c></param> 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt protected void copyInput(byte[] data, int startIndex, int count) 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt Array.Copy(data, startIndex, _inBuffer,0, count); 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _ztream.next_in = _hInput.AddrOfPinnedObject(); 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _ztream.total_in = 0; 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _ztream.avail_in = (uint)count; 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// <summary> 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// Resets the internal output buffers to a known state - ready for processing 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// </summary> 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt protected void resetOutput() 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _ztream.total_out = 0; 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _ztream.avail_out = kBufferSize; 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _ztream.next_out = _hOutput.AddrOfPinnedObject(); 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// <summary> 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// Updates the running checksum property 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// </summary> 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /// <param name="newSum">The new checksum value</param> 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt protected void setChecksum(uint newSum) 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _checksum = newSum; 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt #endregion 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt