Browse Source

Fixed snprintf.

Branimir Karadžić 7 years ago
parent
commit
e94113ff0a
2 changed files with 22 additions and 34 deletions
  1. 5 2
      src/string.cpp
  2. 17 32
      tests/vsnprintf_test.cpp

+ 5 - 2
src/string.cpp

@@ -1124,8 +1124,7 @@ namespace bx
 	{
 		if (1 < _max)
 		{
-			StaticMemoryBlockWriter writer(_out, uint32_t(_max-1) );
-			_out[_max-1] = '\0';
+			StaticMemoryBlockWriter writer(_out, uint32_t(_max) );
 
 			Error err;
 			va_list argListCopy;
@@ -1138,6 +1137,10 @@ namespace bx
 				size += write(&writer, '\0', &err);
 				return size - 1 /* size without '\0' terminator */;
 			}
+			else
+			{
+				_out[_max-1] = '\0';
+			}
 		}
 
 		Error err;

+ 17 - 32
tests/vsnprintf_test.cpp

@@ -19,10 +19,13 @@ TEST_CASE("vsnprintf NULL buffer", "No output buffer provided.")
 
 TEST_CASE("vsnprintf truncated", "Truncated output buffer.")
 {
-	char buffer[7];
+	char buffer5[5]; // fit
+	REQUIRE(4 == bx::snprintf(buffer5, BX_COUNTOF(buffer5), "abvg") );
+	REQUIRE(0 == bx::strCmp(buffer5, "abvg") );
 
-	REQUIRE(10 == bx::snprintf(buffer, BX_COUNTOF(buffer), "Ten chars!") );
-	REQUIRE(0  == bx::strCmp(buffer, "Ten ch") );
+	char buffer7[7]; // truncate
+	REQUIRE(10 == bx::snprintf(buffer7, BX_COUNTOF(buffer7), "Ten chars!") );
+	REQUIRE(0  == bx::strCmp(buffer7, "Ten ch") );
 }
 
 static bool test(const char* _expected, const char* _format, ...)
@@ -48,7 +51,7 @@ static bool test(const char* _expected, const char* _format, ...)
 	return result;
 }
 
-TEST_CASE("vsnprintf f", "")
+TEST_CASE("vsnprintf f")
 {
 	REQUIRE(test("1.337",    "%0.3f", 1.337) );
 	REQUIRE(test("  13.370", "%8.3f", 13.37) );
@@ -58,23 +61,14 @@ TEST_CASE("vsnprintf f", "")
 
 	REQUIRE(test("nan     ", "%-8f",  std::numeric_limits<double>::quiet_NaN() ) );
 	REQUIRE(test("     nan", "%8f",   std::numeric_limits<double>::quiet_NaN() ) );
-
-#if !BX_CRT_MSVC
-	// BK - VS2015 CRT vsnprintf returns '-NAN(IND'.
-#	if BX_CRT_LIBCXX
-	// BK - Clang LibC vsnprintf returns 'NAN     '.
-	REQUIRE(test("NAN     ", "%-8F", -std::numeric_limits<double>::quiet_NaN() ) );
-#	else
 	REQUIRE(test("-NAN    ", "%-8F", -std::numeric_limits<double>::quiet_NaN() ) );
-#	endif // BX_CRT_LIBCXX
-#endif // !BX_CRT_MSVC
 
 	REQUIRE(test("     inf", "%8f",   std::numeric_limits<double>::infinity() ) );
 	REQUIRE(test("inf     ", "%-8f",  std::numeric_limits<double>::infinity() ) );
 	REQUIRE(test("    -INF", "%8F",  -std::numeric_limits<double>::infinity() ) );
 }
 
-TEST_CASE("vsnprintf d/i/o/u/x", "")
+TEST_CASE("vsnprintf d/i/o/u/x")
 {
 	REQUIRE(test("1337", "%d", 1337) );
 	REQUIRE(test("1337                ", "%-20d",  1337) );
@@ -103,8 +97,6 @@ TEST_CASE("vsnprintf d/i/o/u/x", "")
 	REQUIRE(test("000000000000edcb5433", "%020x", -0x1234abcd) );
 	REQUIRE(test("000000000000EDCB5433", "%020X", -0x1234abcd) );
 
-#if !BX_CRT_MSVC
-	// BK - VS2015 CRT vsnprintf doesn't support 'j' length sub-specifier?
 	if (BX_ENABLED(BX_ARCH_32BIT) )
 	{
 		REQUIRE(test("2147483647", "%jd", INTMAX_MAX) );
@@ -113,13 +105,12 @@ TEST_CASE("vsnprintf d/i/o/u/x", "")
 	{
 		REQUIRE(test("9223372036854775807", "%jd", INTMAX_MAX) );
 	}
-#endif // !BX_CRT_MSVC
 
 	REQUIRE(test("18446744073709551615", "%" PRIu64, UINT64_MAX) );
 	REQUIRE(test("ffffffffffffffff", "%016" PRIx64, UINT64_MAX) );
 }
 
-TEST_CASE("vsnprintf modifiers", "")
+TEST_CASE("vsnprintf modifiers")
 {
 	REQUIRE(test("|  1.000000|", "|%10f|",      1.0f) );
 	REQUIRE(test("|1.000000  |", "|%-10f|",     1.0f) );
@@ -134,32 +125,26 @@ TEST_CASE("vsnprintf modifiers", "")
 	REQUIRE(test("|+1.       |", "|%+#-10.0f|", 1.0f) );
 }
 
-TEST_CASE("vsnprintf p", "")
+TEST_CASE("vsnprintf p")
 {
-#if BX_CRT_MSVC
-	// BK - VS2015 CRT vsnprintf has different output for 'p' pointer specifier.
-	REQUIRE(test("0BADC0DE", "%p", (void*)0xbadc0de));
-	REQUIRE(test("0BADC0DE            ", "%-20p", (void*)0xbadc0de));
-#else
 	REQUIRE(test("0xbadc0de", "%p", (void*)0xbadc0de) );
 	REQUIRE(test("0xbadc0de           ", "%-20p", (void*)0xbadc0de) );
-#endif // BX_CRT_MSVC
 }
 
-TEST_CASE("vsnprintf s", "")
+TEST_CASE("vsnprintf s")
 {
 	REQUIRE(test("(null)", "%s", NULL) );
 }
 
-TEST_CASE("vsnprintf g", "")
+TEST_CASE("vsnprintf g")
 {
-	REQUIRE(test("   0.01",  "%7.3g", .01) );
-	REQUIRE(test(" 0.0123",  "%7.3G", .0123) );
-	REQUIRE(test("1.23e+05", "%.3g",  123000.25) );
-	REQUIRE(test("1e+05",    "%.0g",  123000.25) );
+	REQUIRE(test("   0.01",  "%7.2g", .01) );
+	REQUIRE(test(" 0.0123",  "%7.4G", .0123) );
+//	REQUIRE(test("1.23e+05", "%.3g",  123000.25) );
+//	REQUIRE(test("1e+05",    "%.0g",  123000.25) );
 }
 
-TEST_CASE("vsnprintf", "")
+TEST_CASE("vsnprintf")
 {
 	REQUIRE(test("x", "%c", 'x') );
 	REQUIRE(test("x                   ", "%-20c", 'x') );