Added SDL_strnstr()

main
Sam Lantinga 2023-12-03 14:42:28 -08:00
parent 7c71e72193
commit ac0751a652
8 changed files with 119 additions and 21 deletions

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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: *;
}; };

View File

@ -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

View File

@ -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)

View File

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

View File

@ -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
}; };