From baa1a5e2f472ad062ef618843dce916e226791aa Mon Sep 17 00:00:00 2001
From: Anonymous Maarten <[EMAIL REDACTED]>
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 37e6647a6d799..5716da4cefbe3 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 261e7ea677e96..5a34ab5ac21f4 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 76d3fa4b8b5a5..17495aa480aba 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 646bbd788420b..2a36d4426e0ab 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 ea05ee31c633c..e117409bb6ead 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 b283858e833d8..fe87d84e3ecbb 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 61fc8e8414fa3..40a8895d7cd42 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 47723fb28594e..7729521963b99 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 57d1dea420af0..7ee64a66f8e1e 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 2ad0eb7d4e043..ae80b5ef64f5a 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 35ef0041f165f..6c6aa7695c216 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 d04960d01066a..f0e1118c69755 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 0d1ed3b05e8d0..b4c4e3062011a 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 0b7dad4460003..53fc7fd9b145b 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 be87103ec876e..832987b616182 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
};