From a4447f725b03ade83a7ca9070a0504e423241cc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Branimir=20Karad=C5=BEi=C4=87?= Date: Mon, 16 Jul 2018 19:37:49 -0700 Subject: [PATCH] Added commified output when converting from integer to string. --- include/bx/string.h | 8 +++---- src/dtoa.cpp | 51 +++++++++++++++++++++++++++---------------- tests/string_test.cpp | 41 +++++++++++++++++++++++++++------- 3 files changed, 69 insertions(+), 31 deletions(-) diff --git a/include/bx/string.h b/include/bx/string.h index 356d6dc..585cb82 100644 --- a/include/bx/string.h +++ b/include/bx/string.h @@ -280,16 +280,16 @@ namespace bx int32_t toString(char* _out, int32_t _max, double _value); /// Converts 32-bit integer value to string. - int32_t toString(char* _out, int32_t _max, int32_t _value, uint32_t _base = 10); + int32_t toString(char* _out, int32_t _max, int32_t _value, uint32_t _base = 10, char _separator = '\0'); /// Converts 64-bit integer value to string. - int32_t toString(char* _out, int32_t _max, int64_t _value, uint32_t _base = 10); + int32_t toString(char* _out, int32_t _max, int64_t _value, uint32_t _base = 10, char _separator = '\0'); /// Converts 32-bit unsigned integer value to string. - int32_t toString(char* _out, int32_t _max, uint32_t _value, uint32_t _base = 10); + int32_t toString(char* _out, int32_t _max, uint32_t _value, uint32_t _base = 10, char _separator = '\0'); /// Converts 64-bit unsigned integer value to string. - int32_t toString(char* _out, int32_t _max, uint64_t _value, uint32_t _base = 10); + int32_t toString(char* _out, int32_t _max, uint64_t _value, uint32_t _base = 10, char _separator = '\0'); /// Converts string to bool value. bool fromString(bool* _out, const StringView& _str); diff --git a/src/dtoa.cpp b/src/dtoa.cpp index 8674c2e..2c45aae 100644 --- a/src/dtoa.cpp +++ b/src/dtoa.cpp @@ -472,7 +472,7 @@ namespace bx } template - int32_t toStringSigned(char* _dst, int32_t _max, Ty _value, uint32_t _base) + int32_t toStringSigned(char* _dst, int32_t _max, Ty _value, uint32_t _base, char _separator) { if (_base == 10 && _value < 0) @@ -483,10 +483,11 @@ namespace bx } _max = toString(_dst + 1 - , _max - 1 - , typename std::make_unsigned::type(-_value) - , _base - ); + , _max - 1 + , typename std::make_unsigned::type(-_value) + , _base + , _separator + ); if (_max == 0) { return 0; @@ -497,24 +498,25 @@ namespace bx } return toString(_dst - , _max - , typename std::make_unsigned::type(_value) - , _base - ); + , _max + , typename std::make_unsigned::type(_value) + , _base + , _separator + ); } - int32_t toString(char* _dst, int32_t _max, int32_t _value, uint32_t _base) + int32_t toString(char* _dst, int32_t _max, int32_t _value, uint32_t _base, char _separator) { - return toStringSigned(_dst, _max, _value, _base); + return toStringSigned(_dst, _max, _value, _base, _separator); } - int32_t toString(char* _dst, int32_t _max, int64_t _value, uint32_t _base) + int32_t toString(char* _dst, int32_t _max, int64_t _value, uint32_t _base, char _separator) { - return toStringSigned(_dst, _max, _value, _base); + return toStringSigned(_dst, _max, _value, _base, _separator); } template - int32_t toStringUnsigned(char* _dst, int32_t _max, Ty _value, uint32_t _base) + int32_t toStringUnsigned(char* _dst, int32_t _max, Ty _value, uint32_t _base, char _separator) { char data[32]; int32_t len = 0; @@ -525,6 +527,8 @@ namespace bx return 0; } + uint32_t count = 1; + do { const Ty rem = _value % _base; @@ -538,7 +542,16 @@ namespace bx data[len++] = char('a' + rem - 10); } - } while (_value != 0); + if ('\0' != _separator + && 0 == count%3 + && 0 != _value) + { + data[len++] = _separator; + } + + ++count; + } + while (0 != _value); if (_max < len + 1) { @@ -552,14 +565,14 @@ namespace bx return int32_t(len); } - int32_t toString(char* _dst, int32_t _max, uint32_t _value, uint32_t _base) + int32_t toString(char* _dst, int32_t _max, uint32_t _value, uint32_t _base, char _separator) { - return toStringUnsigned(_dst, _max, _value, _base); + return toStringUnsigned(_dst, _max, _value, _base, _separator); } - int32_t toString(char* _dst, int32_t _max, uint64_t _value, uint32_t _base) + int32_t toString(char* _dst, int32_t _max, uint64_t _value, uint32_t _base, char _separator) { - return toStringUnsigned(_dst, _max, _value, _base); + return toStringUnsigned(_dst, _max, _value, _base, _separator); } /* diff --git a/tests/string_test.cpp b/tests/string_test.cpp index 00df4ea..88cbbc3 100644 --- a/tests/string_test.cpp +++ b/tests/string_test.cpp @@ -223,6 +223,39 @@ TEST_CASE("strFind", "") } } +template +static bool testToStringS(Ty _value, const char* _expected, char _separator = '\0') +{ + char tmp[1024]; + int32_t num = bx::toString(tmp, BX_COUNTOF(tmp), _value, 10, _separator); + int32_t len = (int32_t)bx::strLen(_expected); + if (0 == bx::strCmp(tmp, _expected) + && num == len) + { + return true; + } + + printf("result '%s' (%d), expected '%s' (%d)\n", tmp, num, _expected, len); + return false; +} + +TEST_CASE("toString intXX_t/uintXX_t", "") +{ + REQUIRE(testToStringS(0, "0") ); + REQUIRE(testToStringS(-256, "-256") ); + REQUIRE(testToStringS(INT32_MAX, "2147483647") ); + REQUIRE(testToStringS(UINT32_MAX, "4294967295") ); + REQUIRE(testToStringS(INT64_MAX, "9223372036854775807") ); + REQUIRE(testToStringS(UINT64_MAX, "18446744073709551615") ); + + REQUIRE(testToStringS(0, "0", ',') ); + REQUIRE(testToStringS(-256, "-256", ',') ); + REQUIRE(testToStringS(INT32_MAX, "2,147,483,647", ',') ); + REQUIRE(testToStringS(UINT32_MAX, "4,294,967,295", ',') ); + REQUIRE(testToStringS(INT64_MAX, "9,223,372,036,854,775,807", ',') ); + REQUIRE(testToStringS(UINT64_MAX, "18,446,744,073,709,551,615", ',') ); +} + template static bool testToString(Ty _value, const char* _expected) { @@ -239,14 +272,6 @@ static bool testToString(Ty _value, const char* _expected) return false; } -TEST_CASE("toString int32_t/uint32_t", "") -{ - REQUIRE(testToString(0, "0") ); - REQUIRE(testToString(-256, "-256") ); - REQUIRE(testToString(INT32_MAX, "2147483647") ); - REQUIRE(testToString(UINT32_MAX, "4294967295") ); -} - TEST_CASE("toString double", "") { REQUIRE(testToString(0.0, "0.0") );