pjmsg_mcap_wrapper
Loading...
Searching...
No Matches
crc32.hpp
Go to the documentation of this file.
1#include <array>
2#include <cstddef>
3#include <cstdint>
4
5namespace mcap::internal {
6
7/**
8 * Compute CRC32 lookup tables as described at:
9 * https://github.com/komrad36/CRC#option-6-1-byte-tabular
10 *
11 * An iteration of CRC computation can be performed on 8 bits of input at once. By pre-computing a
12 * table of the values of CRC(?) for all 2^8 = 256 possible byte values, during the final
13 * computation we can replace a loop over 8 bits with a single lookup in the table.
14 *
15 * For further speedup, we can also pre-compute the values of CRC(?0) for all possible bytes when a
16 * zero byte is appended. Then we can process two bytes of input at once by computing CRC(AB) =
17 * CRC(A0) ^ CRC(B), using one lookup in the CRC(?0) table and one lookup in the CRC(?) table.
18 *
19 * The same technique applies for any number of bytes to be processed at once, although the speed
20 * improvements diminish.
21 *
22 * @param Polynomial The binary representation of the polynomial to use (reversed, i.e. most
23 * significant bit represents x^0).
24 * @param NumTables The number of bytes of input that will be processed at once.
25 */
26template <size_t Polynomial, size_t NumTables>
27struct CRC32Table {
28private:
30
31public:
32 constexpr CRC32Table() {
33 for (uint32_t i = 0; i < 256; i++) {
34 uint32_t r = i;
35 r = ((r & 1) * Polynomial) ^ (r >> 1);
36 r = ((r & 1) * Polynomial) ^ (r >> 1);
37 r = ((r & 1) * Polynomial) ^ (r >> 1);
38 r = ((r & 1) * Polynomial) ^ (r >> 1);
39 r = ((r & 1) * Polynomial) ^ (r >> 1);
40 r = ((r & 1) * Polynomial) ^ (r >> 1);
41 r = ((r & 1) * Polynomial) ^ (r >> 1);
42 r = ((r & 1) * Polynomial) ^ (r >> 1);
43 table[i] = r;
44 }
45 for (size_t i = 256; i < table.size(); i++) {
46 uint32_t value = table[i - 256];
47 table[i] = table[value & 0xff] ^ (value >> 8);
48 }
49 }
50
51 constexpr uint32_t operator[](size_t index) const {
52 return table[index];
53 }
54};
55
56inline uint32_t getUint32LE(const std::byte* data) {
57 return (uint32_t(data[0]) << 0) | (uint32_t(data[1]) << 8) | (uint32_t(data[2]) << 16) |
58 (uint32_t(data[3]) << 24);
59}
60
62
63/**
64 * Initialize a CRC32 to all 1 bits.
65 */
66static constexpr uint32_t CRC32_INIT = 0xffffffff;
67
68/**
69 * Update a streaming CRC32 calculation.
70 *
71 * For performance, this implementation processes the data 8 bytes at a time, using the algorithm
72 * presented at: https://github.com/komrad36/CRC#option-9-8-byte-tabular
73 */
74inline uint32_t crc32Update(const uint32_t prev, const std::byte* const data, const size_t length) {
75 // Process bytes one by one until we reach the proper alignment.
76 uint32_t r = prev;
77 size_t offset = 0;
78 for (; (uintptr_t(data + offset) & alignof(uint32_t)) != 0 && offset < length; offset++) {
79 r = CRC32_TABLE[(r ^ uint8_t(data[offset])) & 0xff] ^ (r >> 8);
80 }
81 if (offset == length) {
82 return r;
83 }
84
85 // Process 8 bytes (2 uint32s) at a time.
86 size_t remainingBytes = length - offset;
87 for (; remainingBytes >= 8; offset += 8, remainingBytes -= 8) {
88 r ^= getUint32LE(data + offset);
89 uint32_t r2 = getUint32LE(data + offset + 4);
90 r = CRC32_TABLE[0 * 256 + ((r2 >> 24) & 0xff)] ^ CRC32_TABLE[1 * 256 + ((r2 >> 16) & 0xff)] ^
91 CRC32_TABLE[2 * 256 + ((r2 >> 8) & 0xff)] ^ CRC32_TABLE[3 * 256 + ((r2 >> 0) & 0xff)] ^
92 CRC32_TABLE[4 * 256 + ((r >> 24) & 0xff)] ^ CRC32_TABLE[5 * 256 + ((r >> 16) & 0xff)] ^
93 CRC32_TABLE[6 * 256 + ((r >> 8) & 0xff)] ^ CRC32_TABLE[7 * 256 + ((r >> 0) & 0xff)];
94 }
95
96 // Process any remaining bytes one by one.
97 for (; offset < length; offset++) {
98 r = CRC32_TABLE[(r ^ uint8_t(data[offset])) & 0xff] ^ (r >> 8);
99 }
100 return r;
101}
102
103/** Finalize a CRC32 by inverting the output value. */
104inline uint32_t crc32Final(uint32_t crc) {
105 return crc ^ 0xffffffff;
106}
107
108} // namespace mcap::internal
uint32_t getUint32LE(const std::byte *data)
Definition crc32.hpp:56
uint32_t crc32Update(const uint32_t prev, const std::byte *const data, const size_t length)
Definition crc32.hpp:74
uint32_t crc32Final(uint32_t crc)
Definition crc32.hpp:104
static constexpr uint32_t CRC32_INIT
Definition crc32.hpp:66
static constexpr CRC32Table< 0xedb88320, 8 > CRC32_TABLE
Definition crc32.hpp:61
T size(T... args)
constexpr uint32_t operator[](size_t index) const
Definition crc32.hpp:51
std::array< uint32_t, 256 *NumTables > table
Definition crc32.hpp:29