From 5923f6b13745827b763bde470de8aa1bb03cb7ff Mon Sep 17 00:00:00 2001 From: Kaspar Schleiser Date: Mon, 7 Dec 2015 16:35:19 +0100 Subject: [PATCH] sys: fmt: add fmt_u64_dec() --- sys/fmt/fmt.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++ sys/include/fmt.h | 24 ++++++++++++++++++ 2 files changed, 86 insertions(+) diff --git a/sys/fmt/fmt.c b/sys/fmt/fmt.c index ab2d594ad5..0c169e6211 100644 --- a/sys/fmt/fmt.c +++ b/sys/fmt/fmt.c @@ -22,6 +22,7 @@ #include #include #include +#include #ifdef __WITH_AVRLIBC__ #include /* for fwrite() */ @@ -102,6 +103,60 @@ size_t fmt_u64_hex(char *out, uint64_t val) return fmt_bytes_hex_reverse(out, (uint8_t*) &val, 8); } +size_t fmt_u64_dec(char *out, uint64_t val) +{ + uint32_t d[5]; + uint32_t q; + size_t len = 0; + + d[0] = val & 0xFFFF; + d[1] = (val>>16) & 0xFFFF; + d[2] = (val>>32) & 0xFFFF; + d[3] = (val>>48) & 0xFFFF; + + d[0] = 656 * d[3] + 7296 * d[2] + 5536 * d[1] + d[0]; + q = d[0] / 10000; + d[0] = d[0] % 10000; + + d[1] = q + 7671 * d[3] + 9496 * d[2] + 6 * d[1]; + q = d[1] / 10000; + d[1] = d[1] % 10000; + + d[2] = q + 4749 * d[3] + 42 * d[2]; + q = d[2] / 10000; + d[2] = d[2] % 10000; + + d[3] = q + 281 * d[3]; + q = d[3] / 10000; + d[3] = d[3] % 10000; + + d[4] = q; + + int first = 4; + + while (!d[first] && first) { + first--; + } + + len = fmt_u32_dec(out, d[first]); + int total_len = len + (first * 4); + + if (out) { + out += len; + memset(out, '0', total_len - len); + while(first) { + first--; + if (d[first]) { + size_t tmp = fmt_u32_dec(NULL, d[first]); + fmt_u32_dec(out+(4-tmp), d[first]); + } + out += 4; + } + } + + return total_len; +} + size_t fmt_u32_dec(char *out, uint32_t val) { size_t len = 1; @@ -248,6 +303,13 @@ void print_u64_hex(uint64_t val) print_u32_hex(val); } +void print_u64_dec(uint64_t val) +{ + char buf[18]; + size_t len = fmt_u64_dec(buf, val); + print(buf, len); +} + void print_str(const char* str) { print(str, fmt_strlen(str)); diff --git a/sys/include/fmt.h b/sys/include/fmt.h index 02162504d9..09ce002482 100644 --- a/sys/include/fmt.h +++ b/sys/include/fmt.h @@ -101,6 +101,21 @@ size_t fmt_u64_hex(char *out, uint64_t val); */ size_t fmt_u32_dec(char *out, uint32_t val); +/** + * @brief Convert a uint64 value to decimal string. + * + * If @p out is NULL, will only return the number of bytes that would have + * been written. + * + * @note This adds ~400b of code when used. + * + * @param[out] out Pointer to output buffer, or NULL + * @param[in] val Value to convert + * + * @return nr of digits written to (or needed in) @p out + */ +size_t fmt_u64_dec(char *out, uint64_t val); + /** * @brief Convert a uint16 value to decimal string. * @@ -244,6 +259,15 @@ void print_u32_hex(uint32_t val); */ void print_u64_hex(uint64_t val); +/** + * @brief Print uint64 value as decimal to stdout + * + * @note This used fmt_u64_dec(), which uses ~400b of code. + * + * @param[in] val Value to print + */ +void print_u64_dec(uint64_t val); + /** * @brief Print null-terminated string to stdout *