CRC32.cs 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. using System.IO;
  2. namespace VEngine
  3. {
  4. public class CRC32
  5. {
  6. private const uint _initialResidueValue = 0xFFFFFFFF;
  7. private static readonly object _globalSync = new object();
  8. private static uint[] _crc32Table;
  9. private static readonly byte[][] _maskingBitTable =
  10. {
  11. new byte[]
  12. {
  13. 2
  14. },
  15. new byte[]
  16. {
  17. 0, 3
  18. },
  19. new byte[]
  20. {
  21. 0, 1, 4
  22. },
  23. new byte[]
  24. {
  25. 1, 2, 5
  26. },
  27. new byte[]
  28. {
  29. 0, 2, 3, 6
  30. },
  31. new byte[]
  32. {
  33. 1, 3, 4, 7
  34. },
  35. new byte[]
  36. {
  37. 4, 5
  38. },
  39. new byte[]
  40. {
  41. 0, 5, 6
  42. },
  43. new byte[]
  44. {
  45. 1, 6, 7
  46. },
  47. new byte[]
  48. {
  49. 7
  50. },
  51. new byte[]
  52. {
  53. 2
  54. },
  55. new byte[]
  56. {
  57. 3
  58. },
  59. new byte[]
  60. {
  61. 0, 4
  62. },
  63. new byte[]
  64. {
  65. 0, 1, 5
  66. },
  67. new byte[]
  68. {
  69. 1, 2, 6
  70. },
  71. new byte[]
  72. {
  73. 2, 3, 7
  74. },
  75. new byte[]
  76. {
  77. 0, 2, 3, 4
  78. },
  79. new byte[]
  80. {
  81. 0, 1, 3, 4, 5
  82. },
  83. new byte[]
  84. {
  85. 0, 1, 2, 4, 5, 6
  86. },
  87. new byte[]
  88. {
  89. 1, 2, 3, 5, 6, 7
  90. },
  91. new byte[]
  92. {
  93. 3, 4, 6, 7
  94. },
  95. new byte[]
  96. {
  97. 2, 4, 5, 7
  98. },
  99. new byte[]
  100. {
  101. 2, 3, 5, 6
  102. },
  103. new byte[]
  104. {
  105. 3, 4, 6, 7
  106. },
  107. new byte[]
  108. {
  109. 0, 2, 4, 5, 7
  110. },
  111. new byte[]
  112. {
  113. 0, 1, 2, 3, 5, 6
  114. },
  115. new byte[]
  116. {
  117. 0, 1, 2, 3, 4, 6, 7
  118. },
  119. new byte[]
  120. {
  121. 1, 3, 4, 5, 7
  122. },
  123. new byte[]
  124. {
  125. 0, 4, 5, 6
  126. },
  127. new byte[]
  128. {
  129. 0, 1, 5, 6, 7
  130. },
  131. new byte[]
  132. {
  133. 0, 1, 6, 7
  134. },
  135. new byte[]
  136. {
  137. 1, 7
  138. }
  139. };
  140. private uint _residue = _initialResidueValue;
  141. internal CRC32()
  142. {
  143. lock (_globalSync)
  144. {
  145. if (_crc32Table == null) PrepareTable();
  146. }
  147. }
  148. internal uint crc => ~_residue;
  149. internal uint Compute(Stream stream)
  150. {
  151. var buffer = new byte[0x1000];
  152. for (;;)
  153. {
  154. var bytesRead = stream.Read(buffer, 0, buffer.Length);
  155. if (bytesRead > 0)
  156. Accumulate(buffer, 0, bytesRead);
  157. else
  158. break;
  159. }
  160. return crc;
  161. }
  162. internal void Accumulate(byte[] buffer, int offset, int count)
  163. {
  164. for (var i = offset; i < count + offset; i++)
  165. _residue = ((_residue >> 8) & 0x00FFFFFF)
  166. ^
  167. _crc32Table[(_residue ^ buffer[i]) & 0x000000FF];
  168. }
  169. internal void ClearCrc()
  170. {
  171. _residue = _initialResidueValue;
  172. }
  173. private static void PrepareTable()
  174. {
  175. _crc32Table = new uint[256];
  176. for (uint tablePosition = 0; tablePosition < _crc32Table.Length; tablePosition++)
  177. for (byte bitPosition = 0; bitPosition < 32; bitPosition++)
  178. {
  179. var bitValue = false;
  180. foreach (var maskingBit in _maskingBitTable[bitPosition]) bitValue ^= GetBit(maskingBit, tablePosition);
  181. SetBit(bitPosition, ref _crc32Table[tablePosition], bitValue);
  182. }
  183. }
  184. private static bool GetBit(byte bitOrdinal, uint data)
  185. {
  186. return ((data >> bitOrdinal) & 0x1) == 1;
  187. }
  188. private static void SetBit(byte bitOrdinal, ref uint data, bool value)
  189. {
  190. if (value) data |= (uint) 0x1 << bitOrdinal;
  191. }
  192. }
  193. }