SDL: rwops: Add properties for some of the internal implementation details.

From e35c304022c43dc3099f4e3b04e1385984f52d9c Mon Sep 17 00:00:00 2001
From: "Ryan C. Gordon" <[EMAIL REDACTED]>
Date: Wed, 13 Mar 2024 10:12:14 -0400
Subject: [PATCH] rwops: Add properties for some of the internal implementation
 details.

---
 include/SDL3/SDL_rwops.h | 22 ++++++++++++++++++++++
 src/file/SDL_rwops.c     | 18 ++++++++++++++++++
 2 files changed, 40 insertions(+)

diff --git a/include/SDL3/SDL_rwops.h b/include/SDL3/SDL_rwops.h
index 2ac1e34d81616..a99bddeb837e5 100644
--- a/include/SDL3/SDL_rwops.h
+++ b/include/SDL3/SDL_rwops.h
@@ -150,6 +150,24 @@ typedef struct SDL_RWops SDL_RWops;
  *
  * Destroying the SDL_RWops will close the file handle SDL is holding internally.
  *
+ * The following properties may be set at creation time by SDL:
+ *
+ * - `SDL_PROP_RWOPS_WINDOWS_HANDLE_POINTER`: a pointer, that can be cast
+ *   to a win32 `HANDLE`, that this RWops is using to access the filesystem.
+ *   If the program isn't running on Windows, or SDL used some other method
+ *   to access the filesystem, this property will not be set.
+ * - `SDL_PROP_RWOPS_STDIO_HANDLE_POINTER`: a pointer, that can be cast
+ *   to a stdio `FILE *`, that this RWops is using to access the filesystem.
+ *   If SDL used some other method to access the filesystem, this property
+ *   will not be set. PLEASE NOTE that if SDL is using a different C runtime
+ *   than your app, trying to use this pointer will almost certainly result
+ *   in a crash! This is mostly a problem on Windows; make sure you build SDL
+ *   and your app with the same compiler and settings to avoid it.
+ * - `SDL_PROP_RWOPS_ANDROID_AASSET_POINTER`: a pointer, that can be cast
+ *   to an Android NDK `AAsset *`, that this RWops is using to access the
+ *   filesystem. If SDL used some other method to access the filesystem, this
+ *   property will not be set.
+ *
  * \param file a UTF-8 string representing the filename to open
  * \param mode an ASCII string representing the mode to be used for opening
  *             the file.
@@ -167,6 +185,10 @@ typedef struct SDL_RWops SDL_RWops;
  */
 extern DECLSPEC SDL_RWops *SDLCALL SDL_RWFromFile(const char *file, const char *mode);
 
+#define SDL_PROP_RWOPS_WINDOWS_HANDLE_POINTER "SDL.rwops.windows.handle"
+#define SDL_PROP_RWOPS_STDIO_HANDLE_POINTER "SDL.rwops.stdio.handle"
+#define SDL_PROP_RWOPS_ANDROID_AASSET_POINTER "SDL.rwops.android.aasset"
+
 /**
  * Use this function to prepare a read-write memory buffer for use with
  * SDL_RWops.
diff --git a/src/file/SDL_rwops.c b/src/file/SDL_rwops.c
index 5f0fc409cea24..97182e1abcb6c 100644
--- a/src/file/SDL_rwops.c
+++ b/src/file/SDL_rwops.c
@@ -427,7 +427,13 @@ static SDL_RWops *SDL_RWFromFP(FILE *fp, SDL_bool autoclose)
     SDL_RWops *rwops = SDL_OpenRW(&iface, rwopsdata);
     if (!rwops) {
         iface.close(rwopsdata);
+    } else {
+        const SDL_PropertiesID props = SDL_GetRWProperties(rwops);
+        if (props) {
+            SDL_SetProperty(props, SDL_PROP_RWOPS_STDIO_HANDLE_POINTER, fp);
+        }
     }
+
     return rwops;
 }
 #endif /* !HAVE_STDIO_H && !(SDL_PLATFORM_WIN32 || SDL_PLATFORM_GDK) */
@@ -580,7 +586,13 @@ SDL_RWops *SDL_RWFromFile(const char *file, const char *mode)
     rwops = SDL_OpenRW(&iface, rwopsdata);
     if (!rwops) {
         iface.close(rwopsdata);
+    } else {
+        const SDL_PropertiesID props = SDL_GetRWProperties(rwops);
+        if (props) {
+            SDL_SetProperty(props, SDL_PROP_RWOPS_ANDROID_AASSET_POINTER, rwopsdata);
+        }
     }
+
     return rwops;
 
 
@@ -606,7 +618,13 @@ SDL_RWops *SDL_RWFromFile(const char *file, const char *mode)
     rwops = SDL_OpenRW(&iface, rwopsdata);
     if (!rwops) {
         windows_file_close(rwopsdata);
+    } else {
+        const SDL_PropertiesID props = SDL_GetRWProperties(rwops);
+        if (props) {
+            SDL_SetProperty(props, SDL_PROP_RWOPS_WINDOWS_HANDLE_POINTER, rwopsdata->h);
+        }
     }
+
     return rwops;
 
 #elif defined(HAVE_STDIO_H)