CUBRID Engine  latest
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 // *INDENT-OFF*
59 
60 #ifndef CRCPP_CRC_H_
61 #define CRCPP_CRC_H_
62 
63 #include <climits> // Includes CHAR_BIT
64 #ifdef CRCPP_USE_CPP11
65 #include <cstddef> // Includes ::std::size_t
66 #include <cstdint> // Includes ::std::uint8_t, ::std::uint16_t, ::std::uint32_t, ::std::uint64_t
67 #else
68 #include <stddef.h> // Includes size_t
69 #include <stdint.h> // Includes uint8_t, uint16_t, uint32_t, uint64_t
70 #endif
71 #include <limits> // Includes ::std::numeric_limits
72 #include <utility> // Includes ::std::move
73 
74 #ifndef crcpp_uint8
75 # ifdef CRCPP_USE_CPP11
76 # define crcpp_uint8 ::std::uint8_t
78 # else
79 # define crcpp_uint8 uint8_t
81 # endif
82 #endif
83 
84 #ifndef crcpp_uint16
85 # ifdef CRCPP_USE_CPP11
86 # define crcpp_uint16 ::std::uint16_t
88 # else
89 # define crcpp_uint16 uint16_t
91 # endif
92 #endif
93 
94 #ifndef crcpp_uint32
95 # ifdef CRCPP_USE_CPP11
96 # define crcpp_uint32 ::std::uint32_t
98 # else
99 # define crcpp_uint32 uint32_t
101 # endif
102 #endif
103 
104 #ifndef crcpp_uint64
105 # ifdef CRCPP_USE_CPP11
106 # define crcpp_uint64 ::std::uint64_t
108 # else
109 # define crcpp_uint64 uint64_t
111 # endif
112 #endif
113 
114 #ifndef crcpp_size
115 # ifdef CRCPP_USE_CPP11
116 # define crcpp_size ::std::size_t
118 # else
119 # define crcpp_size size_t
121 # endif
122 #endif
123 
124 #ifdef CRCPP_USE_CPP11
125 # define crcpp_constexpr constexpr
127 #else
128 # define crcpp_constexpr const
130 #endif
131 
132 #ifdef CRCPP_USE_NAMESPACE
133 namespace CRCPP
134 {
135 #endif
136 
144 class CRC
145 {
146 public:
147  // Forward declaration
148  template <typename CRCType, crcpp_uint16 CRCWidth>
149  struct Table;
150 
154  template <typename CRCType, crcpp_uint16 CRCWidth>
155  struct Parameters
156  {
157  CRCType polynomial;
158  CRCType initialValue;
159  CRCType finalXOR;
162 
163  Table<CRCType, CRCWidth> MakeTable() const;
164  };
165 
170  template <typename CRCType, crcpp_uint16 CRCWidth>
171  struct Table
172  {
173  // Constructors are intentionally NOT marked explicit.
174  Table(const Parameters<CRCType, CRCWidth> & parameters);
175 
176 #ifdef CRCPP_USE_CPP11
177  Table(Parameters<CRCType, CRCWidth> && parameters);
178 #endif
179 
180  const Parameters<CRCType, CRCWidth> & GetParameters() const;
181 
182  const CRCType * GetTable() const;
183 
184  CRCType operator[](unsigned char index) const;
185 
186  private:
187  void InitTable();
188 
190  CRCType table[1 << CHAR_BIT];
191  };
192 
193  // The number of bits in CRCType must be at least as large as CRCWidth.
194  // CRCType must be an unsigned integer type or a custom type with operator overloads.
195  template <typename CRCType, crcpp_uint16 CRCWidth>
196  static CRCType Calculate(const void * data, crcpp_size size, const Parameters<CRCType, CRCWidth> & parameters);
197 
198  template <typename CRCType, crcpp_uint16 CRCWidth>
199  static CRCType Calculate(const void * data, crcpp_size size, const Parameters<CRCType, CRCWidth> & parameters, CRCType crc);
200 
201  template <typename CRCType, crcpp_uint16 CRCWidth>
202  static CRCType Calculate(const void * data, crcpp_size size, const Table<CRCType, CRCWidth> & lookupTable);
203 
204  template <typename CRCType, crcpp_uint16 CRCWidth>
205  static CRCType Calculate(const void * data, crcpp_size size, const Table<CRCType, CRCWidth> & lookupTable, CRCType crc);
206 
207  // Common CRCs up to 64 bits.
208  // Note: Check values are the computed CRCs when given an ASCII input of "123456789" (without null terminator)
209 #ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
210  static const Parameters< crcpp_uint8, 4> & CRC_4_ITU();
211  static const Parameters< crcpp_uint8, 5> & CRC_5_EPC();
212  static const Parameters< crcpp_uint8, 5> & CRC_5_ITU();
213  static const Parameters< crcpp_uint8, 5> & CRC_5_USB();
214  static const Parameters< crcpp_uint8, 6> & CRC_6_CDMA2000A();
215  static const Parameters< crcpp_uint8, 6> & CRC_6_CDMA2000B();
216  static const Parameters< crcpp_uint8, 6> & CRC_6_ITU();
217  static const Parameters< crcpp_uint8, 7> & CRC_7();
218 #endif
219  static const Parameters< crcpp_uint8, 8> & CRC_8();
220 #ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
221  static const Parameters< crcpp_uint8, 8> & CRC_8_EBU();
222  static const Parameters< crcpp_uint8, 8> & CRC_8_MAXIM();
223  static const Parameters< crcpp_uint8, 8> & CRC_8_WCDMA();
224  static const Parameters<crcpp_uint16, 10> & CRC_10();
225  static const Parameters<crcpp_uint16, 10> & CRC_10_CDMA2000();
226  static const Parameters<crcpp_uint16, 11> & CRC_11();
227  static const Parameters<crcpp_uint16, 12> & CRC_12_CDMA2000();
228  static const Parameters<crcpp_uint16, 12> & CRC_12_DECT();
229  static const Parameters<crcpp_uint16, 12> & CRC_12_UMTS();
230  static const Parameters<crcpp_uint16, 13> & CRC_13_BBC();
231  static const Parameters<crcpp_uint16, 15> & CRC_15();
232  static const Parameters<crcpp_uint16, 15> & CRC_15_MPT1327();
233 #endif
234  static const Parameters<crcpp_uint16, 16> & CRC_16_ARC();
235  static const Parameters<crcpp_uint16, 16> & CRC_16_BUYPASS();
236  static const Parameters<crcpp_uint16, 16> & CRC_16_CCITTFALSE();
237 #ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
238  static const Parameters<crcpp_uint16, 16> & CRC_16_CDMA2000();
239  static const Parameters<crcpp_uint16, 16> & CRC_16_CMS();
240  static const Parameters<crcpp_uint16, 16> & CRC_16_DECTR();
241  static const Parameters<crcpp_uint16, 16> & CRC_16_DECTX();
242  static const Parameters<crcpp_uint16, 16> & CRC_16_DNP();
243 #endif
244  static const Parameters<crcpp_uint16, 16> & CRC_16_GENIBUS();
245  static const Parameters<crcpp_uint16, 16> & CRC_16_KERMIT();
246 #ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
247  static const Parameters<crcpp_uint16, 16> & CRC_16_MAXIM();
248  static const Parameters<crcpp_uint16, 16> & CRC_16_MODBUS();
249  static const Parameters<crcpp_uint16, 16> & CRC_16_T10DIF();
250  static const Parameters<crcpp_uint16, 16> & CRC_16_USB();
251 #endif
252  static const Parameters<crcpp_uint16, 16> & CRC_16_X25();
253  static const Parameters<crcpp_uint16, 16> & CRC_16_XMODEM();
254 #ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
255  static const Parameters<crcpp_uint32, 17> & CRC_17_CAN();
256  static const Parameters<crcpp_uint32, 21> & CRC_21_CAN();
257  static const Parameters<crcpp_uint32, 24> & CRC_24();
258  static const Parameters<crcpp_uint32, 24> & CRC_24_FLEXRAYA();
259  static const Parameters<crcpp_uint32, 24> & CRC_24_FLEXRAYB();
260  static const Parameters<crcpp_uint32, 30> & CRC_30();
261 #endif
262  static const Parameters<crcpp_uint32, 32> & CRC_32();
263  static const Parameters<crcpp_uint32, 32> & CRC_32_BZIP2();
264 #ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
265  static const Parameters<crcpp_uint32, 32> & CRC_32_C();
266 #endif
267  static const Parameters<crcpp_uint32, 32> & CRC_32_MPEG2();
268  static const Parameters<crcpp_uint32, 32> & CRC_32_POSIX();
269 #ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
270  static const Parameters<crcpp_uint32, 32> & CRC_32_Q();
271  static const Parameters<crcpp_uint64, 40> & CRC_40_GSM();
272  static const Parameters<crcpp_uint64, 64> & CRC_64();
273 #endif
274 
275 #ifdef CRCPP_USE_CPP11
276  CRC() = delete;
277  CRC(const CRC & other) = delete;
278  CRC & operator=(const CRC & other) = delete;
279  CRC(CRC && other) = delete;
280  CRC & operator=(CRC && other) = delete;
281 #endif
282 
283 private:
284 #ifndef CRCPP_USE_CPP11
285  CRC();
286  CRC(const CRC & other);
287  CRC & operator=(const CRC & other);
288 #endif
289 
290  template <typename IntegerType>
291  static IntegerType Reflect(IntegerType value, crcpp_uint16 numBits);
292 
293  template <typename CRCType, crcpp_uint16 CRCWidth>
294  static CRCType Finalize(CRCType remainder, CRCType finalXOR, bool reflectOutput);
295 
296  template <typename CRCType, crcpp_uint16 CRCWidth>
297  static CRCType UndoFinalize(CRCType remainder, CRCType finalXOR, bool reflectOutput);
298 
299  template <typename CRCType, crcpp_uint16 CRCWidth>
300  static CRCType CalculateRemainder(const void * data, crcpp_size size, const Parameters<CRCType, CRCWidth> & parameters, CRCType remainder);
301 
302  template <typename CRCType, crcpp_uint16 CRCWidth>
303  static CRCType CalculateRemainder(const void * data, crcpp_size size, const Table<CRCType, CRCWidth> & lookupTable, CRCType remainder);
304 };
305 
314 template <typename CRCType, crcpp_uint16 CRCWidth>
316 {
317  // This should take advantage of RVO and optimize out the copy.
318  return CRC::Table<CRCType, CRCWidth>(*this);
319 }
320 
327 template <typename CRCType, crcpp_uint16 CRCWidth>
329  parameters(params)
330 {
331  InitTable();
332 }
333 
334 #ifdef CRCPP_USE_CPP11
335 
341 template <typename CRCType, crcpp_uint16 CRCWidth>
343  parameters(::std::move(params))
344 {
345  InitTable();
346 }
347 #endif
348 
355 template <typename CRCType, crcpp_uint16 CRCWidth>
357 {
358  return parameters;
359 }
360 
367 template <typename CRCType, crcpp_uint16 CRCWidth>
368 inline const CRCType * CRC::Table<CRCType, CRCWidth>::GetTable() const
369 {
370  return table;
371 }
372 
380 template <typename CRCType, crcpp_uint16 CRCWidth>
381 inline CRCType CRC::Table<CRCType, CRCWidth>::operator[](unsigned char index) const
382 {
383  return table[index];
384 }
385 
391 template <typename CRCType, crcpp_uint16 CRCWidth>
393 {
394  // For masking off the bits for the CRC (in the event that the number of bits in CRCType is larger than CRCWidth)
395  static crcpp_constexpr CRCType BIT_MASK((CRCType(1) << (CRCWidth - CRCType(1))) |
396  ((CRCType(1) << (CRCWidth - CRCType(1))) - CRCType(1)));
397 
398  // The conditional expression is used to avoid a -Wshift-count-overflow warning.
399  static crcpp_constexpr CRCType SHIFT((CHAR_BIT >= CRCWidth) ? static_cast<CRCType>(CHAR_BIT - CRCWidth) : 0);
400 
401  CRCType crc;
402  unsigned char byte = 0;
403 
404  // Loop over each dividend (each possible number storable in an unsigned char)
405  do
406  {
407  crc = CRC::CalculateRemainder<CRCType, CRCWidth>(&byte, sizeof(byte), parameters, CRCType(0));
408 
409  // This mask might not be necessary; all unit tests pass with this line commented out,
410  // but that might just be a coincidence based on the CRC parameters used for testing.
411  // In any case, this is harmless to leave in and only adds a single machine instruction per loop iteration.
412  crc &= BIT_MASK;
413 
414  if (!parameters.reflectInput && CRCWidth < CHAR_BIT)
415  {
416  // Undo the special operation at the end of the CalculateRemainder()
417  // function for non-reflected CRCs < CHAR_BIT.
418  crc = static_cast<CRCType>(crc << SHIFT);
419  }
420 
421  table[byte] = crc;
422  }
423  while (++byte);
424 }
425 
435 template <typename CRCType, crcpp_uint16 CRCWidth>
436 inline CRCType CRC::Calculate(const void * data, crcpp_size size, const Parameters<CRCType, CRCWidth> & parameters)
437 {
438  CRCType remainder = CalculateRemainder(data, size, parameters, parameters.initialValue);
439 
440  // No need to mask the remainder here; the mask will be applied in the Finalize() function.
441 
442  return Finalize<CRCType, CRCWidth>(remainder, parameters.finalXOR, parameters.reflectInput != parameters.reflectOutput);
443 }
455 template <typename CRCType, crcpp_uint16 CRCWidth>
456 inline CRCType CRC::Calculate(const void * data, crcpp_size size, const Parameters<CRCType, CRCWidth> & parameters, CRCType crc)
457 {
458  CRCType remainder = UndoFinalize<CRCType, CRCWidth>(crc, parameters.finalXOR, parameters.reflectInput != parameters.reflectOutput);
459 
460  remainder = CalculateRemainder(data, size, parameters, remainder);
461 
462  // No need to mask the remainder here; the mask will be applied in the Finalize() function.
463 
464  return Finalize<CRCType, CRCWidth>(remainder, parameters.finalXOR, parameters.reflectInput != parameters.reflectOutput);
465 }
466 
476 template <typename CRCType, crcpp_uint16 CRCWidth>
477 inline CRCType CRC::Calculate(const void * data, crcpp_size size, const Table<CRCType, CRCWidth> & lookupTable)
478 {
480 
481  CRCType remainder = CalculateRemainder(data, size, lookupTable, parameters.initialValue);
482 
483  // No need to mask the remainder here; the mask will be applied in the Finalize() function.
484 
485  return Finalize<CRCType, CRCWidth>(remainder, parameters.finalXOR, parameters.reflectInput != parameters.reflectOutput);
486 }
487 
499 template <typename CRCType, crcpp_uint16 CRCWidth>
500 inline CRCType CRC::Calculate(const void * data, crcpp_size size, const Table<CRCType, CRCWidth> & lookupTable, CRCType crc)
501 {
503 
504  CRCType remainder = UndoFinalize<CRCType, CRCWidth>(crc, parameters.finalXOR, parameters.reflectInput != parameters.reflectOutput);
505 
506  remainder = CalculateRemainder(data, size, lookupTable, remainder);
507 
508  // No need to mask the remainder here; the mask will be applied in the Finalize() function.
509 
510  return Finalize<CRCType, CRCWidth>(remainder, parameters.finalXOR, parameters.reflectInput != parameters.reflectOutput);
511 }
512 
520 template <typename IntegerType>
521 inline IntegerType CRC::Reflect(IntegerType value, crcpp_uint16 numBits)
522 {
523  IntegerType reversedValue(0);
524 
525  for (crcpp_uint16 i = 0; i < numBits; ++i)
526  {
527  reversedValue = static_cast<IntegerType>((reversedValue << 1) | (value & 1));
528  value = static_cast<IntegerType>(value >> 1);
529  }
530 
531  return reversedValue;
532 }
533 
543 template <typename CRCType, crcpp_uint16 CRCWidth>
544 inline CRCType CRC::Finalize(CRCType remainder, CRCType finalXOR, bool reflectOutput)
545 {
546  // For masking off the bits for the CRC (in the event that the number of bits in CRCType is larger than CRCWidth)
547  static crcpp_constexpr CRCType BIT_MASK = (CRCType(1) << (CRCWidth - CRCType(1))) |
548  ((CRCType(1) << (CRCWidth - CRCType(1))) - CRCType(1));
549 
550  if (reflectOutput)
551  {
552  remainder = Reflect(remainder, CRCWidth);
553  }
554 
555  return (remainder ^ finalXOR) & BIT_MASK;
556 }
557 
575 template <typename CRCType, crcpp_uint16 CRCWidth>
576 inline CRCType CRC::UndoFinalize(CRCType crc, CRCType finalXOR, bool reflectOutput)
577 {
578  // For masking off the bits for the CRC (in the event that the number of bits in CRCType is larger than CRCWidth)
579  static crcpp_constexpr CRCType BIT_MASK = (CRCType(1) << (CRCWidth - CRCType(1))) |
580  ((CRCType(1) << (CRCWidth - CRCType(1))) - CRCType(1));
581 
582  crc = (crc & BIT_MASK) ^ finalXOR;
583 
584  if (reflectOutput)
585  {
586  crc = Reflect(crc, CRCWidth);
587  }
588 
589  return crc;
590 }
591 
602 template <typename CRCType, crcpp_uint16 CRCWidth>
603 inline CRCType CRC::CalculateRemainder(const void * data, crcpp_size size, const Parameters<CRCType, CRCWidth> & parameters, CRCType remainder)
604 {
605 #ifdef CRCPP_USE_CPP11
606  // This static_assert is put here because this function will always be compiled in no matter what
607  // the template parameters are and whether or not a table lookup or bit-by-bit algorithm is used.
608  static_assert(::std::numeric_limits<CRCType>::digits >= CRCWidth, "CRCType is too small to contain a CRC of width CRCWidth.");
609 #else
610  // Catching this compile-time error is very important. Sadly, the compiler error will be very cryptic, but it's
611  // better than nothing.
612  enum { static_assert_failed_CRCType_is_too_small_to_contain_a_CRC_of_width_CRCWidth = 1 / (::std::numeric_limits<CRCType>::digits >= CRCWidth ? 1 : 0) };
613 #endif
614 
615  const unsigned char * current = reinterpret_cast<const unsigned char *>(data);
616 
617  // Slightly different implementations based on the parameters. The current implementations try to eliminate as much
618  // computation from the inner loop (looping over each bit) as possible.
619  if (parameters.reflectInput)
620  {
621  CRCType polynomial = CRC::Reflect(parameters.polynomial, CRCWidth);
622  while (size--)
623  {
624  remainder = static_cast<CRCType>(remainder ^ *current++);
625 
626  // An optimizing compiler might choose to unroll this loop.
627  for (crcpp_size i = 0; i < CHAR_BIT; ++i)
628  {
629 #ifdef CRCPP_BRANCHLESS
630  // Clever way to avoid a branch at the expense of a multiplication. This code is equivalent to the following:
631  // if (remainder & 1)
632  // remainder = (remainder >> 1) ^ polynomial;
633  // else
634  // remainder >>= 1;
635  remainder = static_cast<CRCType>((remainder >> 1) ^ ((remainder & 1) * polynomial));
636 #else
637  remainder = static_cast<CRCType>((remainder & 1) ? ((remainder >> 1) ^ polynomial) : (remainder >> 1));
638 #endif
639  }
640  }
641  }
642  else if (CRCWidth >= CHAR_BIT)
643  {
644  static crcpp_constexpr CRCType CRC_WIDTH_MINUS_ONE(CRCWidth - CRCType(1));
645 #ifndef CRCPP_BRANCHLESS
646  static crcpp_constexpr CRCType CRC_HIGHEST_BIT_MASK(CRCType(1) << CRC_WIDTH_MINUS_ONE);
647 #endif
648  // The conditional expression is used to avoid a -Wshift-count-overflow warning.
649  static crcpp_constexpr CRCType SHIFT((CRCWidth >= CHAR_BIT) ? static_cast<CRCType>(CRCWidth - CHAR_BIT) : 0);
650 
651  while (size--)
652  {
653  remainder = static_cast<CRCType>(remainder ^ (static_cast<CRCType>(*current++) << SHIFT));
654 
655  // An optimizing compiler might choose to unroll this loop.
656  for (crcpp_size i = 0; i < CHAR_BIT; ++i)
657  {
658 #ifdef CRCPP_BRANCHLESS
659  // Clever way to avoid a branch at the expense of a multiplication. This code is equivalent to the following:
660  // if (remainder & CRC_HIGHEST_BIT_MASK)
661  // remainder = (remainder << 1) ^ parameters.polynomial;
662  // else
663  // remainder <<= 1;
664  remainder = static_cast<CRCType>((remainder << 1) ^ (((remainder >> CRC_WIDTH_MINUS_ONE) & 1) * parameters.polynomial));
665 #else
666  remainder = static_cast<CRCType>((remainder & CRC_HIGHEST_BIT_MASK) ? ((remainder << 1) ^ parameters.polynomial) : (remainder << 1));
667 #endif
668  }
669  }
670  }
671  else
672  {
673  static crcpp_constexpr CRCType CHAR_BIT_MINUS_ONE(CHAR_BIT - 1);
674 #ifndef CRCPP_BRANCHLESS
675  static crcpp_constexpr CRCType CHAR_BIT_HIGHEST_BIT_MASK(CRCType(1) << CHAR_BIT_MINUS_ONE);
676 #endif
677  // The conditional expression is used to avoid a -Wshift-count-overflow warning.
678  static crcpp_constexpr CRCType SHIFT((CHAR_BIT >= CRCWidth) ? static_cast<CRCType>(CHAR_BIT - CRCWidth) : 0);
679 
680  CRCType polynomial = static_cast<CRCType>(parameters.polynomial << SHIFT);
681  remainder = static_cast<CRCType>(remainder << SHIFT);
682 
683  while (size--)
684  {
685  remainder = static_cast<CRCType>(remainder ^ *current++);
686 
687  // An optimizing compiler might choose to unroll this loop.
688  for (crcpp_size i = 0; i < CHAR_BIT; ++i)
689  {
690 #ifdef CRCPP_BRANCHLESS
691  // Clever way to avoid a branch at the expense of a multiplication. This code is equivalent to the following:
692  // if (remainder & CHAR_BIT_HIGHEST_BIT_MASK)
693  // remainder = (remainder << 1) ^ polynomial;
694  // else
695  // remainder <<= 1;
696  remainder = static_cast<CRCType>((remainder << 1) ^ (((remainder >> CHAR_BIT_MINUS_ONE) & 1) * polynomial));
697 #else
698  remainder = static_cast<CRCType>((remainder & CHAR_BIT_HIGHEST_BIT_MASK) ? ((remainder << 1) ^ polynomial) : (remainder << 1));
699 #endif
700  }
701  }
702 
703  remainder = static_cast<CRCType>(remainder >> SHIFT);
704  }
705 
706  return remainder;
707 }
708 
719 template <typename CRCType, crcpp_uint16 CRCWidth>
720 inline CRCType CRC::CalculateRemainder(const void * data, crcpp_size size, const Table<CRCType, CRCWidth> & lookupTable, CRCType remainder)
721 {
722  const unsigned char * current = reinterpret_cast<const unsigned char *>(data);
723 
724  if (lookupTable.GetParameters().reflectInput)
725  {
726  while (size--)
727  {
728 #if defined(WIN32) || defined(_WIN32) || defined(WINCE)
729  // Disable warning about data loss when doing (remainder >> CHAR_BIT) when
730  // remainder is one byte long. The algorithm is still correct in this case,
731  // though it's possible that one additional machine instruction will be executed.
732 # pragma warning (push)
733 # pragma warning (disable : 4333)
734 #endif
735  remainder = static_cast<CRCType>((remainder >> CHAR_BIT) ^ lookupTable[static_cast<unsigned char>(remainder ^ *current++)]);
736 #if defined(WIN32) || defined(_WIN32) || defined(WINCE)
737 # pragma warning (pop)
738 #endif
739  }
740  }
741  else if (CRCWidth >= CHAR_BIT)
742  {
743  // The conditional expression is used to avoid a -Wshift-count-overflow warning.
744  static crcpp_constexpr CRCType SHIFT((CRCWidth >= CHAR_BIT) ? static_cast<CRCType>(CRCWidth - CHAR_BIT) : 0);
745 
746  while (size--)
747  {
748  remainder = static_cast<CRCType>((remainder << CHAR_BIT) ^ lookupTable[static_cast<unsigned char>((remainder >> SHIFT) ^ *current++)]);
749  }
750  }
751  else
752  {
753  // The conditional expression is used to avoid a -Wshift-count-overflow warning.
754  static crcpp_constexpr CRCType SHIFT((CHAR_BIT >= CRCWidth) ? static_cast<CRCType>(CHAR_BIT - CRCWidth) : 0);
755 
756  remainder = static_cast<CRCType>(remainder << SHIFT);
757 
758  while (size--)
759  {
760  // Note: no need to mask here since remainder is guaranteed to fit in a single byte.
761  remainder = lookupTable[static_cast<unsigned char>(remainder ^ *current++)];
762  }
763 
764  remainder = static_cast<CRCType>(remainder >> SHIFT);
765  }
766 
767  return remainder;
768 }
769 
770 #ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
771 
783 inline const CRC::Parameters<crcpp_uint8, 4> & CRC::CRC_4_ITU()
784 {
785  static const Parameters<crcpp_uint8, 4> parameters = { 0x3, 0x0, 0x0, true, true };
786  return parameters;
787 }
788 
801 inline const CRC::Parameters<crcpp_uint8, 5> & CRC::CRC_5_EPC()
802 {
803  static const Parameters<crcpp_uint8, 5> parameters = { 0x09, 0x09, 0x00, false, false };
804  return parameters;
805 }
806 
819 inline const CRC::Parameters<crcpp_uint8, 5> & CRC::CRC_5_ITU()
820 {
821  static const Parameters<crcpp_uint8, 5> parameters = { 0x15, 0x00, 0x00, true, true };
822  return parameters;
823 }
824 
837 inline const CRC::Parameters<crcpp_uint8, 5> & CRC::CRC_5_USB()
838 {
839  static const Parameters<crcpp_uint8, 5> parameters = { 0x05, 0x1F, 0x1F, true, true };
840  return parameters;
841 }
842 
855 inline const CRC::Parameters<crcpp_uint8, 6> & CRC::CRC_6_CDMA2000A()
856 {
857  static const Parameters<crcpp_uint8, 6> parameters = { 0x27, 0x3F, 0x00, false, false };
858  return parameters;
859 }
860 
873 inline const CRC::Parameters<crcpp_uint8, 6> & CRC::CRC_6_CDMA2000B()
874 {
875  static const Parameters<crcpp_uint8, 6> parameters = { 0x07, 0x3F, 0x00, false, false };
876  return parameters;
877 }
878 
891 inline const CRC::Parameters<crcpp_uint8, 6> & CRC::CRC_6_ITU()
892 {
893  static const Parameters<crcpp_uint8, 6> parameters = { 0x03, 0x00, 0x00, true, true };
894  return parameters;
895 }
896 
909 inline const CRC::Parameters<crcpp_uint8, 7> & CRC::CRC_7()
910 {
911  static const Parameters<crcpp_uint8, 7> parameters = { 0x09, 0x00, 0x00, false, false };
912  return parameters;
913 }
914 #endif // CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
915 
929 {
930  static const Parameters<crcpp_uint8, 8> parameters = { 0x07, 0x00, 0x00, false, false };
931  return parameters;
932 }
933 
934 #ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
935 
947 inline const CRC::Parameters<crcpp_uint8, 8> & CRC::CRC_8_EBU()
948 {
949  static const Parameters<crcpp_uint8, 8> parameters = { 0x1D, 0xFF, 0x00, true, true };
950  return parameters;
951 }
952 
965 inline const CRC::Parameters<crcpp_uint8, 8> & CRC::CRC_8_MAXIM()
966 {
967  static const Parameters<crcpp_uint8, 8> parameters = { 0x31, 0x00, 0x00, true, true };
968  return parameters;
969 }
970 
983 inline const CRC::Parameters<crcpp_uint8, 8> & CRC::CRC_8_WCDMA()
984 {
985  static const Parameters<crcpp_uint8, 8> parameters = { 0x9B, 0x00, 0x00, true, true };
986  return parameters;
987 }
988 
1001 inline const CRC::Parameters<crcpp_uint16, 10> & CRC::CRC_10()
1002 {
1003  static const Parameters<crcpp_uint16, 10> parameters = { 0x233, 0x000, 0x000, false, false };
1004  return parameters;
1005 }
1006 
1019 inline const CRC::Parameters<crcpp_uint16, 10> & CRC::CRC_10_CDMA2000()
1020 {
1021  static const Parameters<crcpp_uint16, 10> parameters = { 0x3D9, 0x3FF, 0x000, false, false };
1022  return parameters;
1023 }
1024 
1037 inline const CRC::Parameters<crcpp_uint16, 11> & CRC::CRC_11()
1038 {
1039  static const Parameters<crcpp_uint16, 11> parameters = { 0x385, 0x01A, 0x000, false, false };
1040  return parameters;
1041 }
1042 
1055 inline const CRC::Parameters<crcpp_uint16, 12> & CRC::CRC_12_CDMA2000()
1056 {
1057  static const Parameters<crcpp_uint16, 12> parameters = { 0xF13, 0xFFF, 0x000, false, false };
1058  return parameters;
1059 }
1060 
1073 inline const CRC::Parameters<crcpp_uint16, 12> & CRC::CRC_12_DECT()
1074 {
1075  static const Parameters<crcpp_uint16, 12> parameters = { 0x80F, 0x000, 0x000, false, false };
1076  return parameters;
1077 }
1078 
1091 inline const CRC::Parameters<crcpp_uint16, 12> & CRC::CRC_12_UMTS()
1092 {
1093  static const Parameters<crcpp_uint16, 12> parameters = { 0x80F, 0x000, 0x000, false, true };
1094  return parameters;
1095 }
1096 
1109 inline const CRC::Parameters<crcpp_uint16, 13> & CRC::CRC_13_BBC()
1110 {
1111  static const Parameters<crcpp_uint16, 13> parameters = { 0x1CF5, 0x0000, 0x0000, false, false };
1112  return parameters;
1113 }
1114 
1127 inline const CRC::Parameters<crcpp_uint16, 15> & CRC::CRC_15()
1128 {
1129  static const Parameters<crcpp_uint16, 15> parameters = { 0x4599, 0x0000, 0x0000, false, false };
1130  return parameters;
1131 }
1132 
1145 inline const CRC::Parameters<crcpp_uint16, 15> & CRC::CRC_15_MPT1327()
1146 {
1147  static const Parameters<crcpp_uint16, 15> parameters = { 0x6815, 0x0000, 0x0001, false, false };
1148  return parameters;
1149 }
1150 #endif // CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
1151 
1165 {
1166  static const Parameters<crcpp_uint16, 16> parameters = { 0x8005, 0x0000, 0x0000, true, true };
1167  return parameters;
1168 }
1169 
1183 {
1184  static const Parameters<crcpp_uint16, 16> parameters = { 0x8005, 0x0000, 0x0000, false, false };
1185  return parameters;
1186 }
1187 
1201 {
1202  static const Parameters<crcpp_uint16, 16> parameters = { 0x1021, 0xFFFF, 0x0000, false, false };
1203  return parameters;
1204 }
1205 
1206 #ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
1207 
1219 inline const CRC::Parameters<crcpp_uint16, 16> & CRC::CRC_16_CDMA2000()
1220 {
1221  static const Parameters<crcpp_uint16, 16> parameters = { 0xC867, 0xFFFF, 0x0000, false, false };
1222  return parameters;
1223 }
1224 
1237 inline const CRC::Parameters<crcpp_uint16, 16> & CRC::CRC_16_CMS()
1238 {
1239  static const Parameters<crcpp_uint16, 16> parameters = { 0x8005, 0xFFFF, 0x0000, false, false };
1240  return parameters;
1241 }
1242 
1255 inline const CRC::Parameters<crcpp_uint16, 16> & CRC::CRC_16_DECTR()
1256 {
1257  static const Parameters<crcpp_uint16, 16> parameters = { 0x0589, 0x0000, 0x0001, false, false };
1258  return parameters;
1259 }
1260 
1273 inline const CRC::Parameters<crcpp_uint16, 16> & CRC::CRC_16_DECTX()
1274 {
1275  static const Parameters<crcpp_uint16, 16> parameters = { 0x0589, 0x0000, 0x0000, false, false };
1276  return parameters;
1277 }
1278 
1291 inline const CRC::Parameters<crcpp_uint16, 16> & CRC::CRC_16_DNP()
1292 {
1293  static const Parameters<crcpp_uint16, 16> parameters = { 0x3D65, 0x0000, 0xFFFF, true, true };
1294  return parameters;
1295 }
1296 #endif // CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
1297 
1311 {
1312  static const Parameters<crcpp_uint16, 16> parameters = { 0x1021, 0xFFFF, 0xFFFF, false, false };
1313  return parameters;
1314 }
1315 
1329 {
1330  static const Parameters<crcpp_uint16, 16> parameters = { 0x1021, 0x0000, 0x0000, true, true };
1331  return parameters;
1332 }
1333 
1334 #ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
1335 
1347 inline const CRC::Parameters<crcpp_uint16, 16> & CRC::CRC_16_MAXIM()
1348 {
1349  static const Parameters<crcpp_uint16, 16> parameters = { 0x8005, 0x0000, 0xFFFF, true, true };
1350  return parameters;
1351 }
1352 
1365 inline const CRC::Parameters<crcpp_uint16, 16> & CRC::CRC_16_MODBUS()
1366 {
1367  static const Parameters<crcpp_uint16, 16> parameters = { 0x8005, 0xFFFF, 0x0000, true, true };
1368  return parameters;
1369 }
1370 
1383 inline const CRC::Parameters<crcpp_uint16, 16> & CRC::CRC_16_T10DIF()
1384 {
1385  static const Parameters<crcpp_uint16, 16> parameters = { 0x8BB7, 0x0000, 0x0000, false, false };
1386  return parameters;
1387 }
1388 
1401 inline const CRC::Parameters<crcpp_uint16, 16> & CRC::CRC_16_USB()
1402 {
1403  static const Parameters<crcpp_uint16, 16> parameters = { 0x8005, 0xFFFF, 0xFFFF, true, true };
1404  return parameters;
1405 }
1406 
1407 #endif // CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
1408 
1422 {
1423  static const Parameters<crcpp_uint16, 16> parameters = { 0x1021, 0xFFFF, 0xFFFF, true, true };
1424  return parameters;
1425 }
1426 
1440 {
1441  static const Parameters<crcpp_uint16, 16> parameters = { 0x1021, 0x0000, 0x0000, false, false };
1442  return parameters;
1443 }
1444 
1445 #ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
1446 
1458 inline const CRC::Parameters<crcpp_uint32, 17> & CRC::CRC_17_CAN()
1459 {
1460  static const Parameters<crcpp_uint32, 17> parameters = { 0x1685B, 0x00000, 0x00000, false, false };
1461  return parameters;
1462 }
1463 
1476 inline const CRC::Parameters<crcpp_uint32, 21> & CRC::CRC_21_CAN()
1477 {
1478  static const Parameters<crcpp_uint32, 21> parameters = { 0x102899, 0x000000, 0x000000, false, false };
1479  return parameters;
1480 }
1481 
1494 inline const CRC::Parameters<crcpp_uint32, 24> & CRC::CRC_24()
1495 {
1496  static const Parameters<crcpp_uint32, 24> parameters = { 0x864CFB, 0xB704CE, 0x000000, false, false };
1497  return parameters;
1498 }
1499 
1512 inline const CRC::Parameters<crcpp_uint32, 24> & CRC::CRC_24_FLEXRAYA()
1513 {
1514  static const Parameters<crcpp_uint32, 24> parameters = { 0x5D6DCB, 0xFEDCBA, 0x000000, false, false };
1515  return parameters;
1516 }
1517 
1530 inline const CRC::Parameters<crcpp_uint32, 24> & CRC::CRC_24_FLEXRAYB()
1531 {
1532  static const Parameters<crcpp_uint32, 24> parameters = { 0x5D6DCB, 0xABCDEF, 0x000000, false, false };
1533  return parameters;
1534 }
1535 
1548 inline const CRC::Parameters<crcpp_uint32, 30> & CRC::CRC_30()
1549 {
1550  static const Parameters<crcpp_uint32, 30> parameters = { 0x2030B9C7, 0x3FFFFFFF, 0x00000000, false, false };
1551  return parameters;
1552 }
1553 #endif // CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
1554 
1568 {
1569  static const Parameters<crcpp_uint32, 32> parameters = { 0x04C11DB7, 0xFFFFFFFF, 0xFFFFFFFF, true, true };
1570  return parameters;
1571 }
1572 
1586 {
1587  static const Parameters<crcpp_uint32, 32> parameters = { 0x04C11DB7, 0xFFFFFFFF, 0xFFFFFFFF, false, false };
1588  return parameters;
1589 }
1590 
1591 #ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
1592 
1604 inline const CRC::Parameters<crcpp_uint32, 32> & CRC::CRC_32_C()
1605 {
1606  static const Parameters<crcpp_uint32, 32> parameters = { 0x1EDC6F41, 0xFFFFFFFF, 0xFFFFFFFF, true, true };
1607  return parameters;
1608 }
1609 #endif
1610 
1624 {
1625  static const Parameters<crcpp_uint32, 32> parameters = { 0x04C11DB7, 0xFFFFFFFF, 0x00000000, false, false };
1626  return parameters;
1627 }
1628 
1642 {
1643  static const Parameters<crcpp_uint32, 32> parameters = { 0x04C11DB7, 0x00000000, 0xFFFFFFFF, false, false };
1644  return parameters;
1645 }
1646 
1647 #ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
1648 
1660 inline const CRC::Parameters<crcpp_uint32, 32> & CRC::CRC_32_Q()
1661 {
1662  static const Parameters<crcpp_uint32, 32> parameters = { 0x814141AB, 0x00000000, 0x00000000, false, false };
1663  return parameters;
1664 }
1665 
1678 inline const CRC::Parameters<crcpp_uint64, 40> & CRC::CRC_40_GSM()
1679 {
1680  static const Parameters<crcpp_uint64, 40> parameters = { 0x0004820009, 0x0000000000, 0xFFFFFFFFFF, false, false };
1681  return parameters;
1682 }
1683 
1696 inline const CRC::Parameters<crcpp_uint64, 64> & CRC::CRC_64()
1697 {
1698  static const Parameters<crcpp_uint64, 64> parameters = { 0x42F0E1EBA9EA3693, 0x0000000000000000, 0x0000000000000000, false, false };
1699  return parameters;
1700 }
1701 #endif // CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
1702 
1703 #ifdef CRCPP_USE_NAMESPACE
1704 }
1705 #endif
1706 
1707 #endif // CRCPP_CRC_H_
1708 
1709 // *INDENT-ON*
const CRCType * GetTable() const
Gets the CRC table.
Definition: CRC.h:368
static const Parameters< crcpp_uint16, 16 > & CRC_16_CCITTFALSE()
Returns a set of parameters for CRC-16 CCITT FALSE.
Definition: CRC.h:1200
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:1567
CRCType initialValue
Initial CRC value.
Definition: CRC.h:158
Table< CRCType, CRCWidth > MakeTable() const
Returns a CRC lookup table construct using these CRC parameters.
Definition: CRC.h:315
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:1328
#define crcpp_uint16
Unsigned 16-bit integer definition, used primarily for parameter definitions.
Definition: CRC.h:90
const Parameters< CRCType, CRCWidth > & GetParameters() const
Gets the CRC parameters used to construct the CRC table.
Definition: CRC.h:356
Parameters< CRCType, CRCWidth > parameters
CRC parameters used to construct the table.
Definition: CRC.h:189
static CRCType Finalize(CRCType remainder, CRCType finalXOR, bool reflectOutput)
Computes the final reflection and XOR of a CRC remainder.
Definition: CRC.h:544
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:1164
bool reflectInput
true to reflect all input bytes
Definition: CRC.h:160
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:1421
CRCType table[1<< CHAR_BIT]
CRC lookup table.
Definition: CRC.h:190
static IntegerType Reflect(IntegerType value, crcpp_uint16 numBits)
Reflects (i.e. reverses the bits within) an integer value.
Definition: CRC.h:521
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:1585
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:1182
void InitTable()
Initializes a CRC table.
Definition: CRC.h:392
CRCType finalXOR
Value to XOR with the final CRC.
Definition: CRC.h:159
CRCType operator[](unsigned char index) const
Gets an entry in the CRC table.
Definition: CRC.h:381
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:576
#define crcpp_size
Unsigned size definition, used for specifying data sizes.
Definition: CRC.h:120
CRC lookup table. After construction, the CRC parameters are fixed.
Definition: CRC.h:149
static CRCType Calculate(const void *data, crcpp_size size, const Parameters< CRCType, CRCWidth > &parameters)
Computes a CRC.
Definition: CRC.h:436
CRC parameters.
Definition: CRC.h:155
Static class for computing CRCs.
Definition: CRC.h:144
static const Parameters< crcpp_uint32, 32 > & CRC_32_POSIX()
Returns a set of parameters for CRC-32 POSIX.
Definition: CRC.h:1641
static CRCType CalculateRemainder(const void *data, crcpp_size size, const Parameters< CRCType, CRCWidth > &parameters, CRCType remainder)
Computes a CRC remainder.
Definition: CRC.h:603
Table(const Parameters< CRCType, CRCWidth > &parameters)
Constructs a CRC table from a set of CRC parameters.
Definition: CRC.h:328
CRCType polynomial
CRC polynomial.
Definition: CRC.h:157
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:1439
static const Parameters< crcpp_uint32, 32 > & CRC_32_MPEG2()
Returns a set of parameters for CRC-32 MPEG-2.
Definition: CRC.h:1623
int i
Definition: dynamic_load.c:954
static const Parameters< crcpp_uint8, 8 > & CRC_8()
Returns a set of parameters for CRC-8 SMBus.
Definition: CRC.h:928
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:1310
bool reflectOutput
true to reflect the output CRC (reflection occurs before the final XOR)
Definition: CRC.h:161
#define crcpp_constexpr
Compile-time expression definition.
Definition: CRC.h:129