From baa1a5e2f472ad062ef618843dce916e226791aa Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Mon, 2 Sep 2024 14:13:54 +0200 Subject: [PATCH] Add SDL_strpbrk --- CMakeLists.txt | 2 +- cmake/PreseedEmscriptenCache.cmake | 1 + cmake/PreseedMSVCCache.cmake | 1 + include/SDL3/SDL_stdinc.h | 17 +++++++ include/build_config/SDL_build_config.h.cmake | 1 + include/build_config/SDL_build_config_ios.h | 1 + include/build_config/SDL_build_config_macos.h | 1 + .../build_config/SDL_build_config_windows.h | 1 + include/build_config/SDL_build_config_winrt.h | 1 + include/build_config/SDL_build_config_xbox.h | 1 + src/dynapi/SDL_dynapi.sym | 1 + src/dynapi/SDL_dynapi_overrides.h | 1 + src/dynapi/SDL_dynapi_procs.h | 1 + src/stdlib/SDL_string.c | 19 +++++++ test/testautomation_stdlib.c | 51 +++++++++++++++++-- 15 files changed, 96 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 37e6647a6d..5716da4cef 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -979,7 +979,7 @@ if(SDL_LIBC) pow powf putenv realloc rindex round roundf scalbn scalbnf setenv sin sinf sqr sqrt sqrtf sscanf strchr - strcmp strlcat strlcpy strlen strncmp strnlen + strcmp strlcat strlcpy strlen strncmp strnlen strpbrk strrchr strstr strnstr strtod strtok_r strtol strtoll strtoul strtoull tan tanf trunc truncf unsetenv diff --git a/cmake/PreseedEmscriptenCache.cmake b/cmake/PreseedEmscriptenCache.cmake index 261e7ea677..5a34ab5ac2 100644 --- a/cmake/PreseedEmscriptenCache.cmake +++ b/cmake/PreseedEmscriptenCache.cmake @@ -98,6 +98,7 @@ if(EMSCRIPTEN) set(LIBC_HAS_STRNCMP "1" CACHE INTERNAL "Have symbol strncmp") set(LIBC_HAS_STRNLEN "1" CACHE INTERNAL "Have symbol strnlen") set(LIBC_HAS_STRNSTR "" CACHE INTERNAL "Have symbol strnstr") + set(LIBC_HAS_STRPBRK "1" CACHE INTERNAL "Have symbol strpbrk") set(LIBC_HAS_STRRCHR "1" CACHE INTERNAL "Have symbol strrchr") set(LIBC_HAS_STRSTR "1" CACHE INTERNAL "Have symbol strstr") set(LIBC_HAS_STRTOD "1" CACHE INTERNAL "Have symbol strtod") diff --git a/cmake/PreseedMSVCCache.cmake b/cmake/PreseedMSVCCache.cmake index 76d3fa4b8b..17495aa480 100644 --- a/cmake/PreseedMSVCCache.cmake +++ b/cmake/PreseedMSVCCache.cmake @@ -111,6 +111,7 @@ if(MSVC) set(LIBC_HAS_STRNCMP "1" CACHE INTERNAL "Have symbol strncmp") set(LIBC_HAS_STRNLEN "1" CACHE INTERNAL "Have symbol strnlen") set(LIBC_HAS_STRNSTR "" CACHE INTERNAL "Have symbol strnstr") + set(LIBC_HAS_STRPBRK "1" CACHE INTERNAL "Have symbol strpbrk") set(LIBC_HAS_STRRCHR "1" CACHE INTERNAL "Have symbol strrchr") set(LIBC_HAS_STRSTR "1" CACHE INTERNAL "Have symbol strstr") set(LIBC_HAS_STRTOD "1" CACHE INTERNAL "Have symbol strtod") diff --git a/include/SDL3/SDL_stdinc.h b/include/SDL3/SDL_stdinc.h index 646bbd7884..2a36d4426e 100644 --- a/include/SDL3/SDL_stdinc.h +++ b/include/SDL3/SDL_stdinc.h @@ -1297,6 +1297,22 @@ extern SDL_DECLSPEC int SDLCALL SDL_strcasecmp(const char *str1, const char *str */ extern SDL_DECLSPEC int SDLCALL SDL_strncasecmp(const char *str1, const char *str2, size_t maxlen); +/** + * Searches a string for the first occurence of any character contained in a + * breakset, and returns a pointer from the string to that character. + * + * \param str The null-terminated string to be searched. + * \param breakset A null-terminated string containing the list of characters + * to look for. + * \returns A pointer to the location, in str, of the first occurence of a + * character present in the breakset, or NULL if none is found. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + */ +extern SDL_DECLSPEC char * SDLCALL SDL_strpbrk(const char * SDL_RESTRICT str, const char * SDL_RESTRICT breakset); + /** * The Unicode REPLACEMENT CHARACTER codepoint. * @@ -3079,6 +3095,7 @@ size_t wcslcat(wchar_t *dst, const wchar_t *src, size_t size); #define SDL_wcsncmp wcsncmp #define SDL_strcasecmp strcasecmp #define SDL_strncasecmp strncasecmp +#define SDL_strpbrk strpbrk #define SDL_sscanf sscanf #define SDL_vsscanf vsscanf #define SDL_snprintf snprintf diff --git a/include/build_config/SDL_build_config.h.cmake b/include/build_config/SDL_build_config.h.cmake index ea05ee31c6..e117409bb6 100644 --- a/include/build_config/SDL_build_config.h.cmake +++ b/include/build_config/SDL_build_config.h.cmake @@ -100,6 +100,7 @@ #cmakedefine HAVE_STRNLEN 1 #cmakedefine HAVE_STRLCPY 1 #cmakedefine HAVE_STRLCAT 1 +#cmakedefine HAVE_STRPBRK 1 #cmakedefine HAVE__STRREV 1 #cmakedefine HAVE__STRUPR 1 #cmakedefine HAVE__STRLWR 1 diff --git a/include/build_config/SDL_build_config_ios.h b/include/build_config/SDL_build_config_ios.h index b283858e83..fe87d84e3e 100644 --- a/include/build_config/SDL_build_config_ios.h +++ b/include/build_config/SDL_build_config_ios.h @@ -76,6 +76,7 @@ #define HAVE_ATOF 1 #define HAVE_STRCMP 1 #define HAVE_STRNCMP 1 +#define HAVE_STRPBRK 1 #define HAVE_STRCASESTR 1 #define HAVE_VSSCANF 1 #define HAVE_VSNPRINTF 1 diff --git a/include/build_config/SDL_build_config_macos.h b/include/build_config/SDL_build_config_macos.h index 61fc8e8414..40a8895d7c 100644 --- a/include/build_config/SDL_build_config_macos.h +++ b/include/build_config/SDL_build_config_macos.h @@ -68,6 +68,7 @@ #define HAVE_STRLEN 1 #define HAVE_STRLCPY 1 #define HAVE_STRLCAT 1 +#define HAVE_STRPBRK 1 #define HAVE_STRCHR 1 #define HAVE_STRRCHR 1 #define HAVE_STRSTR 1 diff --git a/include/build_config/SDL_build_config_windows.h b/include/build_config/SDL_build_config_windows.h index 47723fb285..7729521963 100644 --- a/include/build_config/SDL_build_config_windows.h +++ b/include/build_config/SDL_build_config_windows.h @@ -160,6 +160,7 @@ typedef unsigned int uintptr_t; #define HAVE_ATOF 1 #define HAVE_STRCMP 1 #define HAVE_STRNCMP 1 +#define HAVE_STRPBRK 1 #define HAVE__WCSDUP 1 #define HAVE_SSCANF 1 #define HAVE_VSSCANF 1 diff --git a/include/build_config/SDL_build_config_winrt.h b/include/build_config/SDL_build_config_winrt.h index 57d1dea420..7ee64a66f8 100644 --- a/include/build_config/SDL_build_config_winrt.h +++ b/include/build_config/SDL_build_config_winrt.h @@ -85,6 +85,7 @@ #define HAVE__STRREV 1 #define HAVE__STRUPR 1 #define HAVE_STRCHR 1 +#define HAVE_STRPBRK 1 #define HAVE_STRRCHR 1 #define HAVE_STRSTR 1 #define HAVE_STRTOL 1 diff --git a/include/build_config/SDL_build_config_xbox.h b/include/build_config/SDL_build_config_xbox.h index 2ad0eb7d4e..ae80b5ef64 100644 --- a/include/build_config/SDL_build_config_xbox.h +++ b/include/build_config/SDL_build_config_xbox.h @@ -82,6 +82,7 @@ #define HAVE_MEMMOVE 1 #define HAVE_MEMCMP 1 #define HAVE_STRLEN 1 +#define HAVE_STRPBRK 1 #define HAVE__STRREV 1 /* These functions have security warnings, so we won't use them */ /* #undef HAVE__STRUPR */ diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index 35ef0041f1..6c6aa7695c 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -1144,6 +1144,7 @@ SDL3_0.0.0 { SDL_wcsnstr; SDL_wcsstr; SDL_wcstol; + SDL_strpbrk; # extra symbols go here (don't modify this line) local: *; }; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index d04960d010..f0e1118c69 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -1169,3 +1169,4 @@ #define SDL_wcsnstr SDL_wcsnstr_REAL #define SDL_wcsstr SDL_wcsstr_REAL #define SDL_wcstol SDL_wcstol_REAL +#define SDL_strpbrk SDL_strpbrk_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 0d1ed3b05e..b4c4e30620 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -1175,3 +1175,4 @@ SDL_DYNAPI_PROC(size_t,SDL_wcsnlen,(const wchar_t *a, size_t b),(a,b),return) SDL_DYNAPI_PROC(wchar_t*,SDL_wcsnstr,(const wchar_t *a, const wchar_t *b, size_t c),(a,b,c),return) SDL_DYNAPI_PROC(wchar_t*,SDL_wcsstr,(const wchar_t *a, const wchar_t *b),(a,b),return) SDL_DYNAPI_PROC(long,SDL_wcstol,(const wchar_t *a, wchar_t **b, int c),(a,b,c),return) +SDL_DYNAPI_PROC(char*,SDL_strpbrk,(const char *a, const char *b),(a,b),return) diff --git a/src/stdlib/SDL_string.c b/src/stdlib/SDL_string.c index 0b7dad4460..53fc7fd9b1 100644 --- a/src/stdlib/SDL_string.c +++ b/src/stdlib/SDL_string.c @@ -2401,3 +2401,22 @@ int SDL_vasprintf(char **strp, SDL_PRINTF_FORMAT_STRING const char *fmt, va_list } } } + +char * SDL_strpbrk(const char *str, const char *breakset) +{ +#ifdef HAVE_STRPBRK + return strpbrk(str, breakset); +#else + + for (; *str; str++) { + const char *b; + + for (b = breakset; *b; b++) { + if (*str == *b) { + return (char *) str; + } + } + } + return NULL; +#endif +} diff --git a/test/testautomation_stdlib.c b/test/testautomation_stdlib.c index be87103ec8..832987b616 100644 --- a/test/testautomation_stdlib.c +++ b/test/testautomation_stdlib.c @@ -1188,6 +1188,46 @@ stdlib_iconv(void *arg) return TEST_COMPLETED; } + +static int +stdlib_strpbrk(void *arg) +{ + struct { + const char *input; + const char *accept; + int expected[3]; /* negative if NULL */ + } test_cases[] = { + { "", "", { -1, -1, -1 } }, + { "abc", "", { -1, -1, -1 } }, + { "Abc", "a", { -1, -1, -1 } }, + { "abc", "a", { 0, -1, -1 } }, + { "abcbd", "bbbb", { 1, 3, -1 } }, + { "a;b;c", ";", { 1, 3, -1 } }, + { "a;b;c", ",", { -1, -1, -1 } }, + { "a:bbbb;c", ";:", { 1, 6, -1 } }, + { "Hello\tS DL\n", " \t\r\n", { 5, 7, 10 } }, + }; + int i; + + for (i = 0; i < SDL_arraysize(test_cases); i++) { + int j; + const char *input = test_cases[i].input; + + for (j = 0; j < SDL_arraysize(test_cases[i].expected); j++) { + char *result; + + SDLTest_AssertPass("About to call SDL_strpbrk(\"%s\", \"%s\")", input, test_cases[i].accept); + result = SDL_strpbrk(input, test_cases[i].accept); + if (test_cases[i].expected[j] < 0) { + SDLTest_AssertCheck(result == NULL, "Expected NULL, got %p", result); + } else { + SDLTest_AssertCheck(result == test_cases[i].input + test_cases[i].expected[j], "Expected %p, got %p", test_cases[i].input + test_cases[i].expected[j], result); + input = test_cases[i].input + test_cases[i].expected[j] + 1; + } + } + } + return TEST_COMPLETED; +} /* ================= Test References ================== */ /* Standard C routine test cases */ @@ -1227,8 +1267,12 @@ static const SDLTest_TestCaseReference stdlibTestOverflow = { stdlib_overflow, "stdlib_overflow", "Overflow detection", TEST_ENABLED }; -static const SDLTest_TestCaseReference stdlibIconv = { - stdlib_iconv, "stdlib_iconv", "Calls to iconv", TEST_ENABLED +static const SDLTest_TestCaseReference stdlibTest_iconv = { + stdlib_iconv, "stdlib_iconv", "Calls to SDL_iconv", TEST_ENABLED +}; + +static const SDLTest_TestCaseReference stdlibTest_strpbrk = { + stdlib_strpbrk, "stdlib_strpbrk", "Calls to SDL_strpbrk", TEST_ENABLED }; /* Sequence of Standard C routine test cases */ @@ -1242,7 +1286,8 @@ static const SDLTest_TestCaseReference *stdlibTests[] = { &stdlibTest_sscanf, &stdlibTest_aligned_alloc, &stdlibTestOverflow, - &stdlibIconv, + &stdlibTest_iconv, + &stdlibTest_strpbrk, NULL };