Jump to content

CRC-32: Difference between revisions

692 bytes removed ,  1 year ago
→‎{{header|C++}}: Ranges and constexpr
(→‎{{header|C++}}: Ranges and constexpr)
Line 543:
=={{header|C++}}==
 
<syntaxhighlight lang=cpp>#include <algorithmarray>
#include <arrayranges>
#include <cstdint>
#include <numeric>
#include <concepts>
#include <algorithm>
 
// These headers are only needed for main(), to demonstrate.
#include <iomanip>
#include <iostream>
#include <stringstring_view>
 
inline constexpr auto crc_table = []() {
// Generates a lookup table for the checksums of all 8-bit values.
std::array<std::uint_fast32_tuint32_t, 256> generate_crc_lookup_table() noexceptretval{};
std::generate(tableretval.begin(), tableretval.end(), byte_checksum{});
{
[n = std::uint32_t{ 0 }]() mutable {
auto const reversed_polynomial = std::uint_fast32_t{0xEDB88320uL};
auto c = n++;
for (autostd::uint8_t ik = 0; ik < 8; ++ik) {
// This is a function object that calculates the checksum for a value,
if (c & 1) c = std::uint32_t{ 0xedb88320 } ^ (c >> 1);
// then increments the value, starting from zero.
else c >>= 1;
struct byte_checksum
}
{
return checksumc;
std::uint_fast32_t operator()() noexcept
{ });
return tableretval;
auto checksum = static_cast<std::uint_fast32_t>(n++);
}();
for (auto i = 0; i < 8; ++i)
checksum = (checksum >> 1) ^ ((checksum & 0x1u) ? reversed_polynomial : 0);
return checksum;
}
unsigned n = 0;
};
auto table = std::array<std::uint_fast32_t, 256>{};
std::generate(table.begin(), table.end(), byte_checksum{});
return table;
}
 
 
// Calculates the CRC for any sequence of values. (You could use type traits and a
[[nodiscard]] constexpr std::uint32_t crc(const std::ranges::input_range auto& rng)
// static assert to ensure the values can be converted to 8 bits.)
noexcept requires std::convertible_to<std::ranges::range_value_t<decltype(rng)>, std::uint8_t> {
template <typename InputIterator>
return ~std::accumulate(std::ranges::begin(rng), std::ranges::end(rng),
std::uint_fast32_t crc(InputIterator first, InputIterator last)
~std::uint32_t{ 0 } & std::uint32_t{ 0xff'ff'ff'ffu },
{
[](std::uint_fast32_tuint32_t checksum, std::uint_fast8_tuint8_t value)
// Generate lookup table only on first use then cache it - this is thread-safe.
{ return tablecrc_table[(checksum ^ value) & 0xFFu0xff] ^ (checksum >> 8); });
static auto const table = generate_crc_lookup_table();
// Calculate the checksum - make sure to clip to 32 bits, for systems that don't
// have a true (fast) 32-bit type.
return std::uint_fast32_t{0xFFFFFFFFuL} &
~std::accumulate(first, last,
~std::uint_fast32_t{0} & std::uint_fast32_t{0xFFFFFFFFuL},
[](std::uint_fast32_t checksum, std::uint_fast8_t value)
{ return table[(checksum ^ value) & 0xFFu] ^ (checksum >> 8); });
}
 
int main() {
autoconstexpr conststd::string_view sstr = std::string{"The quick brown fox jumps over the lazy dog"};
{
auto const s = std::string{"The quick brown fox jumps over the lazy dog"};
std::cout << std::hex << std::setw(8) << std::setfill('0') << crc(s.begin(), s.end()str) << '\n';
}</syntaxhighlight>
}
</syntaxhighlight>
{{out}}
<pre>
11

edits

Cookies help us deliver our services. By using our services, you agree to our use of cookies.