Bläddra i källkod

Added SDL_strnstr()

Sam Lantinga 1 år sedan
förälder
incheckning
ac0751a652

+ 1 - 1
CMakeLists.txt

@@ -1065,7 +1065,7 @@ if(SDL_LIBC)
     realloc rindex round roundf
     realloc rindex round roundf
     scalbn scalbnf setenv sin sinf sqr sqrt sqrtf sscanf strchr
     scalbn scalbnf setenv sin sinf sqr sqrt sqrtf sscanf strchr
     strcmp strlcat strlcpy strlen strncmp strnlen
     strcmp strlcat strlcpy strlen strncmp strnlen
-    strrchr strstr strtod strtok_r strtol strtoll strtoul strtoull
+    strrchr strstr strnstr strtod strtok_r strtol strtoll strtoul strtoull
     tan tanf trunc truncf
     tan tanf trunc truncf
     unsetenv
     unsetenv
     vsnprintf vsscanf
     vsnprintf vsscanf

+ 2 - 0
include/SDL3/SDL_stdinc.h

@@ -546,6 +546,7 @@ extern DECLSPEC size_t SDLCALL SDL_wcslcpy(SDL_OUT_Z_CAP(maxlen) wchar_t *dst, c
 extern DECLSPEC size_t SDLCALL SDL_wcslcat(SDL_INOUT_Z_CAP(maxlen) wchar_t *dst, const wchar_t *src, size_t maxlen);
 extern DECLSPEC size_t SDLCALL SDL_wcslcat(SDL_INOUT_Z_CAP(maxlen) wchar_t *dst, const wchar_t *src, size_t maxlen);
 extern DECLSPEC wchar_t *SDLCALL SDL_wcsdup(const wchar_t *wstr);
 extern DECLSPEC wchar_t *SDLCALL SDL_wcsdup(const wchar_t *wstr);
 extern DECLSPEC wchar_t *SDLCALL SDL_wcsstr(const wchar_t *haystack, const wchar_t *needle);
 extern DECLSPEC wchar_t *SDLCALL SDL_wcsstr(const wchar_t *haystack, const wchar_t *needle);
+extern DECLSPEC wchar_t *SDLCALL SDL_wcsnstr(const wchar_t *haystack, const wchar_t *needle, size_t maxlen);
 
 
 extern DECLSPEC int SDLCALL SDL_wcscmp(const wchar_t *str1, const wchar_t *str2);
 extern DECLSPEC int SDLCALL SDL_wcscmp(const wchar_t *str1, const wchar_t *str2);
 extern DECLSPEC int SDLCALL SDL_wcsncmp(const wchar_t *str1, const wchar_t *str2, size_t maxlen);
 extern DECLSPEC int SDLCALL SDL_wcsncmp(const wchar_t *str1, const wchar_t *str2, size_t maxlen);
@@ -566,6 +567,7 @@ extern DECLSPEC char *SDLCALL SDL_strlwr(char *str);
 extern DECLSPEC char *SDLCALL SDL_strchr(const char *str, int c);
 extern DECLSPEC char *SDLCALL SDL_strchr(const char *str, int c);
 extern DECLSPEC char *SDLCALL SDL_strrchr(const char *str, int c);
 extern DECLSPEC char *SDLCALL SDL_strrchr(const char *str, int c);
 extern DECLSPEC char *SDLCALL SDL_strstr(const char *haystack, const char *needle);
 extern DECLSPEC char *SDLCALL SDL_strstr(const char *haystack, const char *needle);
+extern DECLSPEC char *SDLCALL SDL_strnstr(const char *haystack, const char *needle, size_t maxlen);
 extern DECLSPEC char *SDLCALL SDL_strcasestr(const char *haystack, const char *needle);
 extern DECLSPEC char *SDLCALL SDL_strcasestr(const char *haystack, const char *needle);
 extern DECLSPEC char *SDLCALL SDL_strtok_r(char *s1, const char *s2, char **saveptr);
 extern DECLSPEC char *SDLCALL SDL_strtok_r(char *s1, const char *s2, char **saveptr);
 extern DECLSPEC size_t SDLCALL SDL_utf8strlen(const char *str);
 extern DECLSPEC size_t SDLCALL SDL_utf8strlen(const char *str);

+ 1 - 0
include/build_config/SDL_build_config.h.cmake

@@ -116,6 +116,7 @@
 #cmakedefine HAVE_STRCHR 1
 #cmakedefine HAVE_STRCHR 1
 #cmakedefine HAVE_STRRCHR 1
 #cmakedefine HAVE_STRRCHR 1
 #cmakedefine HAVE_STRSTR 1
 #cmakedefine HAVE_STRSTR 1
+#cmakedefine HAVE_STRNSTR 1
 #cmakedefine HAVE_STRTOK_R 1
 #cmakedefine HAVE_STRTOK_R 1
 #cmakedefine HAVE_ITOA 1
 #cmakedefine HAVE_ITOA 1
 #cmakedefine HAVE__LTOA 1
 #cmakedefine HAVE__LTOA 1

+ 2 - 0
src/dynapi/SDL_dynapi.sym

@@ -960,6 +960,8 @@ SDL3_0.0.0 {
     SDL_GetGamepadMappings;
     SDL_GetGamepadMappings;
     SDL_GetTouchDevices;
     SDL_GetTouchDevices;
     SDL_GetTouchDeviceName;
     SDL_GetTouchDeviceName;
+    SDL_strnstr;
+    SDL_wcsnstr;
     # extra symbols go here (don't modify this line)
     # extra symbols go here (don't modify this line)
   local: *;
   local: *;
 };
 };

