Merge pull request #10228 from bergzand/pr/checksum/fletcher16_split
Fletcher16: extend with multi-part functions
This commit is contained in:
commit
2bc524fb4d
@ -20,21 +20,41 @@
|
|||||||
|
|
||||||
#include "checksum/fletcher16.h"
|
#include "checksum/fletcher16.h"
|
||||||
|
|
||||||
|
static inline void _reduce(fletcher16_ctx_t *ctx)
|
||||||
|
{
|
||||||
|
ctx->sum1 = (ctx->sum1 & 0xff) + (ctx->sum1 >> 8);
|
||||||
|
ctx->sum2 = (ctx->sum2 & 0xff) + (ctx->sum2 >> 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fletcher16_init(fletcher16_ctx_t *ctx)
|
||||||
|
{
|
||||||
|
ctx->sum1 = 0xff;
|
||||||
|
ctx->sum2 = 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fletcher16_update(fletcher16_ctx_t *ctx, const uint8_t *data, size_t len)
|
||||||
|
{
|
||||||
|
while (len) {
|
||||||
|
size_t tlen = len > 20 ? 20 : len;
|
||||||
|
len -= tlen;
|
||||||
|
do {
|
||||||
|
ctx->sum2 += ctx->sum1 += *data++;
|
||||||
|
} while (--tlen);
|
||||||
|
_reduce(ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t fletcher16_finish(fletcher16_ctx_t *ctx)
|
||||||
|
{
|
||||||
|
/* Second reduction step to reduce sums to 8 bits */
|
||||||
|
_reduce(ctx);
|
||||||
|
return (ctx->sum2 << 8) | ctx->sum1;
|
||||||
|
}
|
||||||
|
|
||||||
uint16_t fletcher16(const uint8_t *data, size_t bytes)
|
uint16_t fletcher16(const uint8_t *data, size_t bytes)
|
||||||
{
|
{
|
||||||
uint16_t sum1 = 0xff, sum2 = 0xff;
|
fletcher16_ctx_t ctx;
|
||||||
|
fletcher16_init(&ctx);
|
||||||
while (bytes) {
|
fletcher16_update(&ctx, data, bytes);
|
||||||
size_t tlen = bytes > 20 ? 20 : bytes;
|
return fletcher16_finish(&ctx);
|
||||||
bytes -= tlen;
|
|
||||||
do {
|
|
||||||
sum2 += sum1 += *data++;
|
|
||||||
} while (--tlen);
|
|
||||||
sum1 = (sum1 & 0xff) + (sum1 >> 8);
|
|
||||||
sum2 = (sum2 & 0xff) + (sum2 >> 8);
|
|
||||||
}
|
|
||||||
/* Second reduction step to reduce sums to 8 bits */
|
|
||||||
sum1 = (sum1 & 0xff) + (sum1 >> 8);
|
|
||||||
sum2 = (sum2 & 0xff) + (sum2 >> 8);
|
|
||||||
return (sum2 << 8) | sum1;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,8 +27,17 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Fletcher's 16 bit checksum context struct
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
uint16_t sum1; /**< First sum of the checksum */
|
||||||
|
uint16_t sum2; /**< Second sum of the checksum */
|
||||||
|
} fletcher16_ctx_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Fletcher's 16 bit checksum
|
* @brief Fletcher's 16 bit checksum
|
||||||
|
* @anchor fletcher16_full
|
||||||
*
|
*
|
||||||
* found on
|
* found on
|
||||||
* http://en.wikipedia.org/w/index.php?title=Fletcher%27s_checksum&oldid=661273016#Optimizations
|
* http://en.wikipedia.org/w/index.php?title=Fletcher%27s_checksum&oldid=661273016#Optimizations
|
||||||
@ -41,6 +50,34 @@ extern "C" {
|
|||||||
*/
|
*/
|
||||||
uint16_t fletcher16(const uint8_t *buf, size_t bytes);
|
uint16_t fletcher16(const uint8_t *buf, size_t bytes);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize a fletcher16 context
|
||||||
|
*
|
||||||
|
* Multi-part version of @ref fletcher16_full.
|
||||||
|
*
|
||||||
|
* @param[in] ctx fletcher16 context to initialize
|
||||||
|
*/
|
||||||
|
void fletcher16_init(fletcher16_ctx_t *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Update the fletcher16 context with new data
|
||||||
|
*
|
||||||
|
* @param[in] ctx fletcher16 context
|
||||||
|
* @param[in] data Data to add to the context
|
||||||
|
* @param[in] len Length of the data
|
||||||
|
*/
|
||||||
|
void fletcher16_update(fletcher16_ctx_t *ctx, const uint8_t *data, size_t len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Finalize the checksum operation and return the checksum
|
||||||
|
*
|
||||||
|
* @param[in] ctx fletcher16 context
|
||||||
|
*
|
||||||
|
* @return Checksum of the data
|
||||||
|
*/
|
||||||
|
uint16_t fletcher16_finish(fletcher16_ctx_t *ctx);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@ -72,6 +72,19 @@ static void test_checksum_fletcher16_wrap_around(void)
|
|||||||
sizeof(wrap_around_data) - 1, expect));
|
sizeof(wrap_around_data) - 1, expect));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_checksum_fletcher16_multipart(void)
|
||||||
|
{
|
||||||
|
static const uint16_t expect = 0xf122;
|
||||||
|
static const size_t half_len = sizeof(wrap_around_data)/2;
|
||||||
|
fletcher16_ctx_t ctx;
|
||||||
|
|
||||||
|
fletcher16_init(&ctx);
|
||||||
|
fletcher16_update(&ctx, wrap_around_data, half_len);
|
||||||
|
fletcher16_update(&ctx, wrap_around_data + half_len,
|
||||||
|
sizeof(wrap_around_data) - half_len - 1);
|
||||||
|
TEST_ASSERT_EQUAL_INT(expect, fletcher16_finish(&ctx));
|
||||||
|
}
|
||||||
|
|
||||||
Test *tests_checksum_fletcher16_tests(void)
|
Test *tests_checksum_fletcher16_tests(void)
|
||||||
{
|
{
|
||||||
EMB_UNIT_TESTFIXTURES(fixtures) {
|
EMB_UNIT_TESTFIXTURES(fixtures) {
|
||||||
@ -79,6 +92,7 @@ Test *tests_checksum_fletcher16_tests(void)
|
|||||||
new_TestFixture(test_checksum_fletcher16_0to1_undetected),
|
new_TestFixture(test_checksum_fletcher16_0to1_undetected),
|
||||||
new_TestFixture(test_checksum_fletcher16_atoe),
|
new_TestFixture(test_checksum_fletcher16_atoe),
|
||||||
new_TestFixture(test_checksum_fletcher16_wrap_around),
|
new_TestFixture(test_checksum_fletcher16_wrap_around),
|
||||||
|
new_TestFixture(test_checksum_fletcher16_multipart),
|
||||||
};
|
};
|
||||||
|
|
||||||
EMB_UNIT_TESTCALLER(checksum_fletcher16_tests, NULL, NULL, fixtures);
|
EMB_UNIT_TESTCALLER(checksum_fletcher16_tests, NULL, NULL, fixtures);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user