From 2321726ff167bbe9d43ea74957c48b54316dbd83 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 15 Jul 2024 20:03:15 -0400 Subject: [PATCH] filesystem: SDL_GetUserFolder() now follows the SDL_GetStringRule. It also now caches at the higher level, so the platform-specific bits don't change their interface much. Reference Issue #10229. --- include/SDL3/SDL_filesystem.h | 17 +++++-------- src/core/SDL_core_unsupported.c | 3 ++- src/dynapi/SDL_dynapi_procs.h | 2 +- src/filesystem/SDL_filesystem.c | 24 +++++++++++++++++++ src/filesystem/SDL_sysfilesystem.h | 1 + src/filesystem/android/SDL_sysfilesystem.c | 2 +- src/filesystem/cocoa/SDL_sysfilesystem.m | 2 +- src/filesystem/dummy/SDL_sysfilesystem.c | 2 +- src/filesystem/emscripten/SDL_sysfilesystem.c | 2 +- src/filesystem/haiku/SDL_sysfilesystem.cc | 2 +- src/filesystem/n3ds/SDL_sysfilesystem.c | 2 +- src/filesystem/ps2/SDL_sysfilesystem.c | 2 +- src/filesystem/psp/SDL_sysfilesystem.c | 2 +- src/filesystem/riscos/SDL_sysfilesystem.c | 2 +- src/filesystem/unix/SDL_sysfilesystem.c | 2 +- src/filesystem/vita/SDL_sysfilesystem.c | 2 +- src/filesystem/windows/SDL_sysfilesystem.c | 2 +- src/filesystem/winrt/SDL_sysfilesystem.cpp | 2 +- test/testdialog.c | 6 +---- 19 files changed, 48 insertions(+), 31 deletions(-) diff --git a/include/SDL3/SDL_filesystem.h b/include/SDL3/SDL_filesystem.h index 26d6401163..dc083fc903 100644 --- a/include/SDL3/SDL_filesystem.h +++ b/include/SDL3/SDL_filesystem.h @@ -204,12 +204,13 @@ typedef enum SDL_Folder SDL_FOLDER_TEMPLATES, /** Video files that can be played using a standard video player (mp4, webm...). */ - SDL_FOLDER_VIDEOS + SDL_FOLDER_VIDEOS, + /** total number of types in this enum, not a folder type by itself. */ + SDL_FOLDER_TOTAL } SDL_Folder; /** - * Finds the most suitable user folder for the specified purpose, and returns - * its path in OS-specific notation. + * Finds the most suitable user folder for a specific purpose. * * Many OSes provide certain standard folders for certain purposes, such as * storing pictures, music or videos for a certain user. This function gives @@ -220,14 +221,10 @@ typedef enum SDL_Folder * data for the application to manage, see SDL_GetBasePath() and * SDL_GetPrefPath(). * - * Note that the function is expensive, and should be called once at the - * beginning of the execution and kept for as long as needed. - * * The returned path is guaranteed to end with a path separator ('\\' on * Windows, '/' on most other platforms). * - * The returned value is owned by the caller and should be freed with - * SDL_free(). + * The returned string follows the SDL_GetStringRule. * * If NULL is returned, the error may be obtained with SDL_GetError(). * @@ -236,10 +233,8 @@ typedef enum SDL_Folder * folder, or NULL if an error happened. * * \since This function is available since SDL 3.0.0. - * - * \sa SDL_Folder */ -extern SDL_DECLSPEC char *SDLCALL SDL_GetUserFolder(SDL_Folder folder); +extern SDL_DECLSPEC const char *SDLCALL SDL_GetUserFolder(SDL_Folder folder); /* Abstract filesystem interface */ diff --git a/src/core/SDL_core_unsupported.c b/src/core/SDL_core_unsupported.c index 32add8afb7..883c50452f 100644 --- a/src/core/SDL_core_unsupported.c +++ b/src/core/SDL_core_unsupported.c @@ -228,8 +228,9 @@ Sint32 JNI_OnLoad(void *vm, void *reserved) } #endif +// !!! FIXME: this probably belongs in src/filesystem/gdk #if defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES) -char *SDL_GetUserFolder(SDL_Folder folder) +const char *SDL_GetUserFolder(SDL_Folder folder) { (void)folder; SDL_Unsupported(); diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 135289933b..12c32e555c 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -502,7 +502,7 @@ SDL_DYNAPI_PROC(const char*,SDL_GetTouchDeviceName,(SDL_TouchID a),(a),return) SDL_DYNAPI_PROC(SDL_TouchDeviceType,SDL_GetTouchDeviceType,(SDL_TouchID a),(a),return) SDL_DYNAPI_PROC(SDL_TouchID*,SDL_GetTouchDevices,(int *a),(a),return) SDL_DYNAPI_PROC(SDL_Finger**,SDL_GetTouchFingers,(SDL_TouchID a, int *b),(a,b),return) -SDL_DYNAPI_PROC(char*,SDL_GetUserFolder,(SDL_Folder a),(a),return) +SDL_DYNAPI_PROC(const char*,SDL_GetUserFolder,(SDL_Folder a),(a),return) SDL_DYNAPI_PROC(int,SDL_GetVersion,(void),(),return) SDL_DYNAPI_PROC(const char*,SDL_GetVideoDriver,(int a),(a),return) SDL_DYNAPI_PROC(SDL_WinRT_DeviceFamily,SDL_GetWinRTDeviceFamily,(void),(),return) diff --git a/src/filesystem/SDL_filesystem.c b/src/filesystem/SDL_filesystem.c index 16c59f6e8b..c714f084ca 100644 --- a/src/filesystem/SDL_filesystem.c +++ b/src/filesystem/SDL_filesystem.c @@ -411,14 +411,38 @@ const char *SDL_GetBasePath(void) return CachedBasePath; } + +static char *CachedUserFolders[SDL_FOLDER_TOTAL]; + +const char *SDL_GetUserFolder(SDL_Folder folder) +{ + const int idx = (int) folder; + if ((idx < 0) || (idx >= SDL_arraysize(CachedUserFolders))) { + SDL_InvalidParamError("folder"); + return NULL; + } + + if (!CachedUserFolders[idx]) { + CachedUserFolders[idx] = SDL_SYS_GetUserFolder(folder); + } + return CachedUserFolders[idx]; +} + + + void SDL_InitFilesystem(void) { CachedBasePath = NULL; // just in case. + SDL_zeroa(CachedUserFolders); } void SDL_QuitFilesystem(void) { SDL_free(CachedBasePath); CachedBasePath = NULL; + for (int i = 0; i < SDL_arraysize(CachedUserFolders); i++) { + SDL_free(CachedUserFolders[i]); + CachedUserFolders[i] = NULL; + } } diff --git a/src/filesystem/SDL_sysfilesystem.h b/src/filesystem/SDL_sysfilesystem.h index b7fe7f6ffb..ca190daa2d 100644 --- a/src/filesystem/SDL_sysfilesystem.h +++ b/src/filesystem/SDL_sysfilesystem.h @@ -24,6 +24,7 @@ // return a string that we can SDL_free(). It will be cached at the higher level. extern char *SDL_SYS_GetBasePath(void); +extern char *SDL_SYS_GetUserFolder(SDL_Folder folder); int SDL_SYS_EnumerateDirectory(const char *path, const char *dirname, SDL_EnumerateDirectoryCallback cb, void *userdata); int SDL_SYS_RemovePath(const char *path); diff --git a/src/filesystem/android/SDL_sysfilesystem.c b/src/filesystem/android/SDL_sysfilesystem.c index 0170264134..95c58efc9a 100644 --- a/src/filesystem/android/SDL_sysfilesystem.c +++ b/src/filesystem/android/SDL_sysfilesystem.c @@ -49,7 +49,7 @@ char *SDL_GetPrefPath(const char *org, const char *app) return NULL; } -char *SDL_GetUserFolder(SDL_Folder folder) +char *SDL_SYS_GetUserFolder(SDL_Folder folder) { /* TODO: see https://developer.android.com/reference/android/os/Environment#lfields and https://stackoverflow.com/questions/39332085/get-path-to-pictures-directory */ diff --git a/src/filesystem/cocoa/SDL_sysfilesystem.m b/src/filesystem/cocoa/SDL_sysfilesystem.m index 308d675615..500482c43f 100644 --- a/src/filesystem/cocoa/SDL_sysfilesystem.m +++ b/src/filesystem/cocoa/SDL_sysfilesystem.m @@ -126,7 +126,7 @@ char *SDL_GetPrefPath(const char *org, const char *app) } } -char *SDL_GetUserFolder(SDL_Folder folder) +char *SDL_SYS_GetUserFolder(SDL_Folder folder) { @autoreleasepool { #ifdef SDL_PLATFORM_TVOS diff --git a/src/filesystem/dummy/SDL_sysfilesystem.c b/src/filesystem/dummy/SDL_sysfilesystem.c index cf9ca53d98..067bf15749 100644 --- a/src/filesystem/dummy/SDL_sysfilesystem.c +++ b/src/filesystem/dummy/SDL_sysfilesystem.c @@ -37,7 +37,7 @@ char *SDL_GetPrefPath(const char *org, const char *app) return NULL; } -char *SDL_GetUserFolder(SDL_Folder folder) +char *SDL_SYS_GetUserFolder(SDL_Folder folder) { SDL_Unsupported(); return NULL; diff --git a/src/filesystem/emscripten/SDL_sysfilesystem.c b/src/filesystem/emscripten/SDL_sysfilesystem.c index ea415547f5..c00107f808 100644 --- a/src/filesystem/emscripten/SDL_sysfilesystem.c +++ b/src/filesystem/emscripten/SDL_sysfilesystem.c @@ -81,7 +81,7 @@ char *SDL_GetPrefPath(const char *org, const char *app) return retval; } -char *SDL_GetUserFolder(SDL_Folder folder) +char *SDL_SYS_GetUserFolder(SDL_Folder folder) { const char *home = NULL; diff --git a/src/filesystem/haiku/SDL_sysfilesystem.cc b/src/filesystem/haiku/SDL_sysfilesystem.cc index 82fc4ea12f..af5de0c41c 100644 --- a/src/filesystem/haiku/SDL_sysfilesystem.cc +++ b/src/filesystem/haiku/SDL_sysfilesystem.cc @@ -97,7 +97,7 @@ char *SDL_GetPrefPath(const char *org, const char *app) return retval; } -char *SDL_GetUserFolder(SDL_Folder folder) +char *SDL_SYS_GetUserFolder(SDL_Folder folder) { const char *home = NULL; char *retval; diff --git a/src/filesystem/n3ds/SDL_sysfilesystem.c b/src/filesystem/n3ds/SDL_sysfilesystem.c index 897d11a508..de9040fa05 100644 --- a/src/filesystem/n3ds/SDL_sysfilesystem.c +++ b/src/filesystem/n3ds/SDL_sysfilesystem.c @@ -60,7 +60,7 @@ char *SDL_GetPrefPath(const char *org, const char *app) } /* TODO */ -char *SDL_GetUserFolder(SDL_Folder folder) +char *SDL_SYS_GetUserFolder(SDL_Folder folder) { SDL_Unsupported(); return NULL; diff --git a/src/filesystem/ps2/SDL_sysfilesystem.c b/src/filesystem/ps2/SDL_sysfilesystem.c index 86d908af73..f50056e309 100644 --- a/src/filesystem/ps2/SDL_sysfilesystem.c +++ b/src/filesystem/ps2/SDL_sysfilesystem.c @@ -108,7 +108,7 @@ char *SDL_GetPrefPath(const char *org, const char *app) } /* TODO */ -char *SDL_GetUserFolder(SDL_Folder folder) +char *SDL_SYS_GetUserFolder(SDL_Folder folder) { SDL_Unsupported(); return NULL; diff --git a/src/filesystem/psp/SDL_sysfilesystem.c b/src/filesystem/psp/SDL_sysfilesystem.c index b29b1b210a..f903abd7f1 100644 --- a/src/filesystem/psp/SDL_sysfilesystem.c +++ b/src/filesystem/psp/SDL_sysfilesystem.c @@ -78,7 +78,7 @@ char *SDL_GetPrefPath(const char *org, const char *app) } /* TODO */ -char *SDL_GetUserFolder(SDL_Folder folder) +char *SDL_SYS_GetUserFolder(SDL_Folder folder) { SDL_Unsupported(); return NULL; diff --git a/src/filesystem/riscos/SDL_sysfilesystem.c b/src/filesystem/riscos/SDL_sysfilesystem.c index 55f69f3b8f..ebb603272b 100644 --- a/src/filesystem/riscos/SDL_sysfilesystem.c +++ b/src/filesystem/riscos/SDL_sysfilesystem.c @@ -197,7 +197,7 @@ char *SDL_GetPrefPath(const char *org, const char *app) } /* TODO */ -char *SDL_GetUserFolder(SDL_Folder folder) +char *SDL_SYS_GetUserFolder(SDL_Folder folder) { SDL_Unsupported(); return NULL; diff --git a/src/filesystem/unix/SDL_sysfilesystem.c b/src/filesystem/unix/SDL_sysfilesystem.c index 8c62d603fa..12b40641cb 100644 --- a/src/filesystem/unix/SDL_sysfilesystem.c +++ b/src/filesystem/unix/SDL_sysfilesystem.c @@ -510,7 +510,7 @@ static char *xdg_user_dir_lookup (const char *type) return NULL; } -char *SDL_GetUserFolder(SDL_Folder folder) +char *SDL_SYS_GetUserFolder(SDL_Folder folder) { const char *param = NULL; char *retval; diff --git a/src/filesystem/vita/SDL_sysfilesystem.c b/src/filesystem/vita/SDL_sysfilesystem.c index d030da2fdd..4b56955d92 100644 --- a/src/filesystem/vita/SDL_sysfilesystem.c +++ b/src/filesystem/vita/SDL_sysfilesystem.c @@ -81,7 +81,7 @@ char *SDL_GetPrefPath(const char *org, const char *app) } /* TODO */ -char *SDL_GetUserFolder(SDL_Folder folder) +char *SDL_SYS_GetUserFolder(SDL_Folder folder) { SDL_Unsupported(); return NULL; diff --git a/src/filesystem/windows/SDL_sysfilesystem.c b/src/filesystem/windows/SDL_sysfilesystem.c index ff30453e02..5608f0ca6e 100644 --- a/src/filesystem/windows/SDL_sysfilesystem.c +++ b/src/filesystem/windows/SDL_sysfilesystem.c @@ -174,7 +174,7 @@ char *SDL_GetPrefPath(const char *org, const char *app) return retval; } -char *SDL_GetUserFolder(SDL_Folder folder) +char *SDL_SYS_GetUserFolder(SDL_Folder folder) { typedef HRESULT (WINAPI *pfnSHGetKnownFolderPath)(REFGUID /* REFKNOWNFOLDERID */, DWORD, HANDLE, PWSTR*); HMODULE lib = LoadLibrary(L"Shell32.dll"); diff --git a/src/filesystem/winrt/SDL_sysfilesystem.cpp b/src/filesystem/winrt/SDL_sysfilesystem.cpp index 9f710e71c2..0046899b5c 100644 --- a/src/filesystem/winrt/SDL_sysfilesystem.cpp +++ b/src/filesystem/winrt/SDL_sysfilesystem.cpp @@ -227,7 +227,7 @@ extern "C" char *SDL_GetPrefPath(const char *org, const char *app) return retval; } -char *SDL_GetUserFolder(SDL_Folder folder) +char *SDL_SYS_GetUserFolder(SDL_Folder folder) { wstring wpath; diff --git a/test/testdialog.c b/test/testdialog.c index eff2525524..29b3472dd9 100644 --- a/test/testdialog.c +++ b/test/testdialog.c @@ -52,7 +52,7 @@ int main(int argc, char *argv[]) { const SDL_FRect save_file_rect = { 50, 290, 220, 140 }; const SDL_FRect open_folder_rect = { 370, 50, 220, 140 }; int i; - char *initial_path = NULL; + const char *initial_path = NULL; const int nfilters = sizeof(filters) / sizeof(*filters); /* Initialize test framework */ @@ -147,10 +147,6 @@ int main(int argc, char *argv[]) { SDL_RenderPresent(r); } - if (initial_path) { - SDL_free(initial_path); - } - SDLTest_CleanupTextDrawing(); SDL_DestroyRenderer(r); SDL_DestroyWindow(w);