SDL: SDL_AddGamepadMappingsFromFile() has been made into a real function

From 75e7a6fcfad631d4a9cd85b8621d00c2342f2326 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Tue, 18 Jul 2023 12:05:04 -0700
Subject: [PATCH] SDL_AddGamepadMappingsFromFile() has been made into a real
 function

---
 include/SDL3/SDL_gamepad.h        | 30 ++++++++++++++++++++++++------
 src/dynapi/SDL_dynapi.sym         |  1 +
 src/dynapi/SDL_dynapi_overrides.h |  1 +
 src/dynapi/SDL_dynapi_procs.h     |  1 +
 src/joystick/SDL_gamepad.c        | 27 ++++++++++++++++-----------
 5 files changed, 43 insertions(+), 17 deletions(-)

diff --git a/include/SDL3/SDL_gamepad.h b/include/SDL3/SDL_gamepad.h
index 15945173780d..1587702a3deb 100644
--- a/include/SDL3/SDL_gamepad.h
+++ b/include/SDL3/SDL_gamepad.h
@@ -175,8 +175,8 @@ extern DECLSPEC int SDLCALL SDL_AddGamepadMapping(const char *mapping);
  * processing it, so take this into consideration if you are in a memory
  * constrained environment.
  *
- * \param rw the data stream for the mappings to be added
- * \param freerw non-zero to close the stream after being read
+ * \param src the data stream for the mappings to be added
+ * \param freesrc non-zero to close the stream after being read
  * \returns the number of mappings added or -1 on error; call SDL_GetError()
  *          for more information.
  *
@@ -186,14 +186,32 @@ extern DECLSPEC int SDLCALL SDL_AddGamepadMapping(const char *mapping);
  * \sa SDL_AddGamepadMappingsFromFile
  * \sa SDL_GetGamepadMappingForGUID
  */
-extern DECLSPEC int SDLCALL SDL_AddGamepadMappingsFromRW(SDL_RWops *rw, int freerw);
+extern DECLSPEC int SDLCALL SDL_AddGamepadMappingsFromRW(SDL_RWops *src, int freesrc);
 
 /**
- *  Load a set of mappings from a file, filtered by the current SDL_GetPlatform()
+ * Load a set of gamepad mappings from a file.
  *
- *  Convenience macro.
+ * You can call this function several times, if needed, to load different
+ * database files.
+ *
+ * If a new mapping is loaded for an already known gamepad GUID, the later
+ * version will overwrite the one currently loaded.
+ *
+ * Mappings not belonging to the current platform or with no platform field
+ * specified will be ignored (i.e. mappings for Linux will be ignored in
+ * Windows, etc).
+ *
+ * \param file the mappings file to load
+ * \returns the number of mappings added or -1 on error; call SDL_GetError()
+ *          for more information.
+ *
+ * \since This function is available since SDL 3.0.0.
+ *
+ * \sa SDL_AddGamepadMapping
+ * \sa SDL_AddGamepadMappingsFromRW
+ * \sa SDL_GetGamepadMappingForGUID
  */
