ChecksumImpl.cs 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  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. using System.Text;
  10. namespace DotZLib
  11. {
  12. #region ChecksumGeneratorBase
  13. /// <summary>
  14. /// Implements the common functionality needed for all <see cref="ChecksumGenerator"/>s
  15. /// </summary>
  16. /// <example></example>
  17. public abstract class ChecksumGeneratorBase : ChecksumGenerator
  18. {
  19. /// <summary>
  20. /// The value of the current checksum
  21. /// </summary>
  22. protected uint _current;
  23. /// <summary>
  24. /// Initializes a new instance of the checksum generator base - the current checksum is
  25. /// set to zero
  26. /// </summary>
  27. public ChecksumGeneratorBase()
  28. {
  29. _current = 0;
  30. }
  31. /// <summary>
  32. /// Initializes a new instance of the checksum generator basewith a specified value
  33. /// </summary>
  34. /// <param name="initialValue">The value to set the current checksum to</param>
  35. public ChecksumGeneratorBase(uint initialValue)
  36. {
  37. _current = initialValue;
  38. }
  39. /// <summary>
  40. /// Resets the current checksum to zero
  41. /// </summary>
  42. public void Reset() { _current = 0; }
  43. /// <summary>
  44. /// Gets the current checksum value
  45. /// </summary>
  46. public uint Value { get { return _current; } }
  47. /// <summary>
  48. /// Updates the current checksum with part of an array of bytes
  49. /// </summary>
  50. /// <param name="data">The data to update the checksum with</param>
  51. /// <param name="offset">Where in <c>data</c> to start updating</param>
  52. /// <param name="count">The number of bytes from <c>data</c> to use</param>
  53. /// <exception cref="ArgumentException">The sum of offset and count is larger than the length of <c>data</c></exception>
  54. /// <exception cref="NullReferenceException"><c>data</c> is a null reference</exception>
  55. /// <exception cref="ArgumentOutOfRangeException">Offset or count is negative.</exception>
  56. /// <remarks>All the other <c>Update</c> methods are implmeneted in terms of this one.
  57. /// This is therefore the only method a derived class has to implement</remarks>
  58. public abstract void Update(byte[] data, int offset, int count);
  59. /// <summary>
  60. /// Updates the current checksum with an array of bytes.
  61. /// </summary>
  62. /// <param name="data">The data to update the checksum with</param>
  63. public void Update(byte[] data)
  64. {
  65. Update(data, 0, data.Length);
  66. }
  67. /// <summary>
  68. /// Updates the current checksum with the data from a string
  69. /// </summary>
  70. /// <param name="data">The string to update the checksum with</param>
  71. /// <remarks>The characters in the string are converted by the UTF-8 encoding</remarks>
  72. public void Update(string data)
  73. {
  74. Update(Encoding.UTF8.GetBytes(data));
  75. }
  76. /// <summary>
  77. /// Updates the current checksum with the data from a string, using a specific encoding
  78. /// </summary>
  79. /// <param name="data">The string to update the checksum with</param>
  80. /// <param name="encoding">The encoding to use</param>
  81. public void Update(string data, Encoding encoding)
  82. {
  83. Update(encoding.GetBytes(data));
  84. }
  85. }
  86. #endregion
  87. #region CRC32
  88. /// <summary>
  89. /// Implements a CRC32 checksum generator
  90. /// </summary>
  91. public sealed class CRC32Checksum : ChecksumGeneratorBase
  92. {
  93. #region DLL imports
  94. [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)]
  95. private static extern uint crc32(uint crc, int data, uint length);
  96. #endregion
  97. /// <summary>
  98. /// Initializes a new instance of the CRC32 checksum generator
  99. /// </summary>
  100. public CRC32Checksum() : base() {}
  101. /// <summary>
  102. /// Initializes a new instance of the CRC32 checksum generator with a specified value
  103. /// </summary>
  104. /// <param name="initialValue">The value to set the current checksum to</param>
  105. public CRC32Checksum(uint initialValue) : base(initialValue) {}
  106. /// <summary>
  107. /// Updates the current checksum with part of an array of bytes
  108. /// </summary>
  109. /// <param name="data">The data to update the checksum with</param>
  110. /// <param name="offset">Where in <c>data</c> to start updating</param>
  111. /// <param name="count">The number of bytes from <c>data</c> to use</param>
  112. /// <exception cref="ArgumentException">The sum of offset and count is larger than the length of <c>data</c></exception>
  113. /// <exception cref="NullReferenceException"><c>data</c> is a null reference</exception>
  114. /// <exception cref="ArgumentOutOfRangeException">Offset or count is negative.</exception>
  115. public override void Update(byte[] data, int offset, int count)
  116. {
  117. if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException();
  118. if ((offset+count) > data.Length) throw new ArgumentException();
  119. GCHandle hData = GCHandle.Alloc(data, GCHandleType.Pinned);
  120. try
  121. {
  122. _current = crc32(_current, hData.AddrOfPinnedObject().ToInt32()+offset, (uint)count);
  123. }
  124. finally
  125. {
  126. hData.Free();
  127. }
  128. }
  129. }
  130. #endregion
  131. #region Adler
  132. /// <summary>
  133. /// Implements a checksum generator that computes the Adler checksum on data
  134. /// </summary>
  135. public sealed class AdlerChecksum : ChecksumGeneratorBase
  136. {
  137. #region DLL imports
  138. [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)]
  139. private static extern uint adler32(uint adler, int data, uint length);
  140. #endregion
  141. /// <summary>
  142. /// Initializes a new instance of the Adler checksum generator
  143. /// </summary>
  144. public AdlerChecksum() : base() {}
  145. /// <summary>
  146. /// Initializes a new instance of the Adler checksum generator with a specified value
  147. /// </summary>
  148. /// <param name="initialValue">The value to set the current checksum to</param>
  149. public AdlerChecksum(uint initialValue) : base(initialValue) {}
  150. /// <summary>
  151. /// Updates the current checksum with part of an array of bytes
  152. /// </summary>
  153. /// <param name="data">The data to update the checksum with</param>
  154. /// <param name="offset">Where in <c>data</c> to start updating</param>
  155. /// <param name="count">The number of bytes from <c>data</c> to use</param>
  156. /// <exception cref="ArgumentException">The sum of offset and count is larger than the length of <c>data</c></exception>
  157. /// <exception cref="NullReferenceException"><c>data</c> is a null reference</exception>
  158. /// <exception cref="ArgumentOutOfRangeException">Offset or count is negative.</exception>
  159. public override void Update(byte[] data, int offset, int count)
  160. {
  161. if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException();
  162. if ((offset+count) > data.Length) throw new ArgumentException();
  163. GCHandle hData = GCHandle.Alloc(data, GCHandleType.Pinned);
  164. try
  165. {
  166. _current = adler32(_current, hData.AddrOfPinnedObject().ToInt32()+offset, (uint)count);
  167. }
  168. finally
  169. {
  170. hData.Free();
  171. }
  172. }
  173. }
  174. #endregion
  175. }