22 inline constexpr uint8_t reverse_bits(uint8_t x)
24 constexpr uint8_t lookup[16] = {0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe, 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf};
25 return (lookup[x & 0x0F] << 4) | lookup[x >> 4];
27 inline constexpr uint16_t reverse_bits(uint16_t x)
29 return uint16_t(reverse_bits(uint8_t(x))) << 8 | uint16_t(reverse_bits(uint8_t(x >> 8)));
31 inline constexpr uint32_t reverse_bits(uint32_t x)
33 return uint32_t(reverse_bits(uint16_t(x))) << 16 | uint32_t(reverse_bits(uint16_t(x >> 16)));
35 inline constexpr uint64_t reverse_bits(uint64_t x)
37 return uint64_t(reverse_bits(uint32_t(x))) << 32 | uint64_t(reverse_bits(uint32_t(x >> 32)));
39 template <
typename out_t, out_t poly,
bool refl_in,
bool refl_out,
size_t index>
40 constexpr out_t get_crc_table_value_at_index()
42 constexpr
size_t bit_width =
sizeof(out_t) * 8;
43 out_t remainder = refl_in ? reverse_bits(
static_cast<out_t
>(index)) >> (bit_width - 8u) :
static_cast<out_t
>(index);
44 constexpr out_t mask =
static_cast<out_t
>(1) << (bit_width - 1u);
45 for (
size_t i = 0; i < bit_width; i++)
48 remainder = (remainder << 1) ^ poly;
52 return refl_in ? reverse_bits(remainder) : remainder;
55 template <
typename out_t, out_t poly,
bool refl_in,
bool refl_out,
size_t size = 256,
typename = std::make_index_sequence<size>>
58 template <
typename out_t, out_t poly,
bool refl_in,
bool refl_out,
size_t size,
size_t... indexes>
59 struct crc_lookup_table<out_t, poly, refl_in, refl_out, size, std::index_sequence<indexes...>>
61 static constexpr out_t value[size] = {get_crc_table_value_at_index<out_t, poly, refl_in, refl_out, indexes>()...};
64 #if ((defined(_MSVC_LANG) && _MSVC_LANG < 201703L) || (defined(__cplusplus) && __cplusplus < 201703L)) // redeclaration is only needed before C++17
65 template <
typename out_t, out_t poly,
bool refl_in,
bool refl_out,
size_t size,
size_t... indexes>
66 constexpr out_t crc_lookup_table<out_t, poly, refl_in, refl_out, size, std::index_sequence<indexes...>>::value[size];
69 template <typename out_t, out_t poly, bool refl_in, bool refl_out, out_t x_or_out, typename std::enable_if<refl_in, int *>::type =
nullptr>
70 constexpr out_t calculate_crc(
const uint8_t *bytes,
size_t n, out_t crc)
72 constexpr
auto &lookup = crc_lookup_table<out_t, poly, refl_in, refl_out>().value;
73 crc = reverse_bits(crc);
75 crc = lookup[
static_cast<uint8_t
>(*bytes++ ^ crc)] ^ (crc >> 8);
76 return (refl_out != refl_in ? reverse_bits(crc) : crc) ^ x_or_out;
79 template <typename out_t, out_t poly, bool refl_in, bool refl_out, out_t x_or_out, typename std::enable_if<!refl_in, int *>::type =
nullptr>
80 constexpr out_t calculate_crc(
const uint8_t *bytes,
size_t n, out_t crc)
82 constexpr
auto &lookup = crc_lookup_table<out_t, poly, refl_in, refl_out>().value;
83 constexpr
size_t bit_width_minus_8 =
sizeof(out_t) * 8 - 8U;
85 crc = lookup[
static_cast<uint8_t
>(*bytes++ ^ (crc >> bit_width_minus_8))] ^ (crc << 8);
86 return (refl_out ? reverse_bits(crc) : crc) ^ x_or_out;
89 template <
typename out_t, out_t poly_arg, out_t init_arg,
bool refl_in_arg,
bool refl_out_arg, out_t x_or_out_arg>
93 static constexpr out_t poly = poly_arg;
94 static constexpr out_t init = init_arg;
95 static constexpr
bool refl_in = refl_in_arg;
96 static constexpr
bool refl_out = refl_out_arg;
97 static constexpr out_t x_or_out = x_or_out_arg;
98 static constexpr out_t null_crc = (refl_out ? reverse_bits(init) : init) ^ x_or_out;
101 static constexpr out_t
calc(
const uint8_t *bytes =
nullptr,
size_t num_bytes = 0u, out_t prior_crc_value = null_crc)
103 prior_crc_value = x_or_out ? prior_crc_value ^ x_or_out : prior_crc_value;
104 prior_crc_value = refl_out ? reverse_bits(prior_crc_value) : prior_crc_value;
105 return calculate_crc<out_t, poly, refl_in, refl_out, x_or_out>(bytes, num_bytes, prior_crc_value);