diff --git a/sys/fmt/fmt.c b/sys/fmt/fmt.c index 4000943f7ddea6c1e32e49e734f43d3831529104..fd1a88d41d0d5cb2f0ef01e45061c2afc3a5859e 100644 --- a/sys/fmt/fmt.c +++ b/sys/fmt/fmt.c @@ -46,6 +46,8 @@ static const uint32_t _tenmap[] = { 10000000LU, }; +#define TENMAP_SIZE (sizeof(_tenmap) / sizeof(_tenmap[0])) + static inline int _is_digit(char c) { return (c >= '0' && c <= '9'); @@ -200,58 +202,17 @@ size_t fmt_s16_dec(char *out, int16_t val) size_t fmt_s16_dfp(char *out, int16_t val, unsigned fp_digits) { - int16_t absolute, divider; - size_t pos = 0; - size_t div_len, len; - unsigned e; - char tmp[4]; - - if (fp_digits > 4) { - return 0; - } - if (fp_digits == 0) { - return fmt_s16_dec(out, val); - } - if (val < 0) { - if (out) { - out[pos++] = '-'; - } - val = -val; - } - - e = _tenmap[fp_digits]; - absolute = (val / (int)e); - divider = val - (absolute * e); - - pos += fmt_s16_dec(&out[pos], absolute); - - if (!out) { - return pos + 1 + fp_digits; /* abs len + decimal point + divider */ - } - - out[pos++] = '.'; - len = pos + fp_digits; - div_len = fmt_s16_dec(tmp, divider); - - while (pos < (len - div_len)) { - out[pos++] = '0'; - } - for (size_t i = 0; i < div_len; i++) { - out[pos++] = tmp[i]; - } - - return pos; + return fmt_s32_dfp(out, val, fp_digits); } size_t fmt_s32_dfp(char *out, int32_t val, unsigned fp_digits) { + assert(fp_digits < TENMAP_SIZE); + int32_t absolute, divider; unsigned div_len, len, pos = 0; char tmp[9]; - if (fp_digits > 9) { - return 0; - } if (fp_digits == 0) { return fmt_s32_dec(out, val); } @@ -292,7 +253,7 @@ size_t fmt_s32_dfp(char *out, int32_t val, unsigned fp_digits) */ size_t fmt_float(char *out, float f, unsigned precision) { - assert (precision <= 7); + assert(precision < TENMAP_SIZE); unsigned negative = (f < 0); uint32_t integer; diff --git a/sys/include/fmt.h b/sys/include/fmt.h index afdb5e2d9525f9b8a42ad20a10f156f2d044675c..e1d0dfb38c5c81920937373b5cb36694afa19572 100644 --- a/sys/include/fmt.h +++ b/sys/include/fmt.h @@ -194,12 +194,13 @@ size_t fmt_s16_dec(char *out, int16_t val); * If @p out is NULL, will only return the number of bytes that would have * been written. * + * @pre fp_digits < 8 (TENMAP_SIZE) + * * @param[out] out Pointer to the output buffer, or NULL - * @param[in] val Fixed point value, MUST be <= 4 + * @param[in] val Fixed point value * @param[in] fp_digits Number of digits after the decimal point * * @return Length of the resulting string - * @return 0 if @p fp_digits is > 4 */ size_t fmt_s16_dfp(char *out, int16_t val, unsigned fp_digits); @@ -222,12 +223,13 @@ size_t fmt_s16_dfp(char *out, int16_t val, unsigned fp_digits); * If @p out is NULL, will only return the number of bytes that would have * been written. * + * @pre fp_digits < 8 (TENMAP_SIZE) + * * @param[out] out Pointer to the output buffer, or NULL * @param[in] val Fixed point value - * @param[in] fp_digits Number of digits after the decimal point, MUST be <= 9 + * @param[in] fp_digits Number of digits after the decimal point * * @return Length of the resulting string - * @return 0 if @p fp_digits is > 9 */ size_t fmt_s32_dfp(char *out, int32_t val, unsigned fp_digits); @@ -236,14 +238,18 @@ size_t fmt_s32_dfp(char *out, int32_t val, unsigned fp_digits); * * Converts float value @p f to string * - * @pre -2^32 < f < 2^32 + * If @p out is NULL, will only return the number of bytes that would have + * been written. * - * @note This function is using floating point math. It pulls in about 2.4k - * bytes of code on ARM Cortex-M platforms. + * @attention This function is using floating point math. + * It pulls in about 2.4k bytes of code on ARM Cortex-M platforms. + * + * @pre -2^32 < f < 2^32 + * @pre precision < 8 (TENMAP_SIZE) * * @param[out] out string to write to (or NULL) * @param[in] f float value to convert - * @param[in] precision number of digits after decimal point (<=7) + * @param[in] precision number of digits after decimal point * * @returns nr of bytes the function did or would write to out */ @@ -340,18 +346,19 @@ void print_u64_dec(uint64_t val); /** * @brief Print float value * + * @note See fmt_float for code size warning! + * * @pre -2^32 < f < 2^32 + * @pre precision < TENMAP_SIZE (== 8) * * @param[in] f float value to print - * @param[in] precision number of digits after decimal point (<=7) + * @param[in] precision number of digits after decimal point */ void print_float(float f, unsigned precision); /** * @brief Print null-terminated string to stdout * - * @note See fmt_float for code size warning! - * * @param[in] str Pointer to string to print */ void print_str(const char* str); diff --git a/tests/unittests/tests-fmt/tests-fmt.c b/tests/unittests/tests-fmt/tests-fmt.c index 251f05cdf7564cf28516f1c736ea94f35953193d..25a94297fa8cfe6257a84ab84806cecc8cb92aff 100644 --- a/tests/unittests/tests-fmt/tests-fmt.c +++ b/tests/unittests/tests-fmt/tests-fmt.c @@ -36,7 +36,7 @@ static void test_fmt_byte_hex(void) static void test_fmt_bytes_hex_reverse(void) { - char out[10]; + char out[9] = "--------"; uint8_t val[4] = { 9, 8, 7, 6 }; uint8_t bytes = 0; @@ -105,7 +105,7 @@ static void test_fmt_u16_dec(void) static void test_fmt_s32_dec(void) { - char out[8] = "--------"; + char out[6] = "-----"; int32_t val = 9876; uint8_t chars = 0; @@ -123,7 +123,7 @@ static void test_fmt_s32_dec(void) static void test_fmt_u64_dec_a(void) { - char out[21] = "------------------"; + char out[21] = "--------------------"; uint64_t val = 0; uint8_t chars = 0; @@ -159,7 +159,7 @@ static void test_fmt_u64_dec_c(void) static void test_fmt_s16_dec(void) { - char out[7] = "-------"; + char out[7] = "------"; int16_t val; size_t len; @@ -184,7 +184,7 @@ static void test_fmt_s16_dec(void) static void test_fmt_s16_dfp(void) { - char out[8] = "--------"; + char out[9] = "--------"; int16_t val; unsigned fpp; size_t len; @@ -239,11 +239,11 @@ static void test_fmt_s16_dfp(void) TEST_ASSERT_EQUAL_STRING("-12345", (char *)out); val = 31987; - fpp = 5; + fpp = 6; len = fmt_s16_dfp(out, val, fpp); out[len] = '\0'; - TEST_ASSERT_EQUAL_INT(0, len); - TEST_ASSERT_EQUAL_STRING("", (char *)out); + TEST_ASSERT_EQUAL_INT(8, len); + TEST_ASSERT_EQUAL_STRING("0.031987", (char *)out); } static void test_fmt_s32_dfp(void) @@ -254,11 +254,11 @@ static void test_fmt_s32_dfp(void) size_t len; val = 0; - fpp = 8; + fpp = 7; len = fmt_s32_dfp(out, val, fpp); out[len] = '\0'; - TEST_ASSERT_EQUAL_INT(10, len); - TEST_ASSERT_EQUAL_STRING("0.00000000", (char *)out); + TEST_ASSERT_EQUAL_INT(9, len); + TEST_ASSERT_EQUAL_STRING("0.0000000", (char *)out); val = 123456789; fpp = 7; @@ -282,11 +282,11 @@ static void test_fmt_s32_dfp(void) TEST_ASSERT_EQUAL_STRING("-3.14159", (char *)out); val = -23; - fpp = 9; + fpp = 7; len = fmt_s32_dfp(out, val, fpp); out[len] = '\0'; - TEST_ASSERT_EQUAL_INT(12, len); - TEST_ASSERT_EQUAL_STRING("-0.000000023", (char *)out); + TEST_ASSERT_EQUAL_INT(10, len); + TEST_ASSERT_EQUAL_STRING("-0.0000023", (char *)out); val = 50; fpp = 6; @@ -301,13 +301,6 @@ static void test_fmt_s32_dfp(void) out[len] = '\0'; TEST_ASSERT_EQUAL_INT(10, len); TEST_ASSERT_EQUAL_STRING("-123456789", (char *)out); - - val = 31987; - fpp = 10; - len = fmt_s32_dfp(out, val, fpp); - out[len] = '\0'; - TEST_ASSERT_EQUAL_INT(0, len); - TEST_ASSERT_EQUAL_STRING("", (char *)out); } static void test_fmt_strlen(void)