+ 2 - 0
src/dynapi/SDL_dynapi_overrides.h

@@ -985,3 +985,5 @@
 #define SDL_GetGamepadMappings SDL_GetGamepadMappings_REAL
 #define SDL_GetGamepadMappings SDL_GetGamepadMappings_REAL
 #define SDL_GetTouchDevices SDL_GetTouchDevices_REAL
 #define SDL_GetTouchDevices SDL_GetTouchDevices_REAL
 #define SDL_GetTouchDeviceName SDL_GetTouchDeviceName_REAL
 #define SDL_GetTouchDeviceName SDL_GetTouchDeviceName_REAL
+#define SDL_strnstr SDL_strnstr_REAL
+#define SDL_wcsnstr SDL_wcsnstr_REAL

+ 2 - 0
src/dynapi/SDL_dynapi_procs.h

@@ -1010,3 +1010,5 @@ SDL_DYNAPI_PROC(SDL_Renderer*,SDL_CreateRendererWithProperties,(SDL_PropertiesID
 SDL_DYNAPI_PROC(char**,SDL_GetGamepadMappings,(int *a),(a),return)
 SDL_DYNAPI_PROC(char**,SDL_GetGamepadMappings,(int *a),(a),return)
 SDL_DYNAPI_PROC(SDL_TouchID*,SDL_GetTouchDevices,(int *a),(a),return)
 SDL_DYNAPI_PROC(SDL_TouchID*,SDL_GetTouchDevices,(int *a),(a),return)
 SDL_DYNAPI_PROC(const char*,SDL_GetTouchDeviceName,(SDL_TouchID a),(a),return)
 SDL_DYNAPI_PROC(const char*,SDL_GetTouchDeviceName,(SDL_TouchID a),(a),return)
+SDL_DYNAPI_PROC(char*,SDL_strnstr,(const char *a, const char *b, size_t c),(a,b,c),return)
+SDL_DYNAPI_PROC(wchar_t*,SDL_wcsnstr,(const wchar_t *a, const wchar_t *b, size_t c),(a,b,c),return)

+ 32 - 10
src/stdlib/SDL_string.c

@@ -468,19 +468,28 @@ wchar_t *SDL_wcsdup(const wchar_t *string)
     return newstr;
     return newstr;
 }
 }
 
 
-wchar_t *SDL_wcsstr(const wchar_t *haystack, const wchar_t *needle)
+wchar_t *SDL_wcsnstr(const wchar_t *haystack, const wchar_t *needle, size_t maxlen)
 {
 {
-#ifdef HAVE_WCSSTR
-    return SDL_const_cast(wchar_t *, wcsstr(haystack, needle));
-#else
     size_t length = SDL_wcslen(needle);
     size_t length = SDL_wcslen(needle);
-    while (*haystack) {
-        if (SDL_wcsncmp(haystack, needle, length) == 0) {
+    if (length == 0) {
+        return (wchar_t *)haystack;
+    }
+    while (maxlen >= length && *haystack) {
+        if (maxlen >= length && SDL_wcsncmp(haystack, needle, length) == 0) {
             return (wchar_t *)haystack;
             return (wchar_t *)haystack;
         }
         }
         ++haystack;
         ++haystack;
+        --maxlen;
     }
     }
     return NULL;
     return NULL;
+}
+
+wchar_t *SDL_wcsstr(const wchar_t *haystack, const wchar_t *needle)
+{
+#ifdef HAVE_WCSSTR
+    return SDL_const_cast(wchar_t *, wcsstr(haystack, needle));
+#else
+    return SDL_wcsnstr(haystack, needle, SDL_wcslen(haystack));
 #endif /* HAVE_WCSSTR */
 #endif /* HAVE_WCSSTR */
 }
 }
 
 
