Skip to content

Instantly share code, notes, and snippets.

@anderay
Last active July 26, 2024 09:11
Show Gist options
  • Select an option

  • Save anderay/705d8209463cd36d013f4627fafe1c4b to your computer and use it in GitHub Desktop.

Select an option

Save anderay/705d8209463cd36d013f4627fafe1c4b to your computer and use it in GitHub Desktop.
CRC templated
template<class T>
constexpr T reflectBits(T v)
{
T r = v;
uint8_t s = sizeof(T)*8 - 1;
for (v >>= 1; v; v >>= 1)
{
r <<= 1;
r |= v & 1;
s--;
}
return r << s;
}
template<typename T>
constexpr std::array<T, 256> crctab(T polynomial, bool reflectInput, bool reflectOutput) noexcept
{
std::array<T, 256> result{};
for (size_t i = 0; i < 256; ++i)
{
T crc = (reflectInput ? reflectBits<uint8_t>(i) : i);
crc <<= (sizeof(T) - 1)*8;
for (uint8_t bit = 0; bit < 8; bit++)
{
if ((crc & (1u << (sizeof(T)*8 - 1))) != 0)
{
crc <<= 1;
crc ^= polynomial;
}
else
{
crc <<= 1;
}
}
result[i] = (reflectOutput ? reflectBits<T>(crc) : crc);
}
return result;
}
template<typename T, T POLY, T INIT, T RESULT_XOR, bool REFLECTED>
T crcT(span<const uint8_t> data)
{
static constexpr auto crc_table = crctab<T>(POLY, REFLECTED, REFLECTED);
return std::accumulate(data.begin(), data.end(), INIT, [](T checksum, uint8_t value) {
if constexpr (REFLECTED)
{
return crc_table[(checksum ^ value) & 0xffu] ^ (checksum >> 8u);
}
else
{
return crc_table[((checksum >> 8) ^ value) & 0xffu] ^ (checksum << 8u);
}
}) ^ RESULT_XOR;
}
std::uint16_t crc16(span<const uint8_t> data)
{
return crcT<std::uint16_t, 0x1021, 0xffffU, 0, false>(data);
}
std::uint16_t crc16arc(span<const uint8_t> data)
{
return crcT<std::uint16_t, 0x8005, 0, 0, true>(data);
}
std::uint32_t crc32(span<const uint8_t> data)
{
return crcT<std::uint32_t, 0x4C11DB7, 0xffffffffUL, 0xffffffffUL, true>(data);
}
std::uint32_t crc32p4(span<const uint8_t> data)
{
return crcT<std::uint32_t, 0xF4ACFB13, 0xffffffffUL, 0xffffffffUL, true>(data);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment