Browse Source

Fixed issue #267 (#268)

Jim Drygiannakis 4 years ago
parent
commit
950f71632d
2 changed files with 77 additions and 16 deletions
  1. 24 15
      src/string.cpp
  2. 53 1
      tests/vsnprintf_test.cpp

+ 24 - 15
src/string.cpp

@@ -887,25 +887,34 @@ namespace bx
 			const char* dot = strFind(str, INT32_MAX, '.');
 			if (NULL != dot)
 			{
-				const int32_t prec = INT32_MAX == _param.prec ? len-(dot+1-str) : _param.prec;
-
-				const int32_t precLen = int32_t(
-						dot
-						+ min(prec + _param.spec, 1)
-						+ prec
-						- str
-						);
-				if (precLen > len)
+				const int32_t prec = INT32_MAX == _param.prec ? 6 : _param.prec;
+				const char* strEnd = str + len;
+				const char* exponent = strFind(str, INT32_MAX, 'e');
+				const char* fracEnd = NULL != exponent ? exponent : strEnd;
+				char* fracBegin = &str[dot - str + min(prec + _param.spec, 1)];
+				const int32_t curPrec = int32_t(fracEnd - fracBegin);
+
+				// Move exponent to its final location after trimming or adding extra 0s.
+				if (fracEnd != strEnd)
 				{
-					for (int32_t ii = len; ii < precLen; ++ii)
+					const int32_t exponentLen = int32_t(strEnd - fracEnd);
+					char* finalExponentPtr = &fracBegin[prec];
+					memMove(finalExponentPtr, fracEnd, exponentLen); // NOTE: Use memMove because there may be overlap.
+					finalExponentPtr[exponentLen] = '\0';
+					len = int32_t(&finalExponentPtr[exponentLen] - str);
+				}
+				else
+				{
+					len = (int32_t)(fracBegin + prec - str);
+				}
+
+				if (curPrec < prec)
+				{
+					for (int32_t ii = curPrec; ii < prec; ++ii)
 					{
-						str[ii] = '0';
+						fracBegin[ii] = '0';
 					}
-
-					str[precLen] = '\0';
 				}
-
-				len = precLen;
 			}
 
 			return write(_writer, str, len, _param, _err);

+ 53 - 1
tests/vsnprintf_test.cpp

@@ -74,9 +74,61 @@ TEST_CASE("vsnprintf f")
 	REQUIRE(test("-001.500", "%+08.3f", -1.5) );
 	REQUIRE(test("0.0039",   "%.4f",     0.00390625) );
 
-	REQUIRE(test("0.00390625",   "%f",   0.00390625) );
+	REQUIRE(test("0.003906",     "%f",   0.00390625) );
 	REQUIRE(test("-1.234567e-9", "%f",  -1.234567e-9) );
 
