From 78075c27fcfc249563a0b79b1cbef4753dabf65f Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 29 Dec 2022 20:42:07 -0800 Subject: [PATCH] Added basic support for %g snprintf format specifier --- src/stdlib/SDL_string.c | 31 +++++++++++++++++++++++++++++++ test/testautomation_stdlib.c | 12 ++++++++++++ 2 files changed, 43 insertions(+) diff --git a/src/stdlib/SDL_string.c b/src/stdlib/SDL_string.c index e6464da631a7a..047dd572749cd 100644 --- a/src/stdlib/SDL_string.c +++ b/src/stdlib/SDL_string.c @@ -1675,6 +1675,29 @@ SDL_PrintFloat(char *text, size_t maxlen, SDL_FormatInfo *info, double arg) return length; } +static size_t +SDL_TrimTrailingFractionalZeroes(char *text, size_t start, size_t length) +{ + size_t i, j; + + for (i = start; i < length; ++i) { + if (text[i] == '.' || text[i] == ',') { + for (j = length - 1; j > i; --j) { + if (text[j] == '0') { + --length; + } else { + break; + } + } + if (j == i) { + --length; + } + break; + } + } + return length; +} + /* NOLINTNEXTLINE(readability-non-const-parameter) */ int SDL_vsnprintf(SDL_OUT_Z_CAP(maxlen) char *text, size_t maxlen, const char *fmt, va_list ap) { @@ -1856,6 +1879,14 @@ int SDL_vsnprintf(SDL_OUT_Z_CAP(maxlen) char *text, size_t maxlen, const char *f length += SDL_PrintFloat(TEXT_AND_LEN_ARGS, &info, va_arg(ap, double)); done = SDL_TRUE; break; + case 'g': + { + size_t starting_length = length; + length += SDL_PrintFloat(TEXT_AND_LEN_ARGS, &info, va_arg(ap, double)); + length = SDL_TrimTrailingFractionalZeroes(text, starting_length, length); + done = SDL_TRUE; + break; + } case 'S': { /* In practice this is used on Windows for WCHAR strings */ diff --git a/test/testautomation_stdlib.c b/test/testautomation_stdlib.c index f818e7a0f458a..2d2ed0fdabe43 100644 --- a/test/testautomation_stdlib.c +++ b/test/testautomation_stdlib.c @@ -153,6 +153,18 @@ int stdlib_snprintf(void *arg) SDLTest_AssertCheck(SDL_strcmp(text, expected) == 0, "Check text, expected: '%s', got: '%s'", expected, text); SDLTest_AssertCheck(result == 6, "Check result value, expected: 6, got: %d", result); + result = SDL_snprintf(text, sizeof(text), "%g", 100.0); + expected = "100"; + SDLTest_AssertPass("Call to SDL_snprintf(\"%%g\", 100.0)"); + SDLTest_AssertCheck(SDL_strcmp(text, expected) == 0, "Check text, expected: '%s', got: '%s'", expected, text); + SDLTest_AssertCheck(result == 3, "Check result value, expected: 3, got: %d", result); + + result = SDL_snprintf(text, sizeof(text), "%g", 100.75); + expected = "100.75"; + SDLTest_AssertPass("Call to SDL_snprintf(\"%%g\", 100.75)"); + SDLTest_AssertCheck(SDL_strcmp(text, expected) == 0, "Check text, expected: '%s', got: '%s'", expected, text); + SDLTest_AssertCheck(result == 6, "Check result value, expected: 6, got: %d", result); + size = 64; result = SDL_snprintf(text, sizeof(text), "%zu %s", size, "test"); expected = "64 test";