Program Listing for File crc32.hpp
↰ Return to documentation for file (include/3rdparty/mcap/crc32.hpp)
#include <array>
#include <cstddef>
#include <cstdint>
namespace mcap::internal {
template <size_t Polynomial, size_t NumTables>
struct CRC32Table {
private:
std::array<uint32_t, 256 * NumTables> table = {};
public:
constexpr CRC32Table() {
for(uint32_t i = 0; i < 256; i++) {
uint32_t r = i;
r = ((r & 1) * Polynomial) ^ (r >> 1);
r = ((r & 1) * Polynomial) ^ (r >> 1);
r = ((r & 1) * Polynomial) ^ (r >> 1);
r = ((r & 1) * Polynomial) ^ (r >> 1);
r = ((r & 1) * Polynomial) ^ (r >> 1);
r = ((r & 1) * Polynomial) ^ (r >> 1);
r = ((r & 1) * Polynomial) ^ (r >> 1);
r = ((r & 1) * Polynomial) ^ (r >> 1);
table[i] = r;
}
for(size_t i = 256; i < table.size(); i++) {
uint32_t value = table[i - 256];
table[i] = table[value & 0xff] ^ (value >> 8);
}
}
constexpr uint32_t operator[](size_t index) const {
return table[index];
}
};
inline uint32_t getUint32LE(const std::byte* data) {
return (uint32_t(data[0]) << 0) | (uint32_t(data[1]) << 8) | (uint32_t(data[2]) << 16) | (uint32_t(data[3]) << 24);
}
static constexpr CRC32Table<0xedb88320, 8> CRC32_TABLE;
static constexpr uint32_t CRC32_INIT = 0xffffffff;
inline uint32_t crc32Update(const uint32_t prev, const std::byte* const data, const size_t length) {
// Process bytes one by one until we reach the proper alignment.
uint32_t r = prev;
size_t offset = 0;
for(; (uintptr_t(data + offset) & alignof(uint32_t)) != 0 && offset < length; offset++) {
r = CRC32_TABLE[(r ^ uint8_t(data[offset])) & 0xff] ^ (r >> 8);
}
if(offset == length) {
return r;
}
// Process 8 bytes (2 uint32s) at a time.
size_t remainingBytes = length - offset;
for(; remainingBytes >= 8; offset += 8, remainingBytes -= 8) {
r ^= getUint32LE(data + offset);
uint32_t r2 = getUint32LE(data + offset + 4);
r = CRC32_TABLE[0 * 256 + ((r2 >> 24) & 0xff)] ^ CRC32_TABLE[1 * 256 + ((r2 >> 16) & 0xff)] ^ CRC32_TABLE[2 * 256 + ((r2 >> 8) & 0xff)]
^ CRC32_TABLE[3 * 256 + ((r2 >> 0) & 0xff)] ^ CRC32_TABLE[4 * 256 + ((r >> 24) & 0xff)] ^ CRC32_TABLE[5 * 256 + ((r >> 16) & 0xff)]
^ CRC32_TABLE[6 * 256 + ((r >> 8) & 0xff)] ^ CRC32_TABLE[7 * 256 + ((r >> 0) & 0xff)];
}
// Process any remaining bytes one by one.
for(; offset < length; offset++) {
r = CRC32_TABLE[(r ^ uint8_t(data[offset])) & 0xff] ^ (r >> 8);
}
return r;
}
inline uint32_t crc32Final(uint32_t crc) {
return crc ^ 0xffffffff;
}
} // namespace mcap::internal