+	REQUIRE(test("-1e-9",            "%.0f",  -1.234567e-9) );
+	REQUIRE(test("-1.2e-9",          "%.1f",  -1.234567e-9) );
+	REQUIRE(test("-1.23e-9",         "%.2f",  -1.234567e-9) );
+	REQUIRE(test("-1.234e-9",        "%.3f",  -1.234567e-9) );
+	REQUIRE(test("-1.2345e-9",       "%.4f",  -1.234567e-9) );
+	REQUIRE(test("-1.23456e-9",      "%.5f",  -1.234567e-9) );
+	REQUIRE(test("-1.234567e-9",     "%.6f",  -1.234567e-9) );
+	REQUIRE(test("-1.2345670e-9",    "%.7f",  -1.234567e-9) );
+	REQUIRE(test("-1.23456700e-9",   "%.8f",  -1.234567e-9) );
+	REQUIRE(test("-1.234567000e-9",  "%.9f",  -1.234567e-9) );
+	REQUIRE(test("-1.2345670000e-9", "%.10f", -1.234567e-9) );
+
+	REQUIRE(test("3.141592",           "%f",    3.1415926535897932) );
+	REQUIRE(test("3",                  "%.0f",  3.1415926535897932) );
+	REQUIRE(test("3.1",                "%.1f",  3.1415926535897932) );
+	REQUIRE(test("3.14",               "%.2f",  3.1415926535897932) );
+	REQUIRE(test("3.141",              "%.3f",  3.1415926535897932) );
+	REQUIRE(test("3.1415",             "%.4f",  3.1415926535897932) );
+	REQUIRE(test("3.14159",            "%.5f",  3.1415926535897932) );
+	REQUIRE(test("3.141592",           "%.6f",  3.1415926535897932) );
+	REQUIRE(test("3.1415926",          "%.7f",  3.1415926535897932) );
+	REQUIRE(test("3.14159265",         "%.8f",  3.1415926535897932) );
+	REQUIRE(test("3.141592653",        "%.9f",  3.1415926535897932) );
+	REQUIRE(test("3.1415926535",       "%.10f", 3.1415926535897932) );
+	REQUIRE(test("3.14159265358",      "%.11f", 3.1415926535897932) );
+	REQUIRE(test("3.141592653589",     "%.12f", 3.1415926535897932) );
+	REQUIRE(test("3.1415926535897",    "%.13f", 3.1415926535897932) );
+	REQUIRE(test("3.14159265358979",   "%.14f", 3.1415926535897932) );
+	REQUIRE(test("3.141592653589793",  "%.15f", 3.1415926535897932) );
+	REQUIRE(test("3.1415926535897930", "%.16f", 3.1415926535897932) );
+
+	REQUIRE(test("-3.141592e-9",           "%f",    -3.1415926535897932e-9) );
+	REQUIRE(test("-3e-9",                  "%.0f",  -3.1415926535897932e-9) );
+	REQUIRE(test("-3.1e-9",                "%.1f",  -3.1415926535897932e-9) );
+	REQUIRE(test("-3.14e-9",               "%.2f",  -3.1415926535897932e-9) );
+	REQUIRE(test("-3.141e-9",              "%.3f",  -3.1415926535897932e-9) );
+	REQUIRE(test("-3.1415e-9",             "%.4f",  -3.1415926535897932e-9) );
+	REQUIRE(test("-3.14159e-9",            "%.5f",  -3.1415926535897932e-9) );
+	REQUIRE(test("-3.141592e-9",           "%.6f",  -3.1415926535897932e-9) );
+	REQUIRE(test("-3.1415926e-9",          "%.7f",  -3.1415926535897932e-9) );
+	REQUIRE(test("-3.14159265e-9",         "%.8f",  -3.1415926535897932e-9) );
+	REQUIRE(test("-3.141592653e-9",        "%.9f",  -3.1415926535897932e-9) );
+	REQUIRE(test("-3.1415926535e-9",       "%.10f", -3.1415926535897932e-9) );
+	REQUIRE(test("-3.14159265358e-9",      "%.11f", -3.1415926535897932e-9) );
+	REQUIRE(test("-3.141592653589e-9",     "%.12f", -3.1415926535897932e-9) );
+	REQUIRE(test("-3.1415926535897e-9",    "%.13f", -3.1415926535897932e-9) );
+	REQUIRE(test("-3.14159265358979e-9",   "%.14f", -3.1415926535897932e-9) );
+	REQUIRE(test("-3.141592653589793e-9",  "%.15f", -3.1415926535897932e-9) );
+	REQUIRE(test("-3.1415926535897930e-9", "%.16f", -3.1415926535897932e-9) );
+
+	REQUIRE(test("1e-12", "%f", 1e-12));
+
 	REQUIRE(test("0.00390625",          "%.8f",  0.00390625) );
 	REQUIRE(test("-0.00390625",         "%.8f", -0.00390625) );
 	REQUIRE(test("1.50000000000000000", "%.17f", 1.5) );