1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-12-26 15:03:53 +01:00

sys/bcd: add bcd_buf_to_u32() and bcd_buf_from_str()

This commit is contained in:
Benjamin Valentin 2025-04-23 19:20:11 +02:00
parent f045ccc34a
commit 2c43918792
2 changed files with 98 additions and 1 deletions

View File

@ -56,3 +56,61 @@ int bcd_buf_from_u32(uint32_t val, void *dst, size_t len)
return (uintptr_t)tgt - (uintptr_t)dst;
}
/* Use the same code for 32 bit and 64 bit sum */
#define _BCD_CONVERT(sum, len) \
for (int i = len * 2 - 1; i >= 0; --i) { \
uint8_t digit = i & 1 \
? bcd[i >> 1] >> 4 \
: bcd[i >> 1] & 0xF; \
sum = sum * 10 + digit; \
}
uint32_t bcd_buf_to_u32(const void *src, size_t len)
{
const uint8_t *bcd = src;
uint32_t sum = 0;
_BCD_CONVERT(sum, len);
return sum;
}
uint64_t bcd_buf_to_u64(const void *src, size_t len)
{
const uint8_t *bcd = src;
uint64_t sum = 0;
_BCD_CONVERT(sum, len);
return sum;
}
static bool _is_digit(char c)
{
return c >= '0' && c <= '9';
}
int bcd_buf_from_str(const char *str, size_t len, void *dst, size_t dst_len)
{
uint8_t *bcd = dst;
memset(dst, 0, dst_len);
dst_len *= 2;
uint8_t i = 0;
for (int j = len; j >= 0; --j) {
if (i == dst_len) {
return -ENOBUFS;
}
if (!_is_digit(str[j])) {
continue;
}
uint8_t d = str[j] & 0xF;
bcd[i >> 1] |= i & 1
? d << 4
: d;
++i;
}
return (i & 1) + (i >> 1);
}

View File

@ -16,10 +16,12 @@
* @brief BCD definitions
*
* @author Martine Lenders <m.lenders@fu-berlin.de>
* @author Benjamin Valentin <benjamin.valentin@ml-pa.com>
*/
#ifndef BCD_H
#define BCD_H
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
@ -64,11 +66,48 @@ static inline uint8_t bcd_to_byte(uint8_t bcd)
* @param[in] len Size of the destination buffer
*
* @return number of bytes written
* @return -ENOBUFS if @p dst is not large enough
* @retval -ENOBUFS if @p dst is not large enough
* In that case the state of @p dst is undefined.
*/
int bcd_buf_from_u32(uint32_t val, void *dst, size_t len);
/**
* @brief Convert a BCD buffer into it's binary representation
* (This will reverse @ref bcd_buf_from_u32)
*
* @param[in] src The BCD buffer to convert
* @param[in] len Bytes in @p src
*
* @returns decimal representation of @p src
*/
uint32_t bcd_buf_to_u32(const void *src, size_t len);
/**
* @brief Convert a BCD buffer into it's binary representation
*
* @param[in] src The BCD buffer to convert
* @param[in] len Bytes in @p src
*
* @returns decimal representation of @p src
*/
uint64_t bcd_buf_to_u64(const void *src, size_t len);
/**
* @brief Convert a string into a BCD buffer
* Digits may be separated by any character.
*
* @param[in] str Input string
* @param[in] str_len Length of the input string
* @param[out] dst Destination buffer
* @param[in] dst_len Size of the destination buffer
*
* @return number of bytes written
* @retval -ENOBUFS if @p dst is not large enough
* In that case the state of @p dst is undefined.
*/
int bcd_buf_from_str(const char *str, size_t str_len,
void *dst, size_t dst_len);
#ifdef __cplusplus
}
#endif