Skip to content

Commit

Permalink
sprintf_s: fix %G NAN, INF, -INF
Browse files Browse the repository at this point in the history
  • Loading branch information
rurban committed Dec 26, 2024
1 parent 80a0379 commit 695e872
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 11 deletions.
15 changes: 10 additions & 5 deletions src/str/vsnprintf_s.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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 {
Expand Down
88 changes: 85 additions & 3 deletions tests/test_sprintf_s.c
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down Expand Up @@ -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);
Expand All @@ -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
{
Expand Down
6 changes: 3 additions & 3 deletions tests/test_vsprintf_s.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down

0 comments on commit 695e872

Please sign in to comment.