CodecBase.cs 6.2 KB

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