From ab7edf7f9f0e95d9975dd8ae6032c1fb36bb9268 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Igor=20Mi=C5=A1i=C4=87?= Date: Mon, 25 Sep 2023 21:28:34 +0200 Subject: [PATCH] crc32: update variants to be capable of calculation from data in chunks --- Inc/crc/crc32_variants/crc32.h | 10 +- Inc/crc/crc32_variants/crc32_bzip2.h | 10 +- Inc/crc/crc32_variants/crc32_c.h | 10 +- Inc/crc/crc32_variants/crc32_d.h | 10 +- Inc/crc/crc32_variants/crc32_jamcrc.h | 6 +- Inc/crc/crc32_variants/crc32_mpeg2.h | 4 +- Inc/crc/crc32_variants/crc32_posix.h | 10 +- Inc/crc/crc32_variants/crc32_q.h | 4 +- Inc/crc/crc32_variants/crc32_xfer.h | 4 +- Src/crc/crc32_variants/crc32.c | 21 ++- Src/crc/crc32_variants/crc32_bzip2.c | 17 ++- Src/crc/crc32_variants/crc32_c.c | 21 ++- Src/crc/crc32_variants/crc32_d.c | 21 ++- Src/crc/crc32_variants/crc32_jamcrc.c | 22 +++- Src/crc/crc32_variants/crc32_mpeg2.c | 14 +- Src/crc/crc32_variants/crc32_posix.c | 17 ++- Src/crc/crc32_variants/crc32_q.c | 14 +- Src/crc/crc32_variants/crc32_xfer.c | 14 +- Tests/test_crc32.c | 180 +++++++++++++++++--------- 19 files changed, 296 insertions(+), 113 deletions(-) diff --git a/Inc/crc/crc32_variants/crc32.h b/Inc/crc/crc32_variants/crc32.h index bb5d561..37d721e 100644 --- a/Inc/crc/crc32_variants/crc32.h +++ b/Inc/crc/crc32_variants/crc32.h @@ -44,20 +44,22 @@ * using a basic algorithm that uses the polynomial (0x4C11DB7). * The 'crc_data_ptr' parameter should be a pointer to the block of data to * calculate the checksum for. The 'crc_length' parameter is the length of the - * data block in bytes. The 'final_xor' parameter indicates whether to perform - * a final XOR operation on the calculated CRC value before returning it. + * data block in bytes. The 'final_crc' parameter indicates whether to perform a final XOR + * and output reflection operation. It shall be used when calculating CRC in chunks. * The calculation is performed using a lookup table for efficiency. * * @param[in] crc_data_ptr A pointer to the data block to calculate the checksum for. * @param[in] crc_length The length of the data block in bytes. - * @param[in] final_xor Whether to perform a final XOR operation on the calculated CRC value. + * @param[in] final_crc Set the flag to 'true' if it is the last or only operation, and 'false' for data chunks. + * @param[in] last_crc_ptr Pointer to the last CRC value for data chunks shall be set to NULL_PTR if it is the first or only operation. * * @return The calculated CRC checksum. */ uint32_t Crc32( const uint8_t* crc_data_ptr, uint32_t crc_length, - bool final_xor + bool final_crc, + const uint32_t* last_crc_ptr ); #endif /* UTILITY_CRC32_H_ */ diff --git a/Inc/crc/crc32_variants/crc32_bzip2.h b/Inc/crc/crc32_variants/crc32_bzip2.h index 0c59830..a491b7c 100644 --- a/Inc/crc/crc32_variants/crc32_bzip2.h +++ b/Inc/crc/crc32_variants/crc32_bzip2.h @@ -45,20 +45,22 @@ * The CRC32_BZIP2 function will not perform reflection on its input and output data. * The 'crc_data_ptr' parameter should be a pointer to the block of data to * calculate the checksum for. The 'crc_length' parameter is the length of the - * data block in bytes. The 'final_xor' parameter indicates whether to perform - * a final XOR operation on the calculated CRC value before returning it. + * data block in bytes. The 'final_crc' parameter indicates whether to perform a final XOR operation. + * It shall be used when calculating CRC in chunks. * The calculation is performed using a lookup table for efficiency. * * @param[in] crc_data_ptr A pointer to the data block to calculate the checksum for. * @param[in] crc_length The length of the data block in bytes. - * @param[in] final_xor Whether to perform a final XOR operation on the calculated CRC value. + * @param[in] final_crc Set the flag to 'true' if it is the last or only operation, and 'false' for data chunks. + * @param[in] last_crc_ptr Pointer to the last CRC value for data chunks shall be set to NULL_PTR if it is the first or only operation. * * @return The calculated CRC checksum. */ uint32_t Crc32_bzip2( const uint8_t* crc_data_ptr, uint32_t crc_length, - bool final_xor + bool final_crc, + const uint32_t* last_crc_ptr ); #endif /* UTILITY_CRC32_BZIP2_H_ */ diff --git a/Inc/crc/crc32_variants/crc32_c.h b/Inc/crc/crc32_variants/crc32_c.h index f33222a..5cb721f 100644 --- a/Inc/crc/crc32_variants/crc32_c.h +++ b/Inc/crc/crc32_variants/crc32_c.h @@ -44,20 +44,22 @@ * using a basic algorithm that uses the polynomial (0x1EDC6F41). * The 'crc_data_ptr' parameter should be a pointer to the block of data to * calculate the checksum for. The 'crc_length' parameter is the length of the - * data block in bytes. The 'final_xor' parameter indicates whether to perform - * a final XOR operation on the calculated CRC value before returning it. + * data block in bytes. The 'final_crc' parameter indicates whether to perform a final XOR + * and output reflection operation. It shall be used when calculating CRC in chunks. * The calculation is performed using a lookup table for efficiency. * * @param[in] crc_data_ptr A pointer to the data block to calculate the checksum for. * @param[in] crc_length The length of the data block in bytes. - * @param[in] final_xor Whether to perform a final XOR operation on the calculated CRC value. + * @param[in] final_crc Set the flag to 'true' if it is the last or only operation, and 'false' for data chunks. + * @param[in] last_crc_ptr Pointer to the last CRC value for data chunks shall be set to NULL_PTR if it is the first or only operation. * * @return The calculated CRC checksum. */ uint32_t Crc32_c( const uint8_t* crc_data_ptr, uint32_t crc_length, - bool final_xor + bool final_crc, + const uint32_t* last_crc_ptr ); #endif /* UTILITY_CRC32_C_H_ */ diff --git a/Inc/crc/crc32_variants/crc32_d.h b/Inc/crc/crc32_variants/crc32_d.h index e40e5cf..0087b74 100644 --- a/Inc/crc/crc32_variants/crc32_d.h +++ b/Inc/crc/crc32_variants/crc32_d.h @@ -44,20 +44,22 @@ * using a basic algorithm that uses the polynomial (0x4C11DB7). * The 'crc_data_ptr' parameter should be a pointer to the block of data to * calculate the checksum for. The 'crc_length' parameter is the length of the - * data block in bytes. The 'final_xor' parameter indicates whether to perform - * a final XOR operation on the calculated CRC value before returning it. + * data block in bytes. The 'final_crc' parameter indicates whether to perform a final XOR + * and output reflection operation. It shall be used when calculating CRC in chunks. * The calculation is performed using a lookup table for efficiency. * * @param[in] crc_data_ptr A pointer to the data block to calculate the checksum for. * @param[in] crc_length The length of the data block in bytes. - * @param[in] final_xor Whether to perform a final XOR operation on the calculated CRC value. + * @param[in] final_crc Set the flag to 'true' if it is the last or only operation, and 'false' for data chunks. + * @param[in] last_crc_ptr Pointer to the last CRC value for data chunks shall be set to NULL_PTR if it is the first or only operation. * * @return The calculated CRC checksum. */ uint32_t Crc32_d( const uint8_t* crc_data_ptr, uint32_t crc_length, - bool final_xor + bool final_crc, + const uint32_t* last_crc_ptr ); #endif /* UTILITY_CRC32_D_H_ */ diff --git a/Inc/crc/crc32_variants/crc32_jamcrc.h b/Inc/crc/crc32_variants/crc32_jamcrc.h index 6dc6365..f1829c2 100644 --- a/Inc/crc/crc32_variants/crc32_jamcrc.h +++ b/Inc/crc/crc32_variants/crc32_jamcrc.h @@ -47,12 +47,16 @@ * * @param[in] crc_data_ptr A pointer to the block of data to calculate the checksum for. * @param[in] crc_length The length of the data block in bytes. + * @param[in] final_crc Set the flag to 'true' if it is the last or only operation, and 'false' for data chunks. + * @param[in] last_crc_ptr Pointer to the last CRC value for data chunks shall be set to NULL_PTR if it is the first or only operation. * * @return The calculated CRC-32 checksum. */ uint32_t Crc32_jamcrc( const uint8_t* crc_data_ptr, - uint32_t crc_length + uint32_t crc_length, + bool final_crc, + const uint32_t* last_crc_ptr ); #endif /* UTILITY_CRC32_JAMCRC_H_ */ diff --git a/Inc/crc/crc32_variants/crc32_mpeg2.h b/Inc/crc/crc32_variants/crc32_mpeg2.h index 097ba33..f312f81 100644 --- a/Inc/crc/crc32_variants/crc32_mpeg2.h +++ b/Inc/crc/crc32_variants/crc32_mpeg2.h @@ -48,12 +48,14 @@ * * @param[in] crc_data_ptr A pointer to the block of data to calculate the checksum for. * @param[in] crc_length The length of the data block in bytes. + * @param[in] last_crc_ptr Pointer to the last CRC value for data chunks shall be set to NULL_PTR if it is the first or only operation. * * @return The calculated CRC-32 checksum. */ uint32_t Crc32_mpeg2( const uint8_t* crc_data_ptr, - uint32_t crc_length + uint32_t crc_length, + const uint32_t* last_crc_ptr ); #endif /* UTILITY_CRC32_MPEG2_H_ */ diff --git a/Inc/crc/crc32_variants/crc32_posix.h b/Inc/crc/crc32_variants/crc32_posix.h index 5d9ec88..d9c3bab 100644 --- a/Inc/crc/crc32_variants/crc32_posix.h +++ b/Inc/crc/crc32_variants/crc32_posix.h @@ -44,20 +44,22 @@ * using a basic algorithm that uses the polynomial (0xA833982B). * The 'crc_data_ptr' parameter should be a pointer to the block of data to * calculate the checksum for. The 'crc_length' parameter is the length of the - * data block in bytes. The 'final_xor' parameter indicates whether to perform - * a final XOR operation on the calculated CRC value before returning it. + * data block in bytes.The 'final_crc' parameter indicates whether to perform a final XOR operation. + * It shall be used when calculating CRC in chunks. * The calculation is performed using a lookup table for efficiency. * * @param[in] crc_data_ptr A pointer to the data block to calculate the checksum for. * @param[in] crc_length The length of the data block in bytes. - * @param[in] final_xor Whether to perform a final XOR operation on the calculated CRC value. + * @param[in] final_crc Set the flag to 'true' if it is the last or only operation, and 'false' for data chunks. + * @param[in] last_crc_ptr Pointer to the last CRC value for data chunks shall be set to NULL_PTR if it is the first or only operation. * * @return The calculated CRC checksum. */ uint32_t Crc32_posix( const uint8_t* crc_data_ptr, uint32_t crc_length, - bool final_xor + bool final_crc, + const uint32_t* last_crc_ptr ); #endif /* UTILITY_CRC32_POSIX_H_ */ diff --git a/Inc/crc/crc32_variants/crc32_q.h b/Inc/crc/crc32_variants/crc32_q.h index a9065c8..a948904 100644 --- a/Inc/crc/crc32_variants/crc32_q.h +++ b/Inc/crc/crc32_variants/crc32_q.h @@ -48,12 +48,14 @@ * * @param[in] crc_data_ptr A pointer to the block of data to calculate the checksum for. * @param[in] crc_length The length of the data block in bytes. + * @param[in] last_crc_ptr Pointer to the last CRC value for data chunks shall be set to NULL_PTR if it is the first or only operation. * * @return The calculated CRC-32 checksum. */ uint32_t Crc32_q( const uint8_t* crc_data_ptr, - uint32_t crc_length + uint32_t crc_length, + const uint32_t* last_crc_ptr ); #endif /* UTILITY_CRC32_Q_H_ */ diff --git a/Inc/crc/crc32_variants/crc32_xfer.h b/Inc/crc/crc32_variants/crc32_xfer.h index fe0e468..1f6a223 100644 --- a/Inc/crc/crc32_variants/crc32_xfer.h +++ b/Inc/crc/crc32_variants/crc32_xfer.h @@ -48,12 +48,14 @@ * * @param[in] crc_data_ptr A pointer to the block of data to calculate the checksum for. * @param[in] crc_length The length of the data block in bytes. + * @param[in] last_crc_ptr Pointer to the last CRC value for data chunks shall be set to NULL_PTR if it is the first or only operation. * * @return The calculated CRC-32 checksum. */ uint32_t Crc32_xfer( const uint8_t* crc_data_ptr, - uint32_t crc_length + uint32_t crc_length, + const uint32_t* last_crc_ptr ); #endif /* UTILITY_CRC32_XFER_H_ */ diff --git a/Src/crc/crc32_variants/crc32.c b/Src/crc/crc32_variants/crc32.c index 5a94414..11bfa13 100644 --- a/Src/crc/crc32_variants/crc32.c +++ b/Src/crc/crc32_variants/crc32.c @@ -40,12 +40,14 @@ #define FINAL_XOR_VALUE (0xFFFFFFFFU) #define REFLECTED_OUTPUT (true) #define REFLECTED_INPUT (true) +#define FINAL_XOR (true) uint32_t Crc32( const uint8_t* crc_data_ptr, uint32_t crc_length, - bool final_xor) { + bool final_crc, + const uint32_t* last_crc_ptr) { /* CRC32 also know as Ethernet CRC (Polynomial 0x4C11DB7) */ static const uint32_t crc_table[256] = { @@ -83,13 +85,26 @@ Crc32( 0xAFB010B1U, 0xAB710D06U, 0xA6322BDFU, 0xA2F33668U, 0xBCB4666DU, 0xB8757BDAU, 0xB5365D03U, 0xB1F740B4U }; + bool reflect_output = false; + bool final_xor = false; + uint32_t crc_initial_value = INITIAL_CRC32_VALUE; + + if (NULL_PTR != last_crc_ptr) { + crc_initial_value = *last_crc_ptr; + } + + if (final_crc) { + reflect_output = REFLECTED_OUTPUT; + final_xor = FINAL_XOR; + } + return Crc32Base( crc_table, crc_data_ptr, crc_length, - INITIAL_CRC32_VALUE, + crc_initial_value, FINAL_XOR_VALUE, - REFLECTED_OUTPUT, + reflect_output, REFLECTED_INPUT, final_xor ); diff --git a/Src/crc/crc32_variants/crc32_bzip2.c b/Src/crc/crc32_variants/crc32_bzip2.c index 55a0600..ad72268 100644 --- a/Src/crc/crc32_variants/crc32_bzip2.c +++ b/Src/crc/crc32_variants/crc32_bzip2.c @@ -40,12 +40,14 @@ #define FINAL_XOR_VALUE (0xFFFFFFFFU) #define REFLECTED_OUTPUT (false) #define REFLECTED_INPUT (false) +#define FINAL_XOR (true) uint32_t Crc32_bzip2( const uint8_t* crc_data_ptr, uint32_t crc_length, - bool final_xor) { + bool final_crc, + const uint32_t* last_crc_ptr) { /* CRC32-BZIP2 (Polynomial 0x4C11DB7) */ static const uint32_t crc_table[256] = { @@ -83,11 +85,22 @@ Crc32_bzip2( 0xAFB010B1U, 0xAB710D06U, 0xA6322BDFU, 0xA2F33668U, 0xBCB4666DU, 0xB8757BDAU, 0xB5365D03U, 0xB1F740B4U }; + bool final_xor = false; + uint32_t crc_initial_value = INITIAL_CRC32_VALUE; + + if (NULL_PTR != last_crc_ptr) { + crc_initial_value = *last_crc_ptr; + } + + if (final_crc) { + final_xor = FINAL_XOR; + } + return Crc32Base( crc_table, crc_data_ptr, crc_length, - INITIAL_CRC32_VALUE, + crc_initial_value, FINAL_XOR_VALUE, REFLECTED_OUTPUT, REFLECTED_INPUT, diff --git a/Src/crc/crc32_variants/crc32_c.c b/Src/crc/crc32_variants/crc32_c.c index 1c60896..e69d31c 100644 --- a/Src/crc/crc32_variants/crc32_c.c +++ b/Src/crc/crc32_variants/crc32_c.c @@ -40,12 +40,14 @@ #define FINAL_XOR_VALUE (0xFFFFFFFFU) #define REFLECTED_OUTPUT (true) #define REFLECTED_INPUT (true) +#define FINAL_XOR (true) uint32_t Crc32_c( const uint8_t* crc_data_ptr, uint32_t crc_length, - bool final_xor) { + bool final_crc, + const uint32_t* last_crc_ptr) { /* CRC32-C (Castagnoli) (Polynomial 0x1EDC6F41) */ static const uint32_t crc_table[256] = { @@ -83,13 +85,26 @@ Crc32_c( 0xD2DFB272U, 0xCC03DD33U, 0xEF676CF0U, 0xF1BB03B1U, 0xA9AE0F76U, 0xB7726037U, 0x9416D1F4U, 0x8ACABEB5U }; + bool reflect_output = false; + bool final_xor = false; + uint32_t crc_initial_value = INITIAL_CRC32_VALUE; + + if (NULL_PTR != last_crc_ptr) { + crc_initial_value = *last_crc_ptr; + } + + if (final_crc) { + reflect_output = REFLECTED_OUTPUT; + final_xor = FINAL_XOR; + } + return Crc32Base( crc_table, crc_data_ptr, crc_length, - INITIAL_CRC32_VALUE, + crc_initial_value, FINAL_XOR_VALUE, - REFLECTED_OUTPUT, + reflect_output, REFLECTED_INPUT, final_xor ); diff --git a/Src/crc/crc32_variants/crc32_d.c b/Src/crc/crc32_variants/crc32_d.c index d119498..fc42922 100644 --- a/Src/crc/crc32_variants/crc32_d.c +++ b/Src/crc/crc32_variants/crc32_d.c @@ -40,12 +40,14 @@ #define FINAL_XOR_VALUE (0xFFFFFFFFU) #define REFLECTED_OUTPUT (true) #define REFLECTED_INPUT (true) +#define FINAL_XOR (true) uint32_t Crc32_d( const uint8_t* crc_data_ptr, uint32_t crc_length, - bool final_xor) { + bool final_crc, + const uint32_t* last_crc_ptr) { /* CRC32-D (Polynomial 0xA833982B) */ static const uint32_t crc_table[256] = { @@ -83,13 +85,26 @@ Crc32_d( 0xCCE1A206U, 0x64D23A2DU, 0x34B50A7BU, 0x9C869250U, 0x947B6AD7U, 0x3C48F2FCU, 0x6C2FC2AAU, 0xC41C5A81U }; + bool reflect_output = false; + bool final_xor = false; + uint32_t crc_initial_value = INITIAL_CRC32_VALUE; + + if (NULL_PTR != last_crc_ptr) { + crc_initial_value = *last_crc_ptr; + } + + if (final_crc) { + reflect_output = REFLECTED_OUTPUT; + final_xor = FINAL_XOR; + } + return Crc32Base( crc_table, crc_data_ptr, crc_length, - INITIAL_CRC32_VALUE, + crc_initial_value, FINAL_XOR_VALUE, - REFLECTED_OUTPUT, + reflect_output, REFLECTED_INPUT, final_xor ); diff --git a/Src/crc/crc32_variants/crc32_jamcrc.c b/Src/crc/crc32_variants/crc32_jamcrc.c index 549e267..b8f06d2 100644 --- a/Src/crc/crc32_variants/crc32_jamcrc.c +++ b/Src/crc/crc32_variants/crc32_jamcrc.c @@ -40,11 +40,14 @@ #define FINAL_XOR_VALUE (0x0U) #define REFLECTED_OUTPUT (true) #define REFLECTED_INPUT (true) +#define FINAL_XOR (false) uint32_t Crc32_jamcrc( const uint8_t* crc_data_ptr, - uint32_t crc_length) { + uint32_t crc_length, + bool final_crc, + const uint32_t* last_crc_ptr) { /* CRC32-JAMCRC (Polynomial 0x4C11DB7) */ static const uint32_t crc_table[256] = { @@ -82,14 +85,25 @@ Crc32_jamcrc( 0xAFB010B1U, 0xAB710D06U, 0xA6322BDFU, 0xA2F33668U, 0xBCB4666DU, 0xB8757BDAU, 0xB5365D03U, 0xB1F740B4U }; + bool reflect_output = false; + uint32_t crc_initial_value = INITIAL_CRC32_VALUE; + + if (NULL_PTR != last_crc_ptr) { + crc_initial_value = *last_crc_ptr; + } + + if (final_crc) { + reflect_output = REFLECTED_OUTPUT; + } + return Crc32Base( crc_table, crc_data_ptr, crc_length, - INITIAL_CRC32_VALUE, + crc_initial_value, FINAL_XOR_VALUE, - REFLECTED_OUTPUT, + reflect_output, REFLECTED_INPUT, - false + FINAL_XOR ); } diff --git a/Src/crc/crc32_variants/crc32_mpeg2.c b/Src/crc/crc32_variants/crc32_mpeg2.c index 99d8bf7..8c336d8 100644 --- a/Src/crc/crc32_variants/crc32_mpeg2.c +++ b/Src/crc/crc32_variants/crc32_mpeg2.c @@ -40,11 +40,13 @@ #define FINAL_XOR_VALUE (0x0U) #define REFLECTED_OUTPUT (false) #define REFLECTED_INPUT (false) +#define FINAL_XOR (false) uint32_t Crc32_mpeg2( const uint8_t* crc_data_ptr, - uint32_t crc_length) { + uint32_t crc_length, + const uint32_t* last_crc_ptr) { /* CRC32-MPEG2 (Polynomial 0x4C11DB7) */ static const uint32_t crc_table[256] = { @@ -82,14 +84,20 @@ Crc32_mpeg2( 0xAFB010B1U, 0xAB710D06U, 0xA6322BDFU, 0xA2F33668U, 0xBCB4666DU, 0xB8757BDAU, 0xB5365D03U, 0xB1F740B4U }; + uint32_t crc_initial_value = INITIAL_CRC32_VALUE; + + if (NULL_PTR != last_crc_ptr) { + crc_initial_value = *last_crc_ptr; + } + return Crc32Base( crc_table, crc_data_ptr, crc_length, - INITIAL_CRC32_VALUE, + crc_initial_value, FINAL_XOR_VALUE, REFLECTED_OUTPUT, REFLECTED_INPUT, - false + FINAL_XOR ); } diff --git a/Src/crc/crc32_variants/crc32_posix.c b/Src/crc/crc32_variants/crc32_posix.c index bb0778b..05cb916 100644 --- a/Src/crc/crc32_variants/crc32_posix.c +++ b/Src/crc/crc32_variants/crc32_posix.c @@ -40,12 +40,14 @@ #define FINAL_XOR_VALUE (0xFFFFFFFFU) #define REFLECTED_OUTPUT (false) #define REFLECTED_INPUT (false) +#define FINAL_XOR (true) uint32_t Crc32_posix( const uint8_t* crc_data_ptr, uint32_t crc_length, - bool final_xor) { + bool final_crc, + const uint32_t* last_crc_ptr) { /* CRC32-POSIX (Polynomial 0x4C11DB7) */ static const uint32_t crc_table[256] = { @@ -83,11 +85,22 @@ Crc32_posix( 0xAFB010B1U, 0xAB710D06U, 0xA6322BDFU, 0xA2F33668U, 0xBCB4666DU, 0xB8757BDAU, 0xB5365D03U, 0xB1F740B4U }; + bool final_xor = false; + uint32_t crc_initial_value = INITIAL_CRC32_VALUE; + + if (NULL_PTR != last_crc_ptr) { + crc_initial_value = *last_crc_ptr; + } + + if (final_crc) { + final_xor = FINAL_XOR; + } + return Crc32Base( crc_table, crc_data_ptr, crc_length, - INITIAL_CRC32_VALUE, + crc_initial_value, FINAL_XOR_VALUE, REFLECTED_OUTPUT, REFLECTED_INPUT, diff --git a/Src/crc/crc32_variants/crc32_q.c b/Src/crc/crc32_variants/crc32_q.c index 69c3aac..538e882 100644 --- a/Src/crc/crc32_variants/crc32_q.c +++ b/Src/crc/crc32_variants/crc32_q.c @@ -40,11 +40,13 @@ #define FINAL_XOR_VALUE (0x0U) #define REFLECTED_OUTPUT (false) #define REFLECTED_INPUT (false) +#define FINAL_XOR (false) uint32_t Crc32_q( const uint8_t* crc_data_ptr, - uint32_t crc_length) { + uint32_t crc_length, + const uint32_t* last_crc_ptr) { /* CRC32-Q (Polynomial 0x4C11DB7) */ static const uint32_t crc_table[256] = { @@ -82,14 +84,20 @@ Crc32_q( 0x044429E9U, 0x85056842U, 0x8787EB14U, 0x06C6AABFU, 0x8282EDB8U, 0x03C3AC13U, 0x01412F45U, 0x80006EEEU }; + uint32_t crc_initial_value = INITIAL_CRC32_VALUE; + + if (NULL_PTR != last_crc_ptr) { + crc_initial_value = *last_crc_ptr; + } + return Crc32Base( crc_table, crc_data_ptr, crc_length, - INITIAL_CRC32_VALUE, + crc_initial_value, FINAL_XOR_VALUE, REFLECTED_OUTPUT, REFLECTED_INPUT, - false + FINAL_XOR ); } diff --git a/Src/crc/crc32_variants/crc32_xfer.c b/Src/crc/crc32_variants/crc32_xfer.c index 0bacda1..864e567 100644 --- a/Src/crc/crc32_variants/crc32_xfer.c +++ b/Src/crc/crc32_variants/crc32_xfer.c @@ -40,11 +40,13 @@ #define FINAL_XOR_VALUE (0x0U) #define REFLECTED_OUTPUT (false) #define REFLECTED_INPUT (false) +#define FINAL_XOR (false) uint32_t Crc32_xfer( const uint8_t* crc_data_ptr, - uint32_t crc_length) { + uint32_t crc_length, + const uint32_t* last_crc_ptr) { /* CRC32-XFER (Polynomial 0xAF) */ static const uint32_t crc_table[256] = { @@ -82,14 +84,20 @@ Crc32_xfer( 0x00006628U, 0x00006687U, 0x00006776U, 0x000067D9U, 0x00006494U, 0x0000643BU, 0x000065CAU, 0x00006565U }; + uint32_t crc_initial_value = INITIAL_CRC32_VALUE; + + if (NULL_PTR != last_crc_ptr) { + crc_initial_value = *last_crc_ptr; + } + return Crc32Base( crc_table, crc_data_ptr, crc_length, - INITIAL_CRC32_VALUE, + crc_initial_value, FINAL_XOR_VALUE, REFLECTED_OUTPUT, REFLECTED_INPUT, - false + FINAL_XOR ); } diff --git a/Tests/test_crc32.c b/Tests/test_crc32.c index 7529f90..814a490 100644 --- a/Tests/test_crc32.c +++ b/Tests/test_crc32.c @@ -162,91 +162,145 @@ TEST(Crc32, CRC32Base_Without_finish_xor) { } TEST(Crc32, Crc32) { - TEST_ASSERT_EQUAL_HEX32(0x2144DF1CU, Crc32(message1, sizeof(message1), true)); - TEST_ASSERT_EQUAL_HEX32(0x24AB9D77U, Crc32(message2, sizeof(message2), true)); - TEST_ASSERT_EQUAL_HEX32(0xB6C9B287U, Crc32(message3, sizeof(message3), true)); - TEST_ASSERT_EQUAL_HEX32(0x32A06212U, Crc32(message4, sizeof(message4), true)); - TEST_ASSERT_EQUAL_HEX32(0xB0AE863DU, Crc32(message5, sizeof(message5), true)); - TEST_ASSERT_EQUAL_HEX32(0x9CDEA29BU, Crc32(message6, sizeof(message6), true)); - TEST_ASSERT_EQUAL_HEX32(0xFFFFFFFFU, Crc32(message7, sizeof(message7), true)); + TEST_ASSERT_EQUAL_HEX32(0x2144DF1CU, Crc32(message1, sizeof(message1), true, NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0x24AB9D77U, Crc32(message2, sizeof(message2), true, NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0xB6C9B287U, Crc32(message3, sizeof(message3), true, NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0x32A06212U, Crc32(message4, sizeof(message4), true, NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0xB0AE863DU, Crc32(message5, sizeof(message5), true, NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0x9CDEA29BU, Crc32(message6, sizeof(message6), true, NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0xFFFFFFFFU, Crc32(message7, sizeof(message7), true, NULL_PTR)); + + // Test with message in chunks + uint32_t crc_result = Crc32(&message5[0], 2U, false, NULL_PTR); + crc_result = Crc32(&message5[2], 5U, false, &crc_result); + crc_result = Crc32(&message5[7], 2U, true, &crc_result); + TEST_ASSERT_EQUAL_HEX32(0xB0AE863DU, crc_result); } TEST(Crc32, Crc32_bzip2) { - TEST_ASSERT_EQUAL_HEX32(0x38FB2284U, Crc32_bzip2(message1, sizeof(message1), true)); - TEST_ASSERT_EQUAL_HEX32(0x419EE6CAU, Crc32_bzip2(message2, sizeof(message2), true)); - TEST_ASSERT_EQUAL_HEX32(0x68F66ADFU, Crc32_bzip2(message3, sizeof(message3), true)); - TEST_ASSERT_EQUAL_HEX32(0x012DEA14U, Crc32_bzip2(message4, sizeof(message4), true)); - TEST_ASSERT_EQUAL_HEX32(0xD6039CBDU, Crc32_bzip2(message5, sizeof(message5), true)); - TEST_ASSERT_EQUAL_HEX32(0x4CE2D686U, Crc32_bzip2(message6, sizeof(message6), true)); - TEST_ASSERT_EQUAL_HEX32(0xFFFFFFFFU, Crc32_bzip2(message7, sizeof(message7), true)); + TEST_ASSERT_EQUAL_HEX32(0x38FB2284U, Crc32_bzip2(message1, sizeof(message1), true, NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0x419EE6CAU, Crc32_bzip2(message2, sizeof(message2), true, NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0x68F66ADFU, Crc32_bzip2(message3, sizeof(message3), true, NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0x012DEA14U, Crc32_bzip2(message4, sizeof(message4), true, NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0xD6039CBDU, Crc32_bzip2(message5, sizeof(message5), true, NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0x4CE2D686U, Crc32_bzip2(message6, sizeof(message6), true, NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0xFFFFFFFFU, Crc32_bzip2(message7, sizeof(message7), true, NULL_PTR)); + + // Test with message in chunks + uint32_t crc_result = Crc32_bzip2(&message5[0], 2U, false, NULL_PTR); + crc_result = Crc32_bzip2(&message5[2], 5U, false, &crc_result); + crc_result = Crc32_bzip2(&message5[7], 2U, true, &crc_result); + TEST_ASSERT_EQUAL_HEX32(0xD6039CBDU, crc_result); } TEST(Crc32, Crc32_c) { - TEST_ASSERT_EQUAL_HEX32(0x48674BC7U, Crc32_c(message1, sizeof(message1), true)); - TEST_ASSERT_EQUAL_HEX32(0x70ABD088U, Crc32_c(message2, sizeof(message2), true)); - TEST_ASSERT_EQUAL_HEX32(0xDEAABEBBU, Crc32_c(message3, sizeof(message3), true)); - TEST_ASSERT_EQUAL_HEX32(0xA6ADEA2DU, Crc32_c(message4, sizeof(message4), true)); - TEST_ASSERT_EQUAL_HEX32(0xB59CA09BU, Crc32_c(message5, sizeof(message5), true)); - TEST_ASSERT_EQUAL_HEX32(0x99357B56U, Crc32_c(message6, sizeof(message6), true)); - TEST_ASSERT_EQUAL_HEX32(0xFFFFFFFFU, Crc32_c(message7, sizeof(message7), true)); + TEST_ASSERT_EQUAL_HEX32(0x48674BC7U, Crc32_c(message1, sizeof(message1), true, NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0x70ABD088U, Crc32_c(message2, sizeof(message2), true, NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0xDEAABEBBU, Crc32_c(message3, sizeof(message3), true, NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0xA6ADEA2DU, Crc32_c(message4, sizeof(message4), true, NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0xB59CA09BU, Crc32_c(message5, sizeof(message5), true, NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0x99357B56U, Crc32_c(message6, sizeof(message6), true, NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0xFFFFFFFFU, Crc32_c(message7, sizeof(message7), true, NULL_PTR)); + + // Test with message in chunks + uint32_t crc_result = Crc32_c(&message5[0], 2U, false, NULL_PTR); + crc_result = Crc32_c(&message5[2], 5U, false, &crc_result); + crc_result = Crc32_c(&message5[7], 2U, true, &crc_result); + TEST_ASSERT_EQUAL_HEX32(0xB59CA09BU, crc_result); } TEST(Crc32, Crc32_d) { - TEST_ASSERT_EQUAL_HEX32(0xBAD8FAAEU, Crc32_d(message1, sizeof(message1), true)); - TEST_ASSERT_EQUAL_HEX32(0x001A059CU, Crc32_d(message2, sizeof(message2), true)); - TEST_ASSERT_EQUAL_HEX32(0x1A266FFAU, Crc32_d(message3, sizeof(message3), true)); - TEST_ASSERT_EQUAL_HEX32(0xC636481BU, Crc32_d(message4, sizeof(message4), true)); - TEST_ASSERT_EQUAL_HEX32(0xCF0E6328U, Crc32_d(message5, sizeof(message5), true)); - TEST_ASSERT_EQUAL_HEX32(0x4B92ADBEU, Crc32_d(message6, sizeof(message6), true)); - TEST_ASSERT_EQUAL_HEX32(0xFFFFFFFFU, Crc32_d(message7, sizeof(message7), true)); + TEST_ASSERT_EQUAL_HEX32(0xBAD8FAAEU, Crc32_d(message1, sizeof(message1), true, NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0x001A059CU, Crc32_d(message2, sizeof(message2), true, NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0x1A266FFAU, Crc32_d(message3, sizeof(message3), true, NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0xC636481BU, Crc32_d(message4, sizeof(message4), true, NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0xCF0E6328U, Crc32_d(message5, sizeof(message5), true, NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0x4B92ADBEU, Crc32_d(message6, sizeof(message6), true, NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0xFFFFFFFFU, Crc32_d(message7, sizeof(message7), true, NULL_PTR)); + + // Test with message in chunks + uint32_t crc_result = Crc32_d(&message5[0], 2U, false, NULL_PTR); + crc_result = Crc32_d(&message5[2], 5U, false, &crc_result); + crc_result = Crc32_d(&message5[7], 2U, true, &crc_result); + TEST_ASSERT_EQUAL_HEX32(0xCF0E6328U, crc_result); } TEST(Crc32, Crc32_jamcrc) { - TEST_ASSERT_EQUAL_HEX32(0xDEBB20E3U, Crc32_jamcrc(message1, sizeof(message1))); - TEST_ASSERT_EQUAL_HEX32(0xDB546288U, Crc32_jamcrc(message2, sizeof(message2))); - TEST_ASSERT_EQUAL_HEX32(0x49364D78U, Crc32_jamcrc(message3, sizeof(message3))); - TEST_ASSERT_EQUAL_HEX32(0xCD5F9DEDU, Crc32_jamcrc(message4, sizeof(message4))); - TEST_ASSERT_EQUAL_HEX32(0x4F5179C2U, Crc32_jamcrc(message5, sizeof(message5))); - TEST_ASSERT_EQUAL_HEX32(0x63215D64U, Crc32_jamcrc(message6, sizeof(message6))); - TEST_ASSERT_EQUAL_HEX32(0x00000000U, Crc32_jamcrc(message7, sizeof(message7))); + TEST_ASSERT_EQUAL_HEX32(0xDEBB20E3U, Crc32_jamcrc(message1, sizeof(message1), true, NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0xDB546288U, Crc32_jamcrc(message2, sizeof(message2), true, NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0x49364D78U, Crc32_jamcrc(message3, sizeof(message3), true, NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0xCD5F9DEDU, Crc32_jamcrc(message4, sizeof(message4), true, NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0x4F5179C2U, Crc32_jamcrc(message5, sizeof(message5), true, NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0x63215D64U, Crc32_jamcrc(message6, sizeof(message6), true, NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0x00000000U, Crc32_jamcrc(message7, sizeof(message7), true, NULL_PTR)); + + // Test with message in chunks + uint32_t crc_result = Crc32_jamcrc(&message5[0], 2U, false, NULL_PTR); + crc_result = Crc32_jamcrc(&message5[2], 5U, false, &crc_result); + crc_result = Crc32_jamcrc(&message5[7], 2U, true, &crc_result); + TEST_ASSERT_EQUAL_HEX32(0x4F5179C2U, crc_result); } TEST(Crc32, Crc32_mpeg2) { - TEST_ASSERT_EQUAL_HEX32(0xC704DD7BU, Crc32_mpeg2(message1, sizeof(message1))); - TEST_ASSERT_EQUAL_HEX32(0xBE611935U, Crc32_mpeg2(message2, sizeof(message2))); - TEST_ASSERT_EQUAL_HEX32(0x97099520U, Crc32_mpeg2(message3, sizeof(message3))); - TEST_ASSERT_EQUAL_HEX32(0xFED215EBU, Crc32_mpeg2(message4, sizeof(message4))); - TEST_ASSERT_EQUAL_HEX32(0x29FC6342U, Crc32_mpeg2(message5, sizeof(message5))); - TEST_ASSERT_EQUAL_HEX32(0xB31D2979U, Crc32_mpeg2(message6, sizeof(message6))); - TEST_ASSERT_EQUAL_HEX32(0x00000000U, Crc32_mpeg2(message7, sizeof(message7))); + TEST_ASSERT_EQUAL_HEX32(0xC704DD7BU, Crc32_mpeg2(message1, sizeof(message1), NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0xBE611935U, Crc32_mpeg2(message2, sizeof(message2), NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0x97099520U, Crc32_mpeg2(message3, sizeof(message3), NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0xFED215EBU, Crc32_mpeg2(message4, sizeof(message4), NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0x29FC6342U, Crc32_mpeg2(message5, sizeof(message5), NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0xB31D2979U, Crc32_mpeg2(message6, sizeof(message6), NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0x00000000U, Crc32_mpeg2(message7, sizeof(message7), NULL_PTR)); + + // Test with message in chunks + uint32_t crc_result = Crc32_mpeg2(&message5[0], 2U, NULL_PTR); + crc_result = Crc32_mpeg2(&message5[2], 5U, &crc_result); + crc_result = Crc32_mpeg2(&message5[7], 2U, &crc_result); + TEST_ASSERT_EQUAL_HEX32(0x29FC6342U, crc_result); } TEST(Crc32, Crc32_posix) { - TEST_ASSERT_EQUAL_HEX32(0xFFFFFFFFU, Crc32_posix(message1, sizeof(message1), true)); - TEST_ASSERT_EQUAL_HEX32(0xF6FA9BCAU, Crc32_posix(message2, sizeof(message2), true)); - TEST_ASSERT_EQUAL_HEX32(0xAFF2B7A4U, Crc32_posix(message3, sizeof(message3), true)); - TEST_ASSERT_EQUAL_HEX32(0xC629376FU, Crc32_posix(message4, sizeof(message4), true)); - TEST_ASSERT_EQUAL_HEX32(0x5CD4F325U, Crc32_posix(message5, sizeof(message5), true)); - TEST_ASSERT_EQUAL_HEX32(0xFB86AB86U, Crc32_posix(message6, sizeof(message6), true)); - TEST_ASSERT_EQUAL_HEX32(0x38FB2284U, Crc32_posix(message7, sizeof(message7), true)); + TEST_ASSERT_EQUAL_HEX32(0xFFFFFFFFU, Crc32_posix(message1, sizeof(message1), true, NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0xF6FA9BCAU, Crc32_posix(message2, sizeof(message2), true, NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0xAFF2B7A4U, Crc32_posix(message3, sizeof(message3), true, NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0xC629376FU, Crc32_posix(message4, sizeof(message4), true, NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0x5CD4F325U, Crc32_posix(message5, sizeof(message5), true, NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0xFB86AB86U, Crc32_posix(message6, sizeof(message6), true, NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0x38FB2284U, Crc32_posix(message7, sizeof(message7), true, NULL_PTR)); + + // Test with message in chunks + uint32_t crc_result = Crc32_posix(&message5[0], 2U, false, NULL_PTR); + crc_result = Crc32_posix(&message5[2], 5U, false, &crc_result); + crc_result = Crc32_posix(&message5[7], 2U, true, &crc_result); + TEST_ASSERT_EQUAL_HEX32(0x5CD4F325U, crc_result); } TEST(Crc32, Crc32_q) { - TEST_ASSERT_EQUAL_HEX32(0x00000000U, Crc32_q(message1, sizeof(message1))); - TEST_ASSERT_EQUAL_HEX32(0x09F26687U, Crc32_q(message2, sizeof(message2))); - TEST_ASSERT_EQUAL_HEX32(0x2C8E43FCU, Crc32_q(message3, sizeof(message3))); - TEST_ASSERT_EQUAL_HEX32(0xA854EA7CU, Crc32_q(message4, sizeof(message4))); - TEST_ASSERT_EQUAL_HEX32(0x64E7EA17U, Crc32_q(message5, sizeof(message5))); - TEST_ASSERT_EQUAL_HEX32(0x35BD0C6CU, Crc32_q(message6, sizeof(message6))); - TEST_ASSERT_EQUAL_HEX32(0x90A54352U, Crc32_q(message7, sizeof(message7))); + TEST_ASSERT_EQUAL_HEX32(0x00000000U, Crc32_q(message1, sizeof(message1), NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0x09F26687U, Crc32_q(message2, sizeof(message2), NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0x2C8E43FCU, Crc32_q(message3, sizeof(message3), NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0xA854EA7CU, Crc32_q(message4, sizeof(message4), NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0x64E7EA17U, Crc32_q(message5, sizeof(message5), NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0x35BD0C6CU, Crc32_q(message6, sizeof(message6), NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0x90A54352U, Crc32_q(message7, sizeof(message7), NULL_PTR)); + + // Test with message in chunks + uint32_t crc_result = Crc32_q(&message5[0], 2U, NULL_PTR); + crc_result = Crc32_q(&message5[2], 5U, &crc_result); + crc_result = Crc32_q(&message5[7], 2U, &crc_result); + TEST_ASSERT_EQUAL_HEX32(0x64E7EA17U, crc_result); } TEST(Crc32, Crc32_xfer) { - TEST_ASSERT_EQUAL_HEX32(0x00000000U, Crc32_xfer(message1, sizeof(message1))); - TEST_ASSERT_EQUAL_HEX32(0x620EF971U, Crc32_xfer(message2, sizeof(message2))); - TEST_ASSERT_EQUAL_HEX32(0x734620C1U, Crc32_xfer(message3, sizeof(message3))); - TEST_ASSERT_EQUAL_HEX32(0x6546295FU, Crc32_xfer(message4, sizeof(message4))); - TEST_ASSERT_EQUAL_HEX32(0xD543C03CU, Crc32_xfer(message5, sizeof(message5))); - TEST_ASSERT_EQUAL_HEX32(0x5C148A23U, Crc32_xfer(message6, sizeof(message6))); - TEST_ASSERT_EQUAL_HEX32(0x00003C56U, Crc32_xfer(message7, sizeof(message7))); + TEST_ASSERT_EQUAL_HEX32(0x00000000U, Crc32_xfer(message1, sizeof(message1), NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0x620EF971U, Crc32_xfer(message2, sizeof(message2), NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0x734620C1U, Crc32_xfer(message3, sizeof(message3), NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0x6546295FU, Crc32_xfer(message4, sizeof(message4), NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0xD543C03CU, Crc32_xfer(message5, sizeof(message5), NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0x5C148A23U, Crc32_xfer(message6, sizeof(message6), NULL_PTR)); + TEST_ASSERT_EQUAL_HEX32(0x00003C56U, Crc32_xfer(message7, sizeof(message7), NULL_PTR)); + + // Test with message in chunks + uint32_t crc_result = Crc32_xfer(&message5[0], 2U, NULL_PTR); + crc_result = Crc32_xfer(&message5[2], 5U, &crc_result); + crc_result = Crc32_xfer(&message5[7], 2U, &crc_result); + TEST_ASSERT_EQUAL_HEX32(0xD543C03CU, crc_result); }