From 950f71632de89bc91d54cbd0d71180a635085a2a Mon Sep 17 00:00:00 2001 From: Jim Drygiannakis Date: Fri, 3 Dec 2021 20:10:41 +0200 Subject: [PATCH] Fixed issue #267 (#268) --- src/string.cpp | 39 ++++++++++++++++++----------- tests/vsnprintf_test.cpp | 54 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 77 insertions(+), 16 deletions(-) diff --git a/src/string.cpp b/src/string.cpp index d5caf6f..d086bc8 100644 --- a/src/string.cpp +++ b/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 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); - const int32_t precLen = int32_t( - dot - + min(prec + _param.spec, 1) - + prec - - str - ); - if (precLen > len) + // Move exponent to its final location after trimming or adding extra 0s. + if (fracEnd != strEnd) { - for (int32_t ii = len; ii < precLen; ++ii) - { - str[ii] = '0'; - } - - str[precLen] = '\0'; + 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); } - len = precLen; + if (curPrec < prec) + { + for (int32_t ii = curPrec; ii < prec; ++ii) + { + fracBegin[ii] = '0'; + } + } } return write(_writer, str, len, _param, _err); diff --git a/tests/vsnprintf_test.cpp b/tests/vsnprintf_test.cpp index 4b5e2c0..2b91f7c 100644 --- a/tests/vsnprintf_test.cpp +++ b/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) );