From fcd43b93ac06bf396ff54373997d374b0e4a5bd1 Mon Sep 17 00:00:00 2001 From: matejcik Date: Tue, 2 Aug 2022 15:17:24 +0200 Subject: [PATCH] feat(crypto): add thousands separator to bn_format --- crypto/address.c | 2 +- crypto/bignum.c | 31 ++++++-- crypto/bignum.h | 15 +++- crypto/fuzzer/fuzzer.c | 2 +- crypto/nem.c | 2 +- crypto/tests/test_bignum.py | 29 ++++--- crypto/tests/test_check.c | 146 ++++++++++++++++++++++++++---------- 7 files changed, 164 insertions(+), 63 deletions(-) diff --git a/crypto/address.c b/crypto/address.c index f639b1db9..598a49f71 100644 --- a/crypto/address.c +++ b/crypto/address.c @@ -73,7 +73,7 @@ void ethereum_address_checksum(const uint8_t *addr, char *address, bool rskip60, keccak_256_Init(&ctx); if (rskip60) { char prefix[16] = {0}; - int prefix_size = bn_format_uint64(chain_id, NULL, "0x", 0, 0, false, + int prefix_size = bn_format_uint64(chain_id, NULL, "0x", 0, 0, false, 0, prefix, sizeof(prefix)); keccak_Update(&ctx, (const uint8_t *)prefix, prefix_size); } diff --git a/crypto/bignum.c b/crypto/bignum.c index e2bb9a129..b23adf7a8 100644 --- a/crypto/bignum.c +++ b/crypto/bignum.c @@ -1670,27 +1670,31 @@ void bn_divmod10(bignum256 *x, uint32_t *r) { bn_long_division(x, 10, x, r); } // Assumes output is an array of length output_length // The function doesn't have neither constant control flow nor constant memory // access flow with regard to any its argument -size_t bn_format(const bignum256 *amount, const char *prefix, const char *suffix, unsigned int decimals, int exponent, bool trailing, char *output, size_t output_length) { +size_t bn_format(const bignum256 *amount, const char *prefix, const char *suffix, unsigned int decimals, int exponent, bool trailing, char thousands, char *output, size_t output_length) { /* Python prototype of the function: - def format(amount, prefix, suffix, decimals, exponent, trailing): + def format(amount, prefix, suffix, decimals, exponent, trailing, thousands): if exponent >= 0: - amount *= 10 ** exponent + amount *= 10**exponent else: amount //= 10 ** (-exponent) d = pow(10, decimals) + integer_part = amount // d + integer_str = f"{integer_part:,}".replace(",", thousands or "") + if decimals: - output = "%d.%0*d" % (amount // d, decimals, amount % d) + decimal_part = amount % d + decimal_str = f".{decimal_part:0{decimals}d}" if not trailing: - output = output.rstrip("0").rstrip(".") + decimal_str = decimal_str.rstrip("0").rstrip(".") else: - output = "%d" % (amount // d) + decimal_str = "" - return prefix + output + suffix + return prefix + integer_str + decimal_str + suffix */ // Auxiliary macro for bn_format @@ -1773,18 +1777,29 @@ size_t bn_format(const bignum256 *amount, const char *prefix, const char *suffix { // Add integer-part digits of amount // Add trailing zeroes + int digits = 0; if (!bn_is_zero(&temp)) { for (; exponent > 0; --exponent) { + ++digits; BN_FORMAT_ADD_OUTPUT_CHAR('0') + if (thousands != 0 && digits % 3 == 0) { + BN_FORMAT_ADD_OUTPUT_CHAR(thousands) + } } } // decimals == 0 && exponent == 0 // Add significant digits + bool is_zero = false; do { + ++digits; bn_divmod10(&temp, &digit); + is_zero = bn_is_zero(&temp); BN_FORMAT_ADD_OUTPUT_CHAR('0' + digit) - } while (!bn_is_zero(&temp)); + if (thousands != 0 && !is_zero && digits % 3 == 0) { + BN_FORMAT_ADD_OUTPUT_CHAR(thousands) + } + } while (!is_zero); } // Add prefix diff --git a/crypto/bignum.h b/crypto/bignum.h index fcae2f773..f9213fbe7 100644 --- a/crypto/bignum.h +++ b/crypto/bignum.h @@ -114,7 +114,8 @@ void bn_divmod1000(bignum256 *x, uint32_t *r); void bn_inverse(bignum256 *x, const bignum256 *prime); size_t bn_format(const bignum256 *amount, const char *prefix, const char *suffix, unsigned int decimals, int exponent, - bool trailing, char *output, size_t output_length); + bool trailing, char thousands, char *output, + size_t output_length); // Returns (uint32_t) in_number // Assumes in_number < 2**32 @@ -149,13 +150,21 @@ static inline int bn_is_odd(const bignum256 *x) { return (x->val[0] & 1) == 1; } static inline size_t bn_format_uint64(uint64_t amount, const char *prefix, const char *suffix, unsigned int decimals, - int exponent, bool trailing, char *output, + int exponent, bool trailing, + char thousands, char *output, size_t output_length) { bignum256 bn_amount; bn_read_uint64(amount, &bn_amount); return bn_format(&bn_amount, prefix, suffix, decimals, exponent, trailing, - output, output_length); + thousands, output, output_length); +} + +static inline size_t bn_format_amount(uint64_t amount, const char *prefix, + const char *suffix, unsigned int decimals, + char *output, size_t output_length) { + return bn_format_uint64(amount, prefix, suffix, decimals, 0, false, ',', + output, output_length); } #if USE_BN_PRINT diff --git a/crypto/fuzzer/fuzzer.c b/crypto/fuzzer/fuzzer.c index 767eea4f9..41bff315d 100644 --- a/crypto/fuzzer/fuzzer.c +++ b/crypto/fuzzer/fuzzer.c @@ -165,7 +165,7 @@ int fuzz_bn_format(void) { } ret = bn_format(&target_bignum, prefix, suffix, decimals, exponent, trailing, - buf, FUZZ_BN_FORMAT_OUTPUT_BUFFER_SIZE); + 0, buf, FUZZ_BN_FORMAT_OUTPUT_BUFFER_SIZE); // basic sanity checks for r if (ret > FUZZ_BN_FORMAT_OUTPUT_BUFFER_SIZE) { diff --git a/crypto/nem.c b/crypto/nem.c index dd77241ce..57e18557d 100644 --- a/crypto/nem.c +++ b/crypto/nem.c @@ -118,7 +118,7 @@ static inline bool nem_write_mosaic_u64(nem_transaction_ctx *ctx, const char *name, uint64_t value) { char buffer[21] = {0}; - if (bn_format_uint64(value, NULL, NULL, 0, 0, false, buffer, + if (bn_format_uint64(value, NULL, NULL, 0, 0, false, 0, buffer, sizeof(buffer)) == 0) { return false; } diff --git a/crypto/tests/test_bignum.py b/crypto/tests/test_bignum.py index 1aab86a2d..99ad8c86e 100755 --- a/crypto/tests/test_bignum.py +++ b/crypto/tests/test_bignum.py @@ -5,6 +5,7 @@ import os import random from ctypes import ( c_bool, + c_char, c_int, c_size_t, c_uint, @@ -607,8 +608,8 @@ def assert_bn_divmod10(x_old): assert r == x_old % 10 -def assert_bn_format(x, prefix, suffix, decimals, exponent, trailing): - def format(amount, prefix, suffix, decimals, exponent, trailing): +def assert_bn_format(x, prefix, suffix, decimals, exponent, trailing, thousands): + def format(amount, prefix, suffix, decimals, exponent, trailing, thousands): if exponent >= 0: amount *= 10**exponent else: @@ -616,14 +617,18 @@ def assert_bn_format(x, prefix, suffix, decimals, exponent, trailing): d = pow(10, decimals) + integer_part = amount // d + integer_str = f"{integer_part:,}".replace(",", thousands or "") + if decimals: - output = "%d.%0*d" % (amount // d, decimals, amount % d) + decimal_part = amount % d + decimal_str = f".{decimal_part:0{decimals}d}" if not trailing: - output = output.rstrip("0").rstrip(".") + decimal_str = decimal_str.rstrip("0").rstrip(".") else: - output = "%d" % (amount // d) + decimal_str = "" - return prefix + output + suffix + return prefix + integer_str + decimal_str + suffix def string_to_char_p(string): return ctypes.create_string_buffer(string.encode("ascii")) @@ -641,11 +646,12 @@ def assert_bn_format(x, prefix, suffix, decimals, exponent, trailing): c_uint(decimals), c_int(exponent), c_bool(trailing), + c_char(0), output, c_size_t(output_length), ) - correct_output = format(x, prefix, suffix, decimals, exponent, trailing) + correct_output = format(x, prefix, suffix, decimals, exponent, trailing, "") correct_return_value = len(correct_output) if len(correct_output) >= output_length: correct_output = "" @@ -1018,15 +1024,16 @@ def test_bn_divmod10(r): @pytest.mark.parametrize( - "decimals,exponent,trailing,prefix,suffix,value", + "decimals,exponent,trailing,prefix,suffix,thousands,value", itertools.product( range(0, 5), range(-5, 5), [True, False], ["", "prefix"], ["", "suffix"], - [123, 120], + ["", ",", " "], + [123, 120, 123_456, 12_345, 100001, 10001000], ), ) -def test_bn_format(decimals, exponent, trailing, prefix, suffix, value): - assert_bn_format(value, prefix, suffix, decimals, exponent, trailing) +def test_bn_format(decimals, exponent, trailing, prefix, suffix, thousands, value): + assert_bn_format(value, prefix, suffix, decimals, exponent, trailing, thousands) diff --git a/crypto/tests/test_check.c b/crypto/tests/test_check.c index a95c35b66..562f06656 100644 --- a/crypto/tests/test_check.c +++ b/crypto/tests/test_check.c @@ -563,13 +563,13 @@ START_TEST(test_bignum_format_uint64) { uint64_t m = 1; for (int i = 0; i <= 19; i++, m *= 10) { sprintf(str, "%" PRIu64, m); - r = bn_format_uint64(m, NULL, NULL, 0, 0, false, buf, sizeof(buf)); + r = bn_format_uint64(m, NULL, NULL, 0, 0, false, 0, buf, sizeof(buf)); ck_assert_uint_eq(r, strlen(str)); ck_assert_str_eq(buf, str); uint64_t n = m - 1; sprintf(str, "%" PRIu64, n); - r = bn_format_uint64(n, NULL, NULL, 0, 0, false, buf, sizeof(buf)); + r = bn_format_uint64(n, NULL, NULL, 0, 0, false, 0, buf, sizeof(buf)); ck_assert_uint_eq(r, strlen(str)); ck_assert_str_eq(buf, str); } @@ -585,7 +585,7 @@ START_TEST(test_bignum_format) { fromhex( "0000000000000000000000000000000000000000000000000000000000000000"), &a); - r = bn_format(&a, NULL, NULL, 0, 0, false, buf, sizeof(buf)); + r = bn_format(&a, NULL, NULL, 0, 0, false, 0, buf, sizeof(buf)); ck_assert_uint_eq(r, 1); ck_assert_str_eq(buf, "0"); @@ -593,7 +593,7 @@ START_TEST(test_bignum_format) { fromhex( "0000000000000000000000000000000000000000000000000000000000000000"), &a); - r = bn_format(&a, NULL, NULL, 20, 0, true, buf, sizeof(buf)); + r = bn_format(&a, NULL, NULL, 20, 0, true, 0, buf, sizeof(buf)); ck_assert_uint_eq(r, 22); ck_assert_str_eq(buf, "0.00000000000000000000"); @@ -601,7 +601,7 @@ START_TEST(test_bignum_format) { fromhex( "0000000000000000000000000000000000000000000000000000000000000000"), &a); - r = bn_format(&a, NULL, NULL, 0, 5, false, buf, sizeof(buf)); + r = bn_format(&a, NULL, NULL, 0, 5, false, 0, buf, sizeof(buf)); ck_assert_uint_eq(r, 1); ck_assert_str_eq(buf, "0"); @@ -609,7 +609,7 @@ START_TEST(test_bignum_format) { fromhex( "0000000000000000000000000000000000000000000000000000000000000000"), &a); - r = bn_format(&a, NULL, NULL, 0, -5, false, buf, sizeof(buf)); + r = bn_format(&a, NULL, NULL, 0, -5, false, 0, buf, sizeof(buf)); ck_assert_uint_eq(r, 1); ck_assert_str_eq(buf, "0"); @@ -617,7 +617,7 @@ START_TEST(test_bignum_format) { fromhex( "0000000000000000000000000000000000000000000000000000000000000000"), &a); - r = bn_format(&a, "", "", 0, 0, false, buf, sizeof(buf)); + r = bn_format(&a, "", "", 0, 0, false, 0, buf, sizeof(buf)); ck_assert_uint_eq(r, 1); ck_assert_str_eq(buf, "0"); @@ -625,7 +625,7 @@ START_TEST(test_bignum_format) { fromhex( "0000000000000000000000000000000000000000000000000000000000000000"), &a); - r = bn_format(&a, NULL, "SFFX", 0, 0, false, buf, sizeof(buf)); + r = bn_format(&a, NULL, "SFFX", 0, 0, false, 0, buf, sizeof(buf)); ck_assert_uint_eq(r, 1 + 4); ck_assert_str_eq(buf, "0SFFX"); @@ -633,7 +633,7 @@ START_TEST(test_bignum_format) { fromhex( "0000000000000000000000000000000000000000000000000000000000000000"), &a); - r = bn_format(&a, "PRFX", NULL, 0, 0, false, buf, sizeof(buf)); + r = bn_format(&a, "PRFX", NULL, 0, 0, false, 0, buf, sizeof(buf)); ck_assert_uint_eq(r, 4 + 1); ck_assert_str_eq(buf, "PRFX0"); @@ -641,7 +641,7 @@ START_TEST(test_bignum_format) { fromhex( "0000000000000000000000000000000000000000000000000000000000000000"), &a); - r = bn_format(&a, "PRFX", "SFFX", 0, 0, false, buf, sizeof(buf)); + r = bn_format(&a, "PRFX", "SFFX", 0, 0, false, 0, buf, sizeof(buf)); ck_assert_uint_eq(r, 4 + 1 + 4); ck_assert_str_eq(buf, "PRFX0SFFX"); @@ -649,7 +649,7 @@ START_TEST(test_bignum_format) { fromhex( "0000000000000000000000000000000000000000000000000000000000000000"), &a); - r = bn_format(&a, NULL, NULL, 18, 0, false, buf, sizeof(buf)); + r = bn_format(&a, NULL, NULL, 18, 0, false, 0, buf, sizeof(buf)); ck_assert_uint_eq(r, 1); ck_assert_str_eq(buf, "0"); @@ -657,7 +657,7 @@ START_TEST(test_bignum_format) { fromhex( "0000000000000000000000000000000000000000000000000000000000000001"), &a); - r = bn_format(&a, NULL, NULL, 0, 0, false, buf, sizeof(buf)); + r = bn_format(&a, NULL, NULL, 0, 0, false, 0, buf, sizeof(buf)); ck_assert_uint_eq(r, 1); ck_assert_str_eq(buf, "1"); @@ -665,15 +665,55 @@ START_TEST(test_bignum_format) { fromhex( "0000000000000000000000000000000000000000000000000000000000000001"), &a); - r = bn_format(&a, NULL, NULL, 6, 6, true, buf, sizeof(buf)); + r = bn_format(&a, NULL, NULL, 6, 6, true, 0, buf, sizeof(buf)); ck_assert_uint_eq(r, 8); ck_assert_str_eq(buf, "1.000000"); + bn_read_be( + fromhex( + "0000000000000000000000000000000000000000000000000000000000000001"), + &a); + r = bn_format(&a, NULL, NULL, 1, 5, true, 0, buf, sizeof(buf)); + ck_assert_uint_eq(r, 7); + ck_assert_str_eq(buf, "10000.0"); + + bn_read_be( + fromhex( + "0000000000000000000000000000000000000000000000000000000000000001"), + &a); + r = bn_format(&a, NULL, NULL, 1, 5, true, ',', buf, sizeof(buf)); + ck_assert_uint_eq(r, 8); + ck_assert_str_eq(buf, "10,000.0"); + + bn_read_be( + fromhex( + "000000000000000000000000000000000000000000000000000000000001e240"), + &a); + r = bn_format(&a, NULL, NULL, 0, 0, true, ',', buf, sizeof(buf)); + ck_assert_uint_eq(r, 7); + ck_assert_str_eq(buf, "123,456"); + + bn_read_be( + fromhex( + "000000000000000000000000000000000000000000000000000000000001e240"), + &a); + r = bn_format(&a, NULL, NULL, 0, 1, true, ',', buf, sizeof(buf)); + ck_assert_uint_eq(r, 9); + ck_assert_str_eq(buf, "1,234,560"); + + bn_read_be( + fromhex( + "000000000000000000000000000000000000000000000000000000000001e240"), + &a); + r = bn_format(&a, NULL, NULL, 0, 5, true, ',', buf, sizeof(buf)); + ck_assert_uint_eq(r, 14); + ck_assert_str_eq(buf, "12,345,600,000"); + bn_read_be( fromhex( "0000000000000000000000000000000000000000000000000000000000000002"), &a); - r = bn_format(&a, NULL, NULL, 0, 0, false, buf, sizeof(buf)); + r = bn_format(&a, NULL, NULL, 0, 0, false, 0, buf, sizeof(buf)); ck_assert_uint_eq(r, 1); ck_assert_str_eq(buf, "2"); @@ -681,7 +721,7 @@ START_TEST(test_bignum_format) { fromhex( "0000000000000000000000000000000000000000000000000000000000000005"), &a); - r = bn_format(&a, NULL, NULL, 0, 0, false, buf, sizeof(buf)); + r = bn_format(&a, NULL, NULL, 0, 0, false, 0, buf, sizeof(buf)); ck_assert_uint_eq(r, 1); ck_assert_str_eq(buf, "5"); @@ -689,7 +729,7 @@ START_TEST(test_bignum_format) { fromhex( "0000000000000000000000000000000000000000000000000000000000000009"), &a); - r = bn_format(&a, NULL, NULL, 0, 0, false, buf, sizeof(buf)); + r = bn_format(&a, NULL, NULL, 0, 0, false, 0, buf, sizeof(buf)); ck_assert_uint_eq(r, 1); ck_assert_str_eq(buf, "9"); @@ -697,7 +737,7 @@ START_TEST(test_bignum_format) { fromhex( "000000000000000000000000000000000000000000000000000000000000000a"), &a); - r = bn_format(&a, NULL, NULL, 0, 0, false, buf, sizeof(buf)); + r = bn_format(&a, NULL, NULL, 0, 0, false, 0, buf, sizeof(buf)); ck_assert_uint_eq(r, 2); ck_assert_str_eq(buf, "10"); @@ -705,7 +745,7 @@ START_TEST(test_bignum_format) { fromhex( "0000000000000000000000000000000000000000000000000000000000000014"), &a); - r = bn_format(&a, NULL, NULL, 0, 0, false, buf, sizeof(buf)); + r = bn_format(&a, NULL, NULL, 0, 0, false, 0, buf, sizeof(buf)); ck_assert_uint_eq(r, 2); ck_assert_str_eq(buf, "20"); @@ -713,7 +753,7 @@ START_TEST(test_bignum_format) { fromhex( "0000000000000000000000000000000000000000000000000000000000000032"), &a); - r = bn_format(&a, NULL, NULL, 0, 0, false, buf, sizeof(buf)); + r = bn_format(&a, NULL, NULL, 0, 0, false, 0, buf, sizeof(buf)); ck_assert_uint_eq(r, 2); ck_assert_str_eq(buf, "50"); @@ -721,7 +761,7 @@ START_TEST(test_bignum_format) { fromhex( "0000000000000000000000000000000000000000000000000000000000000063"), &a); - r = bn_format(&a, NULL, NULL, 0, 0, false, buf, sizeof(buf)); + r = bn_format(&a, NULL, NULL, 0, 0, false, 0, buf, sizeof(buf)); ck_assert_uint_eq(r, 2); ck_assert_str_eq(buf, "99"); @@ -729,7 +769,7 @@ START_TEST(test_bignum_format) { fromhex( "0000000000000000000000000000000000000000000000000000000000000064"), &a); - r = bn_format(&a, NULL, NULL, 0, 0, false, buf, sizeof(buf)); + r = bn_format(&a, NULL, NULL, 0, 0, false, 0, buf, sizeof(buf)); ck_assert_uint_eq(r, 3); ck_assert_str_eq(buf, "100"); @@ -737,7 +777,7 @@ START_TEST(test_bignum_format) { fromhex( "00000000000000000000000000000000000000000000000000000000000000c8"), &a); - r = bn_format(&a, NULL, NULL, 0, 0, false, buf, sizeof(buf)); + r = bn_format(&a, NULL, NULL, 0, 0, false, 0, buf, sizeof(buf)); ck_assert_uint_eq(r, 3); ck_assert_str_eq(buf, "200"); @@ -745,7 +785,7 @@ START_TEST(test_bignum_format) { fromhex( "00000000000000000000000000000000000000000000000000000000000001f4"), &a); - r = bn_format(&a, NULL, NULL, 0, 0, false, buf, sizeof(buf)); + r = bn_format(&a, NULL, NULL, 0, 0, false, 0, buf, sizeof(buf)); ck_assert_uint_eq(r, 3); ck_assert_str_eq(buf, "500"); @@ -753,7 +793,7 @@ START_TEST(test_bignum_format) { fromhex( "00000000000000000000000000000000000000000000000000000000000003e7"), &a); - r = bn_format(&a, NULL, NULL, 0, 0, false, buf, sizeof(buf)); + r = bn_format(&a, NULL, NULL, 0, 0, false, 0, buf, sizeof(buf)); ck_assert_uint_eq(r, 3); ck_assert_str_eq(buf, "999"); @@ -761,15 +801,23 @@ START_TEST(test_bignum_format) { fromhex( "00000000000000000000000000000000000000000000000000000000000003e8"), &a); - r = bn_format(&a, NULL, NULL, 0, 0, false, buf, sizeof(buf)); + r = bn_format(&a, NULL, NULL, 0, 0, false, 0, buf, sizeof(buf)); ck_assert_uint_eq(r, 4); ck_assert_str_eq(buf, "1000"); + bn_read_be( + fromhex( + "00000000000000000000000000000000000000000000000000000000000003e8"), + &a); + r = bn_format(&a, NULL, NULL, 0, 0, false, ',', buf, sizeof(buf)); + ck_assert_uint_eq(r, 5); + ck_assert_str_eq(buf, "1,000"); + bn_read_be( fromhex( "0000000000000000000000000000000000000000000000000000000000989680"), &a); - r = bn_format(&a, NULL, NULL, 7, 0, false, buf, sizeof(buf)); + r = bn_format(&a, NULL, NULL, 7, 0, false, 0, buf, sizeof(buf)); ck_assert_uint_eq(r, 1); ck_assert_str_eq(buf, "1"); @@ -777,7 +825,7 @@ START_TEST(test_bignum_format) { fromhex( "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), &a); - r = bn_format(&a, NULL, NULL, 0, 0, false, buf, sizeof(buf)); + r = bn_format(&a, NULL, NULL, 0, 0, false, 0, buf, sizeof(buf)); ck_assert_uint_eq(r, 78); ck_assert_str_eq(buf, "11579208923731619542357098500868790785326998466564056403945" @@ -787,7 +835,7 @@ START_TEST(test_bignum_format) { fromhex( "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), &a); - r = bn_format(&a, NULL, NULL, 1, 0, false, buf, sizeof(buf)); + r = bn_format(&a, NULL, NULL, 1, 0, false, 0, buf, sizeof(buf)); ck_assert_uint_eq(r, 79); ck_assert_str_eq(buf, "11579208923731619542357098500868790785326998466564056403945" @@ -797,7 +845,7 @@ START_TEST(test_bignum_format) { fromhex( "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), &a); - r = bn_format(&a, NULL, NULL, 2, 0, false, buf, sizeof(buf)); + r = bn_format(&a, NULL, NULL, 2, 0, false, 0, buf, sizeof(buf)); ck_assert_uint_eq(r, 79); ck_assert_str_eq(buf, "11579208923731619542357098500868790785326998466564056403945" @@ -807,17 +855,39 @@ START_TEST(test_bignum_format) { fromhex( "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), &a); - r = bn_format(&a, NULL, NULL, 8, 0, false, buf, sizeof(buf)); + r = bn_format(&a, NULL, NULL, 8, 0, false, 0, buf, sizeof(buf)); ck_assert_uint_eq(r, 79); ck_assert_str_eq(buf, "11579208923731619542357098500868790785326998466564056403945" "75840079131.29639935"); + bn_read_be( + fromhex( + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), + &a); + r = bn_format(&a, NULL, NULL, 9, 0, false, ',', buf, sizeof(buf)); + ck_assert_uint_eq(r, 101); + ck_assert_str_eq( + buf, + "115,792,089,237,316,195,423,570,985,008,687,907,853,269,984," + "665,640,564,039,457,584,007,913.129639935"); + + bn_read_be( + fromhex( + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), + &a); + r = bn_format(&a, NULL, NULL, 9, 0, false, ' ', buf, sizeof(buf)); + ck_assert_uint_eq(r, 101); + ck_assert_str_eq( + buf, + "115 792 089 237 316 195 423 570 985 008 687 907 853 269 984 " + "665 640 564 039 457 584 007 913.129639935"); + bn_read_be( fromhex( "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffe3bbb00"), &a); - r = bn_format(&a, NULL, NULL, 8, 0, false, buf, sizeof(buf)); + r = bn_format(&a, NULL, NULL, 8, 0, false, 0, buf, sizeof(buf)); ck_assert_uint_eq(r, 70); ck_assert_str_eq(buf, "11579208923731619542357098500868790785326998466564056403945" @@ -827,7 +897,7 @@ START_TEST(test_bignum_format) { fromhex( "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), &a); - r = bn_format(&a, NULL, NULL, 18, 0, false, buf, sizeof(buf)); + r = bn_format(&a, NULL, NULL, 18, 0, false, 0, buf, sizeof(buf)); ck_assert_uint_eq(r, 79); ck_assert_str_eq(buf, "11579208923731619542357098500868790785326998466564056403945" @@ -837,7 +907,7 @@ START_TEST(test_bignum_format) { fromhex( "fffffffffffffffffffffffffffffffffffffffffffffffff7e52fe5afe40000"), &a); - r = bn_format(&a, NULL, NULL, 18, 0, false, buf, sizeof(buf)); + r = bn_format(&a, NULL, NULL, 18, 0, false, 0, buf, sizeof(buf)); ck_assert_uint_eq(r, 60); ck_assert_str_eq( buf, "115792089237316195423570985008687907853269984665640564039457"); @@ -846,7 +916,7 @@ START_TEST(test_bignum_format) { fromhex( "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), &a); - r = bn_format(&a, NULL, NULL, 78, 0, false, buf, sizeof(buf)); + r = bn_format(&a, NULL, NULL, 78, 0, false, 0, buf, sizeof(buf)); ck_assert_uint_eq(r, 80); ck_assert_str_eq(buf, "0." @@ -857,7 +927,7 @@ START_TEST(test_bignum_format) { fromhex( "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), &a); - r = bn_format(&a, NULL, NULL, 0, 10, false, buf, sizeof(buf)); + r = bn_format(&a, NULL, NULL, 0, 10, false, 0, buf, sizeof(buf)); ck_assert_uint_eq(r, 88); ck_assert_str_eq(buf, "11579208923731619542357098500868790785326998466564056403945" @@ -868,7 +938,7 @@ START_TEST(test_bignum_format) { "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), &a); r = bn_format(&a, "quite a long prefix", "even longer suffix", 60, 0, false, - buf, sizeof(buf)); + 0, buf, sizeof(buf)); ck_assert_uint_eq(r, 116); ck_assert_str_eq(buf, "quite a long " @@ -881,12 +951,12 @@ START_TEST(test_bignum_format) { "0000000000000000000000000000000000000000000000000123456789abcdef"), &a); memset(buf, 'a', sizeof(buf)); - r = bn_format(&a, "prefix", "suffix", 10, 0, false, buf, 31); + r = bn_format(&a, "prefix", "suffix", 10, 0, false, 0, buf, 31); ck_assert_str_eq(buf, "prefix8198552.9216486895suffix"); ck_assert_uint_eq(r, 30); memset(buf, 'a', sizeof(buf)); - r = bn_format(&a, "prefix", "suffix", 10, 0, false, buf, 30); + r = bn_format(&a, "prefix", "suffix", 10, 0, false, 0, buf, 30); ck_assert_uint_eq(r, 0); ck_assert_str_eq(buf, ""); }