diff --git a/dependencies/CRCpp/CRC.h b/dependencies/CRCpp/CRC.h index 8bab176a..f737cc45 100644 --- a/dependencies/CRCpp/CRC.h +++ b/dependencies/CRCpp/CRC.h @@ -1,11 +1,11 @@ /** @file CRC.h @author Daniel Bahr - @version 1.0.1.0 + @version 1.2.0.0 @copyright @parblock CRC++ - Copyright (c) 2020, Daniel Bahr + Copyright (c) 2022, Daniel Bahr All rights reserved. Redistribution and use in source and binary forms, with or without @@ -47,19 +47,20 @@ #define crcpp_uint64 - Specifies the type used to store CRCs that have a width between 33 and 64 bits (inclusive). This type is not used in CRC calculations. Defaults to ::std::uint64_t. #define crcpp_size - This type is used for loop iteration and function signatures only. Defaults to ::std::size_t. - */ #define CRCPP_USE_NAMESPACE - Define to place all CRC++ code within the ::CRCPP namespace. - /* #define CRCPP_BRANCHLESS - Define to enable a branchless CRC implementation. The branchless implementation uses a single integer multiplication in the bit-by-bit calculation instead of a small conditional. The branchless implementation may be faster on processor architectures which support single-instruction integer multiplication. #define CRCPP_USE_CPP11 - Define to enables C++11 features (move semantics, constexpr, static_assert, etc.). - #define CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS - Define to include definitions for little-used CRCs. + #define CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS - Define to include definitions for little-used CRCs. */ #ifndef CRCPP_CRC_H_ #define CRCPP_CRC_H_ +/* OpenRGB: We define our configuration macros here. */ +#define CRCPP_USE_NAMESPACE + #include // Includes CHAR_BIT #ifdef CRCPP_USE_CPP11 #include // Includes ::std::size_t @@ -204,6 +205,18 @@ public: template static CRCType Calculate(const void * data, crcpp_size size, const Table & lookupTable, CRCType crc); + template + static CRCType CalculateBits(const void * data, crcpp_size size, const Parameters & parameters); + + template + static CRCType CalculateBits(const void * data, crcpp_size size, const Parameters & parameters, CRCType crc); + + template + static CRCType CalculateBits(const void * data, crcpp_size size, const Table & lookupTable); + + template + static CRCType CalculateBits(const void * data, crcpp_size size, const Table & lookupTable, CRCType crc); + // Common CRCs up to 64 bits. // Note: Check values are the computed CRCs when given an ASCII input of "123456789" (without null terminator) #ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS @@ -214,6 +227,7 @@ public: static const Parameters< crcpp_uint8, 6> & CRC_6_CDMA2000A(); static const Parameters< crcpp_uint8, 6> & CRC_6_CDMA2000B(); static const Parameters< crcpp_uint8, 6> & CRC_6_ITU(); + static const Parameters< crcpp_uint8, 6> & CRC_6_NR(); static const Parameters< crcpp_uint8, 7> & CRC_7(); #endif static const Parameters< crcpp_uint8, 8> & CRC_8(); @@ -221,9 +235,11 @@ public: static const Parameters< crcpp_uint8, 8> & CRC_8_EBU(); static const Parameters< crcpp_uint8, 8> & CRC_8_MAXIM(); static const Parameters< crcpp_uint8, 8> & CRC_8_WCDMA(); + static const Parameters< crcpp_uint8, 8> & CRC_8_LTE(); static const Parameters & CRC_10(); static const Parameters & CRC_10_CDMA2000(); static const Parameters & CRC_11(); + static const Parameters & CRC_11_NR(); static const Parameters & CRC_12_CDMA2000(); static const Parameters & CRC_12_DECT(); static const Parameters & CRC_12_UMTS(); @@ -234,6 +250,7 @@ public: static const Parameters & CRC_16_ARC(); static const Parameters & CRC_16_BUYPASS(); static const Parameters & CRC_16_CCITTFALSE(); + static const Parameters & CRC_16_MCRF4XX(); #ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS static const Parameters & CRC_16_CDMA2000(); static const Parameters & CRC_16_CMS(); @@ -257,6 +274,9 @@ public: static const Parameters & CRC_24(); static const Parameters & CRC_24_FLEXRAYA(); static const Parameters & CRC_24_FLEXRAYB(); + static const Parameters & CRC_24_LTEA(); + static const Parameters & CRC_24_LTEB(); + static const Parameters & CRC_24_NRC(); static const Parameters & CRC_30(); #endif static const Parameters & CRC_32(); @@ -301,6 +321,9 @@ private: template static CRCType CalculateRemainder(const void * data, crcpp_size size, const Table & lookupTable, CRCType remainder); + + template + static CRCType CalculateRemainderBits(unsigned char byte, crcpp_size numBits, const Parameters & parameters, CRCType remainder); }; /** @@ -426,7 +449,7 @@ inline void CRC::Table::InitTable() /** @brief Computes a CRC. @param[in] data Data over which CRC will be computed - @param[in] size Size of the data + @param[in] size Size of the data, in bytes @param[in] parameters CRC parameters @tparam CRCType Integer type for storing the CRC result @tparam CRCWidth Number of bits in the CRC @@ -445,7 +468,7 @@ inline CRCType CRC::Calculate(const void * data, crcpp_size size, const Paramete @brief Appends additional data to a previous CRC calculation. @note This function can be used to compute multi-part CRCs. @param[in] data Data over which CRC will be computed - @param[in] size Size of the data + @param[in] size Size of the data, in bytes @param[in] parameters CRC parameters @param[in] crc CRC from a previous calculation @tparam CRCType Integer type for storing the CRC result @@ -467,7 +490,7 @@ inline CRCType CRC::Calculate(const void * data, crcpp_size size, const Paramete /** @brief Computes a CRC via a lookup table. @param[in] data Data over which CRC will be computed - @param[in] size Size of the data + @param[in] size Size of the data, in bytes @param[in] lookupTable CRC lookup table @tparam CRCType Integer type for storing the CRC result @tparam CRCWidth Number of bits in the CRC @@ -489,7 +512,7 @@ inline CRCType CRC::Calculate(const void * data, crcpp_size size, const Table(remainder, parameters.finalXOR, parameters.reflectInput != parameters.reflectOutput); } +/** + @brief Computes a CRC. + @param[in] data Data over which CRC will be computed + @param[in] size Size of the data, in bits + @param[in] parameters CRC parameters + @tparam CRCType Integer type for storing the CRC result + @tparam CRCWidth Number of bits in the CRC + @return CRC +*/ +template +inline CRCType CRC::CalculateBits(const void * data, crcpp_size size, const Parameters & parameters) +{ + CRCType remainder = parameters.initialValue; + + // Calculate the remainder on a whole number of bytes first, then call + // a special-case function for the remaining bits. + crcpp_size wholeNumberOfBytes = size / CHAR_BIT; + if (wholeNumberOfBytes > 0) + { + remainder = CalculateRemainder(data, wholeNumberOfBytes, parameters, remainder); + } + + crcpp_size remainingNumberOfBits = size % CHAR_BIT; + if (remainingNumberOfBits != 0) + { + unsigned char lastByte = *(reinterpret_cast(data) + wholeNumberOfBytes); + remainder = CalculateRemainderBits(lastByte, remainingNumberOfBits, parameters, remainder); + } + + // No need to mask the remainder here; the mask will be applied in the Finalize() function. + + return Finalize(remainder, parameters.finalXOR, parameters.reflectInput != parameters.reflectOutput); +} +/** + @brief Appends additional data to a previous CRC calculation. + @note This function can be used to compute multi-part CRCs. + @param[in] data Data over which CRC will be computed + @param[in] size Size of the data, in bits + @param[in] parameters CRC parameters + @param[in] crc CRC from a previous calculation + @tparam CRCType Integer type for storing the CRC result + @tparam CRCWidth Number of bits in the CRC + @return CRC +*/ +template +inline CRCType CRC::CalculateBits(const void * data, crcpp_size size, const Parameters & parameters, CRCType crc) +{ + CRCType remainder = UndoFinalize(crc, parameters.finalXOR, parameters.reflectInput != parameters.reflectOutput); + + // Calculate the remainder on a whole number of bytes first, then call + // a special-case function for the remaining bits. + crcpp_size wholeNumberOfBytes = size / CHAR_BIT; + if (wholeNumberOfBytes > 0) + { + remainder = CalculateRemainder(data, wholeNumberOfBytes, parameters, parameters.initialValue); + } + + crcpp_size remainingNumberOfBits = size % CHAR_BIT; + if (remainingNumberOfBits != 0) + { + unsigned char lastByte = *(reinterpret_cast(data) + wholeNumberOfBytes); + remainder = CalculateRemainderBits(lastByte, remainingNumberOfBits, parameters, remainder); + } + + // No need to mask the remainder here; the mask will be applied in the Finalize() function. + + return Finalize(remainder, parameters.finalXOR, parameters.reflectInput != parameters.reflectOutput); +} + +/** + @brief Computes a CRC via a lookup table. + @param[in] data Data over which CRC will be computed + @param[in] size Size of the data, in bits + @param[in] lookupTable CRC lookup table + @tparam CRCType Integer type for storing the CRC result + @tparam CRCWidth Number of bits in the CRC + @return CRC +*/ +template +inline CRCType CRC::CalculateBits(const void * data, crcpp_size size, const Table & lookupTable) +{ + const Parameters & parameters = lookupTable.GetParameters(); + + CRCType remainder = parameters.initialValue; + + // Calculate the remainder on a whole number of bytes first, then call + // a special-case function for the remaining bits. + crcpp_size wholeNumberOfBytes = size / CHAR_BIT; + if (wholeNumberOfBytes > 0) + { + remainder = CalculateRemainder(data, wholeNumberOfBytes, lookupTable, remainder); + } + + crcpp_size remainingNumberOfBits = size % CHAR_BIT; + if (remainingNumberOfBits != 0) + { + unsigned char lastByte = *(reinterpret_cast(data) + wholeNumberOfBytes); + remainder = CalculateRemainderBits(lastByte, remainingNumberOfBits, parameters, remainder); + } + + // No need to mask the remainder here; the mask will be applied in the Finalize() function. + + return Finalize(remainder, parameters.finalXOR, parameters.reflectInput != parameters.reflectOutput); +} + +/** + @brief Appends additional data to a previous CRC calculation using a lookup table. + @note This function can be used to compute multi-part CRCs. + @param[in] data Data over which CRC will be computed + @param[in] size Size of the data, in bits + @param[in] lookupTable CRC lookup table + @param[in] crc CRC from a previous calculation + @tparam CRCType Integer type for storing the CRC result + @tparam CRCWidth Number of bits in the CRC + @return CRC +*/ +template +inline CRCType CRC::CalculateBits(const void * data, crcpp_size size, const Table & lookupTable, CRCType crc) +{ + const Parameters & parameters = lookupTable.GetParameters(); + + CRCType remainder = UndoFinalize(crc, parameters.finalXOR, parameters.reflectInput != parameters.reflectOutput); + + // Calculate the remainder on a whole number of bytes first, then call + // a special-case function for the remaining bits. + crcpp_size wholeNumberOfBytes = size / CHAR_BIT; + if (wholeNumberOfBytes > 0) + { + remainder = CalculateRemainder(data, wholeNumberOfBytes, lookupTable, parameters.initialValue); + } + + crcpp_size remainingNumberOfBits = size % CHAR_BIT; + if (remainingNumberOfBits > 0) + { + unsigned char lastByte = *(reinterpret_cast(data) + wholeNumberOfBytes); + remainder = CalculateRemainderBits(lastByte, remainingNumberOfBits, parameters, remainder); + } + + // No need to mask the remainder here; the mask will be applied in the Finalize() function. + + return Finalize(remainder, parameters.finalXOR, parameters.reflectInput != parameters.reflectOutput); +} + /** @brief Reflects (i.e. reverses the bits within) an integer value. @param[in] value Value to reflect @@ -592,7 +758,7 @@ inline CRCType CRC::UndoFinalize(CRCType crc, CRCType finalXOR, bool reflectOutp /** @brief Computes a CRC remainder. @param[in] data Data over which the remainder will be computed - @param[in] size Size of the data + @param[in] size Size of the data, in bytes @param[in] parameters CRC parameters @param[in] remainder Running CRC remainder. Can be an initial value or the result of a previous CRC remainder calculation. @tparam CRCType Integer type for storing the CRC result @@ -709,7 +875,7 @@ inline CRCType CRC::CalculateRemainder(const void * data, crcpp_size size, const /** @brief Computes a CRC remainder using lookup table. @param[in] data Data over which the remainder will be computed - @param[in] size Size of the data + @param[in] size Size of the data, in bytes @param[in] lookupTable CRC lookup table @param[in] remainder Running CRC remainder. Can be an initial value or the result of a previous CRC remainder calculation. @tparam CRCType Integer type for storing the CRC result @@ -767,6 +933,90 @@ inline CRCType CRC::CalculateRemainder(const void * data, crcpp_size size, const return remainder; } +template +inline CRCType CRC::CalculateRemainderBits(unsigned char byte, crcpp_size numBits, const Parameters & parameters, CRCType remainder) +{ + // Slightly different implementations based on the parameters. The current implementations try to eliminate as much + // computation from the inner loop (looping over each bit) as possible. + if (parameters.reflectInput) + { + CRCType polynomial = CRC::Reflect(parameters.polynomial, CRCWidth); + remainder = static_cast(remainder ^ byte); + + // An optimizing compiler might choose to unroll this loop. + for (crcpp_size i = 0; i < numBits; ++i) + { +#ifdef CRCPP_BRANCHLESS + // Clever way to avoid a branch at the expense of a multiplication. This code is equivalent to the following: + // if (remainder & 1) + // remainder = (remainder >> 1) ^ polynomial; + // else + // remainder >>= 1; + remainder = static_cast((remainder >> 1) ^ ((remainder & 1) * polynomial)); +#else + remainder = static_cast((remainder & 1) ? ((remainder >> 1) ^ polynomial) : (remainder >> 1)); +#endif + } + } + else if (CRCWidth >= CHAR_BIT) + { + static crcpp_constexpr CRCType CRC_WIDTH_MINUS_ONE(CRCWidth - CRCType(1)); +#ifndef CRCPP_BRANCHLESS + static crcpp_constexpr CRCType CRC_HIGHEST_BIT_MASK(CRCType(1) << CRC_WIDTH_MINUS_ONE); +#endif + // The conditional expression is used to avoid a -Wshift-count-overflow warning. + static crcpp_constexpr CRCType SHIFT((CRCWidth >= CHAR_BIT) ? static_cast(CRCWidth - CHAR_BIT) : 0); + + remainder = static_cast(remainder ^ (static_cast(byte) << SHIFT)); + + // An optimizing compiler might choose to unroll this loop. + for (crcpp_size i = 0; i < numBits; ++i) + { +#ifdef CRCPP_BRANCHLESS + // Clever way to avoid a branch at the expense of a multiplication. This code is equivalent to the following: + // if (remainder & CRC_HIGHEST_BIT_MASK) + // remainder = (remainder << 1) ^ parameters.polynomial; + // else + // remainder <<= 1; + remainder = static_cast((remainder << 1) ^ (((remainder >> CRC_WIDTH_MINUS_ONE) & 1) * parameters.polynomial)); +#else + remainder = static_cast((remainder & CRC_HIGHEST_BIT_MASK) ? ((remainder << 1) ^ parameters.polynomial) : (remainder << 1)); +#endif + } + } + else + { + static crcpp_constexpr CRCType CHAR_BIT_MINUS_ONE(CHAR_BIT - 1); +#ifndef CRCPP_BRANCHLESS + static crcpp_constexpr CRCType CHAR_BIT_HIGHEST_BIT_MASK(CRCType(1) << CHAR_BIT_MINUS_ONE); +#endif + // The conditional expression is used to avoid a -Wshift-count-overflow warning. + static crcpp_constexpr CRCType SHIFT((CHAR_BIT >= CRCWidth) ? static_cast(CHAR_BIT - CRCWidth) : 0); + + CRCType polynomial = static_cast(parameters.polynomial << SHIFT); + remainder = static_cast((remainder << SHIFT) ^ byte); + + // An optimizing compiler might choose to unroll this loop. + for (crcpp_size i = 0; i < numBits; ++i) + { +#ifdef CRCPP_BRANCHLESS + // Clever way to avoid a branch at the expense of a multiplication. This code is equivalent to the following: + // if (remainder & CHAR_BIT_HIGHEST_BIT_MASK) + // remainder = (remainder << 1) ^ polynomial; + // else + // remainder <<= 1; + remainder = static_cast((remainder << 1) ^ (((remainder >> CHAR_BIT_MINUS_ONE) & 1) * polynomial)); +#else + remainder = static_cast((remainder & CHAR_BIT_HIGHEST_BIT_MASK) ? ((remainder << 1) ^ polynomial) : (remainder << 1)); +#endif + } + + remainder = static_cast(remainder >> SHIFT); + } + + return remainder; +} + #ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS /** @brief Returns a set of parameters for CRC-4 ITU. @@ -894,6 +1144,25 @@ inline const CRC::Parameters & CRC::CRC_6_ITU() return parameters; } +/** + @brief Returns a set of parameters for CRC-6 NR. + @note The parameters are static and are delayed-constructed to reduce memory + footprint. + @note CRC-6 NR has the following parameters and check value: + - polynomial = 0x21 + - initial value = 0x00 + - final XOR = 0x00 + - reflect input = false + - reflect output = false + - check value = 0x15 + @return CRC-6 NR parameters +*/ +inline const CRC::Parameters & CRC::CRC_6_NR() +{ + static const Parameters parameters = { 0x21, 0x00, 0x00, false, false }; + return parameters; +} + /** @brief Returns a set of parameters for CRC-7 JEDEC. @note The parameters are static and are delayed-constructed to reduce memory footprint. @@ -986,6 +1255,24 @@ inline const CRC::Parameters & CRC::CRC_8_WCDMA() return parameters; } +/** + @brief Returns a set of parameters for CRC-8 LTE. + @note The parameters are static and are delayed-constructed to reduce memory footprint. + @note CRC-8 LTE has the following parameters and check value: + - polynomial = 0x9B + - initial value = 0x00 + - final XOR = 0x00 + - reflect input = false + - reflect output = false + - check value = 0xEA + @return CRC-8 LTE parameters +*/ +inline const CRC::Parameters & CRC::CRC_8_LTE() +{ + static const Parameters parameters = { 0x9B, 0x00, 0x00, false, false }; + return parameters; +} + /** @brief Returns a set of parameters for CRC-10 ITU. @note The parameters are static and are delayed-constructed to reduce memory footprint. @@ -1040,6 +1327,25 @@ inline const CRC::Parameters & CRC::CRC_11() return parameters; } +/** + @brief Returns a set of parameters for CRC-11 NR. + @note The parameters are static and are delayed-constructed to reduce memory + footprint. + @note CRC-11 NR has the following parameters and check value: + - polynomial = 0x621 + - initial value = 0x000 + - final XOR = 0x000 + - reflect input = false + - reflect output = false + - check value = 0x5CA + @return CRC-11 NR parameters +*/ +inline const CRC::Parameters & CRC::CRC_11_NR() +{ + static const Parameters parameters = { 0x621, 0x000, 0x000, false, false }; + return parameters; +} + /** @brief Returns a set of parameters for CRC-12 CDMA2000. @note The parameters are static and are delayed-constructed to reduce memory footprint. @@ -1203,6 +1509,24 @@ inline const CRC::Parameters & CRC::CRC_16_CCITTFALSE() return parameters; } +/** + @brief Returns a set of parameters for CRC-16 MCRF4XX. + @note The parameters are static and are delayed-constructed to reduce memory footprint. + @note CRC-16 MCRF4XX has the following parameters and check value: + - polynomial = 0x1021 + - initial value = 0xFFFF + - final XOR = 0x0000 + - reflect input = true + - reflect output = true + - check value = 0x6F91 + @return CRC-16 MCRF4XX parameters +*/ +inline const CRC::Parameters & CRC::CRC_16_MCRF4XX() +{ + static const Parameters parameters = { 0x1021, 0xFFFF, 0x0000, true, true}; + return parameters; +} + #ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS /** @brief Returns a set of parameters for CRC-16 CDMA2000. @@ -1533,6 +1857,63 @@ inline const CRC::Parameters & CRC::CRC_24_FLEXRAYB() return parameters; } +/** + @brief Returns a set of parameters for CRC-24 LTE-A/NR-A. + @note The parameters are static and are delayed-constructed to reduce memory + footprint. + @note CRC-24 LTE-A has the following parameters and check value: + - polynomial = 0x864CFB + - initial value = 0x000000 + - final XOR = 0x000000 + - reflect input = false + - reflect output = false + - check value = 0xCDE703 + @return CRC-24 LTE-A parameters +*/ +inline const CRC::Parameters & CRC::CRC_24_LTEA() +{ + static const Parameters parameters = { 0x864CFB, 0x000000, 0x000000, false, false }; + return parameters; +} + +/** + @brief Returns a set of parameters for CRC-24 LTE-B/NR-B. + @note The parameters are static and are delayed-constructed to reduce memory + footprint. + @note CRC-24 LTE-B has the following parameters and check value: + - polynomial = 0x800063 + - initial value = 0x000000 + - final XOR = 0x000000 + - reflect input = false + - reflect output = false + - check value = 0x23EF52 + @return CRC-24 LTE-B parameters +*/ +inline const CRC::Parameters & CRC::CRC_24_LTEB() +{ + static const Parameters parameters = { 0x800063, 0x000000, 0x000000, false, false }; + return parameters; +} + +/** + @brief Returns a set of parameters for CRC-24 NR-C. + @note The parameters are static and are delayed-constructed to reduce memory + footprint. + @note CRC-24 NR-C has the following parameters and check value: + - polynomial = 0xB2B117 + - initial value = 0x000000 + - final XOR = 0x000000 + - reflect input = false + - reflect output = false + - check value = 0xF48279 + @return CRC-24 NR-C parameters +*/ +inline const CRC::Parameters & CRC::CRC_24_NRC() +{ + static const Parameters parameters = { 0xB2B117, 0x000000, 0x000000, false, false }; + return parameters; +} + /** @brief Returns a set of parameters for CRC-30 CDMA. @note The parameters are static and are delayed-constructed to reduce memory footprint.