SDL: Added SDL_strndup()

From f3d6320bac5f0d4d45842fcf4b66931881ecf53d Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Sat, 15 Jul 2023 09:12:39 -0700
Subject: [PATCH] Added SDL_strndup()

---
 include/SDL3/SDL_stdinc.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           | 11 +++++++++++
 5 files changed, 15 insertions(+)

diff --git a/include/SDL3/SDL_stdinc.h b/include/SDL3/SDL_stdinc.h
index 304c8b5b5d44..c9b787b6b605 100644
--- a/include/SDL3/SDL_stdinc.h
+++ b/include/SDL3/SDL_stdinc.h
@@ -549,6 +549,7 @@ extern DECLSPEC size_t SDLCALL SDL_strlcpy(SDL_OUT_Z_CAP(maxlen) char *dst, cons
 extern DECLSPEC size_t SDLCALL SDL_utf8strlcpy(SDL_OUT_Z_CAP(dst_bytes) char *dst, const char *src, size_t dst_bytes);
 extern DECLSPEC size_t SDLCALL SDL_strlcat(SDL_INOUT_Z_CAP(maxlen) char *dst, const char *src, size_t maxlen);
 extern DECLSPEC SDL_MALLOC char *SDLCALL SDL_strdup(const char *str);
+extern DECLSPEC SDL_MALLOC char *SDLCALL SDL_strndup(const char *str, size_t maxlen);
 extern DECLSPEC char *SDLCALL SDL_strrev(char *str);
 extern DECLSPEC char *SDLCALL SDL_strupr(char *str);
 extern DECLSPEC char *SDLCALL SDL_strlwr(char *str);
diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym
index 7557cb4b8f9c..d919e7bb1b39 100644
--- a/src/dynapi/SDL_dynapi.sym
+++ b/src/dynapi/SDL_dynapi.sym
@@ -870,6 +870,7 @@ SDL3_0.0.0 {
     SDL_GetGamepadInstanceID;
     SDL_GetGamepadPowerLevel;
     SDL_SetGamepadMapping;
+    SDL_strndup;
     # 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 5dee578eff66..145111f84c1f 100644
--- a/src/dynapi/SDL_dynapi_overrides.h
+++ b/src/dynapi/SDL_dynapi_overrides.h
@@ -896,3 +896,4 @@
 #define SDL_GetGamepadInstanceID SDL_GetGamepadInstanceID_REAL
 #define SDL_GetGamepadPowerLevel SDL_GetGamepadPowerLevel_REAL
 #define SDL_SetGamepadMapping SDL_SetGamepadMapping_REAL
+#define SDL_strndup SDL_strndup_REAL
diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h
index 443d31d4835b..d1fb03fdb5d2 100644
--- a/src/dynapi/SDL_dynapi_procs.h
+++ b/src/dynapi/SDL_dynapi_procs.h
@@ -941,3 +941,4 @@ SDL_DYNAPI_PROC(int,SDL_ClearClipboardData,(void),(),return)
 SDL_DYNAPI_PROC(SDL_JoystickID,SDL_GetGamepadInstanceID,(SDL_Gamepad *a),(a),return)
 SDL_DYNAPI_PROC(SDL_JoystickPowerLevel,SDL_GetGamepadPowerLevel,(SDL_Gamepad *a),(a),return)
 SDL_DYNAPI_PROC(int,SDL_SetGamepadMapping,(SDL_JoystickID a, const char *b),(a,b),return)
+SDL_DYNAPI_PROC(char*,SDL_strndup,(const char *a, size_t b),(a,b),return)
diff --git a/src/stdlib/SDL_string.c b/src/stdlib/SDL_string.c
index 2af043f2e050..bb674786b758 100644
--- a/src/stdlib/SDL_string.c
+++ b/src/stdlib/SDL_string.c
@@ -700,6 +700,17 @@ char *SDL_strdup(const char *string)
     return newstr;
 }
 
+char *SDL_strndup(const char *string, size_t maxlen)
+{
+    size_t len = SDL_min(SDL_strlen(string), maxlen) + 1;
+    char *newstr = (char *)SDL_malloc(len);
+    if (newstr) {
+        SDL_memcpy(newstr, string, len);
+        newstr[len - 1] = '\0';
+    }
+    return newstr;
+}
+
 char *SDL_strrev(char *string)
 {
 #ifdef HAVE__STRREV