@@ -821,22 +830,35 @@ char *SDL_strrchr(const char *string, int c)
 #endif /* HAVE_STRRCHR */
 #endif /* HAVE_STRRCHR */
 }
 }
 
 
-char *SDL_strstr(const char *haystack, const char *needle)
+char *SDL_strnstr(const char *haystack, const char *needle, size_t maxlen)
 {
 {
-#ifdef HAVE_STRSTR
-    return SDL_const_cast(char *, strstr(haystack, needle));
+#ifdef HAVE_STRNSTR
+    return SDL_const_cast(char *, strnstr(haystack, needle, maxlen));
 #else
 #else
     size_t length = SDL_strlen(needle);
     size_t length = SDL_strlen(needle);
-    while (*haystack) {
+    if (length == 0) {
+        return (char *)haystack;
+    }
+    while (maxlen >= length && *haystack) {
         if (SDL_strncmp(haystack, needle, length) == 0) {
         if (SDL_strncmp(haystack, needle, length) == 0) {
             return (char *)haystack;
             return (char *)haystack;
         }
         }
         ++haystack;
         ++haystack;
+        --maxlen;
     }
     }
     return NULL;
     return NULL;
 #endif /* HAVE_STRSTR */
 #endif /* HAVE_STRSTR */
 }
 }
 
 
+char *SDL_strstr(const char *haystack, const char *needle)
+{
+#ifdef HAVE_STRSTR
+    return SDL_const_cast(char *, strstr(haystack, needle));
+#else
+    return SDL_strnstr(haystack, needle, SDL_strlen(haystack));
+#endif /* HAVE_STRSTR */
+}
+
 char *SDL_strcasestr(const char *haystack, const char *needle)
 char *SDL_strcasestr(const char *haystack, const char *needle)
 {
 {
 #ifdef HAVE_STRCASESTR
 #ifdef HAVE_STRCASESTR

+ 71 - 4
test/testautomation_stdlib.c

@@ -60,6 +60,68 @@ static int stdlib_strlcpy(void *arg)
     return TEST_COMPLETED;
     return TEST_COMPLETED;
 }
 }
 
 
+/**
+ * Call to SDL_strstr
+ */
+static int stdlib_strstr(void *arg)
+{
+    char *result;
+    const char *text = "abcdef";
+    const char *expected;
+
+    result = SDL_strstr(text, "");
+    expected = text;
+    SDLTest_AssertPass("Call to SDL_strstr(text, \"\")");
+    SDLTest_AssertCheck(result == expected, "Check result, expected: %s, got: %s", expected, result);
+
+    result = SDL_strstr(text, "abc");
+    expected = text;
+    SDLTest_AssertPass("Call to SDL_strstr(text, \"abc\")");
+    SDLTest_AssertCheck(result == expected, "Check result, expected: %s, got: %s", expected, result);
+
+    result = SDL_strstr(text, "bcd");
+    expected = text+1;
+    SDLTest_AssertPass("Call to SDL_strstr(text, \"bcd\")");
+    SDLTest_AssertCheck(result == expected, "Check result, expected: %s, got: %s", expected, result);
+
+    result = SDL_strstr(text, "xyz");
+    expected = NULL;
+    SDLTest_AssertPass("Call to SDL_strstr(text, \"xyz\")");
+    SDLTest_AssertCheck(result == expected, "Check result, expected: (null), got: %s", result);
+
+    result = SDL_strnstr(text, "", SDL_strlen(text));
+    expected = text;
+    SDLTest_AssertPass("Call to SDL_strnstr(text, \"\", SDL_strlen(text))");
+    SDLTest_AssertCheck(result == expected, "Check result, expected: %s, got: %s", expected, result);
+
+    result = SDL_strnstr(text, "abc", SDL_strlen(text));
+    expected = text;
+    SDLTest_AssertPass("Call to SDL_strnstr(text, \"abc\", SDL_strlen(text))");
+    SDLTest_AssertCheck(result == expected, "Check result, expected: %s, got: %s", expected, result);
+
+    result = SDL_strnstr(text, "bcd", SDL_strlen(text));
+    expected = text+1;
+    SDLTest_AssertPass("Call to SDL_strnstr(text, \"bcd\", SDL_strlen(text))");
+    SDLTest_AssertCheck(result == expected, "Check result, expected: %s, got: %s", expected, result);
+
+    result = SDL_strnstr(text, "bcd", 3);
+    expected = NULL;
+    SDLTest_AssertPass("Call to SDL_strnstr(text, \"bcd\", 3)");
+    SDLTest_AssertCheck(result == expected, "Check result, expected: (null), got: %s", result);
+
+    result = SDL_strnstr(text, "xyz", 3);
+    expected = NULL;
+    SDLTest_AssertPass("Call to SDL_strnstr(text, \"xyz\", 3)");
+    SDLTest_AssertCheck(result == expected, "Check result, expected: (null), got: %s", result);
+
+    result = SDL_strnstr(text, "xyz", SDL_strlen(text)*100000);
+    expected = NULL;
+    SDLTest_AssertPass("Call to SDL_strnstr(text, \"xyz\", SDL_strlen(text)*100000)");
+    SDLTest_AssertCheck(result == expected, "Check result, expected: (null), got: %s", result);
+
+    return TEST_COMPLETED;
+}
+
 #if defined(HAVE_WFORMAT) || defined(HAVE_WFORMAT_EXTRA_ARGS)
 #if defined(HAVE_WFORMAT) || defined(HAVE_WFORMAT_EXTRA_ARGS)
 #pragma GCC diagnostic push
 #pragma GCC diagnostic push
 #ifdef HAVE_WFORMAT
 #ifdef HAVE_WFORMAT
