https://github.com/localspook/crc
A high performance C++ CRC library with all the bells and whistles.
https://github.com/localspook/crc
cpp cpp20 crc header-only no-dependencies single-file
Last synced: 5 months ago
JSON representation
A high performance C++ CRC library with all the bells and whistles.
- Host: GitHub
- URL: https://github.com/localspook/crc
- Owner: LocalSpook
- License: mit
- Created: 2025-04-20T04:17:45.000Z (6 months ago)
- Default Branch: main
- Last Pushed: 2025-05-07T05:18:53.000Z (5 months ago)
- Last Synced: 2025-05-07T06:20:52.216Z (5 months ago)
- Topics: cpp, cpp20, crc, header-only, no-dependencies, single-file
- Language: C++
- Homepage:
- Size: 25.4 KB
- Stars: 2
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE.md
Awesome Lists containing this project
README
# CRC
**Warning: this library is under construction.
It's functional, but its main selling point—SIMD acceleration—is not yet implemented.**[](https://github.com/LocalSpook/crc/actions/workflows/codeql.yml)
A C++20 SIMD-accelerated high-performance constexpr-capable single-header-only CRC library with over 100 predefined CRCs and the ability to create custom ones.
## API
Most likely, all you're looking for is a simple function that calculates a common CRC variant.
There are two fundamental CRC operations: *building* a CRC to append to your message,
and *verifying* whether an existing message is valid:```cpp
#include // Or: import crc;// Build a CRC:
std::string_view data {"Hello world!"};
std::uint32_t crc {crc::crc32c::calculate(data)};// Verify a CRC:
if (!crc::crc8_bluetooth::is_valid(some_message)) {
throw std::runtime_error {"Message is corrupted!"};
}
```For more complex cases, the CRC can be built up incrementally:
```cpp
// Step 1: initialize CRC state.
crc::crc64_xz crc {};// Step 2: feed it data.
// Notice how you can pass in any byte-like type, without any casts.
crc = crc::process(crc, "Some da"sv);
crc = crc::process(crc, u8"ta processed in "sv);
crc = crc::process(crc, std::vector {'p', 'a', 'r', 't', 's'});// Step 3: extract the final CRC.
std::uint64_t result {crc::finalize(crc};
assert(result == crc::crc64_xz::calculate("Some data processed in parts"sv));
```All the functions above also have overloads taking iterator pairs instead of ranges.
### Choosing an algorithm
There are many algorithms for calculating CRCs.
The library will pick a good default (currently, that's `crc::algorithms::slice_by<8>`),
but it isn't omniscient,
so you have the ability to specify which algorithm you want.
The following algorithms are available:- **`crc::algorithms::slice_by`:** process `N` bytes at a time.
Requires an `N * 256 * sizeof(CRCType)` byte lookup table.
For example, CRC32C implemented with slice-by-4 requires a 4 KiB lookup table.To specify an algorithm, pass it as the first parameter to `crc::<...>::calculate` or `crc::process`:
```cpp
crc::crc32_mpeg2::calculate(crc::algorithms::slice_by<8>, ...);crc::crc32_mpeg2 crc {};
crc = crc::process(crc::algorithms::slice_by<8>, crc, ...);
```If you want to write your own functions that take CRC algorithms as arguments,
constrain them with the `crc::algorithm` concept:```cpp
void my_function(crc::algorithm auto algo, ...) {
crc::crc32c::calculate(algo, ...); // Pass along the algorithm.
}
```### Defining your own CRCs
The CRC you're looking for almost certainly comes predefined
(if it's missing, consider [filing an issue](https://github.com/LocalSpook/crc/issues)),
but you can define your own too:```cpp
using crc32c = crc::crc<
std::uint32_t, // The CRC's type; an unsigned integer at least as wide as the polynomial.
32, // The polynomial's width.
0x1EDC6F41, // The polynomial, with an implicit leading term.
0xFFFFFFFF, // The initial value of the CRC register.
true, // True if the bits in a byte should be ordered from LSb to MSb, false if vice-versa.
true, // True if the result should be reflected during finalization.
0xFFFFFFFF // The value XORed into the result at the very end, after any reflection.
>;
```Or you can adapt existing CRCs:
```cpp
// Identical to crc::crc32, but with the opposite bit ordering.
using crc32_reflected = crc::crc<
crc::crc32::crc_type,
crc::crc32::width,
crc::crc32::poly,
crc::crc32::initial,
!crc::crc32::refin, // ⭐
!crc::crc32::refout, // ⭐
crc::crc32::xorout
>;
```Note that CRCs of width greater than 64 are currently unsupported.
### Composability
All provided functions are function objects and can be passed to other algorithms:
```cpp
std::vector strings {"Apple", "Banana", "Cherry", "Dragonfruit"};
std::vector crcs {std::from_range, strings | std::views::transform(crc::crc32c::calculate)};// Calculate a CRC over several noncontiguous chunks.
std::vector> data {...};
std::uint32_t crc {crc::finalize(std::ranges::fold_left(data, crc::crc32c {}, crc::process))};
```## Installing
### With FetchContent (recommended)
```cmake
FetchContent_Declare(crc
GIT_REPOSITORY https://github.com/LocalSpook/crc
GIT_TAG ... # You should use the latest commit on the main branch.
SYSTEM
)
FetchContent_MakeAvailable(crc)target_link_libraries(... crc::crc)
```### With find_package
```cmake
find_package(crc REQUIRED)
target_link_libraries(... crc::crc)
```### With vendoring (discouraged)
Just copy [`include/crc/crc.hpp`](include/crc/crc.hpp) into your directory structure.
For any serious project, you're highly recommended to use a proper dependency management
system instead, but this method *is* officially supported.## Building
Simply run:
```sh
cmake -B build [-G Ninja]
cmake --build build
```To also build the module, add `-DCRC_MODULE=ON`, then pass `crc::crc-module` to `target_link_libraries`.
The module cannot currently be installed, so this is only available when using FetchContent.To build tests, add `-DBUILD_TESTING=ON`.
The resulting test binary will be `build/bin/tests`.
Our testing framework is Catch2;
it will be downloaded automatically using FetchContent.
If you also configured with `-DCRC_MODULE=ON`,
the module tests will be added to the binary.
We have a 2 by 2 testing matrix:
compile versus run time, and header versus module.
To test just the header, run `./build/bin/tests --section header`.
To test just the module, run `./build/bin/tests --section module`.## Miscellaneous
- This library provides zero ABI stability guarantees.
- It should compile cleanly even at very high warning levels.
If you see a warning, [file an issue](https://github.com/LocalSpook/crc/issues).