crc.h
Go to the documentation of this file.
1 
38 /*
39  CRC++ can be configured by setting various #defines before #including this header file:
40 
41  #define crcpp_uint8 - Specifies the type used to store CRCs that have a width of 8 bits or less.
42  This type is not used in CRC calculations. Defaults to ::std::uint8_t.
43  #define crcpp_uint16 - Specifies the type used to store CRCs that have a width between 9 and 16 bits (inclusive).
44  This type is not used in CRC calculations. Defaults to ::std::uint16_t.
45  #define crcpp_uint32 - Specifies the type used to store CRCs that have a width between 17 and 32 bits (inclusive).
46  This type is not used in CRC calculations. Defaults to ::std::uint32_t.
47  #define crcpp_uint64 - Specifies the type used to store CRCs that have a width between 33 and 64 bits (inclusive).
48  This type is not used in CRC calculations. Defaults to ::std::uint64_t.
49  #define crcpp_size - This type is used for loop iteration and function signatures only. Defaults to ::std::size_t.
50  #define CRCPP_USE_NAMESPACE - Define to place all CRC++ code within the ::CRCPP namespace.
51  #define CRCPP_BRANCHLESS - Define to enable a branchless CRC implementation. The branchless implementation uses a single integer
52  multiplication in the bit-by-bit calculation instead of a small conditional. The branchless implementation
53  may be faster on processor architectures which support single-instruction integer multiplication.
54  #define CRCPP_USE_CPP11 - Define to enables C++11 features (move semantics, constexpr, static_assert, etc.).
55  #define CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS - Define to include definitions for little-used CRCs.
56 */
57 
58 #ifndef VESC_DRIVER_CRC_H_
59 #define VESC_DRIVER_CRC_H_
60 
61 #include <climits> // Includes CHAR_BIT
62 #ifdef CRCPP_USE_CPP11
63 #include <cstddef> // Includes ::std::size_t
64 #include <cstdint> // Includes ::std::uint8_t, ::std::uint16_t, ::std::uint32_t, ::std::uint64_t
65 #else
66 #include <stddef.h> // Includes size_t
67 #include <stdint.h> // Includes uint8_t, uint16_t, uint32_t, uint64_t
68 #endif
69 #include <limits> // Includes ::std::numeric_limits
70 #include <utility> // Includes ::std::move
71 
72 #ifndef crcpp_uint8
73 # ifdef CRCPP_USE_CPP11
74 # define crcpp_uint8 ::std::uint8_t
76 # else
77 # define crcpp_uint8 uint8_t
79 # endif
80 #endif
81 
82 #ifndef crcpp_uint16
83 # ifdef CRCPP_USE_CPP11
84 # define crcpp_uint16 ::std::uint16_t
86 # else
87 # define crcpp_uint16 uint16_t
89 # endif
90 #endif
91 
92 #ifndef crcpp_uint32
93 # ifdef CRCPP_USE_CPP11
94 # define crcpp_uint32 ::std::uint32_t
96 # else
97 # define crcpp_uint32 uint32_t
99 # endif
100 #endif
101 
102 #ifndef crcpp_uint64
103 # ifdef CRCPP_USE_CPP11
104 # define crcpp_uint64 ::std::uint64_t
106 # else
107 # define crcpp_uint64 uint64_t
109 # endif
110 #endif
111 
112 #ifndef crcpp_size
113 # ifdef CRCPP_USE_CPP11
114 # define crcpp_size ::std::size_t
116 # else
117 # define crcpp_size size_t
119 # endif
120 #endif
121 
122 #ifdef CRCPP_USE_CPP11
123 # define crcpp_constexpr constexpr
125 #else
126 # define crcpp_constexpr const
128 #endif
129 
130 #ifdef CRCPP_USE_NAMESPACE
131 namespace CRCPP
132 {
133 #endif
134 
142 class CRC
143 {
144 public:
145  // Forward declaration
146  template <typename CRCType, crcpp_uint16 CRCWidth>
147  struct Table;
148 
152  template <typename CRCType, crcpp_uint16 CRCWidth>
153  struct Parameters
154  {
155  CRCType polynomial;
156  CRCType initialValue;
157  CRCType finalXOR;
160 
161  Table<CRCType, CRCWidth> MakeTable() const;
162  };
163 
168  template <typename CRCType, crcpp_uint16 CRCWidth>
169  struct Table
170  {
171  // Constructors are intentionally NOT marked explicit.
172  Table(const Parameters<CRCType, CRCWidth> & parameters);
173 
174 #ifdef CRCPP_USE_CPP11
175  Table(Parameters<CRCType, CRCWidth> && parameters);
176 #endif
177 
178  const Parameters<CRCType, CRCWidth> & GetParameters() const;
179 
180  const CRCType * GetTable() const;
181 
182  CRCType operator[](unsigned char index) const;
183 
184  private:
185  void InitTable();
186 
188  CRCType table[1 << CHAR_BIT];
189  };
190 
191  // The number of bits in CRCType must be at least as large as CRCWidth.
192  // CRCType must be an unsigned integer type or a custom type with operator overloads.
193  template <typename CRCType, crcpp_uint16 CRCWidth>
194  static CRCType Calculate(const void * data, crcpp_size size, const Parameters<CRCType, CRCWidth> & parameters);
195 
196  template <typename CRCType, crcpp_uint16 CRCWidth>
197  static CRCType Calculate(const void * data, crcpp_size size, const Parameters<CRCType, CRCWidth> & parameters, CRCType crc);
198 
199  template <typename CRCType, crcpp_uint16 CRCWidth>
200  static CRCType Calculate(const void * data, crcpp_size size, const Table<CRCType, CRCWidth> & lookupTable);
201 
202  template <typename CRCType, crcpp_uint16 CRCWidth>
203  static CRCType Calculate(const void * data, crcpp_size size, const Table<CRCType, CRCWidth> & lookupTable, CRCType crc);
204 
205  // Common CRCs up to 64 bits.
206  // Note: Check values are the computed CRCs when given an ASCII input of "123456789" (without null terminator)
207 #ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
208  static const Parameters< crcpp_uint8, 4> & CRC_4_ITU();
209  static const Parameters< crcpp_uint8, 5> & CRC_5_EPC();
210  static const Parameters< crcpp_uint8, 5> & CRC_5_ITU();
211  static const Parameters< crcpp_uint8, 5> & CRC_5_USB();
212  static const Parameters< crcpp_uint8, 6> & CRC_6_CDMA2000A();
213  static const Parameters< crcpp_uint8, 6> & CRC_6_CDMA2000B();
214  static const Parameters< crcpp_uint8, 6> & CRC_6_ITU();
215  static const Parameters< crcpp_uint8, 7> & CRC_7();
216 #endif
217  static const Parameters< crcpp_uint8, 8> & CRC_8();
218 #ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
219  static const Parameters< crcpp_uint8, 8> & CRC_8_EBU();
220  static const Parameters< crcpp_uint8, 8> & CRC_8_MAXIM();
221  static const Parameters< crcpp_uint8, 8> & CRC_8_WCDMA();
222  static const Parameters<crcpp_uint16, 10> & CRC_10();
223  static const Parameters<crcpp_uint16, 10> & CRC_10_CDMA2000();
224  static const Parameters<crcpp_uint16, 11> & CRC_11();
225  static const Parameters<crcpp_uint16, 12> & CRC_12_CDMA2000();
226  static const Parameters<crcpp_uint16, 12> & CRC_12_DECT();
227  static const Parameters<crcpp_uint16, 12> & CRC_12_UMTS();
228  static const Parameters<crcpp_uint16, 13> & CRC_13_BBC();
229  static const Parameters<crcpp_uint16, 15> & CRC_15();
230  static const Parameters<crcpp_uint16, 15> & CRC_15_MPT1327();
231 #endif
232  static const Parameters<crcpp_uint16, 16> & CRC_16_ARC();
233  static const Parameters<crcpp_uint16, 16> & CRC_16_BUYPASS();
234  static const Parameters<crcpp_uint16, 16> & CRC_16_CCITTFALSE();
235 #ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
236  static const Parameters<crcpp_uint16, 16> & CRC_16_CDMA2000();
237  static const Parameters<crcpp_uint16, 16> & CRC_16_CMS();
238  static const Parameters<crcpp_uint16, 16> & CRC_16_DECTR();
239  static const Parameters<crcpp_uint16, 16> & CRC_16_DECTX();
240  static const Parameters<crcpp_uint16, 16> & CRC_16_DNP();
241 #endif
242  static const Parameters<crcpp_uint16, 16> & CRC_16_GENIBUS();
243  static const Parameters<crcpp_uint16, 16> & CRC_16_KERMIT();
244 #ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
245  static const Parameters<crcpp_uint16, 16> & CRC_16_MAXIM();
246  static const Parameters<crcpp_uint16, 16> & CRC_16_MODBUS();
247  static const Parameters<crcpp_uint16, 16> & CRC_16_T10DIF();
248  static const Parameters<crcpp_uint16, 16> & CRC_16_USB();
249 #endif
250  static const Parameters<crcpp_uint16, 16> & CRC_16_X25();
251  static const Parameters<crcpp_uint16, 16> & CRC_16_XMODEM();
252 #ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
253  static const Parameters<crcpp_uint32, 17> & CRC_17_CAN();
254  static const Parameters<crcpp_uint32, 21> & CRC_21_CAN();
255  static const Parameters<crcpp_uint32, 24> & CRC_24();
256  static const Parameters<crcpp_uint32, 24> & CRC_24_FLEXRAYA();
257  static const Parameters<crcpp_uint32, 24> & CRC_24_FLEXRAYB();
258  static const Parameters<crcpp_uint32, 30> & CRC_30();
259 #endif
260  static const Parameters<crcpp_uint32, 32> & CRC_32();
261  static const Parameters<crcpp_uint32, 32> & CRC_32_BZIP2();
262 #ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
263  static const Parameters<crcpp_uint32, 32> & CRC_32_C();
264 #endif
265  static const Parameters<crcpp_uint32, 32> & CRC_32_MPEG2();
266  static const Parameters<crcpp_uint32, 32> & CRC_32_POSIX();
267 #ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
268  static const Parameters<crcpp_uint32, 32> & CRC_32_Q();
269  static const Parameters<crcpp_uint64, 40> & CRC_40_GSM();
270  static const Parameters<crcpp_uint64, 64> & CRC_64();
271 #endif
272 
273 #ifdef CRCPP_USE_CPP11
274  CRC() = delete;
275  CRC(const CRC & other) = delete;
276  CRC & operator=(const CRC & other) = delete;
277  CRC(CRC && other) = delete;
278  CRC & operator=(CRC && other) = delete;
279 #endif
280 
281 private:
282 #ifndef CRCPP_USE_CPP11
283  CRC();
284  CRC(const CRC & other);
285  CRC & operator=(const CRC & other);
286 #endif
287 
288  template <typename IntegerType>
289  static IntegerType Reflect(IntegerType value, crcpp_uint16 numBits);
290 
291  template <typename CRCType, crcpp_uint16 CRCWidth>
292  static CRCType Finalize(CRCType remainder, CRCType finalXOR, bool reflectOutput);
293 
294  template <typename CRCType, crcpp_uint16 CRCWidth>
295  static CRCType UndoFinalize(CRCType remainder, CRCType finalXOR, bool reflectOutput);
296 
297  template <typename CRCType, crcpp_uint16 CRCWidth>
298  static CRCType CalculateRemainder(const void * data, crcpp_size size, const Parameters<CRCType, CRCWidth> & parameters, CRCType remainder);
299 
300  template <typename CRCType, crcpp_uint16 CRCWidth>
301  static CRCType CalculateRemainder(const void * data, crcpp_size size, const Table<CRCType, CRCWidth> & lookupTable, CRCType remainder);
302 };
303 
312 template <typename CRCType, crcpp_uint16 CRCWidth>
314 {
315  // This should take advantage of RVO and optimize out the copy.
316  return CRC::Table<CRCType, CRCWidth>(*this);
317 }
318 
325 template <typename CRCType, crcpp_uint16 CRCWidth>
327  parameters(params)
328 {
329  InitTable();
330 }
331 
332 #ifdef CRCPP_USE_CPP11
333 
339 template <typename CRCType, crcpp_uint16 CRCWidth>
341  parameters(::std::move(params))
342 {
343  InitTable();
344 }
345 #endif
346 
353 template <typename CRCType, crcpp_uint16 CRCWidth>
355 {
356  return parameters;
357 }
358 
365 template <typename CRCType, crcpp_uint16 CRCWidth>
366 inline const CRCType * CRC::Table<CRCType, CRCWidth>::GetTable() const
367 {
368  return table;
369 }
370 
378 template <typename CRCType, crcpp_uint16 CRCWidth>
379 inline CRCType CRC::Table<CRCType, CRCWidth>::operator[](unsigned char index) const
380 {
381  return table[index];
382 }
383 
389 template <typename CRCType, crcpp_uint16 CRCWidth>
391 {
392  // For masking off the bits for the CRC (in the event that the number of bits in CRCType is larger than CRCWidth)
393  static crcpp_constexpr CRCType BIT_MASK((CRCType(1) << (CRCWidth - CRCType(1))) |
394  ((CRCType(1) << (CRCWidth - CRCType(1))) - CRCType(1)));
395 
396  // The conditional expression is used to avoid a -Wshift-count-overflow warning.
397  static crcpp_constexpr CRCType SHIFT((CHAR_BIT >= CRCWidth) ? static_cast<CRCType>(CHAR_BIT - CRCWidth) : 0);
398 
399  CRCType crc;
400  unsigned char byte = 0;
401 
402  // Loop over each dividend (each possible number storable in an unsigned char)
403  do
404  {
405  crc = CRC::CalculateRemainder<CRCType, CRCWidth>(&byte, sizeof(byte), parameters, CRCType(0));
406 
407  // This mask might not be necessary; all unit tests pass with this line commented out,
408  // but that might just be a coincidence based on the CRC parameters used for testing.
409  // In any case, this is harmless to leave in and only adds a single machine instruction per loop iteration.
410  crc &= BIT_MASK;
411 
412  if (!parameters.reflectInput && CRCWidth < CHAR_BIT)
413  {
414  // Undo the special operation at the end of the CalculateRemainder()
415  // function for non-reflected CRCs < CHAR_BIT.
416  crc = static_cast<CRCType>(crc << SHIFT);
417  }
418 
419  table[byte] = crc;
420  }
421  while (++byte);
422 }
423 
433 template <typename CRCType, crcpp_uint16 CRCWidth>
434 inline CRCType CRC::Calculate(const void * data, crcpp_size size, const Parameters<CRCType, CRCWidth> & parameters)
435 {
436  CRCType remainder = CalculateRemainder(data, size, parameters, parameters.initialValue);
437 
438  // No need to mask the remainder here; the mask will be applied in the Finalize() function.
439 
440  return Finalize<CRCType, CRCWidth>(remainder, parameters.finalXOR, parameters.reflectInput != parameters.reflectOutput);
441 }
453 template <typename CRCType, crcpp_uint16 CRCWidth>
454 inline CRCType CRC::Calculate(const void * data, crcpp_size size, const Parameters<CRCType, CRCWidth> & parameters, CRCType crc)
455 {
456  CRCType remainder = UndoFinalize<CRCType, CRCWidth>(crc, parameters.finalXOR, parameters.reflectInput != parameters.reflectOutput);
457 
458  remainder = CalculateRemainder(data, size, parameters, remainder);
459 
460  // No need to mask the remainder here; the mask will be applied in the Finalize() function.
461 
462  return Finalize<CRCType, CRCWidth>(remainder, parameters.finalXOR, parameters.reflectInput != parameters.reflectOutput);
463 }
464 
474 template <typename CRCType, crcpp_uint16 CRCWidth>
475 inline CRCType CRC::Calculate(const void * data, crcpp_size size, const Table<CRCType, CRCWidth> & lookupTable)
476 {
478 
479  CRCType remainder = CalculateRemainder(data, size, lookupTable, parameters.initialValue);
480 
481  // No need to mask the remainder here; the mask will be applied in the Finalize() function.
482 
483  return Finalize<CRCType, CRCWidth>(remainder, parameters.finalXOR, parameters.reflectInput != parameters.reflectOutput);
484 }
485 
497 template <typename CRCType, crcpp_uint16 CRCWidth>
498 inline CRCType CRC::Calculate(const void * data, crcpp_size size, const Table<CRCType, CRCWidth> & lookupTable, CRCType crc)
499 {
501 
502  CRCType remainder = UndoFinalize<CRCType, CRCWidth>(crc, parameters.finalXOR, parameters.reflectInput != parameters.reflectOutput);
503 
504  remainder = CalculateRemainder(data, size, lookupTable, remainder);
505 
506  // No need to mask the remainder here; the mask will be applied in the Finalize() function.
507 
508  return Finalize<CRCType, CRCWidth>(remainder, parameters.finalXOR, parameters.reflectInput != parameters.reflectOutput);
509 }
510 
518 template <typename IntegerType>
519 inline IntegerType CRC::Reflect(IntegerType value, crcpp_uint16 numBits)
520 {
521  IntegerType reversedValue(0);
522 
523  for (crcpp_uint16 i = 0; i < numBits; ++i)
524  {
525  reversedValue = static_cast<IntegerType>((reversedValue << 1) | (value & 1));
526  value = static_cast<IntegerType>(value >> 1);
527  }
528 
529  return reversedValue;
530 }
531 
541 template <typename CRCType, crcpp_uint16 CRCWidth>
542 inline CRCType CRC::Finalize(CRCType remainder, CRCType finalXOR, bool reflectOutput)
543 {
544  // For masking off the bits for the CRC (in the event that the number of bits in CRCType is larger than CRCWidth)
545  static crcpp_constexpr CRCType BIT_MASK = (CRCType(1) << (CRCWidth - CRCType(1))) |
546  ((CRCType(1) << (CRCWidth - CRCType(1))) - CRCType(1));
547 
548  if (reflectOutput)
549  {
550  remainder = Reflect(remainder, CRCWidth);
551  }
552 
553  return (remainder ^ finalXOR) & BIT_MASK;
554 }
555 
573 template <typename CRCType, crcpp_uint16 CRCWidth>
574 inline CRCType CRC::UndoFinalize(CRCType crc, CRCType finalXOR, bool reflectOutput)
575 {
576  // For masking off the bits for the CRC (in the event that the number of bits in CRCType is larger than CRCWidth)
577  static crcpp_constexpr CRCType BIT_MASK = (CRCType(1) << (CRCWidth - CRCType(1))) |
578  ((CRCType(1) << (CRCWidth - CRCType(1))) - CRCType(1));
579 
580  crc = (crc & BIT_MASK) ^ finalXOR;
581 
582  if (reflectOutput)
583  {
584  crc = Reflect(crc, CRCWidth);
585  }
586 
587  return crc;
588 }
589 
600 template <typename CRCType, crcpp_uint16 CRCWidth>
601 inline CRCType CRC::CalculateRemainder(const void * data, crcpp_size size, const Parameters<CRCType, CRCWidth> & parameters, CRCType remainder)
602 {
603 #ifdef CRCPP_USE_CPP11
604  // This static_assert is put here because this function will always be compiled in no matter what
605  // the template parameters are and whether or not a table lookup or bit-by-bit algorithm is used.
606  static_assert(::std::numeric_limits<CRCType>::digits >= CRCWidth, "CRCType is too small to contain a CRC of width CRCWidth.");
607 #else
608  // Catching this compile-time error is very important. Sadly, the compiler error will be very cryptic, but it's
609  // better than nothing.
610  enum { static_assert_failed_CRCType_is_too_small_to_contain_a_CRC_of_width_CRCWidth = 1 / (::std::numeric_limits<CRCType>::digits >= CRCWidth ? 1 : 0) };
611 #endif
612 
613  const unsigned char * current = reinterpret_cast<const unsigned char *>(data);
614 
615  // Slightly different implementations based on the parameters. The current implementations try to eliminate as much
616  // computation from the inner loop (looping over each bit) as possible.
617  if (parameters.reflectInput)
618  {
619  CRCType polynomial = CRC::Reflect(parameters.polynomial, CRCWidth);
620  while (size--)
621  {
622  remainder = static_cast<CRCType>(remainder ^ *current++);
623 
624  // An optimizing compiler might choose to unroll this loop.
625  for (crcpp_size i = 0; i < CHAR_BIT; ++i)
626  {
627 #ifdef CRCPP_BRANCHLESS
628  // Clever way to avoid a branch at the expense of a multiplication. This code is equivalent to the following:
629  // if (remainder & 1)
630  // remainder = (remainder >> 1) ^ polynomial;
631  // else
632  // remainder >>= 1;
633  remainder = static_cast<CRCType>((remainder >> 1) ^ ((remainder & 1) * polynomial));
634 #else
635  remainder = static_cast<CRCType>((remainder & 1) ? ((remainder >> 1) ^ polynomial) : (remainder >> 1));
636 #endif
637  }
638  }
639  }
640  else if (CRCWidth >= CHAR_BIT)
641  {
642  static crcpp_constexpr CRCType CRC_WIDTH_MINUS_ONE(CRCWidth - CRCType(1));
643 #ifndef CRCPP_BRANCHLESS
644  static crcpp_constexpr CRCType CRC_HIGHEST_BIT_MASK(CRCType(1) << CRC_WIDTH_MINUS_ONE);
645 #endif
646  // The conditional expression is used to avoid a -Wshift-count-overflow warning.
647  static crcpp_constexpr CRCType SHIFT((CRCWidth >= CHAR_BIT) ? static_cast<CRCType>(CRCWidth - CHAR_BIT) : 0);
648 
649  while (size--)
650  {
651  remainder = static_cast<CRCType>(remainder ^ (static_cast<CRCType>(*current++) << SHIFT));
652 
653  // An optimizing compiler might choose to unroll this loop.
654  for (crcpp_size i = 0; i < CHAR_BIT; ++i)
655  {
656 #ifdef CRCPP_BRANCHLESS
657  // Clever way to avoid a branch at the expense of a multiplication. This code is equivalent to the following:
658  // if (remainder & CRC_HIGHEST_BIT_MASK)
659  // remainder = (remainder << 1) ^ parameters.polynomial;
660  // else
661  // remainder <<= 1;
662  remainder = static_cast<CRCType>((remainder << 1) ^ (((remainder >> CRC_WIDTH_MINUS_ONE) & 1) * parameters.polynomial));
663 #else
664  remainder = static_cast<CRCType>((remainder & CRC_HIGHEST_BIT_MASK) ? ((remainder << 1) ^ parameters.polynomial) : (remainder << 1));
665 #endif
666  }
667  }
668  }
669  else
670  {
671  static crcpp_constexpr CRCType CHAR_BIT_MINUS_ONE(CHAR_BIT - 1);
672 #ifndef CRCPP_BRANCHLESS
673  static crcpp_constexpr CRCType CHAR_BIT_HIGHEST_BIT_MASK(CRCType(1) << CHAR_BIT_MINUS_ONE);
674 #endif
675  // The conditional expression is used to avoid a -Wshift-count-overflow warning.
676  static crcpp_constexpr CRCType SHIFT((CHAR_BIT >= CRCWidth) ? static_cast<CRCType>(CHAR_BIT - CRCWidth) : 0);
677 
678  CRCType polynomial = static_cast<CRCType>(parameters.polynomial << SHIFT);
679  remainder = static_cast<CRCType>(remainder << SHIFT);
680 
681  while (size--)
682  {
683  remainder = static_cast<CRCType>(remainder ^ *current++);
684 
685  // An optimizing compiler might choose to unroll this loop.
686  for (crcpp_size i = 0; i < CHAR_BIT; ++i)
687  {
688 #ifdef CRCPP_BRANCHLESS
689  // Clever way to avoid a branch at the expense of a multiplication. This code is equivalent to the following:
690  // if (remainder & CHAR_BIT_HIGHEST_BIT_MASK)
691  // remainder = (remainder << 1) ^ polynomial;
692  // else
693  // remainder <<= 1;
694  remainder = static_cast<CRCType>((remainder << 1) ^ (((remainder >> CHAR_BIT_MINUS_ONE) & 1) * polynomial));
695 #else
696  remainder = static_cast<CRCType>((remainder & CHAR_BIT_HIGHEST_BIT_MASK) ? ((remainder << 1) ^ polynomial) : (remainder << 1));
697 #endif
698  }
699  }
700 
701  remainder = static_cast<CRCType>(remainder >> SHIFT);
702  }
703 
704  return remainder;
705 }
706 
717 template <typename CRCType, crcpp_uint16 CRCWidth>
718 inline CRCType CRC::CalculateRemainder(const void * data, crcpp_size size, const Table<CRCType, CRCWidth> & lookupTable, CRCType remainder)
719 {
720  const unsigned char * current = reinterpret_cast<const unsigned char *>(data);
721 
722  if (lookupTable.GetParameters().reflectInput)
723  {
724  while (size--)
725  {
726 #if defined(WIN32) || defined(_WIN32) || defined(WINCE)
727  // Disable warning about data loss when doing (remainder >> CHAR_BIT) when
728  // remainder is one byte long. The algorithm is still correct in this case,
729  // though it's possible that one additional machine instruction will be executed.
730 # pragma warning (push)
731 # pragma warning (disable : 4333)
732 #endif
733  remainder = static_cast<CRCType>((remainder >> CHAR_BIT) ^ lookupTable[static_cast<unsigned char>(remainder ^ *current++)]);
734 #if defined(WIN32) || defined(_WIN32) || defined(WINCE)
735 # pragma warning (pop)
736 #endif
737  }
738  }
739  else if (CRCWidth >= CHAR_BIT)
740  {
741  // The conditional expression is used to avoid a -Wshift-count-overflow warning.
742  static crcpp_constexpr CRCType SHIFT((CRCWidth >= CHAR_BIT) ? static_cast<CRCType>(CRCWidth - CHAR_BIT) : 0);
743 
744  while (size--)
745  {
746  remainder = static_cast<CRCType>((remainder << CHAR_BIT) ^ lookupTable[static_cast<unsigned char>((remainder >> SHIFT) ^ *current++)]);
747  }
748  }
749  else
750  {
751  // The conditional expression is used to avoid a -Wshift-count-overflow warning.
752  static crcpp_constexpr CRCType SHIFT((CHAR_BIT >= CRCWidth) ? static_cast<CRCType>(CHAR_BIT - CRCWidth) : 0);
753 
754  remainder = static_cast<CRCType>(remainder << SHIFT);
755 
756  while (size--)
757  {
758  // Note: no need to mask here since remainder is guaranteed to fit in a single byte.
759  remainder = lookupTable[static_cast<unsigned char>(remainder ^ *current++)];
760  }
761 
762  remainder = static_cast<CRCType>(remainder >> SHIFT);
763  }
764 
765  return remainder;
766 }
767 
768 #ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
769 
781 inline const CRC::Parameters<crcpp_uint8, 4> & CRC::CRC_4_ITU()
782 {
783  static const Parameters<crcpp_uint8, 4> parameters = { 0x3, 0x0, 0x0, true, true };
784  return parameters;
785 }
786 
799 inline const CRC::Parameters<crcpp_uint8, 5> & CRC::CRC_5_EPC()
800 {
801  static const Parameters<crcpp_uint8, 5> parameters = { 0x09, 0x09, 0x00, false, false };
802  return parameters;
803 }
804 
817 inline const CRC::Parameters<crcpp_uint8, 5> & CRC::CRC_5_ITU()
818 {
819  static const Parameters<crcpp_uint8, 5> parameters = { 0x15, 0x00, 0x00, true, true };
820  return parameters;
821 }
822 
835 inline const CRC::Parameters<crcpp_uint8, 5> & CRC::CRC_5_USB()
836 {
837  static const Parameters<crcpp_uint8, 5> parameters = { 0x05, 0x1F, 0x1F, true, true };
838  return parameters;
839 }
840 
853 inline const CRC::Parameters<crcpp_uint8, 6> & CRC::CRC_6_CDMA2000A()
854 {
855  static const Parameters<crcpp_uint8, 6> parameters = { 0x27, 0x3F, 0x00, false, false };
856  return parameters;
857 }
858 
871 inline const CRC::Parameters<crcpp_uint8, 6> & CRC::CRC_6_CDMA2000B()
872 {
873  static const Parameters<crcpp_uint8, 6> parameters = { 0x07, 0x3F, 0x00, false, false };
874  return parameters;
875 }
876 
889 inline const CRC::Parameters<crcpp_uint8, 6> & CRC::CRC_6_ITU()
890 {
891  static const Parameters<crcpp_uint8, 6> parameters = { 0x03, 0x00, 0x00, true, true };
892  return parameters;
893 }
894 
907 inline const CRC::Parameters<crcpp_uint8, 7> & CRC::CRC_7()
908 {
909  static const Parameters<crcpp_uint8, 7> parameters = { 0x09, 0x00, 0x00, false, false };
910  return parameters;
911 }
912 #endif // CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
913 
927 {
928  static const Parameters<crcpp_uint8, 8> parameters = { 0x07, 0x00, 0x00, false, false };
929  return parameters;
930 }
931 
932 #ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
933 
945 inline const CRC::Parameters<crcpp_uint8, 8> & CRC::CRC_8_EBU()
946 {
947  static const Parameters<crcpp_uint8, 8> parameters = { 0x1D, 0xFF, 0x00, true, true };
948  return parameters;
949 }
950 
963 inline const CRC::Parameters<crcpp_uint8, 8> & CRC::CRC_8_MAXIM()
964 {
965  static const Parameters<crcpp_uint8, 8> parameters = { 0x31, 0x00, 0x00, true, true };
966  return parameters;
967 }
968 
981 inline const CRC::Parameters<crcpp_uint8, 8> & CRC::CRC_8_WCDMA()
982 {
983  static const Parameters<crcpp_uint8, 8> parameters = { 0x9B, 0x00, 0x00, true, true };
984  return parameters;
985 }
986 
999 inline const CRC::Parameters<crcpp_uint16, 10> & CRC::CRC_10()
1000 {
1001  static const Parameters<crcpp_uint16, 10> parameters = { 0x233, 0x000, 0x000, false, false };
1002  return parameters;
1003 }
1004 
1017 inline const CRC::Parameters<crcpp_uint16, 10> & CRC::CRC_10_CDMA2000()
1018 {
1019  static const Parameters<crcpp_uint16, 10> parameters = { 0x3D9, 0x3FF, 0x000, false, false };
1020  return parameters;
1021 }
1022 
1035 inline const CRC::Parameters<crcpp_uint16, 11> & CRC::CRC_11()
1036 {
1037  static const Parameters<crcpp_uint16, 11> parameters = { 0x385, 0x01A, 0x000, false, false };
1038  return parameters;
1039 }
1040 
1053 inline const CRC::Parameters<crcpp_uint16, 12> & CRC::CRC_12_CDMA2000()
1054 {
1055  static const Parameters<crcpp_uint16, 12> parameters = { 0xF13, 0xFFF, 0x000, false, false };
1056  return parameters;
1057 }
1058 
1071 inline const CRC::Parameters<crcpp_uint16, 12> & CRC::CRC_12_DECT()
1072 {
1073  static const Parameters<crcpp_uint16, 12> parameters = { 0x80F, 0x000, 0x000, false, false };
1074  return parameters;
1075 }
1076 
1089 inline const CRC::Parameters<crcpp_uint16, 12> & CRC::CRC_12_UMTS()
1090 {
1091  static const Parameters<crcpp_uint16, 12> parameters = { 0x80F, 0x000, 0x000, false, true };
1092  return parameters;
1093 }
1094 
1107 inline const CRC::Parameters<crcpp_uint16, 13> & CRC::CRC_13_BBC()
1108 {
1109  static const Parameters<crcpp_uint16, 13> parameters = { 0x1CF5, 0x0000, 0x0000, false, false };
1110  return parameters;
1111 }
1112 
1125 inline const CRC::Parameters<crcpp_uint16, 15> & CRC::CRC_15()
1126 {
1127  static const Parameters<crcpp_uint16, 15> parameters = { 0x4599, 0x0000, 0x0000, false, false };
1128  return parameters;
1129 }
1130 
1143 inline const CRC::Parameters<crcpp_uint16, 15> & CRC::CRC_15_MPT1327()
1144 {
1145  static const Parameters<crcpp_uint16, 15> parameters = { 0x6815, 0x0000, 0x0001, false, false };
1146  return parameters;
1147 }
1148 #endif // CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
1149 
1163 {
1164  static const Parameters<crcpp_uint16, 16> parameters = { 0x8005, 0x0000, 0x0000, true, true };
1165  return parameters;
1166 }
1167 
1181 {
1182  static const Parameters<crcpp_uint16, 16> parameters = { 0x8005, 0x0000, 0x0000, false, false };
1183  return parameters;
1184 }
1185 
1199 {
1200  static const Parameters<crcpp_uint16, 16> parameters = { 0x1021, 0xFFFF, 0x0000, false, false };
1201  return parameters;
1202 }
1203 
1204 #ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
1205 
1217 inline const CRC::Parameters<crcpp_uint16, 16> & CRC::CRC_16_CDMA2000()
1218 {
1219  static const Parameters<crcpp_uint16, 16> parameters = { 0xC867, 0xFFFF, 0x0000, false, false };
1220  return parameters;
1221 }
1222 
1235 inline const CRC::Parameters<crcpp_uint16, 16> & CRC::CRC_16_CMS()
1236 {
1237  static const Parameters<crcpp_uint16, 16> parameters = { 0x8005, 0xFFFF, 0x0000, false, false };
1238  return parameters;
1239 }
1240 
1253 inline const CRC::Parameters<crcpp_uint16, 16> & CRC::CRC_16_DECTR()
1254 {
1255  static const Parameters<crcpp_uint16, 16> parameters = { 0x0589, 0x0000, 0x0001, false, false };
1256  return parameters;
1257 }
1258 
1271 inline const CRC::Parameters<crcpp_uint16, 16> & CRC::CRC_16_DECTX()
1272 {
1273  static const Parameters<crcpp_uint16, 16> parameters = { 0x0589, 0x0000, 0x0000, false, false };
1274  return parameters;
1275 }
1276 
1289 inline const CRC::Parameters<crcpp_uint16, 16> & CRC::CRC_16_DNP()
1290 {
1291  static const Parameters<crcpp_uint16, 16> parameters = { 0x3D65, 0x0000, 0xFFFF, true, true };
1292  return parameters;
1293 }
1294 #endif // CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
1295 
1309 {
1310  static const Parameters<crcpp_uint16, 16> parameters = { 0x1021, 0xFFFF, 0xFFFF, false, false };
1311  return parameters;
1312 }
1313 
1327 {
1328  static const Parameters<crcpp_uint16, 16> parameters = { 0x1021, 0x0000, 0x0000, true, true };
1329  return parameters;
1330 }
1331 
1332 #ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
1333 
1345 inline const CRC::Parameters<crcpp_uint16, 16> & CRC::CRC_16_MAXIM()
1346 {
1347  static const Parameters<crcpp_uint16, 16> parameters = { 0x8005, 0x0000, 0xFFFF, true, true };
1348  return parameters;
1349 }
1350 
1363 inline const CRC::Parameters<crcpp_uint16, 16> & CRC::CRC_16_MODBUS()
1364 {
1365  static const Parameters<crcpp_uint16, 16> parameters = { 0x8005, 0xFFFF, 0x0000, true, true };
1366  return parameters;
1367 }
1368 
1381 inline const CRC::Parameters<crcpp_uint16, 16> & CRC::CRC_16_T10DIF()
1382 {
1383  static const Parameters<crcpp_uint16, 16> parameters = { 0x8BB7, 0x0000, 0x0000, false, false };
1384  return parameters;
1385 }
1386 
1399 inline const CRC::Parameters<crcpp_uint16, 16> & CRC::CRC_16_USB()
1400 {
1401  static const Parameters<crcpp_uint16, 16> parameters = { 0x8005, 0xFFFF, 0xFFFF, true, true };
1402  return parameters;
1403 }
1404 
1405 #endif // CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
1406 
1420 {
1421  static const Parameters<crcpp_uint16, 16> parameters = { 0x1021, 0xFFFF, 0xFFFF, true, true };
1422  return parameters;
1423 }
1424 
1438 {
1439  static const Parameters<crcpp_uint16, 16> parameters = { 0x1021, 0x0000, 0x0000, false, false };
1440  return parameters;
1441 }
1442 
1443 #ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
1444 
1456 inline const CRC::Parameters<crcpp_uint32, 17> & CRC::CRC_17_CAN()
1457 {
1458  static const Parameters<crcpp_uint32, 17> parameters = { 0x1685B, 0x00000, 0x00000, false, false };
1459  return parameters;
1460 }
1461 
1474 inline const CRC::Parameters<crcpp_uint32, 21> & CRC::CRC_21_CAN()
1475 {
1476  static const Parameters<crcpp_uint32, 21> parameters = { 0x102899, 0x000000, 0x000000, false, false };
1477  return parameters;
1478 }
1479 
1492 inline const CRC::Parameters<crcpp_uint32, 24> & CRC::CRC_24()
1493 {
1494  static const Parameters<crcpp_uint32, 24> parameters = { 0x864CFB, 0xB704CE, 0x000000, false, false };
1495  return parameters;
1496 }
1497 
1510 inline const CRC::Parameters<crcpp_uint32, 24> & CRC::CRC_24_FLEXRAYA()
1511 {
1512  static const Parameters<crcpp_uint32, 24> parameters = { 0x5D6DCB, 0xFEDCBA, 0x000000, false, false };
1513  return parameters;
1514 }
1515 
1528 inline const CRC::Parameters<crcpp_uint32, 24> & CRC::CRC_24_FLEXRAYB()
1529 {
1530  static const Parameters<crcpp_uint32, 24> parameters = { 0x5D6DCB, 0xABCDEF, 0x000000, false, false };
1531  return parameters;
1532 }
1533 
1546 inline const CRC::Parameters<crcpp_uint32, 30> & CRC::CRC_30()
1547 {
1548  static const Parameters<crcpp_uint32, 30> parameters = { 0x2030B9C7, 0x3FFFFFFF, 0x00000000, false, false };
1549  return parameters;
1550 }
1551 #endif // CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
1552 
1566 {
1567  static const Parameters<crcpp_uint32, 32> parameters = { 0x04C11DB7, 0xFFFFFFFF, 0xFFFFFFFF, true, true };
1568  return parameters;
1569 }
1570 
1584 {
1585  static const Parameters<crcpp_uint32, 32> parameters = { 0x04C11DB7, 0xFFFFFFFF, 0xFFFFFFFF, false, false };
1586  return parameters;
1587 }
1588 
1589 #ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
1590 
1602 inline const CRC::Parameters<crcpp_uint32, 32> & CRC::CRC_32_C()
1603 {
1604  static const Parameters<crcpp_uint32, 32> parameters = { 0x1EDC6F41, 0xFFFFFFFF, 0xFFFFFFFF, true, true };
1605  return parameters;
1606 }
1607 #endif
1608 
1622 {
1623  static const Parameters<crcpp_uint32, 32> parameters = { 0x04C11DB7, 0xFFFFFFFF, 0x00000000, false, false };
1624  return parameters;
1625 }
1626 
1640 {
1641  static const Parameters<crcpp_uint32, 32> parameters = { 0x04C11DB7, 0x00000000, 0xFFFFFFFF, false, false };
1642  return parameters;
1643 }
1644 
1645 #ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
1646 
1658 inline const CRC::Parameters<crcpp_uint32, 32> & CRC::CRC_32_Q()
1659 {
1660  static const Parameters<crcpp_uint32, 32> parameters = { 0x814141AB, 0x00000000, 0x00000000, false, false };
1661  return parameters;
1662 }
1663 
1676 inline const CRC::Parameters<crcpp_uint64, 40> & CRC::CRC_40_GSM()
1677 {
1678  static const Parameters<crcpp_uint64, 40> parameters = { 0x0004820009, 0x0000000000, 0xFFFFFFFFFF, false, false };
1679  return parameters;
1680 }
1681 
1694 inline const CRC::Parameters<crcpp_uint64, 64> & CRC::CRC_64()
1695 {
1696  static const Parameters<crcpp_uint64, 64> parameters = { 0x42F0E1EBA9EA3693, 0x0000000000000000, 0x0000000000000000, false, false };
1697  return parameters;
1698 }
1699 #endif // CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
1700 
1701 #ifdef CRCPP_USE_NAMESPACE
1702 }
1703 #endif
1704 
1705 #endif // CRCPP_CRC_H_
const CRCType * GetTable() const
Gets the CRC table.
Definition: crc.h:366
static const Parameters< crcpp_uint16, 16 > & CRC_16_CCITTFALSE()
Returns a set of parameters for CRC-16 CCITT FALSE.
Definition: crc.h:1198
static const Parameters< crcpp_uint32, 32 > & CRC_32()
Returns a set of parameters for CRC-32 (aka CRC-32 ADCCP, CRC-32 PKZip).
Definition: crc.h:1565
CRCType initialValue
Initial CRC value.
Definition: crc.h:156
Table< CRCType, CRCWidth > MakeTable() const
Returns a CRC lookup table construct using these CRC parameters.
Definition: crc.h:313
static const Parameters< crcpp_uint16, 16 > & CRC_16_KERMIT()
Returns a set of parameters for CRC-16 KERMIT (aka CRC-16 CCITT, CRC-16 CCITT-TRUE).
Definition: crc.h:1326
#define crcpp_size
Unsigned size definition, used for specifying data sizes.
Definition: crc.h:118
const Parameters< CRCType, CRCWidth > & GetParameters() const
Gets the CRC parameters used to construct the CRC table.
Definition: crc.h:354
Parameters< CRCType, CRCWidth > parameters
CRC parameters used to construct the table.
Definition: crc.h:187
static CRCType Finalize(CRCType remainder, CRCType finalXOR, bool reflectOutput)
Computes the final reflection and XOR of a CRC remainder.
Definition: crc.h:542
static const Parameters< crcpp_uint16, 16 > & CRC_16_ARC()
Returns a set of parameters for CRC-16 ARC (aka CRC-16 IBM, CRC-16 LHA).
Definition: crc.h:1162
bool reflectInput
true to reflect all input bytes
Definition: crc.h:158
static const Parameters< crcpp_uint16, 16 > & CRC_16_X25()
Returns a set of parameters for CRC-16 X-25 (aka CRC-16 IBM-SDLC, CRC-16 ISO-HDLC, CRC-16 B).
Definition: crc.h:1419
CRCType table[1<< CHAR_BIT]
CRC lookup table.
Definition: crc.h:188
static IntegerType Reflect(IntegerType value, crcpp_uint16 numBits)
Reflects (i.e. reverses the bits within) an integer value.
Definition: crc.h:519
static const Parameters< crcpp_uint32, 32 > & CRC_32_BZIP2()
Returns a set of parameters for CRC-32 BZIP2 (aka CRC-32 AAL5, CRC-32 DECT-B, CRC-32 B-CRC)...
Definition: crc.h:1583
static const Parameters< crcpp_uint16, 16 > & CRC_16_BUYPASS()
Returns a set of parameters for CRC-16 BUYPASS (aka CRC-16 VERIFONE, CRC-16 UMTS).
Definition: crc.h:1180
void InitTable()
Initializes a CRC table.
Definition: crc.h:390
CRCType finalXOR
Value to XOR with the final CRC.
Definition: crc.h:157
CRCType operator[](unsigned char index) const
Gets an entry in the CRC table.
Definition: crc.h:379
static CRCType UndoFinalize(CRCType remainder, CRCType finalXOR, bool reflectOutput)
Undoes the process of computing the final reflection and XOR of a CRC remainder.
Definition: crc.h:574
CRC lookup table. After construction, the CRC parameters are fixed.
Definition: crc.h:147
static CRCType Calculate(const void *data, crcpp_size size, const Parameters< CRCType, CRCWidth > &parameters)
Computes a CRC.
Definition: crc.h:434
CRC parameters.
Definition: crc.h:153
#define crcpp_uint16
Unsigned 16-bit integer definition, used primarily for parameter definitions.
Definition: crc.h:88
Static class for computing CRCs.
Definition: crc.h:142
static const Parameters< crcpp_uint32, 32 > & CRC_32_POSIX()
Returns a set of parameters for CRC-32 POSIX.
Definition: crc.h:1639
static CRCType CalculateRemainder(const void *data, crcpp_size size, const Parameters< CRCType, CRCWidth > &parameters, CRCType remainder)
Computes a CRC remainder.
Definition: crc.h:601
Table(const Parameters< CRCType, CRCWidth > &parameters)
Constructs a CRC table from a set of CRC parameters.
Definition: crc.h:326
CRCType polynomial
CRC polynomial.
Definition: crc.h:155
static const Parameters< crcpp_uint16, 16 > & CRC_16_XMODEM()
Returns a set of parameters for CRC-16 XMODEM (aka CRC-16 ZMODEM, CRC-16 ACORN, CRC-16 LTE)...
Definition: crc.h:1437
static const Parameters< crcpp_uint32, 32 > & CRC_32_MPEG2()
Returns a set of parameters for CRC-32 MPEG-2.
Definition: crc.h:1621
#define crcpp_constexpr
Compile-time expression definition.
Definition: crc.h:127
static const Parameters< crcpp_uint8, 8 > & CRC_8()
Returns a set of parameters for CRC-8 SMBus.
Definition: crc.h:926
static const Parameters< crcpp_uint16, 16 > & CRC_16_GENIBUS()
Returns a set of parameters for CRC-16 GENIBUS (aka CRC-16 EPC, CRC-16 I-CODE, CRC-16 DARC)...
Definition: crc.h:1308
bool reflectOutput
true to reflect the output CRC (reflection occurs before the final XOR)
Definition: crc.h:159


vesc_driver
Author(s): Michael T. Boulet , Joshua Whitley
autogenerated on Sun Apr 18 2021 02:48:01