@@ -930,22 +992,26 @@ static const SDLTest_TestCaseReference stdlibTest2 = {
 };
 };
 
 
 static const SDLTest_TestCaseReference stdlibTest3 = {
 static const SDLTest_TestCaseReference stdlibTest3 = {
-    stdlib_snprintf, "stdlib_snprintf", "Call to SDL_snprintf", TEST_ENABLED
+    stdlib_strstr, "stdlib_strstr", "Call to SDL_strstr", TEST_ENABLED
 };
 };
 
 
 static const SDLTest_TestCaseReference stdlibTest4 = {
 static const SDLTest_TestCaseReference stdlibTest4 = {
-    stdlib_swprintf, "stdlib_swprintf", "Call to SDL_swprintf", TEST_ENABLED
+    stdlib_snprintf, "stdlib_snprintf", "Call to SDL_snprintf", TEST_ENABLED
 };
 };
 
 
 static const SDLTest_TestCaseReference stdlibTest5 = {
 static const SDLTest_TestCaseReference stdlibTest5 = {
-    stdlib_getsetenv, "stdlib_getsetenv", "Call to SDL_getenv and SDL_setenv", TEST_ENABLED
+    stdlib_swprintf, "stdlib_swprintf", "Call to SDL_swprintf", TEST_ENABLED
 };
 };
 
 
 static const SDLTest_TestCaseReference stdlibTest6 = {
 static const SDLTest_TestCaseReference stdlibTest6 = {
-    stdlib_sscanf, "stdlib_sscanf", "Call to SDL_sscanf", TEST_ENABLED
+    stdlib_getsetenv, "stdlib_getsetenv", "Call to SDL_getenv and SDL_setenv", TEST_ENABLED
 };
 };
 
 
 static const SDLTest_TestCaseReference stdlibTest7 = {
 static const SDLTest_TestCaseReference stdlibTest7 = {
+    stdlib_sscanf, "stdlib_sscanf", "Call to SDL_sscanf", TEST_ENABLED
+};
+
+static const SDLTest_TestCaseReference stdlibTest8 = {
     stdlib_aligned_alloc, "stdlib_aligned_alloc", "Call to SDL_aligned_alloc", TEST_ENABLED
     stdlib_aligned_alloc, "stdlib_aligned_alloc", "Call to SDL_aligned_alloc", TEST_ENABLED
 };
 };
 
 
@@ -962,6 +1028,7 @@ static const SDLTest_TestCaseReference *stdlibTests[] = {
     &stdlibTest5,
     &stdlibTest5,
     &stdlibTest6,
     &stdlibTest6,
     &stdlibTest7,
     &stdlibTest7,
+    &stdlibTest8,
     &stdlibTestOverflow,
     &stdlibTestOverflow,
     NULL
     NULL
 };
 };