From 695e8721fdc30be9e95479e739c0286d45798b69 Mon Sep 17 00:00:00 2001 From: Reini Urban Date: Thu, 26 Dec 2024 17:09:14 +0100 Subject: [PATCH] sprintf_s: fix %G NAN, INF, -INF --- src/str/vsnprintf_s.c | 15 ++++--- tests/test_sprintf_s.c | 88 +++++++++++++++++++++++++++++++++++++++-- tests/test_vsprintf_s.c | 6 +-- 3 files changed, 98 insertions(+), 11 deletions(-) diff --git a/src/str/vsnprintf_s.c b/src/str/vsnprintf_s.c index 7d038622..615cc11f 100644 --- a/src/str/vsnprintf_s.c +++ b/src/str/vsnprintf_s.c @@ -166,7 +166,7 @@ #define FLAGS_LEFT (1U << 1U) #define FLAGS_PLUS (1U << 2U) #define FLAGS_SPACE (1U << 3U) -#define FLAGS_HASH (1U << 4U) +#define FLAGS_HASH (1U << 4U) // ALTERNATE_FORM #define FLAGS_UPPERCASE (1U << 5U) #define FLAGS_CHAR (1U << 6U) #define FLAGS_SHORT (1U << 7U) @@ -412,15 +412,19 @@ static size_t safec_ftoa(out_fct_type out, const char *funcname, // test for special values if (value != value) return safec_out_rev(out, buffer, idx, maxlen, - (flags & FLAGS_LONG_DOUBLE) ? "NAN" : "nan", 3, width, flags); + (flags & FLAGS_UPPERCASE) ? "NAN" : "nan", 3, width, flags); { if (isinf(value) < 0) // reverse of -inf - return safec_out_rev(out, buffer, idx, maxlen, "fni-", 4, width, flags); + return safec_out_rev(out, buffer, idx, maxlen, + (flags & FLAGS_UPPERCASE) ? "FNI-" : "fni-", 4, + width, flags); if (isinf(value) > 0) // reverse of inf return safec_out_rev(out, buffer, idx, maxlen, - (flags & FLAGS_PLUS) ? "fni+" : "fni", + (flags & FLAGS_PLUS) + ? (flags & FLAGS_UPPERCASE) ? "FNI+" : "fni+" + : (flags & FLAGS_UPPERCASE) ? "FNI" : "fni", (flags & FLAGS_PLUS) ? 4U : 3U, width, flags); } @@ -692,7 +696,8 @@ static size_t safec_etoa(out_fct_type out, const char *funcname, // in "%g" mode, "prec" is the number of *significant figures* not decimals if (flags & FLAGS_ADAPT_EXP) { // do we want to fall-back to "%f" mode? - if ((value >= 1e-4) && (value < 1e6)) { + // TODO: strip trailing zeros and dot + if ((flags & FLAGS_HASH) || ((value >= 1e-4) && (value < 1e6))) { if ((int)prec > expval) { prec = (unsigned)((int)prec - expval - 1); } else { diff --git a/tests/test_sprintf_s.c b/tests/test_sprintf_s.c index 0ef778d8..d7fc5ebf 100644 --- a/tests/test_sprintf_s.c +++ b/tests/test_sprintf_s.c @@ -302,6 +302,45 @@ int test_sprintf_s(void) { ERR(5) EXPSTR(str2, "56789") + // padding + rc = sprintf_s(str2, 10, "[%6s]", str1); + ERR(8) + EXPSTR(str2, "[ 56789]") + rc = sprintf_s(str2, 10, "[%-6s]", str1); + ERR(8) + EXPSTR(str2, "[56789 ]") + rc = sprintf_s(str2, 10, "[%*s]", 6, str1); + ERR(8) + EXPSTR(str2, "[ 56789]") + + // truncating + rc = sprintf_s(str2, 10, "%.4s", str1); + ERR(4) + EXPSTR(str2, "5678") + rc = sprintf_s(str2, 10, "%.*s", 4, str1); + ERR(4) + EXPSTR(str2, "5678") + + rc = sprintf_s(str2, 10, "%c", 'A'); + ERR(1) + EXPSTR(str2, "A") + + rc = sprintf_s(str2, LEN, "%i", 1); + ERR(1) + EXPSTR(str2, "1") + rc = sprintf_s(str2, LEN, "%d", -1); + ERR(2) + EXPSTR(str2, "-1") + rc = sprintf_s(str2, LEN, "%+i", 1); + ERR(2) + EXPSTR(str2, "+1") + rc = sprintf_s(str2, LEN, "%.3i", 1); + ERR(3) + EXPSTR(str2, "001") + rc = sprintf_s(str2, LEN, "%.0i", 1); + ERR(1) + EXPSTR(str2, "1") + rc = sprintf_s(str2, LEN, "%hhu", (unsigned char)1); ERR(1) EXPSTR(str2, "1") @@ -334,16 +373,34 @@ int test_sprintf_s(void) { rc = sprintf_s(str2, LEN, "%f", 0.1f); NOERRNULL() EXPSTR(str2, "0.100000") + rc = sprintf_s(str2, LEN, "%.1f", 0.1f); + NOERRNULL() + EXPSTR(str2, "0.1") + rc = sprintf_s(str2, LEN, "%.0f", 1.5); + NOERRNULL() + EXPSTR(str2, "2") + rc = sprintf_s(str2, LEN, "%05.2f", 1.5); + NOERRNULL() + EXPSTR(str2, "01.50") + rc = sprintf_s(str2, LEN, "%.2f", 1.5); + NOERRNULL() + EXPSTR(str2, "1.50") + rc = sprintf_s(str2, LEN, "%5.2f", 1.5); + NOERRNULL() + EXPSTR(str2, " 1.50") rc = sprintf_s(str2, LEN, "%F", 0.1f); NOERRNULL() EXPSTR(str2, "0.100000") - rc = sprintf_s(str2, LEN, "%g", 0.1f); + rc = sprintf_s(str2, LEN, "%g", 0.1); NOERRNULL() EXPSTR(str2, "0.1") // FIXME 0.100000 trailing-zeros not stripped - rc = sprintf_s(str2, LEN, "%G", 0.1f); + rc = sprintf_s(str2, LEN, "%#g", 0.1); // alternate form + NOERRNULL() + EXPSTR(str2, "0.100000") + rc = sprintf_s(str2, LEN, "%G", 0.1); NOERRNULL() EXPSTR(str2, "0.1") // FIXME 0.100000 trailing-zeros not stripped - rc = sprintf_s(str2, LEN, "%g", 0.1); + rc = sprintf_s(str2, LEN, "%g", 0.1f); NOERRNULL() EXPSTR(str2, "0.1") // FIXME 0.100000 trailing-zeros not stripped rc = sprintf_s(str2, LEN, "%g", 1.0); @@ -355,6 +412,31 @@ int test_sprintf_s(void) { rc = sprintf_s(str2, LEN, "%a", 0.1f); NOERRNULL() EXPSTR(str2, "0x1.99999ap-4") + + rc = sprintf_s(str2, LEN, "%g", 0.0/0.0); + NOERRNULL() + EXPSTR(str2, "nan") + rc = sprintf_s(str2, LEN, "%G", 0.0/0.0); + NOERRNULL() + EXPSTR(str2, "NAN") + rc = sprintf_s(str2, LEN, "%g", 1.0/0.0); + NOERRNULL() + EXPSTR(str2, "inf") + rc = sprintf_s(str2, LEN, "%g", -1.0/0.0); + NOERRNULL() + EXPSTR(str2, "-inf") + rc = sprintf_s(str2, LEN, "%G", 1.0/0.0); + NOERRNULL() + EXPSTR(str2, "INF") + rc = sprintf_s(str2, LEN, "%G", -1.0/0.0); + NOERRNULL() + EXPSTR(str2, "-INF") + rc = sprintf_s(str2, LEN, "%+g", 1.0/0.0); + NOERRNULL() + EXPSTR(str2, "+inf") + rc = sprintf_s(str2, LEN, "%+G", 1.0/0.0); + NOERRNULL() + EXPSTR(str2, "+INF") #endif #endif { diff --git a/tests/test_vsprintf_s.c b/tests/test_vsprintf_s.c index 93342bf2..21ae9f55 100644 --- a/tests/test_vsprintf_s.c +++ b/tests/test_vsprintf_s.c @@ -336,7 +336,7 @@ int test_vsprintf_s(void) { NOERR() EXPSTR(str1, "nan"); #ifdef HAVE_LONG_DOUBLE - rc = vtprintf_s(str1, LEN, "%Lf", c64.F); + rc = vtprintf_s(str1, LEN, "%LF", c64.F); NOERR() EXPSTR(str1, "NAN"); #endif @@ -348,10 +348,10 @@ int test_vsprintf_s(void) { EXPSTR(str1, "-inf"); #ifdef HAVE_LONG_DOUBLE - rc = vtprintf_s(str1, LEN, "%Lf", HUGE_VALL); + rc = vtprintf_s(str1, LEN, "%LF", HUGE_VALL); NOERR() EXPSTR(str1, "INF"); - rc = vtprintf_s(str1, LEN, "%Lf", -HUGE_VALL); + rc = vtprintf_s(str1, LEN, "%LF", -HUGE_VALL); NOERR() EXPSTR(str1, "-INF"); #endif