{"id":28717424,"url":"https://github.com/localspook/zcrc","last_synced_at":"2025-08-08T17:40:29.452Z","repository":{"id":288997638,"uuid":"969404324","full_name":"LocalSpook/zcrc","owner":"LocalSpook","description":"A high-performance C++ CRC library with all the bells and whistles.","archived":false,"fork":false,"pushed_at":"2025-06-12T22:58:58.000Z","size":81,"stargazers_count":7,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-06-12T23:38:47.761Z","etag":null,"topics":["cpp","cpp20","crc","header-only","no-dependencies","single-file"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/LocalSpook.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-04-20T04:17:45.000Z","updated_at":"2025-06-12T22:59:02.000Z","dependencies_parsed_at":"2025-05-11T09:10:30.677Z","dependency_job_id":"32486efb-0985-4bfd-b0fd-8ad267b84384","html_url":"https://github.com/LocalSpook/zcrc","commit_stats":null,"previous_names":["localspook/crc","localspook/zcrc"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/LocalSpook/zcrc","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LocalSpook%2Fzcrc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LocalSpook%2Fzcrc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LocalSpook%2Fzcrc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LocalSpook%2Fzcrc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/LocalSpook","download_url":"https://codeload.github.com/LocalSpook/zcrc/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LocalSpook%2Fzcrc/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":259914924,"owners_count":22931334,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cpp","cpp20","crc","header-only","no-dependencies","single-file"],"created_at":"2025-06-15T03:15:42.496Z","updated_at":"2025-08-08T17:40:29.405Z","avatar_url":"https://github.com/LocalSpook.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ZCRC\n\n**Warning: this library is under construction.\nIt's functional, but its main selling point—SIMD acceleration—is not yet implemented.**\n\n[![CodeQL](https://github.com/LocalSpook/zcrc/actions/workflows/codeql.yml/badge.svg)](https://github.com/LocalSpook/zcrc/actions/workflows/codeql.yml)\n\nA C++20 high-performance constexpr-capable single-header-only CRC library with over 100 predefined CRCs and the ability to create custom ones.\n\n[Try it live right now on Compiler Explorer!](https://godbolt.org/z/4GKsWhvnz)\n\n## API\n\nThere are two fundamental CRC operations: *computing* a CRC to append to a message,\nand *verifying* whether an existing message is valid. Most likely, all you're looking\nfor is a simple function that does that for a common CRC variant. Here you go:\n\n```cpp\n#include \u003czcrc/zcrc.hpp\u003e // Or: import zcrc;\n\n// Compute a CRC:\nstd::string_view data {\"Hello world!\"};\nstd::uint32_t crc {zcrc::crc32c::compute(data)};\n\n// Verify a CRC:\nif (!zcrc::crc8_bluetooth::is_valid(some_message)) {\n    throw std::runtime_error {\"Message is corrupted!\"};\n}\n```\n\nFor more complex cases, the CRC can be built up incrementally:\n\n```cpp\n// Step 1: initialize CRC state.\nzcrc::crc64_xz crc {};\n\n// Step 2: feed it data.\n// Notice how you can pass in any byte-like type, without any casts.\ncrc = zcrc::process(crc, \"Some data\"sv);\ncrc = zcrc::process(crc, u8\" processed in \"sv);\ncrc = zcrc::process(crc, std::vector\u003cstd::uint8_t\u003e {'p', 'a', 'r', 't', 's'});\n\n// Step 3: extract the final CRC.\nstd::uint64_t result {zcrc::finalize(crc)};\nassert(result == zcrc::crc64_xz::compute(\"Some data processed in parts\"sv));\n```\n\nAll the functions above also have overloads taking iterator pairs instead of ranges.\nWhat's more, they accept ranges as weak as input ranges,\nalthough processing is fastest with contiguous sized ranges.\n\n### Choosing an algorithm\n\nThere are many algorithms for calculating CRCs.\nThe library will pick a good default, but it isn't omniscient,\nso you have the ability to specify one yourself.\nThe following algorithms are available:\n\n- `zcrc::slice_by\u003cN\u003e`: process `N` bytes at a time.\n  Requires an `N * 256 * sizeof(zcrc::\u003c...\u003e::crc_type)` byte lookup table.\n  For example, CRC32C implemented with slice-by-4 requires a 4 KiB lookup table.\n- `zcrc::default_algorithm`: used when no algorithm is specified. Currently `zcrc::slice_by\u003c8\u003e`.\n\nTo specify an algorithm, pass it as the first parameter to `zcrc::\u003c...\u003e::compute`, `zcrc::\u003c...\u003e::is_valid`, or `zcrc::process`:\n\n```cpp\nzcrc::crc32_mpeg2::compute(zcrc::slice_by\u003c8\u003e, ...);\n\nif (!zcrc::crc32_mpeg2::is_valid(zcrc::slice_by\u003c8\u003e, ...)) {\n    ...\n}\n\nzcrc::crc32_mpeg2 crc {};\ncrc = zcrc::process(zcrc::slice_by\u003c8\u003e, crc, ...);\n```\n\nIf you want to write your own functions that take CRC algorithms as arguments,\nconstrain them with the `zcrc::algorithm` concept:\n\n```cpp\nvoid my_function(zcrc::algorithm auto algo, ...) {\n    zcrc::crc32c::compute(algo, ...); // Pass along the algorithm.\n}\n```\n\n### Parallelizing the computation\n\nComputing CRCs is an embarrassingly parallel problem.\nTo enable parallelization,\nsimply wrap an ordinary algorithm with the `zcrc::parallel` adaptor and pass it to a function as you normally would:\n\n```cpp\nzcrc::crc32c::compute(zcrc::parallel\u003czcrc::slice_by\u003c8\u003e\u003e, ...);\n```\n\n(The function is still constexpr! It'll just dispatch to a sequential algorithm if evaluated at compile time.)\n\nThe parallel algorithm divides the message into as many chunks as the system has hardware threads.\nEach thread processes its chunk using the wrapped algorithm (in this case, `zcrc::slice_by\u003c8\u003e`).\nHere's what the scaling can look like:\n\n![image](img/parallel_scaling.svg)\n\nTo get specific numbers for your system, build the benchmarks as described in [Building](#building).\n\n### Defining your own CRCs\n\nThe CRC you're looking for almost certainly comes predefined\n(if it's missing, consider [filing an issue](https://github.com/LocalSpook/zcrc/issues)),\nbut you can define your own too:\n\n```cpp\nusing crc32c = zcrc::crc\u003c\n    32,         // The polynomial's width.\n    0x1EDC6F41, // The polynomial, with an implicit leading term.\n    0xFFFFFFFF, // The initial value of the CRC register.\n    true,       // True if the bits in a byte should be ordered from LSb to MSb, false if vice-versa.\n    true,       // True if the result should be reflected during finalization.\n    0xFFFFFFFF  // The value XORed into the result at the very end, after any reflection.\n\u003e;\n```\n\nOr you can adapt existing CRCs:\n\n```cpp\n// Identical to zcrc::crc32, but with the opposite bit ordering.\nusing crc32_reflected = zcrc::crc\u003c\n    zcrc::crc32::width,\n    zcrc::crc32::poly,\n    zcrc::crc32::init,\n    !zcrc::crc32::refin, // ⭐\n    !zcrc::crc32::refout, // ⭐\n    zcrc::crc32::xorout\n\u003e;\n```\n\nNote that CRCs of width greater than 64 are currently unsupported.\n\n### Composability\n\nAll provided functions are function objects and can be passed to other algorithms:\n\n```cpp\nstd::vector\u003cstd::string\u003e strings {\"Apple\", \"Banana\", \"Cherry\", \"Dragonfruit\"};\nstd::vector\u003cstd::uint32_t\u003e crcs {std::from_range, strings | std::views::transform(zcrc::crc32c::compute)};\n\n// Compute a CRC over several noncontiguous chunks.\nstd::vector\u003cstd::vector\u003cunsigned char\u003e\u003e data {...};\nstd::uint32_t crc {zcrc::finalize(std::ranges::fold_left(data, zcrc::crc32c {}, zcrc::process))};\n```\n\n## Installing\n\n### With FetchContent (recommended)\n\n```cmake\nset(ZCRC_MODULE ON) # If using the module.\nFetchContent_Declare(zcrc\n    GIT_REPOSITORY https://github.com/LocalSpook/zcrc\n    GIT_TAG v0.1.0\n    SYSTEM\n)\nFetchContent_MakeAvailable(zcrc)\n\ntarget_link_libraries(... zcrc::zcrc[-module])\n```\n\n### With find_package\n\n```cmake\n# If consuming the library as a header (#include \u003czcrc/zcrc.hpp\u003e):\nfind_package(zcrc REQUIRED)\ntarget_link_libraries(... zcrc::zcrc)\n\n# If consuming the library as a module (import zcrc;):\nfind_package(zcrc REQUIRED COMPONENTS module)\ntarget_link_libraries(... zcrc::zcrc-module)\n```\n\n### With vendoring (discouraged)\n\nJust copy [`include/zcrc/zcrc.hpp`](include/zcrc/zcrc.hpp) into your directory structure.\nFor any serious project, you're highly recommended to use a proper dependency management\nsystem instead, but this method *is* officially supported.\n\n## Supported toolchains\n\n| Toolchain  | Baseline  | `zcrc::zcrc-module` |\n|------------|-----------|---------------------|\n| CMake      | ≥ 3.23    | ≥ 3.28              |\n| Emscripten | ≥ 3.1.41  | ≥ 4.0.3             |\n\n\u003c!--\nEmscripten before 3.1.41 bundles libc++ 15, which has incomplete ranges support\nand would be too much of a hassle to support:\n\nhttps://github.com/emscripten-core/emscripten/blob/main/ChangeLog.md\n\n4.0.3 is the first version Emscripten advertises support for modules.\nThat support is enough for us, but is still imperfect (see\nhttps://github.com/emscripten-core/emscripten/issues/24454; only fixed in 4.0.10).\n---\u003e\n\n## Building\n\nSimply run:\n\n```sh\ncmake -B build [-G Ninja]\ncmake --build build\n```\n\nTo build tests, add `-DZCRC_TEST=ON`.\nThe resulting test binary will be `build/bin/tests`.\nOur testing framework is Catch2;\nit will be downloaded automatically using FetchContent.\nIf the project was configured with`-DZCRC_MODULE=ON`,\nthe module tests will be added to the binary.\nWe have a 2 by 2 testing matrix:\ncompile versus run time, and header versus module.\nThe compile-time tests of course run at build time.\nWith the runtime tests you have more flexibility:\nto test just the header, run `./build/bin/tests [header]`, and\nto test just the module, run `./build/bin/tests [module]`.\n\nTo build the benchmarks, add `-DZCRC_BENCHMARK=ON`.\nThe benchmarking framework is also Catch2,\nand the resulting binary will be `build/bin/benchmarks`.\n\nPackage maintainers can control where ZCRC installs its files with the following options\n(they should be paths relative to the install prefix):\n\n|             Option           |                  Default               | Controls  |\n|------------------------------|----------------------------------------|-----------|\n| `CMAKE_INSTALL_INCLUDEDIR`   | N/A (CMake builtin)                    | `*.hpp`   |\n| `ZCRC_INSTALL_PKGCONFIG_DIR` | `${CMAKE_INSTALL_LIBDIR}/pkgconfig`    | `*.pc`    |\n| `ZCRC_INSTALL_CMAKE_DIR`     | `${CMAKE_INSTALL_LIBDIR}/cmake/zcrc`   | `*.cmake` |\n| `ZCRC_INSTALL_MODULE_DIR`    | `${CMAKE_INSTALL_INCLUDEDIR}/zcrc/src` | `*.cppm`  |\n\n## Miscellaneous\n\n- This library provides zero ABI stability guarantees.\n- It should compile cleanly even at very high warning levels.\n  If you see a warning, [file an issue](https://github.com/LocalSpook/zcrc/issues).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flocalspook%2Fzcrc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flocalspook%2Fzcrc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flocalspook%2Fzcrc/lists"}