mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-28 23:09:46 +01:00
Fletcher32: Add incremental API
This commit is contained in:
parent
3a4ec8d21e
commit
31df2ba0aa
@ -21,21 +21,43 @@
|
||||
#include "unaligned.h"
|
||||
#include "checksum/fletcher32.h"
|
||||
|
||||
uint32_t fletcher32(const uint16_t *data, size_t words)
|
||||
static inline void _reduce(fletcher32_ctx_t *ctx)
|
||||
{
|
||||
uint32_t sum1 = 0xffff, sum2 = 0xffff;
|
||||
ctx->sum1 = (ctx->sum1 & 0xffff) + (ctx->sum1 >> 16);
|
||||
ctx->sum2 = (ctx->sum2 & 0xffff) + (ctx->sum2 >> 16);
|
||||
}
|
||||
|
||||
void fletcher32_init(fletcher32_ctx_t *ctx)
|
||||
{
|
||||
ctx->sum1 = 0xffff;
|
||||
ctx->sum2 = 0xffff;
|
||||
}
|
||||
|
||||
uint32_t fletcher32_finish(fletcher32_ctx_t *ctx)
|
||||
{
|
||||
/* Second reduction step to reduce sums to 8 bits */
|
||||
_reduce(ctx);
|
||||
return (ctx->sum2 << 16) | ctx->sum1;
|
||||
}
|
||||
|
||||
void fletcher32_update(fletcher32_ctx_t *ctx, const void *data, size_t words)
|
||||
{
|
||||
const uint16_t *u16_data = (const uint16_t*)data;
|
||||
while (words) {
|
||||
unsigned tlen = words > 359 ? 359 : words;
|
||||
words -= tlen;
|
||||
do {
|
||||
sum2 += sum1 += unaligned_get_u16(data++);
|
||||
ctx->sum1 += unaligned_get_u16(u16_data++);
|
||||
ctx->sum2 += ctx->sum1;
|
||||
} while (--tlen);
|
||||
sum1 = (sum1 & 0xffff) + (sum1 >> 16);
|
||||
sum2 = (sum2 & 0xffff) + (sum2 >> 16);
|
||||
_reduce(ctx);
|
||||
}
|
||||
/* Second reduction step to reduce sums to 16 bits */
|
||||
sum1 = (sum1 & 0xffff) + (sum1 >> 16);
|
||||
sum2 = (sum2 & 0xffff) + (sum2 >> 16);
|
||||
return (sum2 << 16) | sum1;
|
||||
}
|
||||
|
||||
uint32_t fletcher32(const uint16_t *data, size_t words)
|
||||
{
|
||||
fletcher32_ctx_t ctx;
|
||||
fletcher32_init(&ctx);
|
||||
fletcher32_update(&ctx, data, words);
|
||||
return fletcher32_finish(&ctx);
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
*
|
||||
* @file
|
||||
* @author Joakim Nohlgård <joakim.nohlgard@eistec.se>
|
||||
* @author Koen Zandberg <koen@bergzand.net>
|
||||
*/
|
||||
|
||||
#ifndef CHECKSUM_FLETCHER32_H
|
||||
@ -27,6 +28,14 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Fletcher's 32 bit checksum context struct
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t sum1; /**< First sum of the checksum */
|
||||
uint32_t sum2; /**< Second sum of the checksum */
|
||||
} fletcher32_ctx_t;
|
||||
|
||||
/**
|
||||
* @brief Fletcher's 32 bit checksum
|
||||
*
|
||||
@ -43,6 +52,37 @@ extern "C" {
|
||||
*/
|
||||
uint32_t fletcher32(const uint16_t *buf, size_t words);
|
||||
|
||||
/**
|
||||
* @brief Initialize a fletcher32 context
|
||||
*
|
||||
* Multi-part version of @ref fletcher32.
|
||||
*
|
||||
* @param[in] ctx fletcher32 context to initialize
|
||||
*/
|
||||
void fletcher32_init(fletcher32_ctx_t *ctx);
|
||||
|
||||
/**
|
||||
* @brief Incrementally update the fletcher32 context with new data. Can be an arbitrary amount of
|
||||
* times with new data to checksum.
|
||||
*
|
||||
* @note @p words is the number of 16 bit words in the buffer
|
||||
* @note @p data should contain an integer number of 16 bit words
|
||||
*
|
||||
* @param[in] ctx fletcher32 context
|
||||
* @param[in] data Data to add to the context
|
||||
* @param[in] words Length of the data in 16 bit words
|
||||
*/
|
||||
void fletcher32_update(fletcher32_ctx_t *ctx, const void *data, size_t words);
|
||||
|
||||
/**
|
||||
* @brief Finalize the checksum operation and return the checksum
|
||||
*
|
||||
* @param[in] ctx fletcher32 context
|
||||
*
|
||||
* @return 32 bit sized hash in the interval [1..2^32]
|
||||
*/
|
||||
uint32_t fletcher32_finish(fletcher32_ctx_t *ctx);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -85,6 +85,20 @@ static void test_checksum_fletcher32_wrap_around(void)
|
||||
sizeof(wrap_around_data) - 1, expect));
|
||||
}
|
||||
|
||||
static void test_checksum_fletcher32_wrap_around_piecewise(void)
|
||||
{
|
||||
/* XXX: not verified with external implementation yet */
|
||||
uint32_t expect = 0x5bac8c3d;
|
||||
fletcher32_ctx_t ctx;
|
||||
fletcher32_init(&ctx);
|
||||
size_t full_len = sizeof(wrap_around_data) - 1;
|
||||
size_t initial_len = full_len / 2;
|
||||
fletcher32_update(&ctx, wrap_around_data, initial_len / 2);
|
||||
fletcher32_update(&ctx, (wrap_around_data + initial_len), (full_len - initial_len) / 2);
|
||||
uint32_t result = fletcher32_finish(&ctx);
|
||||
TEST_ASSERT_EQUAL_INT(result, expect);
|
||||
}
|
||||
|
||||
Test *tests_checksum_fletcher32_tests(void)
|
||||
{
|
||||
EMB_UNIT_TESTFIXTURES(fixtures) {
|
||||
@ -92,6 +106,7 @@ Test *tests_checksum_fletcher32_tests(void)
|
||||
new_TestFixture(test_checksum_fletcher32_0to1_undetected),
|
||||
new_TestFixture(test_checksum_fletcher32_atof),
|
||||
new_TestFixture(test_checksum_fletcher32_wrap_around),
|
||||
new_TestFixture(test_checksum_fletcher32_wrap_around_piecewise),
|
||||
};
|
||||
|
||||
EMB_UNIT_TESTCALLER(checksum_fletcher32_tests, NULL, NULL, fixtures);
|
||||
|
Loading…
Reference in New Issue
Block a user