rogue
Loading...
Searching...
No Matches
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
42 bits or less. This type is not used in CRC calculations. Defaults to ::std::uint8_t. #define crcpp_uint16 - Specifies
43 the type used to store CRCs that have a width between 9 and 16 bits (inclusive). This type is not used in CRC
44 calculations. Defaults to ::std::uint16_t. #define crcpp_uint32 - Specifies the type used
45 to store CRCs that have a width between 17 and 32 bits (inclusive). This type is not used in CRC calculations.
46 Defaults to ::std::uint32_t. #define crcpp_uint64 - Specifies the type used to store CRCs
47 that have a width between 33 and 64 bits (inclusive). This type is not used in CRC calculations. Defaults to
48 ::std::uint64_t. #define crcpp_size - This type is used for loop iteration and function
49 signatures only. Defaults to ::std::size_t. #define CRCPP_USE_NAMESPACE - Define to place all
50 CRC++ code within the ::CRCPP namespace. #define CRCPP_BRANCHLESS - Define to enable a
51 branchless CRC implementation. The branchless implementation uses a single integer multiplication in the bit-by-bit
52 calculation instead of a small conditional. The branchless implementation may be faster on processor architectures
53 which support single-instruction integer multiplication. #define CRCPP_USE_CPP11 - Define to
54 enables C++11 features (move semantics, constexpr, static_assert, etc.). #define
55 CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS - Define to include definitions for little-used CRCs.
56*/
57
58#ifndef CRCPP_CRC_H_
59#define CRCPP_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
75 #define crcpp_uint8 ::std::uint8_t
76 #else
78 #define crcpp_uint8 uint8_t
79 #endif
80#endif
81
82#ifndef crcpp_uint16
83 #ifdef CRCPP_USE_CPP11
85 #define crcpp_uint16 ::std::uint16_t
86 #else
88 #define crcpp_uint16 uint16_t
89 #endif
90#endif
91
92#ifndef crcpp_uint32
93 #ifdef CRCPP_USE_CPP11
95 #define crcpp_uint32 ::std::uint32_t
96 #else
98 #define crcpp_uint32 uint32_t
99 #endif
100#endif
101
102#ifndef crcpp_uint64
103 #ifdef CRCPP_USE_CPP11
105 #define crcpp_uint64 ::std::uint64_t
106 #else
108 #define crcpp_uint64 uint64_t
109 #endif
110#endif
111
112#ifndef crcpp_size
113 #ifdef CRCPP_USE_CPP11
115 #define crcpp_size ::std::size_t
116 #else
118 #define crcpp_size size_t
119 #endif
120#endif
121
122#ifdef CRCPP_USE_CPP11
124 #define crcpp_constexpr constexpr
125#else
127 #define crcpp_constexpr const
128#endif
129
130#ifdef CRCPP_USE_NAMESPACE
131namespace CRCPP {
132#endif
133
141class CRC {
142 public:
143 // Forward declaration
144 template <typename CRCType, crcpp_uint16 CRCWidth>
145 struct Table;
146
150 template <typename CRCType, crcpp_uint16 CRCWidth>
151 struct Parameters {
152 CRCType polynomial;
153 CRCType initialValue;
154 CRCType finalXOR;
157
158 Table<CRCType, CRCWidth> MakeTable() const;
159 };
160
165 template <typename CRCType, crcpp_uint16 CRCWidth>
166 struct Table {
167 // Constructors are intentionally NOT marked explicit.
168 Table(const Parameters<CRCType, CRCWidth>& parameters); // NOLINT
169
170#ifdef CRCPP_USE_CPP11
171 Table(Parameters<CRCType, CRCWidth>&& parameters); // NOLINT
172#endif
173
174 const Parameters<CRCType, CRCWidth>& GetParameters() const;
175
176 const CRCType* GetTable() const;
177
178 CRCType operator[](unsigned char index) const;
179
180 private:
181 void InitTable();
182
184 CRCType table[1 << CHAR_BIT];
185 };
186
187 // The number of bits in CRCType must be at least as large as CRCWidth.
188 // CRCType must be an unsigned integer type or a custom type with operator overloads.
189 template <typename CRCType, crcpp_uint16 CRCWidth>
190 static CRCType Calculate(const void* data, crcpp_size size, const Parameters<CRCType, CRCWidth>& parameters);
191
192 template <typename CRCType, crcpp_uint16 CRCWidth>
193 static CRCType Calculate(const void* data,
194 crcpp_size size,
195 const Parameters<CRCType, CRCWidth>& parameters,
196 CRCType crc);
197
198 template <typename CRCType, crcpp_uint16 CRCWidth>
199 static CRCType Calculate(const void* data, crcpp_size size, const Table<CRCType, CRCWidth>& lookupTable);
200
201 template <typename CRCType, crcpp_uint16 CRCWidth>
202 static CRCType Calculate(const void* data,
203 crcpp_size size,
204 const Table<CRCType, CRCWidth>& lookupTable,
205 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_DECTR();
240 static const Parameters<crcpp_uint16, 16>& CRC_16_DECTX();
241 static const Parameters<crcpp_uint16, 16>& CRC_16_DNP();
242#endif
243 static const Parameters<crcpp_uint16, 16>& CRC_16_GENIBUS();
244 static const Parameters<crcpp_uint16, 16>& CRC_16_KERMIT();
245#ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
246 static const Parameters<crcpp_uint16, 16>& CRC_16_MAXIM();
247 static const Parameters<crcpp_uint16, 16>& CRC_16_MODBUS();
248 static const Parameters<crcpp_uint16, 16>& CRC_16_T10DIF();
249 static const Parameters<crcpp_uint16, 16>& CRC_16_USB();
250 static const Parameters<crcpp_uint16, 16>& CRC_16_CMS();
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,
301 crcpp_size size,
302 const Parameters<CRCType, CRCWidth>& parameters,
303 CRCType remainder);
304
305 template <typename CRCType, crcpp_uint16 CRCWidth>
306 static CRCType CalculateRemainder(const void* data,
307 crcpp_size size,
308 const Table<CRCType, CRCWidth>& lookupTable,
309 CRCType remainder);
310
311 template <typename IntegerType>
312 static crcpp_constexpr IntegerType BoundedConstexprValue(IntegerType x);
313};
314
323template <typename CRCType, crcpp_uint16 CRCWidth>
325 // This should take advantage of RVO and optimize out the copy.
326 return CRC::Table<CRCType, CRCWidth>(*this);
327}
328
335template <typename CRCType, crcpp_uint16 CRCWidth>
336inline CRC::Table<CRCType, CRCWidth>::Table(const Parameters<CRCType, CRCWidth>& parameters) : parameters(parameters) {
337 InitTable();
338}
339
340#ifdef CRCPP_USE_CPP11
347template <typename CRCType, crcpp_uint16 CRCWidth>
349 : parameters(::std::move(parameters)) {
350 InitTable();
351}
352#endif
353
360template <typename CRCType, crcpp_uint16 CRCWidth>
364
371template <typename CRCType, crcpp_uint16 CRCWidth>
372inline const CRCType* CRC::Table<CRCType, CRCWidth>::GetTable() const {
373 return table;
374}
375
383template <typename CRCType, crcpp_uint16 CRCWidth>
384inline CRCType CRC::Table<CRCType, CRCWidth>::operator[](unsigned char index) const {
385 return table[index];
386}
387
393template <typename CRCType, crcpp_uint16 CRCWidth>
395 // For masking off the bits for the CRC (in the event that the number of bits in CRCType is larger than CRCWidth)
396 static crcpp_constexpr CRCType BIT_MASK((CRCType(1) << (CRCWidth - CRCType(1))) |
397 ((CRCType(1) << (CRCWidth - CRCType(1))) - CRCType(1)));
398
399 static crcpp_constexpr CRCType SHIFT(CRC::BoundedConstexprValue(CHAR_BIT - CRCWidth));
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 crc = CRC::CalculateRemainder<CRCType, CRCWidth>(&byte, sizeof(byte), parameters, CRCType(0));
407
408 // This mask might not be necessary; all unit tests pass with this line commented out,
409 // but that might just be a coincidence based on the CRC parameters used for testing.
410 // In any case, this is harmless to leave in and only adds a single machine instruction per loop iteration.
411 crc &= BIT_MASK;
412
413 if (!parameters.reflectInput && CRCWidth < CHAR_BIT) {
414 // Undo the special operation at the end of the CalculateRemainder()
415 // function for non-reflected CRCs < CHAR_BIT.
416 crc <<= SHIFT;
417 }
418
419 table[byte] = crc;
420 } while (++byte);
421}
422
432template <typename CRCType, crcpp_uint16 CRCWidth>
433inline CRCType CRC::Calculate(const void* data, crcpp_size size, const Parameters<CRCType, CRCWidth>& parameters) {
434 CRCType remainder = CalculateRemainder(data, size, parameters, parameters.initialValue);
435
436 // No need to mask the remainder here; the mask will be applied in the Finalize() function.
437
438 return Finalize<CRCType, CRCWidth>(remainder,
439 parameters.finalXOR,
440 parameters.reflectInput != parameters.reflectOutput);
441}
453template <typename CRCType, crcpp_uint16 CRCWidth>
454inline CRCType CRC::Calculate(const void* data,
455 crcpp_size size,
456 const Parameters<CRCType, CRCWidth>& parameters,
457 CRCType crc) {
458 CRCType remainder =
459 UndoFinalize<CRCType, CRCWidth>(crc, parameters.finalXOR, parameters.reflectInput != parameters.reflectOutput);
460
461 remainder = CalculateRemainder(data, size, parameters, remainder);
462
463 // No need to mask the remainder here; the mask will be applied in the Finalize() function.
464
465 return Finalize<CRCType, CRCWidth>(remainder,
466 parameters.finalXOR,
467 parameters.reflectInput != parameters.reflectOutput);
468}
469
479template <typename CRCType, crcpp_uint16 CRCWidth>
480inline CRCType CRC::Calculate(const void* data, crcpp_size size, const Table<CRCType, CRCWidth>& lookupTable) {
481 const Parameters<CRCType, CRCWidth>& parameters = lookupTable.GetParameters();
482
483 CRCType remainder = CalculateRemainder(data, size, lookupTable, parameters.initialValue);
484
485 // No need to mask the remainder here; the mask will be applied in the Finalize() function.
486
487 return Finalize<CRCType, CRCWidth>(remainder,
488 parameters.finalXOR,
489 parameters.reflectInput != parameters.reflectOutput);
490}
491
503template <typename CRCType, crcpp_uint16 CRCWidth>
504inline CRCType CRC::Calculate(const void* data,
505 crcpp_size size,
506 const Table<CRCType, CRCWidth>& lookupTable,
507 CRCType crc) {
508 const Parameters<CRCType, CRCWidth>& parameters = lookupTable.GetParameters();
509
510 CRCType remainder =
511 UndoFinalize<CRCType, CRCWidth>(crc, parameters.finalXOR, parameters.reflectInput != parameters.reflectOutput);
512
513 remainder = CalculateRemainder(data, size, lookupTable, remainder);
514
515 // No need to mask the remainder here; the mask will be applied in the Finalize() function.
516
517 return Finalize<CRCType, CRCWidth>(remainder,
518 parameters.finalXOR,
519 parameters.reflectInput != parameters.reflectOutput);
520}
521
529template <typename IntegerType>
530inline IntegerType CRC::Reflect(IntegerType value, crcpp_uint16 numBits) {
531 IntegerType reversedValue(0);
532
533 for (crcpp_uint16 i = 0; i < numBits; ++i) {
534 reversedValue = (reversedValue << 1) | (value & 1);
535 value >>= 1;
536 }
537
538 return reversedValue;
539}
540
550template <typename CRCType, crcpp_uint16 CRCWidth>
551inline CRCType CRC::Finalize(CRCType remainder, CRCType finalXOR, bool reflectOutput) {
552 // For masking off the bits for the CRC (in the event that the number of bits in CRCType is larger than CRCWidth)
553 static crcpp_constexpr CRCType BIT_MASK =
554 (CRCType(1) << (CRCWidth - CRCType(1))) | ((CRCType(1) << (CRCWidth - CRCType(1))) - CRCType(1));
555
556 if (reflectOutput) {
557 remainder = Reflect(remainder, CRCWidth);
558 }
559
560 return (remainder ^ finalXOR) & BIT_MASK;
561}
562
580template <typename CRCType, crcpp_uint16 CRCWidth>
581inline CRCType CRC::UndoFinalize(CRCType crc, CRCType finalXOR, bool reflectOutput) {
582 // For masking off the bits for the CRC (in the event that the number of bits in CRCType is larger than CRCWidth)
583 static crcpp_constexpr CRCType BIT_MASK =
584 (CRCType(1) << (CRCWidth - CRCType(1))) | ((CRCType(1) << (CRCWidth - CRCType(1))) - CRCType(1));
585
586 crc = (crc & BIT_MASK) ^ finalXOR;
587
588 if (reflectOutput) {
589 crc = Reflect(crc, CRCWidth);
590 }
591
592 return crc;
593}
594
606template <typename CRCType, crcpp_uint16 CRCWidth>
607inline CRCType CRC::CalculateRemainder(const void* data,
608 crcpp_size size,
609 const Parameters<CRCType, CRCWidth>& parameters,
610 CRCType remainder) {
611#ifdef CRCPP_USE_CPP11
612 // This static_assert is put here because this function will always be compiled in no matter what
613 // the template parameters are and whether or not a table lookup or bit-by-bit algorithm is used.
614 static_assert(::std::numeric_limits<CRCType>::digits >= CRCWidth,
615 "CRCType is too small to contain a CRC of width CRCWidth.");
616#else
617 // Catching this compile-time error is very important. Sadly, the compiler error will be very cryptic, but it's
618 // better than nothing.
619 enum {
620 static_assert_failed_CRCType_is_too_small_to_contain_a_CRC_of_width_CRCWidth =
621 1 / (::std::numeric_limits<CRCType>::digits >= CRCWidth ? 1 : 0)
622 };
623#endif
624
625 const unsigned char* current = reinterpret_cast<const unsigned char*>(data);
626
627 // Slightly different implementations based on the parameters. The current implementations try to eliminate as much
628 // computation from the inner loop (looping over each bit) as possible.
629 if (parameters.reflectInput) {
630 CRCType polynomial = CRC::Reflect(parameters.polynomial, CRCWidth);
631 while (size--) {
632 remainder ^= *current++;
633
634 // An optimizing compiler might choose to unroll this loop.
635 for (crcpp_size i = 0; i < CHAR_BIT; ++i) {
636#ifdef CRCPP_BRANCHLESS
637 // Clever way to avoid a branch at the expense of a multiplication. This code is equivalent to the
638 // following: if (remainder & 1)
639 // remainder = (remainder >> 1) ^ polynomial;
640 // else
641 // remainder >>= 1;
642 remainder = (remainder >> 1) ^ ((remainder & 1) * polynomial);
643#else
644 remainder = (remainder & 1) ? ((remainder >> 1) ^ polynomial) : (remainder >> 1);
645#endif
646 }
647 }
648 } else if (CRCWidth >= CHAR_BIT) {
649 static crcpp_constexpr CRCType CRC_WIDTH_MINUS_ONE(CRCWidth - CRCType(1));
650#ifndef CRCPP_BRANCHLESS
651 static crcpp_constexpr CRCType CRC_HIGHEST_BIT_MASK(CRCType(1) << CRC_WIDTH_MINUS_ONE);
652#endif
653 static crcpp_constexpr CRCType SHIFT(BoundedConstexprValue(CRCWidth - CHAR_BIT));
654
655 while (size--) {
656 remainder ^= (static_cast<CRCType>(*current++) << SHIFT);
657
658 // An optimizing compiler might choose to unroll this loop.
659 for (crcpp_size i = 0; i < CHAR_BIT; ++i) {
660#ifdef CRCPP_BRANCHLESS
661 // Clever way to avoid a branch at the expense of a multiplication. This code is equivalent to the
662 // following: if (remainder & CRC_HIGHEST_BIT_MASK)
663 // remainder = (remainder << 1) ^ parameters.polynomial;
664 // else
665 // remainder <<= 1;
666 remainder = (remainder << 1) ^ (((remainder >> CRC_WIDTH_MINUS_ONE) & 1) * parameters.polynomial);
667#else
668 remainder =
669 (remainder & CRC_HIGHEST_BIT_MASK) ? ((remainder << 1) ^ parameters.polynomial) : (remainder << 1);
670#endif
671 }
672 }
673 } else {
674 static crcpp_constexpr CRCType CHAR_BIT_MINUS_ONE(CHAR_BIT - 1);
675#ifndef CRCPP_BRANCHLESS
676 static crcpp_constexpr CRCType CHAR_BIT_HIGHEST_BIT_MASK(CRCType(1) << CHAR_BIT_MINUS_ONE);
677#endif
678 static crcpp_constexpr CRCType SHIFT(BoundedConstexprValue(CHAR_BIT - CRCWidth));
679
680 CRCType polynomial = parameters.polynomial << SHIFT;
681 remainder <<= SHIFT;
682
683 while (size--) {
684 remainder ^= *current++;
685
686 // An optimizing compiler might choose to unroll this loop.
687 for (crcpp_size i = 0; i < CHAR_BIT; ++i) {
688#ifdef CRCPP_BRANCHLESS
689 // Clever way to avoid a branch at the expense of a multiplication. This code is equivalent to the
690 // following: if (remainder & CHAR_BIT_HIGHEST_BIT_MASK)
691 // remainder = (remainder << 1) ^ polynomial;
692 // else
693 // remainder <<= 1;
694 remainder = (remainder << 1) ^ (((remainder >> CHAR_BIT_MINUS_ONE) & 1) * polynomial);
695#else
696 remainder =
697 (remainder & CHAR_BIT_HIGHEST_BIT_MASK) ? ((remainder << 1) ^ polynomial) : (remainder << 1);
698#endif
699 }
700 }
701
702 remainder >>= SHIFT;
703 }
704
705 return remainder;
706}
707
719template <typename CRCType, crcpp_uint16 CRCWidth>
720inline CRCType CRC::CalculateRemainder(const void* data,
721 crcpp_size size,
722 const Table<CRCType, CRCWidth>& lookupTable,
723 CRCType remainder) {
724 const unsigned char* current = reinterpret_cast<const unsigned char*>(data);
725
726 if (lookupTable.GetParameters().reflectInput) {
727 while (size--) {
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 = (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 } else if (CRCWidth >= CHAR_BIT) {
741 static crcpp_constexpr CRCType SHIFT(BoundedConstexprValue(CRCWidth - CHAR_BIT));
742
743 while (size--) {
744 remainder =
745 (remainder << CHAR_BIT) ^ lookupTable[static_cast<unsigned char>((remainder >> SHIFT) ^ *current++)];
746 }
747 } else {
748 static crcpp_constexpr CRCType SHIFT(BoundedConstexprValue(CHAR_BIT - CRCWidth));
749
750 remainder <<= SHIFT;
751
752 while (size--) {
753 // Note: no need to mask here since remainder is guaranteed to fit in a single byte.
754 remainder = lookupTable[static_cast<unsigned char>(remainder ^ *current++)];
755 }
756
757 remainder >>= SHIFT;
758 }
759
760 return remainder;
761}
762
773template <typename IntegerType>
774inline crcpp_constexpr IntegerType CRC::BoundedConstexprValue(IntegerType x) {
775 return (x < IntegerType(0)) ? IntegerType(0) : x;
776}
777
778#ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
791inline const CRC::Parameters<crcpp_uint8, 4>& CRC::CRC_4_ITU() {
792 static const Parameters<crcpp_uint8, 4> parameters = {0x3, 0x0, 0x0, true, true};
793 return parameters;
794}
795
808inline const CRC::Parameters<crcpp_uint8, 5>& CRC::CRC_5_EPC() {
809 static const Parameters<crcpp_uint8, 5> parameters = {0x09, 0x09, 0x00, false, false};
810 return parameters;
811}
812
825inline const CRC::Parameters<crcpp_uint8, 5>& CRC::CRC_5_ITU() {
826 static const Parameters<crcpp_uint8, 5> parameters = {0x15, 0x00, 0x00, true, true};
827 return parameters;
828}
829
842inline const CRC::Parameters<crcpp_uint8, 5>& CRC::CRC_5_USB() {
843 static const Parameters<crcpp_uint8, 5> parameters = {0x05, 0x1F, 0x1F, true, true};
844 return parameters;
845}
846
859inline const CRC::Parameters<crcpp_uint8, 6>& CRC::CRC_6_CDMA2000A() {
860 static const Parameters<crcpp_uint8, 6> parameters = {0x27, 0x3F, 0x00, false, false};
861 return parameters;
862}
863
876inline const CRC::Parameters<crcpp_uint8, 6>& CRC::CRC_6_CDMA2000B() {
877 static const Parameters<crcpp_uint8, 6> parameters = {0x07, 0x3F, 0x00, false, false};
878 return parameters;
879}
880
893inline const CRC::Parameters<crcpp_uint8, 6>& CRC::CRC_6_ITU() {
894 static const Parameters<crcpp_uint8, 6> parameters = {0x03, 0x00, 0x00, true, true};
895 return parameters;
896}
897
910inline const CRC::Parameters<crcpp_uint8, 7>& CRC::CRC_7() {
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 static const Parameters<crcpp_uint8, 8> parameters = {0x07, 0x00, 0x00, false, false};
930 return parameters;
931}
932
933#ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
946inline const CRC::Parameters<crcpp_uint8, 8>& CRC::CRC_8_EBU() {
947 static const Parameters<crcpp_uint8, 8> parameters = {0x1D, 0xFF, 0x00, true, true};
948 return parameters;
949}
950
963inline const CRC::Parameters<crcpp_uint8, 8>& CRC::CRC_8_MAXIM() {
964 static const Parameters<crcpp_uint8, 8> parameters = {0x31, 0x00, 0x00, true, true};
965 return parameters;
966}
967
980inline const CRC::Parameters<crcpp_uint8, 8>& CRC::CRC_8_WCDMA() {
981 static const Parameters<crcpp_uint8, 8> parameters = {0x9B, 0x00, 0x00, true, true};
982 return parameters;
983}
984
997inline const CRC::Parameters<crcpp_uint16, 10>& CRC::CRC_10() {
998 static const Parameters<crcpp_uint16, 10> parameters = {0x233, 0x000, 0x000, false, false};
999 return parameters;
1000}
1001
1014inline const CRC::Parameters<crcpp_uint16, 10>& CRC::CRC_10_CDMA2000() {
1015 static const Parameters<crcpp_uint16, 10> parameters = {0x3D9, 0x3FF, 0x000, false, false};
1016 return parameters;
1017}
1018
1031inline const CRC::Parameters<crcpp_uint16, 11>& CRC::CRC_11() {
1032 static const Parameters<crcpp_uint16, 11> parameters = {0x385, 0x01A, 0x000, false, false};
1033 return parameters;
1034}
1035
1048inline const CRC::Parameters<crcpp_uint16, 12>& CRC::CRC_12_CDMA2000() {
1049 static const Parameters<crcpp_uint16, 12> parameters = {0xF13, 0xFFF, 0x000, false, false};
1050 return parameters;
1051}
1052
1065inline const CRC::Parameters<crcpp_uint16, 12>& CRC::CRC_12_DECT() {
1066 static const Parameters<crcpp_uint16, 12> parameters = {0x80F, 0x000, 0x000, false, false};
1067 return parameters;
1068}
1069
1082inline const CRC::Parameters<crcpp_uint16, 12>& CRC::CRC_12_UMTS() {
1083 static const Parameters<crcpp_uint16, 12> parameters = {0x80F, 0x000, 0x000, false, true};
1084 return parameters;
1085}
1086
1099inline const CRC::Parameters<crcpp_uint16, 13>& CRC::CRC_13_BBC() {
1100 static const Parameters<crcpp_uint16, 13> parameters = {0x1CF5, 0x0000, 0x0000, false, false};
1101 return parameters;
1102}
1103
1116inline const CRC::Parameters<crcpp_uint16, 15>& CRC::CRC_15() {
1117 static const Parameters<crcpp_uint16, 15> parameters = {0x4599, 0x0000, 0x0000, false, false};
1118 return parameters;
1119}
1120
1133inline const CRC::Parameters<crcpp_uint16, 15>& CRC::CRC_15_MPT1327() {
1134 static const Parameters<crcpp_uint16, 15> parameters = {0x6815, 0x0000, 0x0001, false, false};
1135 return parameters;
1136}
1137#endif // CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
1138
1152 static const Parameters<crcpp_uint16, 16> parameters = {0x8005, 0x0000, 0x0000, true, true};
1153 return parameters;
1154}
1155
1169 static const Parameters<crcpp_uint16, 16> parameters = {0x8005, 0x0000, 0x0000, false, false};
1170 return parameters;
1171}
1172
1186 static const Parameters<crcpp_uint16, 16> parameters = {0x1021, 0xFFFF, 0x0000, false, false};
1187 return parameters;
1188}
1189
1190#ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
1203inline const CRC::Parameters<crcpp_uint16, 16>& CRC::CRC_16_CDMA2000() {
1204 static const Parameters<crcpp_uint16, 16> parameters = {0xC867, 0xFFFF, 0x0000, false, false};
1205 return parameters;
1206}
1207
1220inline const CRC::Parameters<crcpp_uint16, 16>& CRC::CRC_16_DECTR() {
1221 static const Parameters<crcpp_uint16, 16> parameters = {0x0589, 0x0000, 0x0001, false, false};
1222 return parameters;
1223}
1224
1237inline const CRC::Parameters<crcpp_uint16, 16>& CRC::CRC_16_DECTX() {
1238 static const Parameters<crcpp_uint16, 16> parameters = {0x0589, 0x0000, 0x0000, false, false};
1239 return parameters;
1240}
1241
1254inline const CRC::Parameters<crcpp_uint16, 16>& CRC::CRC_16_DNP() {
1255 static const Parameters<crcpp_uint16, 16> parameters = {0x3D65, 0x0000, 0xFFFF, true, true};
1256 return parameters;
1257}
1258#endif // CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
1259
1273 static const Parameters<crcpp_uint16, 16> parameters = {0x1021, 0xFFFF, 0xFFFF, false, false};
1274 return parameters;
1275}
1276
1290 static const Parameters<crcpp_uint16, 16> parameters = {0x1021, 0x0000, 0x0000, true, true};
1291 return parameters;
1292}
1293
1294#ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
1307inline const CRC::Parameters<crcpp_uint16, 16>& CRC::CRC_16_MAXIM() {
1308 static const Parameters<crcpp_uint16, 16> parameters = {0x8005, 0x0000, 0xFFFF, true, true};
1309 return parameters;
1310}
1311
1324inline const CRC::Parameters<crcpp_uint16, 16>& CRC::CRC_16_MODBUS() {
1325 static const Parameters<crcpp_uint16, 16> parameters = {0x8005, 0xFFFF, 0x0000, true, true};
1326 return parameters;
1327}
1328
1341inline const CRC::Parameters<crcpp_uint16, 16>& CRC::CRC_16_T10DIF() {
1342 static const Parameters<crcpp_uint16, 16> parameters = {0x8BB7, 0x0000, 0x0000, false, false};
1343 return parameters;
1344}
1345
1358inline const CRC::Parameters<crcpp_uint16, 16>& CRC::CRC_16_USB() {
1359 static const Parameters<crcpp_uint16, 16> parameters = {0x8005, 0xFFFF, 0xFFFF, true, true};
1360 return parameters;
1361}
1362
1375inline const CRC::Parameters<crcpp_uint16, 16>& CRC::CRC_16_CMS() {
1376 static const Parameters<crcpp_uint16, 16> parameters = {0x8005, 0xFFFF, 0x0000, false, false};
1377 return parameters;
1378}
1379
1380#endif // CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
1381
1395 static const Parameters<crcpp_uint16, 16> parameters = {0x1021, 0xFFFF, 0xFFFF, true, true};
1396 return parameters;
1397}
1398
1412 static const Parameters<crcpp_uint16, 16> parameters = {0x1021, 0x0000, 0x0000, false, false};
1413 return parameters;
1414}
1415
1416#ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
1429inline const CRC::Parameters<crcpp_uint32, 17>& CRC::CRC_17_CAN() {
1430 static const Parameters<crcpp_uint32, 17> parameters = {0x1685B, 0x00000, 0x00000, false, false};
1431 return parameters;
1432}
1433
1446inline const CRC::Parameters<crcpp_uint32, 21>& CRC::CRC_21_CAN() {
1447 static const Parameters<crcpp_uint32, 21> parameters = {0x102899, 0x000000, 0x000000, false, false};
1448 return parameters;
1449}
1450
1463inline const CRC::Parameters<crcpp_uint32, 24>& CRC::CRC_24() {
1464 static const Parameters<crcpp_uint32, 24> parameters = {0x864CFB, 0xB704CE, 0x000000, false, false};
1465 return parameters;
1466}
1467
1480inline const CRC::Parameters<crcpp_uint32, 24>& CRC::CRC_24_FLEXRAYA() {
1481 static const Parameters<crcpp_uint32, 24> parameters = {0x5D6DCB, 0xFEDCBA, 0x000000, false, false};
1482 return parameters;
1483}
1484
1497inline const CRC::Parameters<crcpp_uint32, 24>& CRC::CRC_24_FLEXRAYB() {
1498 static const Parameters<crcpp_uint32, 24> parameters = {0x5D6DCB, 0xABCDEF, 0x000000, false, false};
1499 return parameters;
1500}
1501
1514inline const CRC::Parameters<crcpp_uint32, 30>& CRC::CRC_30() {
1515 static const Parameters<crcpp_uint32, 30> parameters = {0x2030B9C7, 0x3FFFFFFF, 0x00000000, false, false};
1516 return parameters;
1517}
1518#endif // CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
1519
1533 static const Parameters<crcpp_uint32, 32> parameters = {0x04C11DB7, 0xFFFFFFFF, 0xFFFFFFFF, true, true};
1534 return parameters;
1535}
1536
1550 static const Parameters<crcpp_uint32, 32> parameters = {0x04C11DB7, 0xFFFFFFFF, 0xFFFFFFFF, false, false};
1551 return parameters;
1552}
1553
1554#ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
1567inline const CRC::Parameters<crcpp_uint32, 32>& CRC::CRC_32_C() {
1568 static const Parameters<crcpp_uint32, 32> parameters = {0x1EDC6F41, 0xFFFFFFFF, 0xFFFFFFFF, true, true};
1569 return parameters;
1570}
1571#endif
1572
1586 static const Parameters<crcpp_uint32, 32> parameters = {0x04C11DB7, 0xFFFFFFFF, 0x00000000, false, false};
1587 return parameters;
1588}
1589
1603 static const Parameters<crcpp_uint32, 32> parameters = {0x04C11DB7, 0x00000000, 0xFFFFFFFF, false, false};
1604 return parameters;
1605}
1606
1607#ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
1620inline const CRC::Parameters<crcpp_uint32, 32>& CRC::CRC_32_Q() {
1621 static const Parameters<crcpp_uint32, 32> parameters = {0x814141AB, 0x00000000, 0x00000000, false, false};
1622 return parameters;
1623}
1624
1637inline const CRC::Parameters<crcpp_uint64, 40>& CRC::CRC_40_GSM() {
1638 static const Parameters<crcpp_uint64, 40> parameters = {0x0004820009, 0x0000000000, 0xFFFFFFFFFF, false, false};
1639 return parameters;
1640}
1641
1654inline const CRC::Parameters<crcpp_uint64, 64>& CRC::CRC_64() {
1655 static const Parameters<crcpp_uint64, 64> parameters = {0x42F0E1EBA9EA3693,
1656 0x0000000000000000,
1657 0x0000000000000000,
1658 false,
1659 false};
1660 return parameters;
1661}
1662#endif // CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
1663
1664#ifdef CRCPP_USE_NAMESPACE
1665} // NOLINT
1666#endif
1667
1668#endif // CRCPP_CRC_H_
#define crcpp_constexpr
Compile-time expression definition.
Definition CRC.h:127
#define crcpp_uint16
Unsigned 16-bit integer definition, used primarily for parameter definitions.
Definition CRC.h:88
#define crcpp_size
Unsigned size definition, used for specifying data sizes.
Definition CRC.h:118
Static class for computing CRCs.
Definition CRC.h:141
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:1411
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_uint32, 32 > & CRC_32_MPEG2()
Returns a set of parameters for CRC-32 MPEG-2.
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:1168
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:1289
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:1272
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:1549
static const Parameters< crcpp_uint16, 16 > & CRC_16_CCITTFALSE()
Returns a set of parameters for CRC-16 CCITT FALSE.
Definition CRC.h:1185
static const Parameters< crcpp_uint32, 32 > & CRC_32_POSIX()
Returns a set of parameters for CRC-32 POSIX.
Definition CRC.h:1602
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,...
Definition CRC.h:1394
static CRCType Calculate(const void *data, crcpp_size size, const Parameters< CRCType, CRCWidth > &parameters)
Computes a CRC.
Definition CRC.h:433
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:1151
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:1532
CRC parameters.
Definition CRC.h:151
Table< CRCType, CRCWidth > MakeTable() const
Returns a CRC lookup table construct using these CRC parameters.
Definition CRC.h:324
CRCType initialValue
Initial CRC value.
Definition CRC.h:153
CRCType polynomial
CRC polynomial.
Definition CRC.h:152
CRCType finalXOR
Value to XOR with the final CRC.
Definition CRC.h:154
bool reflectInput
true to reflect all input bytes
Definition CRC.h:155
bool reflectOutput
true to reflect the output CRC (reflection occurs before the final XOR)
Definition CRC.h:156
CRC lookup table. After construction, the CRC parameters are fixed.
Definition CRC.h:166
const CRCType * GetTable() const
Gets the CRC table.
Definition CRC.h:372
const Parameters< CRCType, CRCWidth > & GetParameters() const
Gets the CRC parameters used to construct the CRC table.
Definition CRC.h:361
CRCType operator[](unsigned char index) const
Gets an entry in the CRC table.
Definition CRC.h:384
Table(const Parameters< CRCType, CRCWidth > &parameters)
Constructs a CRC table from a set of CRC parameters.
Definition CRC.h:336