From ddd2b9319076efa81ca87e2f9582e328824f37db Mon Sep 17 00:00:00 2001 From: heinrich5991 Date: Sun, 10 Feb 2019 17:13:13 +0100 Subject: [PATCH] Allow translations to reorder string substitutions This is supported on Windows (https://docs.microsoft.com/en-us/cpp/c-runtime-library/printf-p-positional-parameters) and on POSIX, so basically everywhere. Add some tests to verify that the target system does indeed support these positional parameters. --- src/base/system.c | 16 ++++++++-------- src/test/str.cpp | 21 +++++++++++++++++++++ 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/src/base/system.c b/src/base/system.c index 27fb564df..f200055a7 100644 --- a/src/base/system.c +++ b/src/base/system.c @@ -100,7 +100,7 @@ void dbg_msg(const char *sys, const char *fmt, ...) va_start(args, fmt); #if defined(CONF_FAMILY_WINDOWS) - _vsnprintf(msg, sizeof(str)-len, fmt, args); + _vsprintf_p(msg, sizeof(str)-len, fmt, args); #else vsnprintf(msg, sizeof(str)-len, fmt, args); #endif @@ -1472,7 +1472,7 @@ int fs_storage_path(const char *appname, char *path, int max) char *home = getenv("APPDATA"); if(!home) return -1; - _snprintf(path, max, "%s/%s", home, appname); + str_format(path, max, "%s/%s", home, appname); return 0; #else char *home = getenv("HOME"); @@ -1484,25 +1484,25 @@ int fs_storage_path(const char *appname, char *path, int max) return -1; #if defined(CONF_PLATFORM_MACOSX) - snprintf(path, max, "%s/Library/Application Support/%s", home, appname); + str_format(path, max, "%s/Library/Application Support/%s", home, appname); return 0; #endif /* old folder location */ - snprintf(path, max, "%s/.%s", home, appname); + str_format(path, max, "%s/.%s", home, appname); for(i = strlen(home)+2; path[i]; i++) path[i] = tolower(path[i]); if(!xdgdatahome) { /* use default location */ - snprintf(xdgpath, max, "%s/.local/share/%s", home, appname); + str_format(xdgpath, max, "%s/.local/share/%s", home, appname); for(i = strlen(home)+14; xdgpath[i]; i++) xdgpath[i] = tolower(xdgpath[i]); } else { - snprintf(xdgpath, max, "%s/%s", xdgdatahome, appname); + str_format(xdgpath, max, "%s/%s", xdgdatahome, appname); for(i = strlen(xdgdatahome)+1; xdgpath[i]; i++) xdgpath[i] = tolower(xdgpath[i]); } @@ -1515,7 +1515,7 @@ int fs_storage_path(const char *appname, char *path, int max) return 0; } - snprintf(path, max, "%s", xdgpath); + str_format(path, max, "%s", xdgpath); return 0; #endif @@ -1774,7 +1774,7 @@ void str_format(char *buffer, int buffer_size, const char *format, ...) #if defined(CONF_FAMILY_WINDOWS) va_list ap; va_start(ap, format); - _vsnprintf(buffer, buffer_size, format, ap); + _vsprintf_p(buffer, buffer_size, format, ap); va_end(ap); #else va_list ap; diff --git a/src/test/str.cpp b/src/test/str.cpp index e404816f5..0e3884646 100644 --- a/src/test/str.cpp +++ b/src/test/str.cpp @@ -40,3 +40,24 @@ TEST(Str, Endswith) EXPECT_EQ(str_endswith(ABCDEFG, DEFG) - ABCDEFG, str_length(ABCDEFG) - str_length(DEFG)); } + +TEST(StrFormat, Positional) +{ + char aBuf[256]; + + // normal + str_format(aBuf, sizeof(aBuf), "%s %s", "first", "second"); + EXPECT_STREQ(aBuf, "first second"); + + // normal with positional arguments + str_format(aBuf, sizeof(aBuf), "%1$s %2$s", "first", "second"); + EXPECT_STREQ(aBuf, "first second"); + + // reverse + str_format(aBuf, sizeof(aBuf), "%2$s %1$s", "first", "second"); + EXPECT_STREQ(aBuf, "second first"); + + // duplicate + str_format(aBuf, sizeof(aBuf), "%1$s %1$s %2$d %1$s %2$d", "str", 1); + EXPECT_STREQ(aBuf, "str str 1 str 1"); +}