-#define SDL_AddGamepadMappingsFromFile(file)   SDL_AddGamepadMappingsFromRW(SDL_RWFromFile(file, "rb"), 1)
+extern DECLSPEC int SDLCALL SDL_AddGamepadMappingsFromFile(const char *file);
 
 /**
  * Get the number of mappings installed.
diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym
index 65964d2d100b..24f5cc80f3b7 100644
--- a/src/dynapi/SDL_dynapi.sym
+++ b/src/dynapi/SDL_dynapi.sym
@@ -877,6 +877,7 @@ SDL3_0.0.0 {
     SDL_GetRealGamepadType;
     SDL_wcsnlen;
     SDL_strnlen;
+    SDL_AddGamepadMappingsFromFile;
     # 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 01e95b07786d..fb0e11285bd3 100644
--- a/src/dynapi/SDL_dynapi_overrides.h
+++ b/src/dynapi/SDL_dynapi_overrides.h
@@ -903,3 +903,4 @@
 #define SDL_GetRealGamepadType SDL_GetRealGamepadType_REAL
 #define SDL_wcsnlen SDL_wcsnlen_REAL
 #define SDL_strnlen SDL_strnlen_REAL
+#define SDL_AddGamepadMappingsFromFile SDL_AddGamepadMappingsFromFile_REAL
diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h
index e4213075b036..4d32a52f59aa 100644
--- a/src/dynapi/SDL_dynapi_procs.h
+++ b/src/dynapi/SDL_dynapi_procs.h
@@ -948,3 +948,4 @@ SDL_DYNAPI_PROC(SDL_GamepadType,SDL_GetRealGamepadInstanceType,(SDL_JoystickID a
 SDL_DYNAPI_PROC(SDL_GamepadType,SDL_GetRealGamepadType,(SDL_Gamepad *a),(a),return)
 SDL_DYNAPI_PROC(size_t,SDL_wcsnlen,(const wchar_t *a, size_t b),(a,b),return)
 SDL_DYNAPI_PROC(size_t,SDL_strnlen,(const char *a, size_t b),(a,b),return)
+SDL_DYNAPI_PROC(int,SDL_AddGamepadMappingsFromFile,(const char *a),(a),return)
diff --git a/src/joystick/SDL_gamepad.c b/src/joystick/SDL_gamepad.c
index 5c6cb469f183..6e86e989e813 100644
--- a/src/joystick/SDL_gamepad.c
+++ b/src/joystick/SDL_gamepad.c
@@ -1661,7 +1661,7 @@ static GamepadMapping_t *SDL_PrivateGetGamepadMapping(SDL_JoystickID instance_id
 /*
  * Add or update an entry into the Mappings Database
  */
-int SDL_AddGamepadMappingsFromRW(SDL_RWops *rw, int freerw)
+int SDL_AddGamepadMappingsFromRW(SDL_RWops *src, int freesrc)
 {
     const char *platform = SDL_GetPlatform();
     int gamepads = 0;
@@ -1669,29 +1669,29 @@ int SDL_AddGamepadMappingsFromRW(SDL_RWops *rw, int freerw)
     Sint64 db_size;
     size_t platform_len;
 
-    if (rw == NULL) {
-        return SDL_SetError("Invalid RWops");
+    if (src == NULL) {
+        return SDL_InvalidParamError("src");
     }
-    db_size = SDL_RWsize(rw);
+    db_size = SDL_RWsize(src);
 
     buf = (char *)SDL_malloc((size_t)db_size + 1);
     if (buf == NULL) {
-        if (freerw) {
-            SDL_RWclose(rw);
+        if (freesrc) {
+            SDL_RWclose(src);
         }
         return SDL_SetError("Could not allocate space to read DB into memory");
     }
 
-    if (SDL_RWread(rw, buf, db_size) != db_size) {
-        if (freerw) {
-            SDL_RWclose(rw);
+    if (SDL_RWread(src, buf, db_size) != db_size) {
+        if (freesrc) {
+            SDL_RWclose(src);
         }
         SDL_free(buf);
         return SDL_SetError("Could not read DB");
     }
 
-    if (freerw) {
-        SDL_RWclose(rw);
+    if (freesrc) {
+        SDL_RWclose(src);
     }
 
     buf[db_size] = '\0';
@@ -1733,6 +1733,11 @@ int SDL_AddGamepadMappingsFromRW(SDL_RWops *rw, int freerw)
     return gamepads;
 }
 
+int SDL_AddGamepadMappingsFromFile(const char *file)
+{
+    return SDL_AddGamepadMappingsFromRW(SDL_RWFromFile(file, "rb"), 1);
+}
+
 /*
  * Add or update an entry into the Mappings Database with a priority
  */