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.
This commit is contained in:
Ryan C. Gordon 2024-07-13 13:34:46 -04:00
parent d65a8146b9
commit 3bc81a81f5
24 changed files with 137 additions and 69 deletions

View File

@ -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);
}
}
```

View File

@ -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.

View File

@ -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();

View File

@ -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)

View File

@ -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;
}

View File

@ -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

View File

@ -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);

View File

@ -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();

View File

@ -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];

View File

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

View File

@ -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)

View File

@ -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

View File

@ -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;
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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)

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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) {