Explorar el Código

filesystem: SDL_GetBasePath() now follows the SDL_GetStringRule.

It also now caches at the higher level, so the platform-specific bits don't
change their interface much.

A little code hygiene work was applied to some of the platform bits on top of
this.

Reference Issue #10229.
Ryan C. Gordon hace 9 meses
padre
commit
3bc81a81f5

+ 1 - 2
docs/README-migration.md

@@ -802,10 +802,9 @@ On Haiku OS, SDL no longer sets the current working directory to the executable'
 
 ```c
 {
-    char *path = SDL_GetBasePath();
+    const char *path = SDL_GetBasePath();
     if (path) {
         chdir(path);
-        SDL_free(path);
     }
 }
 ```

+ 4 - 5
include/SDL3/SDL_filesystem.h

@@ -41,8 +41,8 @@ extern "C" {
 /**
  * Get the directory where the application was run from.
  *
- * This is not necessarily a fast call, so you should call this once near
- * startup and save the string if you need it.
+ * SDL caches the result of this call internally, but the first call to this
+ * function is not necessarily fast, so plan accordingly.
  *
  * **macOS and iOS Specific Functionality**: If the application is in a ".app"
  * bundle, this function returns the Resource directory (e.g.
@@ -68,8 +68,7 @@ extern "C" {
  * The returned path is guaranteed to end with a path separator ('\\' on
  * Windows, '/' on most other platforms).
  *
- * The pointer returned is owned by the caller. Please call SDL_free() on the
- * pointer when done with it.
+ * The returned string follows the SDL_GetStringRule.
  *
  * \returns an absolute path in UTF-8 encoding to the application data
  *          directory. NULL will be returned on error or when the platform
@@ -80,7 +79,7 @@ extern "C" {
  *
  * \sa SDL_GetPrefPath
  */
-extern SDL_DECLSPEC char *SDLCALL SDL_GetBasePath(void);
+extern SDL_DECLSPEC const char *SDLCALL SDL_GetBasePath(void);
 
 /**
  * Get the user-and-app-specific path where files can be written.

+ 3 - 0
src/SDL.c

@@ -53,6 +53,7 @@
 #include "thread/SDL_thread_c.h"
 #include "video/SDL_pixels_c.h"
 #include "video/SDL_video_c.h"
+#include "filesystem/SDL_filesystem_c.h"
 
 #define SDL_INIT_EVERYTHING ~0U
 
@@ -192,6 +193,7 @@ void SDL_InitMainThread(void)
 
     SDL_InitTLSData();
     SDL_InitTicks();
+    SDL_InitFilesystem();
     SDL_InitLog();
     SDL_InitProperties();
     SDL_GetGlobalProperties();
@@ -207,6 +209,7 @@ static void SDL_QuitMainThread(void)
 
     SDL_QuitProperties();
     SDL_QuitLog();
+    SDL_QuitFilesystem();
     SDL_QuitTicks();
     SDL_QuitTLSData();
 

+ 1 - 1
src/dynapi/SDL_dynapi_procs.h

@@ -219,7 +219,7 @@ SDL_DYNAPI_PROC(const int*,SDL_GetAudioStreamInputChannelMap,(SDL_AudioStream *a
 SDL_DYNAPI_PROC(const int*,SDL_GetAudioStreamOutputChannelMap,(SDL_AudioStream *a, int *b),(a,b),return)
 SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetAudioStreamProperties,(SDL_AudioStream *a),(a),return)
 SDL_DYNAPI_PROC(int,SDL_GetAudioStreamQueued,(SDL_AudioStream *a),(a),return)
-SDL_DYNAPI_PROC(char*,SDL_GetBasePath,(void),(),return)
+SDL_DYNAPI_PROC(const char*,SDL_GetBasePath,(void),(),return)
 SDL_DYNAPI_PROC(SDL_bool,SDL_GetBooleanProperty,(SDL_PropertiesID a, const char *b, SDL_bool c),(a,b,c),return)
 SDL_DYNAPI_PROC(int,SDL_GetCPUCacheLineSize,(void),(),return)
 SDL_DYNAPI_PROC(int,SDL_GetCPUCount,(void),(),return)

+ 22 - 0
src/filesystem/SDL_filesystem.c

@@ -400,3 +400,25 @@ char **SDL_GlobDirectory(const char *path, const char *pattern, SDL_GlobFlags fl
     return SDL_InternalGlobDirectory(path, pattern, flags, count, GlobDirectoryEnumerator, GlobDirectoryGetPathInfo, NULL);
 }
 
+
+static char *CachedBasePath = NULL;
+
+const char *SDL_GetBasePath(void)
+{
+    if (!CachedBasePath) {
+        CachedBasePath = SDL_SYS_GetBasePath();
+    }
+    return CachedBasePath;
+}
+
+void SDL_InitFilesystem(void)
+{
+    CachedBasePath = NULL;  // just in case.
+}
+
+void SDL_QuitFilesystem(void)
+{
+    SDL_free(CachedBasePath);
+    CachedBasePath = NULL;
+}
+

+ 29 - 0
src/filesystem/SDL_filesystem_c.h

@@ -0,0 +1,29 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_filesystem_c_h_
+#define SDL_filesystem_c_h_
+
+extern void SDL_InitFilesystem(void);
+extern void SDL_QuitFilesystem(void);
+
+#endif
+

+ 3 - 0
src/filesystem/SDL_sysfilesystem.h

@@ -22,6 +22,9 @@
 #ifndef SDL_sysfilesystem_h_
 #define SDL_sysfilesystem_h_
 
+// return a string that we can SDL_free(). It will be cached at the higher level.
+extern char *SDL_SYS_GetBasePath(void);
+
 int SDL_SYS_EnumerateDirectory(const char *path, const char *dirname, SDL_EnumerateDirectoryCallback cb, void *userdata);
 int SDL_SYS_RemovePath(const char *path);
 int SDL_SYS_RenamePath(const char *oldpath, const char *newpath);

+ 1 - 1
src/filesystem/android/SDL_sysfilesystem.c

@@ -27,7 +27,7 @@
 
 #include <unistd.h>
 
-char *SDL_GetBasePath(void)
+char *SDL_SYS_GetBasePath(void)
 {
     /* The current working directory is / on Android */
     SDL_Unsupported();

+ 1 - 1
src/filesystem/cocoa/SDL_sysfilesystem.m

@@ -29,7 +29,7 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 
-char *SDL_GetBasePath(void)
+char *SDL_SYS_GetBasePath(void)
 {
     @autoreleasepool {
         NSBundle *bundle = [NSBundle mainBundle];

+ 1 - 1
src/filesystem/dummy/SDL_sysfilesystem.c

@@ -25,7 +25,7 @@
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 /* System dependent filesystem routines                                */
 
-char *SDL_GetBasePath(void)
+char *SDL_SYS_GetBasePath(void)
 {
     SDL_Unsupported();
     return NULL;

+ 2 - 3
src/filesystem/emscripten/SDL_sysfilesystem.c

@@ -29,10 +29,9 @@
 
 #include <emscripten/emscripten.h>
 
-char *SDL_GetBasePath(void)
+char *SDL_SYS_GetBasePath(void)
 {
-    char *retval = "/";
-    return SDL_strdup(retval);
+    return SDL_strdup("/");
 }
 
 char *SDL_GetPrefPath(const char *org, const char *app)

+ 1 - 1
src/filesystem/gdk/SDL_sysfilesystem.cpp

@@ -31,7 +31,7 @@
 #include <XGameSaveFiles.h>
 
 char *
-SDL_GetBasePath(void)
+SDL_SYS_GetBasePath(void)
 {
     /* NOTE: This function is a UTF8 version of the Win32 SDL_GetBasePath()!
      * The GDK actually _recommends_ the 'A' functions over the 'W' functions :o

+ 9 - 6
src/filesystem/haiku/SDL_sysfilesystem.cc

@@ -25,6 +25,10 @@
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 /* System dependent filesystem routines                                */
 
+extern "C" {
+#include "../SDL_sysfilesystem.h"
+}
+
 #include <kernel/image.h>
 #include <storage/Directory.h>
 #include <storage/Entry.h>
@@ -32,7 +36,7 @@
 #include <storage/Path.h>
 
 
-char *SDL_GetBasePath(void)
+char *SDL_SYS_GetBasePath(void)
 {
     char name[MAXPATHLEN];
 
@@ -51,13 +55,12 @@ char *SDL_GetBasePath(void)
 
     const size_t len = SDL_strlen(str);
     char *retval = (char *) SDL_malloc(len + 2);
-    if (!retval) {
-        return NULL;
+    if (retval) {
+        SDL_memcpy(retval, str, len);
+        retval[len] = '/';
+        retval[len+1] = '\0';
     }
 
-    SDL_memcpy(retval, str, len);
-    retval[len] = '/';
-    retval[len+1] = '\0';
     return retval;
 }
 

+ 1 - 1
src/filesystem/n3ds/SDL_sysfilesystem.c

@@ -32,7 +32,7 @@
 static char *MakePrefPath(const char *app);
 static int CreatePrefPathDir(const char *pref);
 
-char *SDL_GetBasePath(void)
+char *SDL_SYS_GetBasePath(void)
 {
     char *base_path = SDL_strdup("romfs:/");
     return base_path;

+ 20 - 13
src/filesystem/ps2/SDL_sysfilesystem.c

@@ -28,7 +28,7 @@
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 /* System dependent filesystem routines                                */
 
-char *SDL_GetBasePath(void)
+char *SDL_SYS_GetBasePath(void)
 {
     char *retval = NULL;
     size_t len;
@@ -37,7 +37,9 @@ char *SDL_GetBasePath(void)
     getcwd(cwd, sizeof(cwd));
     len = SDL_strlen(cwd) + 2;
     retval = (char *)SDL_malloc(len);
-    SDL_snprintf(retval, len, "%s/", cwd);
+    if (retval) {
+        SDL_snprintf(retval, len, "%s/", cwd);
+    }
 
     return retval;
 }
@@ -46,7 +48,7 @@ char *SDL_GetBasePath(void)
 static void recursive_mkdir(const char *dir)
 {
     char tmp[FILENAME_MAX];
-    char *base = SDL_GetBasePath();
+    const char *base = SDL_GetBasePath();
     char *p = NULL;
     size_t len;
 
@@ -60,7 +62,7 @@ static void recursive_mkdir(const char *dir)
         if (*p == '/') {
             *p = 0;
             // Just creating subfolders from current path
-            if (SDL_strstr(tmp, base) != NULL) {
+            if (base && SDL_strstr(tmp, base) != NULL) {
                 mkdir(tmp, S_IRWXU);
             }
 
@@ -68,7 +70,6 @@ static void recursive_mkdir(const char *dir)
         }
     }
 
-    SDL_free(base);
     mkdir(tmp, S_IRWXU);
 }
 
@@ -76,26 +77,32 @@ char *SDL_GetPrefPath(const char *org, const char *app)
 {
     char *retval = NULL;
     size_t len;
-    char *base = SDL_GetBasePath();
+
     if (!app) {
         SDL_InvalidParamError("app");
         return NULL;
     }
+
     if (!org) {
         org = "";
     }
 
+    const char *base = SDL_GetBasePath();
+    if (!base) {
+        return NULL;
+    }
+
     len = SDL_strlen(base) + SDL_strlen(org) + SDL_strlen(app) + 4;
     retval = (char *)SDL_malloc(len);
+    if (retval) {
+        if (*org) {
+            SDL_snprintf(retval, len, "%s%s/%s/", base, org, app);
+        } else {
+            SDL_snprintf(retval, len, "%s%s/", base, app);
+        }
 
-    if (*org) {
-        SDL_snprintf(retval, len, "%s%s/%s/", base, org, app);
-    } else {
-        SDL_snprintf(retval, len, "%s%s/", base, app);
+        recursive_mkdir(retval);
     }
-    SDL_free(base);
-
-    recursive_mkdir(retval);
 
     return retval;
 }

+ 17 - 9
src/filesystem/psp/SDL_sysfilesystem.c

@@ -28,7 +28,7 @@
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 /* System dependent filesystem routines                                */
 
-char *SDL_GetBasePath(void)
+char *SDL_SYS_GetBasePath(void)
 {
     char *retval = NULL;
     size_t len;
@@ -37,7 +37,9 @@ char *SDL_GetBasePath(void)
     getcwd(cwd, sizeof(cwd));
     len = SDL_strlen(cwd) + 2;
     retval = (char *)SDL_malloc(len);
-    SDL_snprintf(retval, len, "%s/", cwd);
+    if (retval) {
+        SDL_snprintf(retval, len, "%s/", cwd);
+    }
 
     return retval;
 }
@@ -46,26 +48,32 @@ char *SDL_GetPrefPath(const char *org, const char *app)
 {
     char *retval = NULL;
     size_t len;
-    char *base = SDL_GetBasePath();
     if (!app) {
         SDL_InvalidParamError("app");
         return NULL;
     }
+
+    const char *base = SDL_GetBasePath();
+    if (!base) {
+        return NULL;
+    }
+
     if (!org) {
         org = "";
     }
 
     len = SDL_strlen(base) + SDL_strlen(org) + SDL_strlen(app) + 4;
     retval = (char *)SDL_malloc(len);
+    if (retval) {
+        if (*org) {
+            SDL_snprintf(retval, len, "%s%s/%s/", base, org, app);
+        } else {
+            SDL_snprintf(retval, len, "%s%s/", base, app);
+        }
 
-    if (*org) {
-        SDL_snprintf(retval, len, "%s%s/%s/", base, org, app);
-    } else {
-        SDL_snprintf(retval, len, "%s%s/", base, app);
+        mkdir(retval, 0755);
     }
-    SDL_free(base);
 
-    mkdir(retval, 0755);
     return retval;
 }
 

+ 1 - 1
src/filesystem/riscos/SDL_sysfilesystem.c

@@ -123,7 +123,7 @@ static _kernel_oserror *createDirectoryRecursive(char *path)
     return _kernel_swi(OS_File, &regs, &regs);
 }
 
-char *SDL_GetBasePath(void)
+char *SDL_SYS_GetBasePath(void)
 {
     _kernel_swi_regs regs;
     _kernel_oserror *error;

+ 1 - 1
src/filesystem/unix/SDL_sysfilesystem.c

@@ -119,7 +119,7 @@ static char *search_path_for_binary(const char *bin)
 }
 #endif
 
-char *SDL_GetBasePath(void)
+char *SDL_SYS_GetBasePath(void)
 {
     char *retval = NULL;
 

+ 2 - 4
src/filesystem/vita/SDL_sysfilesystem.c

@@ -34,11 +34,9 @@
 #include <limits.h>
 #include <fcntl.h>
 
-char *SDL_GetBasePath(void)
+char *SDL_SYS_GetBasePath(void)
 {
-    const char *basepath = "app0:/";
-    char *retval = SDL_strdup(basepath);
-    return retval;
+    return SDL_strdup("app0:/");
 }
 
 char *SDL_GetPrefPath(const char *org, const char *app)

+ 1 - 1
src/filesystem/windows/SDL_sysfilesystem.c

@@ -41,7 +41,7 @@ DEFINE_GUID(SDL_FOLDERID_Screenshots, 0xb7bede81, 0xdf94, 0x4682, 0xa7, 0xd8, 0x
 DEFINE_GUID(SDL_FOLDERID_Templates, 0xA63293E8, 0x664E, 0x48DB, 0xA0, 0x79, 0xDF, 0x75, 0x9E, 0x05, 0x09, 0xF7);
 DEFINE_GUID(SDL_FOLDERID_Videos, 0x18989B1D, 0x99B5, 0x455B, 0x84, 0x1C, 0xAB, 0x7C, 0x74, 0xE4, 0xDD, 0xFC);
 
-char *SDL_GetBasePath(void)
+char *SDL_SYS_GetBasePath(void)
 {
     DWORD buflen = 128;
     WCHAR *path = NULL;

+ 2 - 1
src/filesystem/winrt/SDL_sysfilesystem.cpp

@@ -27,6 +27,7 @@
 
 extern "C" {
 #include "../../core/windows/SDL_windows.h"
+#include "../SDL_sysfilesystem.h"
 }
 
 #include <string>
@@ -115,7 +116,7 @@ extern "C" const char *SDL_GetWinRTFSPath(SDL_WinRT_Path pathType)
     return utf8Paths[pathType].c_str();
 }
 
-extern "C" char *SDL_GetBasePath(void)
+extern "C" char *SDL_SYS_GetBasePath(void)
 {
     const char *srcPath = SDL_GetWinRTFSPath(SDL_WINRT_PATH_INSTALLED_LOCATION);
     size_t destPathLen;

+ 12 - 9
src/storage/generic/SDL_genericstorage.c

@@ -181,22 +181,25 @@ static const SDL_StorageInterface GENERIC_title_iface = {
 
 static SDL_Storage *GENERIC_Title_Create(const char *override, SDL_PropertiesID props)
 {
-    SDL_Storage *result;
+    SDL_Storage *result = NULL;
 
-    char *basepath;
+    char *basepath = NULL;
     if (override != NULL) {
         basepath = SDL_strdup(override);
     } else {
-        basepath = SDL_GetBasePath();
-    }
-    if (basepath == NULL) {
-        return NULL;
+        const char *sdlbasepath = SDL_GetBasePath();
+        if (sdlbasepath) {
+            basepath = SDL_strdup(sdlbasepath);
+        }
     }
 
-    result = SDL_OpenStorage(&GENERIC_title_iface, basepath);
-    if (result == NULL) {
-        SDL_free(basepath);
+    if (basepath != NULL) {
+        result = SDL_OpenStorage(&GENERIC_title_iface, basepath);
+        if (result == NULL) {
+            SDL_free(basepath);  // otherwise CloseStorage will free it.
+        }
     }
+
     return result;
 }
 

+ 1 - 3
test/testfilesystem.c

@@ -62,7 +62,7 @@ int main(int argc, char *argv[])
 {
     SDLTest_CommonState *state;
     char *pref_path;
-    char *base_path;
+    const char *base_path;
 
     /* Initialize test framework */
     state = SDLTest_CommonCreateState(argv, 0);
@@ -145,8 +145,6 @@ int main(int argc, char *argv[])
         }
     }
 
-    SDL_free(base_path);
-
     SDL_Quit();
     SDLTest_CommonDestroyState(state);
     return 0;

+ 1 - 5
test/testutils.c

@@ -23,11 +23,9 @@
 char *
 GetNearbyFilename(const char *file)
 {
-    char *base;
+    const char *base = SDL_GetBasePath();
     char *path;
 
-    base = SDL_GetBasePath();
-
     if (base) {
         SDL_IOStream *rw;
         size_t len = SDL_strlen(base) + SDL_strlen(file) + 1;
@@ -35,12 +33,10 @@ GetNearbyFilename(const char *file)
         path = SDL_malloc(len);
 
         if (!path) {
-            SDL_free(base);
             return NULL;
         }
 
         (void)SDL_snprintf(path, len, "%s%s", base, file);
-        SDL_free(base);
 
         rw = SDL_IOFromFile(path, "rb");
         if (rw) {