Browse Source

Added SDL_OpenFileStorage() for local file storage

Sam Lantinga 1 year ago
parent
commit
ec3ba387d1

+ 22 - 2
include/SDL3/SDL_storage.h

@@ -85,8 +85,8 @@ extern DECLSPEC SDL_Storage *SDLCALL SDL_OpenTitleStorage(const char *override,
  *
  * While title storage can generally be kept open throughout runtime, user
  * storage should only be opened when the client is ready to read/write files.
- * This allows the backend to properly batch R/W operations and flush them
- * when the container has been closed; ensuring safe and optimal save I/O.
+ * This allows the backend to properly batch file operations and flush them when
+ * the container has been closed; ensuring safe and optimal save I/O.
  *
  * \param org the name of your organization
  * \param app the name of your application
@@ -107,6 +107,26 @@ extern DECLSPEC SDL_Storage *SDLCALL SDL_OpenTitleStorage(const char *override,
  */
 extern DECLSPEC SDL_Storage *SDLCALL SDL_OpenUserStorage(const char *org, const char *app, SDL_PropertiesID props);
 
+/**
+ * Opens up a container for local filesystem storage.
+ *
+ * This is provided for development and tools. Portable applications should use SDL_OpenTitleStorage() for access to game data and SDL_OpenUserStorage() for access to user data.
+ *
+ * \param path the base path prepended to all storage paths, or NULL for no base path
+ * \returns a filesystem storage container on success or NULL on failure; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 3.0.0.
+ *
+ * \sa SDL_OpenStorage
+ * \sa SDL_CloseStorage
+ * \sa SDL_StorageReady
+ * \sa SDL_GetStorageFileSize
+ * \sa SDL_ReadStorageFile
+ * \sa SDL_WriteStorageFile
+ * \sa SDL_GetStorageSpaceRemaining
+ */
+extern DECLSPEC SDL_Storage *SDLCALL SDL_OpenFileStorage(const char *path);
+
 /**
  * Opens up a container using a client-provided storage interface.
  *

+ 1 - 0
src/dynapi/SDL_dynapi.sym

@@ -993,6 +993,7 @@ SDL3_0.0.0 {
     SDL_RenamePath;
     SDL_GetPathInfo;
     SDL_FileTimeToWindows;
+    SDL_OpenFileStorage;
     # extra symbols go here (don't modify this line)
   local: *;
 };

+ 1 - 0
src/dynapi/SDL_dynapi_overrides.h

@@ -1018,3 +1018,4 @@
 #define SDL_RenamePath SDL_RenamePath_REAL
 #define SDL_GetPathInfo SDL_GetPathInfo_REAL
 #define SDL_FileTimeToWindows SDL_FileTimeToWindows_REAL
+#define SDL_OpenFileStorage SDL_OpenFileStorage_REAL

+ 1 - 0
src/dynapi/SDL_dynapi_procs.h

@@ -1043,3 +1043,4 @@ SDL_DYNAPI_PROC(int,SDL_RemovePath,(const char *a),(a),return)
 SDL_DYNAPI_PROC(int,SDL_RenamePath,(const char *a, const char *b),(a,b),return)
 SDL_DYNAPI_PROC(int,SDL_GetPathInfo,(const char *a, SDL_PathInfo *b),(a,b),return)
 SDL_DYNAPI_PROC(void,SDL_FileTimeToWindows,(Sint64 a, Uint32 *b, Uint32 *c),(a,b,c),)
+SDL_DYNAPI_PROC(SDL_Storage*,SDL_OpenFileStorage,(const char *a),(a),return)

+ 5 - 0
src/storage/SDL_storage.c

@@ -137,6 +137,11 @@ SDL_Storage *SDL_OpenUserStorage(const char *org, const char *app, SDL_Propertie
     return storage;
 }
 
+SDL_Storage *SDL_OpenFileStorage(const char *path)
+{
+    return GENERIC_OpenFileStorage(path);
+}
+
 SDL_Storage *SDL_OpenStorage(const SDL_StorageInterface *iface, void *userdata)
 {
     SDL_Storage *storage;

+ 2 - 0
src/storage/SDL_sysstorage.h

@@ -46,4 +46,6 @@ extern TitleStorageBootStrap GENERIC_titlebootstrap;
 extern UserStorageBootStrap GENERIC_userbootstrap;
 extern UserStorageBootStrap STEAM_userbootstrap;
 
+extern SDL_Storage *GENERIC_OpenFileStorage(const char *path);
+
 #endif /* SDL_sysstorage_h_ */

+ 46 - 3
src/storage/generic/SDL_genericstorage.c

@@ -25,10 +25,16 @@
 
 static char *GENERIC_INTERNAL_CreateFullPath(const char *base, const char *relative)
 {
-    size_t fulllen = SDL_strlen(base) + SDL_strlen(relative) + 1;
-    char *result = (char*) SDL_malloc(fulllen);
+    size_t len = 0;
+
+    if (base) {
+        len += SDL_strlen(base);
+    }
+    len += SDL_strlen(relative) + 1;
+
+    char *result = (char*) SDL_malloc(len);
     if (result != NULL) {
-        SDL_snprintf(result, fulllen, "%s%s", base, relative);
+        SDL_snprintf(result, len, "%s%s", base, relative);
     }
     return result;
 }
@@ -186,3 +192,40 @@ UserStorageBootStrap GENERIC_userbootstrap = {
     "SDL generic user storage driver",
     GENERIC_User_Create
 };
+
+static const SDL_StorageInterface GENERIC_file_iface = {
+    GENERIC_StorageClose,
+    GENERIC_StorageReady,
+    GENERIC_StorageFileSize,
+    GENERIC_StorageReadFile,
+    GENERIC_StorageWriteFile,
+    GENERIC_StorageSpaceRemaining
+};
+
+SDL_Storage *GENERIC_OpenFileStorage(const char *path)
+{
+    SDL_Storage *result;
+    size_t len = 0;
+    char *basepath = NULL;
+
+    if (path) {
+        len += SDL_strlen(path);
+    }
+    if (len > 0) {
+        if (path[len-1] == '/') {
+            basepath = SDL_strdup(path);
+            if (!basepath) {
+                return NULL;
+            }
+        } else {
+            if (SDL_asprintf(&basepath, "%s/", path) < 0) {
+                return NULL;
+            }
+        }
+    }
+    result = SDL_OpenStorage(&GENERIC_file_iface, basepath);
+    if (result == NULL) {
+        SDL_free(basepath);
+    }
+    return result;
+}