diff --git a/lib_standard_app/format.c b/lib_standard_app/format.c index 9c889f6ee..a38d5e4e8 100644 --- a/lib_standard_app/format.c +++ b/lib_standard_app/format.c @@ -129,6 +129,24 @@ bool format_fpu64(char *dst, size_t dst_len, const uint64_t value, uint8_t decim return true; } +bool format_fpu64_trimmed(char *dst, size_t dst_len, const uint64_t value, uint8_t decimals) { + if (!format_fpu64(dst, dst_len, value, decimals)) { + return false; + } + + size_t len = strlen(dst); + + while (len > 0 && (dst[len - 1] == '0' || dst[len - 1] == '.')) { + if (dst[len - 1] == '.') { + dst[len - 1] = '\0'; + return true; + } + len--; + } + dst[len] = '\0'; + return true; +} + int format_hex(const uint8_t *in, size_t in_len, char *out, size_t out_len) { if (out_len < 2 * in_len + 1) { return -1; diff --git a/lib_standard_app/format.h b/lib_standard_app/format.h index f1457483a..00242d53b 100644 --- a/lib_standard_app/format.h +++ b/lib_standard_app/format.h @@ -51,6 +51,23 @@ bool format_u64(char *dst, size_t dst_len, uint64_t value); */ bool format_fpu64(char *dst, size_t dst_len, const uint64_t value, uint8_t decimals); +/** + * Format 64-bit unsigned integer as string with decimals and trimmed zeros and dot. + * + * @param[out] dst + * Pointer to output string. + * @param[in] dst_len + * Length of output string. + * @param[in] value + * 64-bit unsigned integer to format. + * @param[in] decimals + * Number of digits after decimal separator. + * + * @return true if success, false otherwise. + * + */ +bool format_fpu64_trimmed(char *dst, size_t dst_len, const uint64_t value, uint8_t decimals); + /** * Format byte buffer to uppercase hexadecimal string. * diff --git a/unit-tests/lib_standard_app/test_format.c b/unit-tests/lib_standard_app/test_format.c index 54fab79c7..d1092dde0 100644 --- a/unit-tests/lib_standard_app/test_format.c +++ b/unit-tests/lib_standard_app/test_format.c @@ -82,6 +82,32 @@ static void test_format_fpu64(void **state) { assert_false(format_fpu64(temp2, sizeof(temp2) - 20, amount, 18)); } +static void test_format_fpu64_trimmed(void **state) { + (void) state; + + char temp[22] = {0}; + + uint64_t amount = 100000000ull; // satoshi + memset(temp, 0, sizeof(temp)); + assert_true(format_fpu64_trimmed(temp, sizeof(temp), amount, 8)); + assert_string_equal(temp, "1"); // BTC + + amount = 24964823ull; // satoshi + memset(temp, 0, sizeof(temp)); + assert_true(format_fpu64_trimmed(temp, sizeof(temp), amount, 8)); + assert_string_equal(temp, "0.24964823"); // BTC + + amount = 100ull; // satoshi + memset(temp, 0, sizeof(temp)); + assert_true(format_fpu64_trimmed(temp, sizeof(temp), amount, 8)); + assert_string_equal(temp, "0.000001"); // BTC + + amount = 1000000000ull; // satoshi + memset(temp, 0, sizeof(temp)); + assert_true(format_fpu64_trimmed(temp, sizeof(temp), amount, 8)); + assert_string_equal(temp, "10"); // BTC +} + static void test_format_hex(void **state) { (void) state; @@ -99,6 +125,7 @@ int main() { const struct CMUnitTest tests[] = {cmocka_unit_test(test_format_i64), cmocka_unit_test(test_format_u64), cmocka_unit_test(test_format_fpu64), + cmocka_unit_test(test_format_fpu64_trimmed), cmocka_unit_test(test_format_hex)}; return cmocka_run_group_tests(tests, NULL, NULL);