├── benchmark ├── Makefile ├── CMakeLists.txt └── main.cpp ├── .gitignore ├── CMakeLists.txt ├── examples ├── 01_using_built_in_crc_functions.cpp ├── 02_creating_your_own_crc_functions.cpp └── 03_splitting_a_checksum_eval_into_chunks.cpp ├── LICENSE ├── README.md ├── test └── test_cppcrc.cpp └── cppcrc.h /benchmark/Makefile: -------------------------------------------------------------------------------- 1 | 2 | 3 | .PHONY: benchmark 4 | benchmark: 5 | @mkdir -p build && \ 6 | cd build && \ 7 | cmake .. && \ 8 | make && \ 9 | ./benchmark 10 | 11 | .PHONY: clean 12 | clean: 13 | @rm -rf build 14 | 15 | # all other libraries should get auto-fetched using CMake from github 16 | install_boost_ubuntu: 17 | sudo apt-get install libboost-all-dev 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | 34 | # CMake 35 | build -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project( 4 | cppcrc 5 | VERSION 1.3.0 6 | LANGUAGES CXX 7 | DESCRIPTION "A very small, fast, header-only, C++ library for generating CRCs" 8 | ) 9 | 10 | add_library(cppcrc INTERFACE) 11 | target_include_directories(cppcrc INTERFACE 12 | $ 13 | $ 14 | ) 15 | 16 | # To include cppcrc in your project, just add the following two lines to your CMakeLists.txt file 17 | # add_subdirectory(cppcrc/) 18 | # target_link_libraries(your_project_name cppcrc) 19 | -------------------------------------------------------------------------------- /examples/01_using_built_in_crc_functions.cpp: -------------------------------------------------------------------------------- 1 | // 1) include "cppcrc.h" 2 | #include "../cppcrc.h" 3 | #include 4 | 5 | // 2) use the CRC8/CRC16/CRC32 functions, for example: 6 | int main() 7 | { 8 | uint8_t data[] = {0x12, 0x5A, 0x23, 0x19, 0x92, 0xF3, 0xDE, 0xC2, 0x5A, 0x1F, 0x91, 0xA3}; 9 | 10 | // calculate a checksum: 11 | uint16_t crc_value = CRC16::CCITT_FALSE::calc(data, sizeof(data)); 12 | printf("crc_value = 0x%04X\n", crc_value); 13 | 14 | // optionally continue an existing calculation by passing in the previous crc value 15 | uint8_t more_data[] = {0x78, 0x9A}; 16 | crc_value = CRC16::CCITT_FALSE::calc(more_data, sizeof(more_data), crc_value); 17 | printf("crc_value = 0x%04X (continued)\n", crc_value); 18 | 19 | // view the lookup table: 20 | auto &crc_table = CRC16::CCITT_FALSE::table(); 21 | printf("crc_table = {0x%04X", crc_table[0]); 22 | for (int i = 1; i < 256; i++) 23 | printf(", 0x%04X", crc_table[i]); 24 | printf("}\n"); 25 | } -------------------------------------------------------------------------------- /examples/02_creating_your_own_crc_functions.cpp: -------------------------------------------------------------------------------- 1 | // 1) include "cppcrc.h" 2 | #include "../cppcrc.h" 3 | #include 4 | 5 | int main() 6 | { 7 | // 2) pick some CRC settings (these are just an example) 8 | using base_type = uint8_t; 9 | constexpr base_type poly = 0x12; 10 | constexpr base_type init_value = 0x34; 11 | constexpr bool reflect_in = true; 12 | constexpr bool reflect_out = true; 13 | constexpr base_type Xor_out = 0xFF; 14 | 15 | // 3) create a new CRC type by filling in the CRC parameters 16 | using your_crc_name = crc_utils::crc; 17 | 18 | // you can use your new CRC type to calculate a checksum 19 | uint8_t data[] = {0x12, 0x34, 0x56}; 20 | auto calculated_crc = your_crc_name::calc(data, sizeof(data)); 21 | printf("calculated_crc = 0x%02X\n", calculated_crc); 22 | 23 | // and access the underlying lookup table for your CRC function 24 | auto &crc_table = your_crc_name::table(); 25 | printf("crc_table[1] = 0x%02X\n", crc_table[1]); 26 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Darren V Levine 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /examples/03_splitting_a_checksum_eval_into_chunks.cpp: -------------------------------------------------------------------------------- 1 | #include "../cppcrc.h" 2 | #include 3 | 4 | int main() 5 | { 6 | // you can chunk up a calculation into multiple parts by passing in the previous crc value: 7 | uint8_t data_chunk1[] = {0x12, 0x34, 0x56}; 8 | uint8_t data_chunk2[] = {0x78, 0x9A, 0xBC, 0xDE}; 9 | { 10 | auto crc16 = CRC16::CCITT_FALSE::calc(data_chunk1, sizeof(data_chunk1)); 11 | crc16 = CRC16::CCITT_FALSE::calc(data_chunk2, sizeof(data_chunk2), crc16); 12 | printf("CRC16 = 0x%08X - when split into multiple calculations\n", crc16); 13 | } 14 | 15 | { 16 | uint8_t all_data[] = {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE}; 17 | auto crc16 = CRC16::CCITT_FALSE::calc(all_data, sizeof(all_data)); 18 | printf("CRC16 = 0x%08X - when calculated in one pass (same as the split version)\n", crc16); 19 | } 20 | 21 | // WARNING: The "calc" function's third argument is "prior_crc_value", which assumes 22 | // you're passing in a valid CRC value to continue from, this first CRC is NOT 23 | // always equivalent to the crc algorithm's "init" parameter. So never pass in "init"! 24 | // Instead, prefer "null_crc", or "calc()" if you're manually initializing a chunked up 25 | // calculation, like so: 26 | { 27 | uint32_t crc32 = CRC32::CRC32::null_crc; // or use "= CRC32::CRC32::calc();" 28 | crc32 = CRC32::CRC32::calc(data_chunk1, sizeof(data_chunk1), crc32); 29 | crc32 = CRC32::CRC32::calc(data_chunk2, sizeof(data_chunk2), crc32); 30 | printf("CRC32 = 0x%08X\n", crc32); 31 | } 32 | } -------------------------------------------------------------------------------- /benchmark/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | project(benchmark 4 | VERSION 1.0 5 | DESCRIPTION "Benchmarking several C++ CRC libraries" 6 | LANGUAGES CXX) 7 | 8 | add_executable(benchmark main.cpp) 9 | target_compile_options(benchmark PUBLIC -Wall -std=c++17 -O3) 10 | 11 | # for https://github.com/DarrenLevine/cppcrc 12 | target_include_directories(benchmark PRIVATE ..) 13 | 14 | # for https://github.com/pstolarz/CRaC/tree/master 15 | include(FetchContent) 16 | FetchContent_Populate(crac 17 | GIT_REPOSITORY https://github.com/pstolarz/CRaC.git 18 | GIT_TAG "origin/master") 19 | add_library(crac INTERFACE) 20 | target_include_directories(crac SYSTEM INTERFACE "${crac_SOURCE_DIR}/include") 21 | target_link_libraries(benchmark PRIVATE crac) 22 | 23 | # for https://github.com/d-bahr/CRCpp 24 | include(FetchContent) 25 | FetchContent_Populate(crccpp 26 | GIT_REPOSITORY https://github.com/d-bahr/CRCpp.git 27 | GIT_TAG "origin/master") 28 | add_library(crccpp INTERFACE) 29 | target_include_directories(crccpp SYSTEM INTERFACE "${crccpp_SOURCE_DIR}/inc") 30 | add_subdirectory("${crccpp_SOURCE_DIR}") 31 | target_link_libraries(benchmark PRIVATE crccpp) 32 | 33 | # for boost crc 34 | find_package(Boost 1.72.0) 35 | IF (Boost_FOUND) 36 | ADD_DEFINITIONS("-DHAS_BOOST") 37 | include_directories(${Boost_INCLUDE_DIRS}) 38 | target_link_libraries(benchmark ${Boost_LIBRARIES}) 39 | ENDIF() 40 | 41 | # for https://github.com/martinus/nanobench 42 | FetchContent_Declare( 43 | nanobench 44 | GIT_REPOSITORY https://github.com/martinus/nanobench.git 45 | GIT_TAG v4.1.0 46 | GIT_SHALLOW TRUE) 47 | FetchContent_MakeAvailable(nanobench) 48 | target_link_libraries(benchmark PRIVATE nanobench) 49 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CPP/CRC 2 | 3 | A very small, fast, header-only, C++ library for generating CRCs 4 | 5 | ![license](https://img.shields.io/badge/license-MIT-informational) ![version](https://img.shields.io/badge/version-1.3-blue) 6 | 7 | ## Requirements 8 | 9 | * C++14 or greater 10 | 11 | ## Features 12 | 13 | * Can be used to generate arbitrary/custom CRC calculators, and CRC lookup tables **at compile time** 14 | * Header-only, single file, very small backend implementation (<100 lines) 15 | * Very fast [check out the benchmarks](#benchmarks) 16 | * Each CRC function has the signature: 17 | 18 | ```cpp 19 | constexpr out_t crc_type::crc_name::calc( 20 | const uint8_t *bytes, size_t num_bytes, out_t prior_crc_value = null_crc) 21 | ``` 22 | 23 | * Support for the following algorithms are built-in: 24 | * CRC8::CRC8::calc 25 | * CRC8::CDMA2000::calc 26 | * CRC8::DARC::calc 27 | * CRC8::DVB_S2::calc 28 | * CRC8::EBU::calc 29 | * CRC8::I_CODE::calc 30 | * CRC8::ITU::calc 31 | * CRC8::MAXIM::calc 32 | * CRC8::ROHC::calc 33 | * CRC8::WCDMA::calc 34 | * CRC16::ARC::calc 35 | * CRC16::AUG_CCITT::calc 36 | * CRC16::BUYPASS::calc 37 | * CRC16::CCITT_FALSE::calc 38 | * CRC16::CDMA2000::calc 39 | * CRC16::DDS_110::calc 40 | * CRC16::DECT_R::calc 41 | * CRC16::DECT_X::calc 42 | * CRC16::DNP::calc 43 | * CRC16::EN_13757::calc 44 | * CRC16::GENIBUS::calc 45 | * CRC16::KERMIT::calc 46 | * CRC16::MAXIM::calc 47 | * CRC16::MCRF4XX::calc 48 | * CRC16::MODBUS::calc 49 | * CRC16::RIELLO::calc 50 | * CRC16::T10_DIF::calc 51 | * CRC16::TELEDISK::calc 52 | * CRC16::TMS37157::calc 53 | * CRC16::USB::calc 54 | * CRC16::X_25::calc 55 | * CRC16::XMODEM::calc 56 | * CRC16::A::calc 57 | * CRC32::CRC32::calc 58 | * CRC32::BZIP2::calc 59 | * CRC32::JAMCRC::calc 60 | * CRC32::MPEG_2::calc 61 | * CRC32::POSIX::calc 62 | * CRC32::SATA::calc 63 | * CRC32::XFER::calc 64 | * CRC32::C::calc 65 | * CRC32::D::calc 66 | * CRC32::Q::calc 67 | * CRC64::ECMA::calc 68 | * CRC64::GO_ISO::calc 69 | * CRC64::WE::calc 70 | * CRC64::XY::calc 71 | 72 | ## Usage Examples 73 | 74 | ### Using the built-in CRC functions 75 | 76 | ```cpp 77 | // 1) include "cppcrc.h" 78 | #include "cppcrc.h" 79 | #include 80 | 81 | // 2) use the CRC8/CRC16/CRC32 functions, for example: 82 | int main() 83 | { 84 | uint8_t data[] = {0x12, 0x5A, 0x23, 0x19, 0x92, 0xF3, 0xDE, 0xC2, 0x5A, 0x1F, 0x91, 0xA3}; 85 | 86 | // calculate a checksum: 87 | uint16_t crc_value = CRC16::CCITT_FALSE::calc(data, sizeof(data)); 88 | printf("crc_value = 0x%04X\n", crc_value); 89 | 90 | // view the lookup table: 91 | auto &crc_table = CRC16::CCITT_FALSE::table(); 92 | printf("crc_table = {0x%04X", crc_table[0]); 93 | for (int i = 1; i < 256; i++) 94 | printf(", 0x%04X", crc_table[i]); 95 | printf("}\n"); 96 | } 97 | ``` 98 | 99 | ### Creating Your Own CRC Function 100 | 101 | ```cpp 102 | // 1) include "cppcrc.h" 103 | #include "cppcrc.h" 104 | #include 105 | 106 | int main() 107 | { 108 | // 2) pick some CRC settings (these are just an example) 109 | using base_type = uint8_t; 110 | constexpr base_type poly = 0x12; 111 | constexpr base_type init_value = 0x34; 112 | constexpr bool reflect_in = true; 113 | constexpr bool reflect_out = true; 114 | constexpr base_type Xor_out = 0xFF; 115 | 116 | // 3) create a new CRC type by filling in the CRC parameters 117 | using your_crc_name = crc_utils::crc; 118 | 119 | // you can use your new CRC type to calculate a checksum 120 | uint8_t data[] = {0x12, 0x34, 0x56}; 121 | auto calculated_crc = your_crc_name::calc(data, sizeof(data)); 122 | printf("calculated_crc = 0x%02X\n", calculated_crc); 123 | 124 | // and even continue an existing calculation 125 | uint8_t more_data[] = {0x78, 0x9A}; 126 | calculated_crc = your_crc_name::calc(more_data, sizeof(more_data), calculated_crc); 127 | printf("calculated_crc = 0x%02X\n", calculated_crc); 128 | 129 | // and access the underlying lookup table for your CRC function 130 | auto &crc_table = your_crc_name::table(); 131 | } 132 | ``` 133 | 134 | ## Benchmarks 135 | 136 | ### Using data generated at **run-time** with various array sizes and checksum algorithms 137 | 138 | | ns/64kB | 64kB/s | err% | ins/64kB | bra/64kB | miss% | total | Checkum Calculators 139 | |--------------------:|--------------------:|--------:|----------------:|---------------:|--------:|----------:|:-------------------- 140 | | 118,718.50 | 8,423.29 | 0.5% | 527,620.00 | 65,943.00 | 0.0% | 1.20 | `DarrenLevine/cppcrc` 141 | | 118,729.00 | 8,422.54 | 0.5% | 577,143.00 | 65,959.00 | 0.0% | 1.20 | `boostorg/crc` 142 | | 122,306.00 | 8,176.21 | 0.5% | 560,697.00 | 65,987.00 | 0.0% | 1.23 | `d-bahr/CRCpp [w/ static table]` 143 | | 151,351.00 | 6,607.16 | 0.5% | 890,311.00 | 65,943.00 | 0.0% | 1.53 | `pstolarz/CRaC` 144 | | 380,683.00 | 2,626.86 | 1.2% | 3,083,889.00 | 115,556.00 | 5.3% | 3.83 | `d-bahr/CRCpp` 145 | 146 | ### Using data generated at **compile-time** with various array sizes and checksum algorithms 147 | 148 | | ns/64kB | 64kB/s | err% | ins/64kB | bra/64kB | miss% | total | Checkum Calculators 149 | |--------------------:|--------------------:|--------:|----------------:|---------------:|--------:|----------:|:-------------------- 150 | | 0.45 | 2,229,858,535.96 | 0.5% | 1.00 | 0.00 | 0.0% | 0.22 | `DarrenLevine/cppcrc [w/ constexpr data]` 151 | | 0.45 | 2,219,406,249.99 | 0.5% | 1.00 | 0.00 | 0.0% | 0.22 | `pstolarz/CRaC [w/ constexpr data]` 152 | | 995.09 | 1,004,933.31 | 0.5% | 5,805.27 | 643.95 | 0.2% | 0.22 | `boostorg/crc [w/ constexpr data]` 153 | | 1,014.95 | 985,270.21 | 0.4% | 5,716.24 | 667.95 | 0.2% | 0.22 | `d-bahr/CRCpp [w/ constexpr data]` 154 | 155 | Benchmarked using nanobench on a AMD Ryzen 9 5900HS CPU. See benchmark/main.cpp for exact details. 156 | 157 | How to run the benchmarks (it's recommended you install boost first): 158 | 159 | ```sh 160 | git clone https://github.com/DarrenLevine/cppcrc.git 161 | cd cppcrc/benchmark && make 162 | ``` 163 | -------------------------------------------------------------------------------- /benchmark/main.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include 4 | #include 5 | 6 | // github.com/DarrenLevine/cppcrc 7 | #include "cppcrc.h" 8 | 9 | // Boost/crc 10 | #ifdef HAS_BOOST 11 | #include 12 | using boost_CRC8 = boost::crc_optimal<8, 0x07, 0x00, 0x00, false, false>; 13 | using boost_CRC16_CCITT_FALSE = boost::crc_optimal<16, 0x1021, 0xFFFF, 0, false, false>; 14 | using boost_CRC32 = boost::crc_optimal<32, 0x04C11DB7, 0xFFFFFFFF, 0xFFFFFFFF, true, true>; 15 | using boost_CRC64_ECMA = boost::crc_optimal<64, 0x42F0E1EBA9EA3693, 0x0000000000000000, 0x0000000000000000, false, false>; 16 | template 17 | constexpr typename T::value_type boost_calc(const uint8_t* data, size_t size) 18 | { 19 | T res; 20 | res.process_bytes(data, size); 21 | return res.checksum(); 22 | } 23 | #endif 24 | 25 | // github.com/d-bahr/CRCpp 26 | #define CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS 27 | #include "CRC.h" 28 | static auto CRC_8_table = CRC::CRC_8().MakeTable(); 29 | static auto CRC_16_CCITTFALSE_table = CRC::CRC_16_CCITTFALSE().MakeTable(); 30 | static auto CRC_32_table = CRC::CRC_32().MakeTable(); 31 | static auto CRC_64_table = CRC::CRC_64().MakeTable(); 32 | 33 | // https://github.com/pstolarz/CRaC 34 | #include "crac.h" 35 | 36 | // testing macros (runs through four types of CRCs with four different lengths) 37 | // avoiding any for-loops or additional non-constexpr variables that could add 38 | // time/overhead 39 | #define TEST_CHECKSUM_DATA(data_array, name, func1, func2, func3, func4) \ 40 | { \ 41 | b.run( \ 42 | name, \ 43 | [&]() \ 44 | { \ 45 | { \ 46 | constexpr size_t size = sizeof(data_array); \ 47 | ankerl::nanobench::doNotOptimizeAway(func1); \ 48 | ankerl::nanobench::doNotOptimizeAway(func2); \ 49 | ankerl::nanobench::doNotOptimizeAway(func3); \ 50 | ankerl::nanobench::doNotOptimizeAway(func4); \ 51 | } \ 52 | { \ 53 | constexpr size_t size = sizeof(data_array) / 2u; \ 54 | ankerl::nanobench::doNotOptimizeAway(func1); \ 55 | ankerl::nanobench::doNotOptimizeAway(func2); \ 56 | ankerl::nanobench::doNotOptimizeAway(func3); \ 57 | ankerl::nanobench::doNotOptimizeAway(func4); \ 58 | } \ 59 | { \ 60 | constexpr size_t size = sizeof(data_array) / 10u; \ 61 | ankerl::nanobench::doNotOptimizeAway(func1); \ 62 | ankerl::nanobench::doNotOptimizeAway(func2); \ 63 | ankerl::nanobench::doNotOptimizeAway(func3); \ 64 | ankerl::nanobench::doNotOptimizeAway(func4); \ 65 | } \ 66 | { \ 67 | constexpr size_t size = sizeof(data_array) / 100u; \ 68 | ankerl::nanobench::doNotOptimizeAway(func1); \ 69 | ankerl::nanobench::doNotOptimizeAway(func2); \ 70 | ankerl::nanobench::doNotOptimizeAway(func3); \ 71 | ankerl::nanobench::doNotOptimizeAway(func4); \ 72 | } \ 73 | }); \ 74 | } \ 75 | static_assert(1) 76 | #define TEST_CHECKSUM(...) TEST_CHECKSUM_DATA(bytes, __VA_ARGS__) 77 | #define TEST_CHECKSUM_CONSTEXPR(...) TEST_CHECKSUM_DATA(bytes_constexpr, __VA_ARGS__) 78 | 79 | int main() 80 | { 81 | std::random_device dev; 82 | std::mt19937_64 rng(dev()); 83 | constexpr size_t kilobytes_of_test_data = 10; 84 | uint8_t bytes[kilobytes_of_test_data * 1024]; 85 | for (size_t i = 0; i < sizeof(bytes); i++) 86 | bytes[i] = rng(); 87 | constexpr uint8_t bytes_constexpr[] = { 88 | // size doesn't really matter here, since evaluation will be at compile time 89 | 0x09, 0x03, 0x5E, 0x57, 0x3F, 0xA7, 0x11, 0xF1, 0xED, 0xF4, 0xEA, 0xE1, 0x33, 0x96, 0x6A, 90 | 0x22, 0xE1, 0x93, 0x83, 0xC2, 0x56, 0x07, 0x48, 0x47, 0x80, 0xCD, 0x48, 0x19, 0x38, 0xA2, 91 | 0x4E, 0x81, 0x05, 0xF9, 0xE8, 0x02, 0x0E, 0x5F, 0x16, 0x2D, 0x28, 0x11, 0x45, 0x0E, 0x1C, 92 | 0x09, 0x03, 0x5E, 0x57, 0x3F, 0xA7, 0x11, 0xF1, 0xED, 0xF4, 0xEA, 0xE1, 0x33, 0x96, 0x6A, 93 | 0x22, 0xE1, 0x93, 0x83, 0xC2, 0x56, 0x07, 0x48, 0x47, 0x80, 0xCD, 0x48, 0x19, 0x38, 0xA2, 94 | 0x4E, 0x81, 0x05, 0xF9, 0xE8, 0x02, 0x0E, 0x5F, 0x16, 0x2D, 0x28, 0x11, 0x45, 0x0E, 0x1C, 95 | 0x09, 0x03, 0x5E, 0x57, 0x3F, 0xA7, 0x11, 0xF1, 0xED, 0xF4, 0xEA, 0xE1, 0x33, 0x96, 0x6A}; 96 | 97 | ankerl::nanobench::Bench b; 98 | b.title("Checkum Calculators"); 99 | b.unit("64kB"); // approximately 64k = 4*10kB + 4*10kB/2 + 4*10kB/10 + 4*10kB/100 100 | b.epochs(10000); 101 | 102 | // run-time data tests: 103 | TEST_CHECKSUM( 104 | "DarrenLevine/cppcrc", 105 | CRC8::CRC8::calc(bytes, size), 106 | CRC16::CCITT_FALSE::calc(bytes, size), 107 | CRC32::CRC32::calc(bytes, size), 108 | CRC64::ECMA::calc(bytes, size)); 109 | #ifdef HAS_BOOST 110 | TEST_CHECKSUM( 111 | "boostorg/crc", 112 | boost_calc(bytes, size), 113 | boost_calc(bytes, size), 114 | boost_calc(bytes, size), 115 | boost_calc(bytes, size)); 116 | #endif 117 | TEST_CHECKSUM( 118 | "d-bahr/CRCpp [w/ static table]", 119 | CRC::Calculate(bytes, size, CRC_8_table), 120 | CRC::Calculate(bytes, size, CRC_16_CCITTFALSE_table), 121 | CRC::Calculate(bytes, size, CRC_32_table), 122 | CRC::Calculate(bytes, size, CRC_64_table)); 123 | TEST_CHECKSUM( 124 | "pstolarz/CRaC", 125 | crac::CRC8::calc(bytes, size), 126 | crac::CRC16_CCITT_FALSE::calc(bytes, size), 127 | crac::CRC32::calc(bytes, size), 128 | crac::CRC64_ECMA182::calc(bytes, size)); 129 | TEST_CHECKSUM( 130 | "d-bahr/CRCpp", 131 | CRC::Calculate(bytes, size, CRC::CRC_8()), 132 | CRC::Calculate(bytes, size, CRC::CRC_16_CCITTFALSE()), 133 | CRC::Calculate(bytes, size, CRC::CRC_32()), 134 | CRC::Calculate(bytes, size, CRC::CRC_64())); 135 | 136 | // a separator for the compile time tests 137 | printf( 138 | "|--------------------:|--------------------:" 139 | "|--------:|----------------:|---------------:|--------:" 140 | "|----------:|:--------------------\n"); 141 | 142 | // constexpr data tests: 143 | TEST_CHECKSUM_CONSTEXPR( 144 | "DarrenLevine/cppcrc [w/ constexpr data]", 145 | CRC8::CRC8::calc(bytes_constexpr, size), 146 | CRC16::CCITT_FALSE::calc(bytes_constexpr, size), 147 | CRC32::CRC32::calc(bytes_constexpr, size), 148 | CRC64::ECMA::calc(bytes_constexpr, size)); 149 | TEST_CHECKSUM_CONSTEXPR( 150 | "pstolarz/CRaC [w/ constexpr data]", 151 | crac::CRC8::calc(bytes_constexpr, size), 152 | crac::CRC16_CCITT_FALSE::calc(bytes_constexpr, size), 153 | crac::CRC32::calc(bytes_constexpr, size), 154 | crac::CRC64_ECMA182::calc(bytes_constexpr, size)); 155 | #ifdef HAS_BOOST 156 | TEST_CHECKSUM_CONSTEXPR( 157 | "boostorg/crc [w/ constexpr data]", 158 | boost_calc(bytes_constexpr, size), 159 | boost_calc(bytes_constexpr, size), 160 | boost_calc(bytes_constexpr, size), 161 | boost_calc(bytes_constexpr, size)); 162 | #endif 163 | TEST_CHECKSUM_CONSTEXPR( 164 | "d-bahr/CRCpp [w/ constexpr data]", 165 | CRC::Calculate(bytes_constexpr, size, CRC_8_table), 166 | CRC::Calculate(bytes_constexpr, size, CRC_16_CCITTFALSE_table), 167 | CRC::Calculate(bytes_constexpr, size, CRC_32_table), 168 | CRC::Calculate(bytes_constexpr, size, CRC_64_table)); 169 | } -------------------------------------------------------------------------------- /test/test_cppcrc.cpp: -------------------------------------------------------------------------------- 1 | #include "../cppcrc.h" 2 | #include 3 | 4 | // some helpful literals 5 | inline constexpr uint8_t operator""_u8(unsigned long long val) noexcept { return val; } 6 | inline constexpr uint16_t operator""_u16(unsigned long long val) noexcept { return val; } 7 | inline constexpr uint32_t operator""_u32(unsigned long long val) noexcept { return val; } 8 | inline constexpr uint64_t operator""_u64(unsigned long long val) noexcept { return val; } 9 | 10 | constexpr uint8_t test_sequence[] = { 11 | 0x09, 0x03, 0x5E, 0x57, 0x3F, 0xA7, 0x11, 0xF1, 0xED, 0xF4, 0xEA, 0xE1, 0x33, 0x96, 0x6A, 0x00, 12 | 0x22, 0xE1, 0x93, 0x83, 0xC2, 0x56, 0x07, 0x48, 0x47, 0x80, 0xCD, 0x48, 0x19, 0x38, 0xA2, 0x4C, 13 | 0x4E, 0x81, 0x05, 0xF9, 0xE8, 0x02, 0x0E, 0x5F, 0x16, 0x2D, 0x28, 0x11, 0x45, 0x0E, 0x1C, 0x4F, 14 | 0x84, 0x63, 0x84, 0x1E, 0x2F, 0x28, 0x6E, 0x26, 0x12, 0xBC, 0xC3, 0x82, 0x11, 0x70, 0x18, 0x41}; 15 | 16 | // tests both a single crc calc and a chunked up calculation 17 | #define TEST_CRC(name, expected) \ 18 | static_assert(name::calc( \ 19 | test_sequence, \ 20 | sizeof(test_sequence)) == expected, \ 21 | "validate one pass data sequence"); \ 22 | static_assert(name::calc( \ 23 | test_sequence + 10, \ 24 | sizeof(test_sequence) - 10, \ 25 | name::calc(test_sequence, 10)) == expected, \ 26 | "validate chunked up data"); \ 27 | static_assert(name::null_crc == name::calc(), "matches") 28 | 29 | TEST_CRC(CRC8::CRC8, 0x45_u8); 30 | TEST_CRC(CRC8::CDMA2000, 0x92_u8); 31 | TEST_CRC(CRC8::DARC, 0x19_u8); 32 | TEST_CRC(CRC8::DVB_S2, 0xA7_u8); 33 | TEST_CRC(CRC8::EBU, 0x7C_u8); 34 | TEST_CRC(CRC8::I_CODE, 0x07_u8); 35 | TEST_CRC(CRC8::ITU, 0x10_u8); 36 | TEST_CRC(CRC8::MAXIM, 0xE6_u8); 37 | TEST_CRC(CRC8::ROHC, 0xB6_u8); 38 | TEST_CRC(CRC8::WCDMA, 0x6E_u8); 39 | TEST_CRC(CRC16::ARC, 0xCC8C_u16); 40 | TEST_CRC(CRC16::AUG_CCITT, 0x3AA1_u16); 41 | TEST_CRC(CRC16::BUYPASS, 0x98B1_u16); 42 | TEST_CRC(CRC16::CCITT_FALSE, 0x39CD_u16); 43 | TEST_CRC(CRC16::CDMA2000, 0x935B_u16); 44 | TEST_CRC(CRC16::DDS_110, 0x9689_u16); 45 | TEST_CRC(CRC16::DECT_R, 0x509C_u16); 46 | TEST_CRC(CRC16::DECT_X, 0x509D_u16); 47 | TEST_CRC(CRC16::DNP, 0xB832_u16); 48 | TEST_CRC(CRC16::EN_13757, 0x7B5D_u16); 49 | TEST_CRC(CRC16::GENIBUS, 0xC632_u16); 50 | TEST_CRC(CRC16::KERMIT, 0xDFD2_u16); 51 | TEST_CRC(CRC16::MAXIM, 0x3373_u16); 52 | TEST_CRC(CRC16::MCRF4XX, 0x84B9_u16); 53 | TEST_CRC(CRC16::MODBUS, 0xE3CC_u16); 54 | TEST_CRC(CRC16::RIELLO, 0xCA61_u16); 55 | TEST_CRC(CRC16::T10_DIF, 0x9A7B_u16); 56 | TEST_CRC(CRC16::TELEDISK, 0x3C4F_u16); 57 | TEST_CRC(CRC16::TMS37157, 0x9337_u16); 58 | TEST_CRC(CRC16::USB, 0x1C33_u16); 59 | TEST_CRC(CRC16::X_25, 0x7B46_u16); 60 | TEST_CRC(CRC16::XMODEM, 0xEF17_u16); 61 | TEST_CRC(CRC16::A, 0xB10E_u16); 62 | TEST_CRC(CRC32::CRC32, 0x6B7D6115_u32); 63 | TEST_CRC(CRC32::BZIP2, 0xAB94EA2E_u32); 64 | TEST_CRC(CRC32::JAMCRC, 0x94829EEA_u32); 65 | TEST_CRC(CRC32::MPEG_2, 0x546B15D1_u32); 66 | TEST_CRC(CRC32::POSIX, 0x38ADA47F_u32); 67 | TEST_CRC(CRC32::SATA, 0xB4B8412F_u32); 68 | TEST_CRC(CRC32::XFER, 0xA6CAEBDE_u32); 69 | TEST_CRC(CRC32::C, 0xB64A90F7_u32); 70 | TEST_CRC(CRC32::D, 0xCFACF452_u32); 71 | TEST_CRC(CRC32::Q, 0x7FDF7CA6_u32); 72 | TEST_CRC(CRC64::ECMA, 0x0D408B7A4211A473_u64); 73 | TEST_CRC(CRC64::GO_ISO, 0xAA139955A8E60504_u64); 74 | TEST_CRC(CRC64::WE, 0x4D648712E74F8E08_u64); 75 | TEST_CRC(CRC64::XY, 0x13CEC7423537E08D_u64); 76 | 77 | // testing that a non-matching reflection in/out values still work 78 | static_assert(crc_utils::crc::calc(nullptr, 0) == 0xF54EEE00_u32, "validate"); 79 | static_assert(crc_utils::crc::calc(test_sequence, sizeof(test_sequence)) == 0xEB8C5295_u32, "validate"); 80 | static_assert(crc_utils::crc::calc(nullptr, 0) == 0x007772AF_u32, "validate"); 81 | static_assert(crc_utils::crc::calc(test_sequence, sizeof(test_sequence)) == 0xB6607917_u32, "validate"); 82 | 83 | // testing that null buffers returns bit reversed init value 84 | static_assert(crc_utils::crc::calc(nullptr, 0) == 0xfd_u8, "validate"); 85 | 86 | static_assert(CRC8::CRC8::calc(nullptr, 0) == 0x00_u8, "validate"); 87 | static_assert(CRC8::CDMA2000::calc(nullptr, 0) == 0xFF_u8, "validate"); 88 | static_assert(CRC8::DARC::calc(nullptr, 0) == 0x00_u8, "validate"); 89 | static_assert(CRC8::DVB_S2::calc(nullptr, 0) == 0x00_u8, "validate"); 90 | static_assert(CRC8::EBU::calc(nullptr, 0) == 0xFF_u8, "validate"); 91 | static_assert(CRC8::I_CODE::calc(nullptr, 0) == 0xFD_u8, "validate"); 92 | static_assert(CRC8::ITU::calc(nullptr, 0) == 0x55_u8, "validate"); 93 | static_assert(CRC8::MAXIM::calc(nullptr, 0) == 0x00_u8, "validate"); 94 | static_assert(CRC8::ROHC::calc(nullptr, 0) == 0xFF_u8, "validate"); 95 | static_assert(CRC8::WCDMA::calc(nullptr, 0) == 0x00_u8, "validate"); 96 | static_assert(CRC16::ARC::calc(nullptr, 0) == 0x0000_u16, "validate"); 97 | static_assert(CRC16::AUG_CCITT::calc(nullptr, 0) == 0x1D0F_u16, "validate"); 98 | static_assert(CRC16::BUYPASS::calc(nullptr, 0) == 0x0000_u16, "validate"); 99 | static_assert(CRC16::CCITT_FALSE::calc(nullptr, 0) == 0xFFFF_u16, "validate"); 100 | static_assert(CRC16::CDMA2000::calc(nullptr, 0) == 0xFFFF_u16, "validate"); 101 | static_assert(CRC16::DDS_110::calc(nullptr, 0) == 0x800D_u16, "validate"); 102 | static_assert(CRC16::DECT_R::calc(nullptr, 0) == 0x0001_u16, "validate"); 103 | static_assert(CRC16::DECT_X::calc(nullptr, 0) == 0x0000_u16, "validate"); 104 | static_assert(CRC16::DNP::calc(nullptr, 0) == 0xFFFF_u16, "validate"); 105 | static_assert(CRC16::EN_13757::calc(nullptr, 0) == 0xFFFF_u16, "validate"); 106 | static_assert(CRC16::GENIBUS::calc(nullptr, 0) == 0x0000_u16, "validate"); 107 | static_assert(CRC16::KERMIT::calc(nullptr, 0) == 0x0000_u16, "validate"); 108 | static_assert(CRC16::MAXIM::calc(nullptr, 0) == 0xFFFF_u16, "validate"); 109 | static_assert(CRC16::MCRF4XX::calc(nullptr, 0) == 0xFFFF_u16, "validate"); 110 | static_assert(CRC16::MODBUS::calc(nullptr, 0) == 0xFFFF_u16, "validate"); 111 | static_assert(CRC16::RIELLO::calc(nullptr, 0) == 0x554D_u16, "validate"); 112 | static_assert(CRC16::T10_DIF::calc(nullptr, 0) == 0x0000_u16, "validate"); 113 | static_assert(CRC16::TELEDISK::calc(nullptr, 0) == 0x0000_u16, "validate"); 114 | static_assert(CRC16::TMS37157::calc(nullptr, 0) == 0x3791_u16, "validate"); 115 | static_assert(CRC16::USB::calc(nullptr, 0) == 0x0000_u16, "validate"); 116 | static_assert(CRC16::X_25::calc(nullptr, 0) == 0x0000_u16, "validate"); 117 | static_assert(CRC16::XMODEM::calc(nullptr, 0) == 0x0000_u16, "validate"); 118 | static_assert(CRC16::A::calc(nullptr, 0) == 0x6363_u16, "validate"); 119 | static_assert(CRC32::CRC32::calc(nullptr, 0) == 0x00000000_u32, "validate"); 120 | static_assert(CRC32::BZIP2::calc(nullptr, 0) == 0x00000000_u32, "validate"); 121 | static_assert(CRC32::JAMCRC::calc(nullptr, 0) == 0xFFFFFFFF_u32, "validate"); 122 | static_assert(CRC32::MPEG_2::calc(nullptr, 0) == 0xFFFFFFFF_u32, "validate"); 123 | static_assert(CRC32::POSIX::calc(nullptr, 0) == 0xFFFFFFFF_u32, "validate"); 124 | static_assert(CRC32::SATA::calc(nullptr, 0) == 0x52325032_u32, "validate"); 125 | static_assert(CRC32::XFER::calc(nullptr, 0) == 0x00000000_u32, "validate"); 126 | static_assert(CRC32::C::calc(nullptr, 0) == 0x00000000_u32, "validate"); 127 | static_assert(CRC32::D::calc(nullptr, 0) == 0x00000000_u32, "validate"); 128 | static_assert(CRC32::Q::calc(nullptr, 0) == 0x00000000_u32, "validate"); 129 | static_assert(CRC64::ECMA::calc(nullptr, 0) == 0x0000000000000000_u64, "validate"); 130 | static_assert(CRC64::GO_ISO::calc(nullptr, 0) == 0x0000000000000000_u64, "validate"); 131 | static_assert(CRC64::WE::calc(nullptr, 0) == 0x0000000000000000_u64, "validate"); 132 | static_assert(CRC64::XY::calc(nullptr, 0) == 0x0000000000000000_u64, "validate"); 133 | 134 | constexpr uint8_t test_sequence2[] = {0xff, 0x01}; 135 | static_assert(crc_utils::crc::calc(test_sequence2, 2) == 0x2A_u8, "validate"); 136 | 137 | constexpr uint8_t test_sequence3[] = {0x01}; 138 | static_assert(crc_utils::crc::calc(test_sequence3, 1) == 0xE0_u8, "validate"); 139 | 140 | // algorithms without output reflection x-ors should have the same init and null crc 141 | static_assert(CRC16::CCITT_FALSE::calc() == CRC16::CCITT_FALSE::init); 142 | static_assert(CRC16::CCITT_FALSE::calc() == CRC16::CCITT_FALSE::null_crc); 143 | 144 | // algorithms with output reflection x-ors should NOT have the same init and null crc 145 | static_assert(CRC32::CRC32::calc() != CRC32::CRC32::init); 146 | static_assert(CRC32::CRC32::calc() == CRC32::CRC32::null_crc); 147 | 148 | int main() 149 | { 150 | constexpr uint8_t data[] = {0x12, 0x5A, 0x23, 0x19, 0x92, 0xF3, 0xDE, 0xC2, 0x5A, 0x1F, 0x91, 0xA3}; 151 | constexpr uint8_t crc_val = CRC8::CRC8::calc(data, 12); 152 | static_assert(crc_val == 0x71); 153 | 154 | auto &crc_table = CRC8::CRC8::table(); 155 | static_assert(crc_table[0] == 0x00); 156 | static_assert(crc_table[1] == 0x07); 157 | 158 | printf("PASSED! (all the tests run at compile time)\n"); 159 | } -------------------------------------------------------------------------------- /cppcrc.h: -------------------------------------------------------------------------------- 1 | /// @file cppcrc.h 2 | /// @author Darren V Levine (DarrenVLevine@gmail.com) 3 | /// @brief A very small, fast, header-only, C++ library for generating CRCs 4 | /// @version 1.3 5 | /// @date 2022-11-17 6 | /// 7 | /// @copyright (c) 2022 Darren V Levine. This code is licensed under MIT license (see LICENSE file for details). 8 | 9 | #ifndef CPPCRC_H_ 10 | #define CPPCRC_H_ 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | // 17 | // Backend implementation: 18 | // 19 | 20 | namespace crc_utils 21 | { 22 | inline constexpr uint8_t reverse_bits(uint8_t x) 23 | { 24 | constexpr uint8_t lookup[16] = {0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe, 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf}; 25 | return (lookup[x & 0x0F] << 4) | lookup[x >> 4]; 26 | } 27 | inline constexpr uint16_t reverse_bits(uint16_t x) 28 | { 29 | return uint16_t(reverse_bits(uint8_t(x))) << 8 | uint16_t(reverse_bits(uint8_t(x >> 8))); 30 | } 31 | inline constexpr uint32_t reverse_bits(uint32_t x) 32 | { 33 | return uint32_t(reverse_bits(uint16_t(x))) << 16 | uint32_t(reverse_bits(uint16_t(x >> 16))); 34 | } 35 | inline constexpr uint64_t reverse_bits(uint64_t x) 36 | { 37 | return uint64_t(reverse_bits(uint32_t(x))) << 32 | uint64_t(reverse_bits(uint32_t(x >> 32))); 38 | } 39 | template 40 | constexpr out_t get_crc_table_value_at_index() 41 | { 42 | constexpr size_t bit_width = sizeof(out_t) * 8; 43 | out_t remainder = refl_in ? reverse_bits(static_cast(index)) >> (bit_width - 8u) : static_cast(index); 44 | constexpr out_t mask = static_cast(1) << (bit_width - 1u); 45 | for (size_t i = 0; i < bit_width; i++) 46 | { 47 | if (remainder & mask) 48 | remainder = (remainder << 1) ^ poly; 49 | else 50 | remainder <<= 1; 51 | } 52 | return refl_in ? reverse_bits(remainder) : remainder; 53 | } 54 | 55 | template > 56 | struct crc_lookup_table; 57 | 58 | template 59 | struct crc_lookup_table> 60 | { 61 | static constexpr out_t value[size] = {get_crc_table_value_at_index()...}; 62 | }; 63 | 64 | #if ((defined(_MSVC_LANG) && _MSVC_LANG < 201703L) || (defined(__cplusplus) && __cplusplus < 201703L)) // redeclaration is only needed before C++17 65 | template 66 | constexpr out_t crc_lookup_table>::value[size]; 67 | #endif 68 | 69 | template ::type = nullptr> 70 | constexpr out_t calculate_crc(const uint8_t *bytes, size_t n, out_t crc) 71 | { 72 | constexpr auto &lookup = crc_lookup_table().value; 73 | crc = reverse_bits(crc); 74 | while (n--) 75 | crc = lookup[static_cast(*bytes++ ^ crc)] ^ (crc >> 8); 76 | return (refl_out != refl_in ? reverse_bits(crc) : crc) ^ x_or_out; // needed since the reflections are baked into the table for speed 77 | } 78 | 79 | template ::type = nullptr> 80 | constexpr out_t calculate_crc(const uint8_t *bytes, size_t n, out_t crc) 81 | { 82 | constexpr auto &lookup = crc_lookup_table().value; 83 | constexpr size_t bit_width_minus_8 = sizeof(out_t) * 8 - 8U; 84 | while (n--) 85 | crc = lookup[static_cast(*bytes++ ^ (crc >> bit_width_minus_8))] ^ (crc << 8); 86 | return (refl_out ? reverse_bits(crc) : crc) ^ x_or_out; 87 | } 88 | 89 | template 90 | struct crc 91 | { 92 | using type = out_t; // base type of the crc algorithm 93 | static constexpr out_t poly = poly_arg; // polynomial of the crc algorithm 94 | static constexpr out_t init = init_arg; // initial CRC internal state, WARNING: may be different from "null_crc" 95 | static constexpr bool refl_in = refl_in_arg; // true if the bits of the crc should be reflected/reversed on input 96 | static constexpr bool refl_out = refl_out_arg; // true if the bits of the crc should be reflected/reversed on output 97 | static constexpr out_t x_or_out = x_or_out_arg; // the value to X-OR the output with 98 | static constexpr out_t null_crc = (refl_out ? reverse_bits(init) : init) ^ x_or_out; // CRC value of no/null data 99 | 100 | /// @brief Calculate the checksum of some bytes, or continue an existing calculation by passing in the prior crc value 101 | static constexpr out_t calc(const uint8_t *bytes = nullptr, size_t num_bytes = 0u, out_t prior_crc_value = null_crc) 102 | { 103 | prior_crc_value = x_or_out ? prior_crc_value ^ x_or_out : prior_crc_value; 104 | prior_crc_value = refl_out ? reverse_bits(prior_crc_value) : prior_crc_value; 105 | return calculate_crc(bytes, num_bytes, prior_crc_value); 106 | } 107 | /// @brief the underlying pre-computed CRC table used for fast lookup-table-based calculations 108 | static constexpr auto &table() 109 | { 110 | return crc_lookup_table().value; 111 | } 112 | }; 113 | } // namespace crc_utils 114 | 115 | // 116 | // Default CRC Configurations: 117 | // 118 | 119 | namespace CRC8 120 | { 121 | using CRC8 = crc_utils::crc; 122 | using CDMA2000 = crc_utils::crc; 123 | using DARC = crc_utils::crc; 124 | using DVB_S2 = crc_utils::crc; 125 | using EBU = crc_utils::crc; 126 | using I_CODE = crc_utils::crc; 127 | using ITU = crc_utils::crc; 128 | using MAXIM = crc_utils::crc; 129 | using ROHC = crc_utils::crc; 130 | using WCDMA = crc_utils::crc; 131 | } // namespace CRC8 132 | namespace CRC16 133 | { 134 | using ARC = crc_utils::crc; 135 | using AUG_CCITT = crc_utils::crc; 136 | using BUYPASS = crc_utils::crc; 137 | using CCITT_FALSE = crc_utils::crc; 138 | using CDMA2000 = crc_utils::crc; 139 | using DDS_110 = crc_utils::crc; 140 | using DECT_R = crc_utils::crc; 141 | using DECT_X = crc_utils::crc; 142 | using DNP = crc_utils::crc; 143 | using EN_13757 = crc_utils::crc; 144 | using GENIBUS = crc_utils::crc; 145 | using KERMIT = crc_utils::crc; 146 | using MAXIM = crc_utils::crc; 147 | using MCRF4XX = crc_utils::crc; 148 | using MODBUS = crc_utils::crc; 149 | using RIELLO = crc_utils::crc; 150 | using T10_DIF = crc_utils::crc; 151 | using TELEDISK = crc_utils::crc; 152 | using TMS37157 = crc_utils::crc; 153 | using USB = crc_utils::crc; 154 | using X_25 = crc_utils::crc; 155 | using XMODEM = crc_utils::crc; 156 | using A = crc_utils::crc; 157 | } // namespace CRC16 158 | namespace CRC32 159 | { 160 | using CRC32 = crc_utils::crc; 161 | using BZIP2 = crc_utils::crc; 162 | using JAMCRC = crc_utils::crc; 163 | using MPEG_2 = crc_utils::crc; 164 | using POSIX = crc_utils::crc; 165 | using SATA = crc_utils::crc; 166 | using XFER = crc_utils::crc; 167 | using C = crc_utils::crc; 168 | using D = crc_utils::crc; 169 | using Q = crc_utils::crc; 170 | } // namespace CRC32 171 | namespace CRC64 172 | { 173 | using ECMA = crc_utils::crc; 174 | using GO_ISO = crc_utils::crc; 175 | using WE = crc_utils::crc; 176 | using XY = crc_utils::crc; 177 | } // namespace CRC64 178 | 179 | #endif // CPPCRC_H_ --------------------------------------------------------------------------------