Browse Source

Added commified output when converting from integer to string.

Branimir Karadžić 7 years ago
parent
commit
a4447f725b
3 changed files with 68 additions and 30 deletions
  1. 4 4
      include/bx/string.h
  2. 32 19
      src/dtoa.cpp
  3. 32 7
      tests/string_test.cpp

+ 4 - 4
include/bx/string.h

@@ -280,16 +280,16 @@ namespace bx
 	int32_t toString(char* _out, int32_t _max, double _value);
 	int32_t toString(char* _out, int32_t _max, double _value);
 
 
 	/// Converts 32-bit integer value to string.
 	/// 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.
 	/// 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.
 	/// 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.
 	/// 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.
 	/// Converts string to bool value.
 	bool fromString(bool* _out, const StringView& _str);
 	bool fromString(bool* _out, const StringView& _str);

+ 32 - 19
src/dtoa.cpp

@@ -472,7 +472,7 @@ namespace bx
 	}
 	}
 
 
 	template<typename Ty>
 	template<typename Ty>
-	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
 		if (_base == 10
 		&&  _value < 0)
 		&&  _value < 0)
@@ -483,10 +483,11 @@ namespace bx
 			}
 			}
 
 
 			_max = toString(_dst + 1
 			_max = toString(_dst + 1
-					, _max - 1
-					, typename std::make_unsigned<Ty>::type(-_value)
-					, _base
-					);
+				, _max - 1
+				, typename std::make_unsigned<Ty>::type(-_value)
+				, _base
+				, _separator
+				);
 			if (_max == 0)
 			if (_max == 0)
 			{
 			{
 				return 0;
 				return 0;
@@ -497,24 +498,25 @@ namespace bx
 		}
 		}
 
 
 		return toString(_dst
 		return toString(_dst
-					, _max
-					, typename std::make_unsigned<Ty>::type(_value)
-					, _base
-					);
+			, _max
+			, typename std::make_unsigned<Ty>::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<typename Ty>
 	template<typename Ty>
-	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];
 		char data[32];
 		int32_t len = 0;
 		int32_t len = 0;
@@ -525,6 +527,8 @@ namespace bx
 			return 0;
 			return 0;
 		}
 		}
 
 
+		uint32_t count = 1;
+
 		do
 		do
 		{
 		{
 			const Ty rem = _value % _base;
 			const Ty rem = _value % _base;
@@ -538,7 +542,16 @@ namespace bx
 				data[len++] = char('a' + rem - 10);
 				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)
 		if (_max < len + 1)
 		{
 		{
@@ -552,14 +565,14 @@ namespace bx
 		return int32_t(len);
 		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);
 	}
 	}
 
 
 	/*
 	/*

+ 32 - 7
tests/string_test.cpp

@@ -224,10 +224,10 @@ TEST_CASE("strFind", "")
 }
 }
 
 
 template<typename Ty>
 template<typename Ty>
-static bool testToString(Ty _value, const char* _expected)
+static bool testToStringS(Ty _value, const char* _expected, char _separator = '\0')
 {
 {
 	char tmp[1024];
 	char tmp[1024];
-	int32_t num = bx::toString(tmp, BX_COUNTOF(tmp), _value);
+	int32_t num = bx::toString(tmp, BX_COUNTOF(tmp), _value, 10, _separator);
 	int32_t len = (int32_t)bx::strLen(_expected);
 	int32_t len = (int32_t)bx::strLen(_expected);
 	if (0 == bx::strCmp(tmp, _expected)
 	if (0 == bx::strCmp(tmp, _expected)
 	&&  num == len)
 	&&  num == len)
@@ -239,12 +239,37 @@ static bool testToString(Ty _value, const char* _expected)
 	return false;
 	return false;
 }
 }
 
 
-TEST_CASE("toString int32_t/uint32_t", "")
+TEST_CASE("toString intXX_t/uintXX_t", "")
 {
 {
-	REQUIRE(testToString(0,          "0") );
-	REQUIRE(testToString(-256,       "-256") );
-	REQUIRE(testToString(INT32_MAX,  "2147483647") );
-	REQUIRE(testToString(UINT32_MAX, "4294967295") );
+	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<typename Ty>
+static bool testToString(Ty _value, const char* _expected)
+{
+	char tmp[1024];
+	int32_t num = bx::toString(tmp, BX_COUNTOF(tmp), _value);
+	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 double", "")
 TEST_CASE("toString double", "")