Mercurial > foo_out_sdl
comparison SDL3/SDL_storage.h @ 1:20d02a178406 default tip
*: check in everything else
yay
| author | Paper <paper@tflc.us> |
|---|---|
| date | Mon, 05 Jan 2026 02:15:46 -0500 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 0:e9bb126753e7 | 1:20d02a178406 |
|---|---|
| 1 /* | |
| 2 Simple DirectMedia Layer | |
| 3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org> | |
| 4 | |
| 5 This software is provided 'as-is', without any express or implied | |
| 6 warranty. In no event will the authors be held liable for any damages | |
| 7 arising from the use of this software. | |
| 8 | |
| 9 Permission is granted to anyone to use this software for any purpose, | |
| 10 including commercial applications, and to alter it and redistribute it | |
| 11 freely, subject to the following restrictions: | |
| 12 | |
| 13 1. The origin of this software must not be misrepresented; you must not | |
| 14 claim that you wrote the original software. If you use this software | |
| 15 in a product, an acknowledgment in the product documentation would be | |
| 16 appreciated but is not required. | |
| 17 2. Altered source versions must be plainly marked as such, and must not be | |
| 18 misrepresented as being the original software. | |
| 19 3. This notice may not be removed or altered from any source distribution. | |
| 20 */ | |
| 21 | |
| 22 /** | |
| 23 * # CategoryStorage | |
| 24 * | |
| 25 * The storage API is a high-level API designed to abstract away the | |
| 26 * portability issues that come up when using something lower-level (in SDL's | |
| 27 * case, this sits on top of the [Filesystem](CategoryFilesystem) and | |
| 28 * [IOStream](CategoryIOStream) subsystems). It is significantly more | |
| 29 * restrictive than a typical filesystem API, for a number of reasons: | |
| 30 * | |
| 31 * 1. **What to Access:** A common pitfall with existing filesystem APIs is | |
| 32 * the assumption that all storage is monolithic. However, many other | |
| 33 * platforms (game consoles in particular) are more strict about what _type_ | |
| 34 * of filesystem is being accessed; for example, game content and user data | |
| 35 * are usually two separate storage devices with entirely different | |
| 36 * characteristics (and possibly different low-level APIs altogether!). | |
| 37 * | |
| 38 * 2. **How to Access:** Another common mistake is applications assuming that | |
| 39 * all storage is universally writeable - again, many platforms treat game | |
| 40 * content and user data as two separate storage devices, and only user data | |
| 41 * is writeable while game content is read-only. | |
| 42 * | |
| 43 * 3. **When to Access:** The most common portability issue with filesystem | |
| 44 * access is _timing_ - you cannot always assume that the storage device is | |
| 45 * always accessible all of the time, nor can you assume that there are no | |
| 46 * limits to how long you have access to a particular device. | |
| 47 * | |
| 48 * Consider the following example: | |
| 49 * | |
| 50 * ```c | |
| 51 * void ReadGameData(void) | |
| 52 * { | |
| 53 * extern char** fileNames; | |
| 54 * extern size_t numFiles; | |
| 55 * for (size_t i = 0; i < numFiles; i += 1) { | |
| 56 * FILE *data = fopen(fileNames[i], "rwb"); | |
| 57 * if (data == NULL) { | |
| 58 * // Something bad happened! | |
| 59 * } else { | |
| 60 * // A bunch of stuff happens here | |
| 61 * fclose(data); | |
| 62 * } | |
| 63 * } | |
| 64 * } | |
| 65 * | |
| 66 * void ReadSave(void) | |
| 67 * { | |
| 68 * FILE *save = fopen("saves/save0.sav", "rb"); | |
| 69 * if (save == NULL) { | |
| 70 * // Something bad happened! | |
| 71 * } else { | |
| 72 * // A bunch of stuff happens here | |
| 73 * fclose(save); | |
| 74 * } | |
| 75 * } | |
| 76 * | |
| 77 * void WriteSave(void) | |
| 78 * { | |
| 79 * FILE *save = fopen("saves/save0.sav", "wb"); | |
| 80 * if (save == NULL) { | |
| 81 * // Something bad happened! | |
| 82 * } else { | |
| 83 * // A bunch of stuff happens here | |
| 84 * fclose(save); | |
| 85 * } | |
| 86 * } | |
| 87 * ``` | |
| 88 * | |
| 89 * Going over the bullet points again: | |
| 90 * | |
| 91 * 1. **What to Access:** This code accesses a global filesystem; game data | |
| 92 * and saves are all presumed to be in the current working directory (which | |
| 93 * may or may not be the game's installation folder!). | |
| 94 * | |
| 95 * 2. **How to Access:** This code assumes that content paths are writeable, | |
| 96 * and that save data is also writeable despite being in the same location as | |
| 97 * the game data. | |
| 98 * | |
| 99 * 3. **When to Access:** This code assumes that they can be called at any | |
| 100 * time, since the filesystem is always accessible and has no limits on how | |
| 101 * long the filesystem is being accessed. | |
| 102 * | |
| 103 * Due to these assumptions, the filesystem code is not portable and will fail | |
| 104 * under these common scenarios: | |
| 105 * | |
| 106 * - The game is installed on a device that is read-only, both content loading | |
| 107 * and game saves will fail or crash outright | |
| 108 * - Game/User storage is not implicitly mounted, so no files will be found | |
| 109 * for either scenario when a platform requires explicitly mounting | |
| 110 * filesystems | |
| 111 * - Save data may not be safe since the I/O is not being flushed or | |
| 112 * validated, so an error occurring elsewhere in the program may result in | |
| 113 * missing/corrupted save data | |
| 114 * | |
| 115 * When using SDL_Storage, these types of problems are virtually impossible to | |
| 116 * trip over: | |
| 117 * | |
| 118 * ```c | |
| 119 * void ReadGameData(void) | |
| 120 * { | |
| 121 * extern char** fileNames; | |
| 122 * extern size_t numFiles; | |
| 123 * | |
| 124 * SDL_Storage *title = SDL_OpenTitleStorage(NULL, 0); | |
| 125 * if (title == NULL) { | |
| 126 * // Something bad happened! | |
| 127 * } | |
| 128 * while (!SDL_StorageReady(title)) { | |
| 129 * SDL_Delay(1); | |
| 130 * } | |
| 131 * | |
| 132 * for (size_t i = 0; i < numFiles; i += 1) { | |
| 133 * void* dst; | |
| 134 * Uint64 dstLen = 0; | |
| 135 * | |
| 136 * if (SDL_GetStorageFileSize(title, fileNames[i], &dstLen) && dstLen > 0) { | |
| 137 * dst = SDL_malloc(dstLen); | |
| 138 * if (SDL_ReadStorageFile(title, fileNames[i], dst, dstLen)) { | |
| 139 * // A bunch of stuff happens here | |
| 140 * } else { | |
| 141 * // Something bad happened! | |
| 142 * } | |
| 143 * SDL_free(dst); | |
| 144 * } else { | |
| 145 * // Something bad happened! | |
| 146 * } | |
| 147 * } | |
| 148 * | |
| 149 * SDL_CloseStorage(title); | |
| 150 * } | |
| 151 * | |
| 152 * void ReadSave(void) | |
| 153 * { | |
| 154 * SDL_Storage *user = SDL_OpenUserStorage("libsdl", "Storage Example", 0); | |
| 155 * if (user == NULL) { | |
| 156 * // Something bad happened! | |
| 157 * } | |
| 158 * while (!SDL_StorageReady(user)) { | |
| 159 * SDL_Delay(1); | |
| 160 * } | |
| 161 * | |
| 162 * Uint64 saveLen = 0; | |
| 163 * if (SDL_GetStorageFileSize(user, "save0.sav", &saveLen) && saveLen > 0) { | |
| 164 * void* dst = SDL_malloc(saveLen); | |
| 165 * if (SDL_ReadStorageFile(user, "save0.sav", dst, saveLen)) { | |
| 166 * // A bunch of stuff happens here | |
| 167 * } else { | |
| 168 * // Something bad happened! | |
| 169 * } | |
| 170 * SDL_free(dst); | |
| 171 * } else { | |
| 172 * // Something bad happened! | |
| 173 * } | |
| 174 * | |
| 175 * SDL_CloseStorage(user); | |
| 176 * } | |
| 177 * | |
| 178 * void WriteSave(void) | |
| 179 * { | |
| 180 * SDL_Storage *user = SDL_OpenUserStorage("libsdl", "Storage Example", 0); | |
| 181 * if (user == NULL) { | |
| 182 * // Something bad happened! | |
| 183 * } | |
| 184 * while (!SDL_StorageReady(user)) { | |
| 185 * SDL_Delay(1); | |
| 186 * } | |
| 187 * | |
| 188 * extern void *saveData; // A bunch of stuff happened here... | |
| 189 * extern Uint64 saveLen; | |
| 190 * if (!SDL_WriteStorageFile(user, "save0.sav", saveData, saveLen)) { | |
| 191 * // Something bad happened! | |
| 192 * } | |
| 193 * | |
| 194 * SDL_CloseStorage(user); | |
| 195 * } | |
| 196 * ``` | |
| 197 * | |
| 198 * Note the improvements that SDL_Storage makes: | |
| 199 * | |
| 200 * 1. **What to Access:** This code explicitly reads from a title or user | |
| 201 * storage device based on the context of the function. | |
| 202 * | |
| 203 * 2. **How to Access:** This code explicitly uses either a read or write | |
| 204 * function based on the context of the function. | |
| 205 * | |
| 206 * 3. **When to Access:** This code explicitly opens the device when it needs | |
| 207 * to, and closes it when it is finished working with the filesystem. | |
| 208 * | |
| 209 * The result is an application that is significantly more robust against the | |
| 210 * increasing demands of platforms and their filesystems! | |
| 211 * | |
| 212 * A publicly available example of an SDL_Storage backend is the | |
| 213 * [Steam Cloud](https://partner.steamgames.com/doc/features/cloud) | |
| 214 * backend - you can initialize Steamworks when starting the program, and then | |
| 215 * SDL will recognize that Steamworks is initialized and automatically use | |
| 216 * ISteamRemoteStorage when the application opens user storage. More | |
| 217 * importantly, when you _open_ storage it knows to begin a "batch" of | |
| 218 * filesystem operations, and when you _close_ storage it knows to end and | |
| 219 * flush the batch. This is used by Steam to support | |
| 220 * [Dynamic Cloud Sync](https://steamcommunity.com/groups/steamworks/announcements/detail/3142949576401813670) | |
| 221 * ; users can save data on one PC, put the device to sleep, and then continue | |
| 222 * playing on another PC (and vice versa) with the save data fully | |
| 223 * synchronized across all devices, allowing for a seamless experience without | |
| 224 * having to do full restarts of the program. | |
| 225 * | |
| 226 * ## Notes on valid paths | |
| 227 * | |
| 228 * All paths in the Storage API use Unix-style path separators ('/'). Using a | |
| 229 * different path separator will not work, even if the underlying platform | |
| 230 * would otherwise accept it. This is to keep code using the Storage API | |
| 231 * portable between platforms and Storage implementations and simplify app | |
| 232 * code. | |
| 233 * | |
| 234 * Paths with relative directories ("." and "..") are forbidden by the Storage | |
| 235 * API. | |
| 236 * | |
| 237 * All valid UTF-8 strings (discounting the NULL terminator character and the | |
| 238 * '/' path separator) are usable for filenames, however, an underlying | |
| 239 * Storage implementation may not support particularly strange sequences and | |
| 240 * refuse to create files with those names, etc. | |
| 241 */ | |
| 242 | |
| 243 #ifndef SDL_storage_h_ | |
| 244 #define SDL_storage_h_ | |
| 245 | |
| 246 #include <SDL3/SDL_stdinc.h> | |
| 247 #include <SDL3/SDL_error.h> | |
| 248 #include <SDL3/SDL_filesystem.h> | |
| 249 #include <SDL3/SDL_properties.h> | |
| 250 | |
| 251 #include <SDL3/SDL_begin_code.h> | |
| 252 | |
| 253 /* Set up for C function definitions, even when using C++ */ | |
| 254 #ifdef __cplusplus | |
| 255 extern "C" { | |
| 256 #endif | |
| 257 | |
| 258 /** | |
| 259 * Function interface for SDL_Storage. | |
| 260 * | |
| 261 * Apps that want to supply a custom implementation of SDL_Storage will fill | |
| 262 * in all the functions in this struct, and then pass it to SDL_OpenStorage to | |
| 263 * create a custom SDL_Storage object. | |
| 264 * | |
| 265 * It is not usually necessary to do this; SDL provides standard | |
| 266 * implementations for many things you might expect to do with an SDL_Storage. | |
| 267 * | |
| 268 * This structure should be initialized using SDL_INIT_INTERFACE() | |
| 269 * | |
| 270 * \since This struct is available since SDL 3.2.0. | |
| 271 * | |
| 272 * \sa SDL_INIT_INTERFACE | |
| 273 */ | |
| 274 typedef struct SDL_StorageInterface | |
| 275 { | |
| 276 /* The version of this interface */ | |
| 277 Uint32 version; | |
| 278 | |
| 279 /* Called when the storage is closed */ | |
| 280 bool (SDLCALL *close)(void *userdata); | |
| 281 | |
| 282 /* Optional, returns whether the storage is currently ready for access */ | |
| 283 bool (SDLCALL *ready)(void *userdata); | |
| 284 | |
| 285 /* Enumerate a directory, optional for write-only storage */ | |
| 286 bool (SDLCALL *enumerate)(void *userdata, const char *path, SDL_EnumerateDirectoryCallback callback, void *callback_userdata); | |
| 287 | |
| 288 /* Get path information, optional for write-only storage */ | |
| 289 bool (SDLCALL *info)(void *userdata, const char *path, SDL_PathInfo *info); | |
| 290 | |
| 291 /* Read a file from storage, optional for write-only storage */ | |
| 292 bool (SDLCALL *read_file)(void *userdata, const char *path, void *destination, Uint64 length); | |
| 293 | |
| 294 /* Write a file to storage, optional for read-only storage */ | |
| 295 bool (SDLCALL *write_file)(void *userdata, const char *path, const void *source, Uint64 length); | |
| 296 | |
| 297 /* Create a directory, optional for read-only storage */ | |
| 298 bool (SDLCALL *mkdir)(void *userdata, const char *path); | |
| 299 | |
| 300 /* Remove a file or empty directory, optional for read-only storage */ | |
| 301 bool (SDLCALL *remove)(void *userdata, const char *path); | |
| 302 | |
| 303 /* Rename a path, optional for read-only storage */ | |
| 304 bool (SDLCALL *rename)(void *userdata, const char *oldpath, const char *newpath); | |
| 305 | |
| 306 /* Copy a file, optional for read-only storage */ | |
| 307 bool (SDLCALL *copy)(void *userdata, const char *oldpath, const char *newpath); | |
| 308 | |
| 309 /* Get the space remaining, optional for read-only storage */ | |
| 310 Uint64 (SDLCALL *space_remaining)(void *userdata); | |
| 311 } SDL_StorageInterface; | |
| 312 | |
| 313 /* Check the size of SDL_StorageInterface | |
| 314 * | |
| 315 * If this assert fails, either the compiler is padding to an unexpected size, | |
| 316 * or the interface has been updated and this should be updated to match and | |
| 317 * the code using this interface should be updated to handle the old version. | |
| 318 */ | |
| 319 SDL_COMPILE_TIME_ASSERT(SDL_StorageInterface_SIZE, | |
| 320 (sizeof(void *) == 4 && sizeof(SDL_StorageInterface) == 48) || | |
| 321 (sizeof(void *) == 8 && sizeof(SDL_StorageInterface) == 96)); | |
| 322 | |
| 323 /** | |
| 324 * An abstract interface for filesystem access. | |
| 325 * | |
| 326 * This is an opaque datatype. One can create this object using standard SDL | |
| 327 * functions like SDL_OpenTitleStorage or SDL_OpenUserStorage, etc, or create | |
| 328 * an object with a custom implementation using SDL_OpenStorage. | |
| 329 * | |
| 330 * \since This struct is available since SDL 3.2.0. | |
| 331 */ | |
| 332 typedef struct SDL_Storage SDL_Storage; | |
| 333 | |
| 334 /** | |
| 335 * Opens up a read-only container for the application's filesystem. | |
| 336 * | |
| 337 * By default, SDL_OpenTitleStorage uses the generic storage implementation. | |
| 338 * When the path override is not provided, the generic implementation will use | |
| 339 * the output of SDL_GetBasePath as the base path. | |
| 340 * | |
| 341 * \param override a path to override the backend's default title root. | |
| 342 * \param props a property list that may contain backend-specific information. | |
| 343 * \returns a title storage container on success or NULL on failure; call | |
| 344 * SDL_GetError() for more information. | |
| 345 * | |
| 346 * \since This function is available since SDL 3.2.0. | |
| 347 * | |
| 348 * \sa SDL_CloseStorage | |
| 349 * \sa SDL_GetStorageFileSize | |
| 350 * \sa SDL_OpenUserStorage | |
| 351 * \sa SDL_ReadStorageFile | |
| 352 */ | |
| 353 extern SDL_DECLSPEC SDL_Storage * SDLCALL SDL_OpenTitleStorage(const char *override, SDL_PropertiesID props); | |
| 354 | |
| 355 /** | |
| 356 * Opens up a container for a user's unique read/write filesystem. | |
| 357 * | |
| 358 * While title storage can generally be kept open throughout runtime, user | |
| 359 * storage should only be opened when the client is ready to read/write files. | |
| 360 * This allows the backend to properly batch file operations and flush them | |
| 361 * when the container has been closed; ensuring safe and optimal save I/O. | |
| 362 * | |
| 363 * \param org the name of your organization. | |
| 364 * \param app the name of your application. | |
| 365 * \param props a property list that may contain backend-specific information. | |
| 366 * \returns a user storage container on success or NULL on failure; call | |
| 367 * SDL_GetError() for more information. | |
| 368 * | |
| 369 * \since This function is available since SDL 3.2.0. | |
| 370 * | |
| 371 * \sa SDL_CloseStorage | |
| 372 * \sa SDL_GetStorageFileSize | |
| 373 * \sa SDL_GetStorageSpaceRemaining | |
| 374 * \sa SDL_OpenTitleStorage | |
| 375 * \sa SDL_ReadStorageFile | |
| 376 * \sa SDL_StorageReady | |
| 377 * \sa SDL_WriteStorageFile | |
| 378 */ | |
| 379 extern SDL_DECLSPEC SDL_Storage * SDLCALL SDL_OpenUserStorage(const char *org, const char *app, SDL_PropertiesID props); | |
| 380 | |
| 381 /** | |
| 382 * Opens up a container for local filesystem storage. | |
| 383 * | |
| 384 * This is provided for development and tools. Portable applications should | |
| 385 * use SDL_OpenTitleStorage() for access to game data and | |
| 386 * SDL_OpenUserStorage() for access to user data. | |
| 387 * | |
| 388 * \param path the base path prepended to all storage paths, or NULL for no | |
| 389 * base path. | |
| 390 * \returns a filesystem storage container on success or NULL on failure; call | |
| 391 * SDL_GetError() for more information. | |
| 392 * | |
| 393 * \since This function is available since SDL 3.2.0. | |
| 394 * | |
| 395 * \sa SDL_CloseStorage | |
| 396 * \sa SDL_GetStorageFileSize | |
| 397 * \sa SDL_GetStorageSpaceRemaining | |
| 398 * \sa SDL_OpenTitleStorage | |
| 399 * \sa SDL_OpenUserStorage | |
| 400 * \sa SDL_ReadStorageFile | |
| 401 * \sa SDL_WriteStorageFile | |
| 402 */ | |
| 403 extern SDL_DECLSPEC SDL_Storage * SDLCALL SDL_OpenFileStorage(const char *path); | |
| 404 | |
| 405 /** | |
| 406 * Opens up a container using a client-provided storage interface. | |
| 407 * | |
| 408 * Applications do not need to use this function unless they are providing | |
| 409 * their own SDL_Storage implementation. If you just need an SDL_Storage, you | |
| 410 * should use the built-in implementations in SDL, like SDL_OpenTitleStorage() | |
| 411 * or SDL_OpenUserStorage(). | |
| 412 * | |
| 413 * This function makes a copy of `iface` and the caller does not need to keep | |
| 414 * it around after this call. | |
| 415 * | |
| 416 * \param iface the interface that implements this storage, initialized using | |
| 417 * SDL_INIT_INTERFACE(). | |
| 418 * \param userdata the pointer that will be passed to the interface functions. | |
| 419 * \returns a storage container on success or NULL on failure; call | |
| 420 * SDL_GetError() for more information. | |
| 421 * | |
| 422 * \since This function is available since SDL 3.2.0. | |
| 423 * | |
| 424 * \sa SDL_CloseStorage | |
| 425 * \sa SDL_GetStorageFileSize | |
| 426 * \sa SDL_GetStorageSpaceRemaining | |
| 427 * \sa SDL_INIT_INTERFACE | |
| 428 * \sa SDL_ReadStorageFile | |
| 429 * \sa SDL_StorageReady | |
| 430 * \sa SDL_WriteStorageFile | |
| 431 */ | |
| 432 extern SDL_DECLSPEC SDL_Storage * SDLCALL SDL_OpenStorage(const SDL_StorageInterface *iface, void *userdata); | |
| 433 | |
| 434 /** | |
| 435 * Closes and frees a storage container. | |
| 436 * | |
| 437 * \param storage a storage container to close. | |
| 438 * \returns true if the container was freed with no errors, false otherwise; | |
| 439 * call SDL_GetError() for more information. Even if the function | |
| 440 * returns an error, the container data will be freed; the error is | |
| 441 * only for informational purposes. | |
| 442 * | |
| 443 * \since This function is available since SDL 3.2.0. | |
| 444 * | |
| 445 * \sa SDL_OpenFileStorage | |
| 446 * \sa SDL_OpenStorage | |
| 447 * \sa SDL_OpenTitleStorage | |
| 448 * \sa SDL_OpenUserStorage | |
| 449 */ | |
| 450 extern SDL_DECLSPEC bool SDLCALL SDL_CloseStorage(SDL_Storage *storage); | |
| 451 | |
| 452 /** | |
| 453 * Checks if the storage container is ready to use. | |
| 454 * | |
| 455 * This function should be called in regular intervals until it returns true - | |
| 456 * however, it is not recommended to spinwait on this call, as the backend may | |
| 457 * depend on a synchronous message loop. You might instead poll this in your | |
| 458 * game's main loop while processing events and drawing a loading screen. | |
| 459 * | |
| 460 * \param storage a storage container to query. | |
| 461 * \returns true if the container is ready, false otherwise. | |
| 462 * | |
| 463 * \since This function is available since SDL 3.2.0. | |
| 464 */ | |
| 465 extern SDL_DECLSPEC bool SDLCALL SDL_StorageReady(SDL_Storage *storage); | |
| 466 | |
| 467 /** | |
| 468 * Query the size of a file within a storage container. | |
| 469 * | |
| 470 * \param storage a storage container to query. | |
| 471 * \param path the relative path of the file to query. | |
| 472 * \param length a pointer to be filled with the file's length. | |
| 473 * \returns true if the file could be queried or false on failure; call | |
| 474 * SDL_GetError() for more information. | |
| 475 * | |
| 476 * \since This function is available since SDL 3.2.0. | |
| 477 * | |
| 478 * \sa SDL_ReadStorageFile | |
| 479 * \sa SDL_StorageReady | |
| 480 */ | |
| 481 extern SDL_DECLSPEC bool SDLCALL SDL_GetStorageFileSize(SDL_Storage *storage, const char *path, Uint64 *length); | |
| 482 | |
| 483 /** | |
| 484 * Synchronously read a file from a storage container into a client-provided | |
| 485 * buffer. | |
| 486 * | |
| 487 * The value of `length` must match the length of the file exactly; call | |
| 488 * SDL_GetStorageFileSize() to get this value. This behavior may be relaxed in | |
| 489 * a future release. | |
| 490 * | |
| 491 * \param storage a storage container to read from. | |
| 492 * \param path the relative path of the file to read. | |
| 493 * \param destination a client-provided buffer to read the file into. | |
| 494 * \param length the length of the destination buffer. | |
| 495 * \returns true if the file was read or false on failure; call SDL_GetError() | |
| 496 * for more information. | |
| 497 * | |
| 498 * \since This function is available since SDL 3.2.0. | |
| 499 * | |
| 500 * \sa SDL_GetStorageFileSize | |
| 501 * \sa SDL_StorageReady | |
| 502 * \sa SDL_WriteStorageFile | |
| 503 */ | |
| 504 extern SDL_DECLSPEC bool SDLCALL SDL_ReadStorageFile(SDL_Storage *storage, const char *path, void *destination, Uint64 length); | |
| 505 | |
| 506 /** | |
| 507 * Synchronously write a file from client memory into a storage container. | |
| 508 * | |
| 509 * \param storage a storage container to write to. | |
| 510 * \param path the relative path of the file to write. | |
| 511 * \param source a client-provided buffer to write from. | |
| 512 * \param length the length of the source buffer. | |
| 513 * \returns true if the file was written or false on failure; call | |
| 514 * SDL_GetError() for more information. | |
| 515 * | |
| 516 * \since This function is available since SDL 3.2.0. | |
| 517 * | |
| 518 * \sa SDL_GetStorageSpaceRemaining | |
| 519 * \sa SDL_ReadStorageFile | |
| 520 * \sa SDL_StorageReady | |
| 521 */ | |
| 522 extern SDL_DECLSPEC bool SDLCALL SDL_WriteStorageFile(SDL_Storage *storage, const char *path, const void *source, Uint64 length); | |
| 523 | |
| 524 /** | |
| 525 * Create a directory in a writable storage container. | |
| 526 * | |
| 527 * \param storage a storage container. | |
| 528 * \param path the path of the directory to create. | |
| 529 * \returns true on success or false on failure; call SDL_GetError() for more | |
| 530 * information. | |
| 531 * | |
| 532 * \since This function is available since SDL 3.2.0. | |
| 533 * | |
| 534 * \sa SDL_StorageReady | |
| 535 */ | |
| 536 extern SDL_DECLSPEC bool SDLCALL SDL_CreateStorageDirectory(SDL_Storage *storage, const char *path); | |
| 537 | |
| 538 /** | |
| 539 * Enumerate a directory in a storage container through a callback function. | |
| 540 * | |
| 541 * This function provides every directory entry through an app-provided | |
| 542 * callback, called once for each directory entry, until all results have been | |
| 543 * provided or the callback returns either SDL_ENUM_SUCCESS or | |
| 544 * SDL_ENUM_FAILURE. | |
| 545 * | |
| 546 * This will return false if there was a system problem in general, or if a | |
| 547 * callback returns SDL_ENUM_FAILURE. A successful return means a callback | |
| 548 * returned SDL_ENUM_SUCCESS to halt enumeration, or all directory entries | |
| 549 * were enumerated. | |
| 550 * | |
| 551 * If `path` is NULL, this is treated as a request to enumerate the root of | |
| 552 * the storage container's tree. An empty string also works for this. | |
| 553 * | |
| 554 * \param storage a storage container. | |
| 555 * \param path the path of the directory to enumerate, or NULL for the root. | |
| 556 * \param callback a function that is called for each entry in the directory. | |
| 557 * \param userdata a pointer that is passed to `callback`. | |
| 558 * \returns true on success or false on failure; call SDL_GetError() for more | |
| 559 * information. | |
| 560 * | |
| 561 * \since This function is available since SDL 3.2.0. | |
| 562 * | |
| 563 * \sa SDL_StorageReady | |
| 564 */ | |
| 565 extern SDL_DECLSPEC bool SDLCALL SDL_EnumerateStorageDirectory(SDL_Storage *storage, const char *path, SDL_EnumerateDirectoryCallback callback, void *userdata); | |
| 566 | |
| 567 /** | |
| 568 * Remove a file or an empty directory in a writable storage container. | |
| 569 * | |
| 570 * \param storage a storage container. | |
| 571 * \param path the path of the directory to enumerate. | |
| 572 * \returns true on success or false on failure; call SDL_GetError() for more | |
| 573 * information. | |
| 574 * | |
| 575 * \since This function is available since SDL 3.2.0. | |
| 576 * | |
| 577 * \sa SDL_StorageReady | |
| 578 */ | |
| 579 extern SDL_DECLSPEC bool SDLCALL SDL_RemoveStoragePath(SDL_Storage *storage, const char *path); | |
| 580 | |
| 581 /** | |
| 582 * Rename a file or directory in a writable storage container. | |
| 583 * | |
| 584 * \param storage a storage container. | |
| 585 * \param oldpath the old path. | |
| 586 * \param newpath the new path. | |
| 587 * \returns true on success or false on failure; call SDL_GetError() for more | |
| 588 * information. | |
| 589 * | |
| 590 * \since This function is available since SDL 3.2.0. | |
| 591 * | |
| 592 * \sa SDL_StorageReady | |
| 593 */ | |
| 594 extern SDL_DECLSPEC bool SDLCALL SDL_RenameStoragePath(SDL_Storage *storage, const char *oldpath, const char *newpath); | |
| 595 | |
| 596 /** | |
| 597 * Copy a file in a writable storage container. | |
| 598 * | |
| 599 * \param storage a storage container. | |
| 600 * \param oldpath the old path. | |
| 601 * \param newpath the new path. | |
| 602 * \returns true on success or false on failure; call SDL_GetError() for more | |
| 603 * information. | |
| 604 * | |
| 605 * \since This function is available since SDL 3.2.0. | |
| 606 * | |
| 607 * \sa SDL_StorageReady | |
| 608 */ | |
| 609 extern SDL_DECLSPEC bool SDLCALL SDL_CopyStorageFile(SDL_Storage *storage, const char *oldpath, const char *newpath); | |
| 610 | |
| 611 /** | |
| 612 * Get information about a filesystem path in a storage container. | |
| 613 * | |
| 614 * \param storage a storage container. | |
| 615 * \param path the path to query. | |
| 616 * \param info a pointer filled in with information about the path, or NULL to | |
| 617 * check for the existence of a file. | |
| 618 * \returns true on success or false if the file doesn't exist, or another | |
| 619 * failure; call SDL_GetError() for more information. | |
| 620 * | |
| 621 * \since This function is available since SDL 3.2.0. | |
| 622 * | |
| 623 * \sa SDL_StorageReady | |
| 624 */ | |
| 625 extern SDL_DECLSPEC bool SDLCALL SDL_GetStoragePathInfo(SDL_Storage *storage, const char *path, SDL_PathInfo *info); | |
| 626 | |
| 627 /** | |
| 628 * Queries the remaining space in a storage container. | |
| 629 * | |
| 630 * \param storage a storage container to query. | |
| 631 * \returns the amount of remaining space, in bytes. | |
| 632 * | |
| 633 * \since This function is available since SDL 3.2.0. | |
| 634 * | |
| 635 * \sa SDL_StorageReady | |
| 636 * \sa SDL_WriteStorageFile | |
| 637 */ | |
| 638 extern SDL_DECLSPEC Uint64 SDLCALL SDL_GetStorageSpaceRemaining(SDL_Storage *storage); | |
| 639 | |
| 640 /** | |
| 641 * Enumerate a directory tree, filtered by pattern, and return a list. | |
| 642 * | |
| 643 * Files are filtered out if they don't match the string in `pattern`, which | |
| 644 * may contain wildcard characters `*` (match everything) and `?` (match one | |
| 645 * character). If pattern is NULL, no filtering is done and all results are | |
| 646 * returned. Subdirectories are permitted, and are specified with a path | |
| 647 * separator of '/'. Wildcard characters `*` and `?` never match a path | |
| 648 * separator. | |
| 649 * | |
| 650 * `flags` may be set to SDL_GLOB_CASEINSENSITIVE to make the pattern matching | |
| 651 * case-insensitive. | |
| 652 * | |
| 653 * The returned array is always NULL-terminated, for your iterating | |
| 654 * convenience, but if `count` is non-NULL, on return it will contain the | |
| 655 * number of items in the array, not counting the NULL terminator. | |
| 656 * | |
| 657 * If `path` is NULL, this is treated as a request to enumerate the root of | |
| 658 * the storage container's tree. An empty string also works for this. | |
| 659 * | |
| 660 * \param storage a storage container. | |
| 661 * \param path the path of the directory to enumerate, or NULL for the root. | |
| 662 * \param pattern the pattern that files in the directory must match. Can be | |
| 663 * NULL. | |
| 664 * \param flags `SDL_GLOB_*` bitflags that affect this search. | |
| 665 * \param count on return, will be set to the number of items in the returned | |
| 666 * array. Can be NULL. | |
| 667 * \returns an array of strings on success or NULL on failure; call | |
| 668 * SDL_GetError() for more information. The caller should pass the | |
| 669 * returned pointer to SDL_free when done with it. This is a single | |
| 670 * allocation that should be freed with SDL_free() when it is no | |
| 671 * longer needed. | |
| 672 * | |
| 673 * \threadsafety It is safe to call this function from any thread, assuming | |
| 674 * the `storage` object is thread-safe. | |
| 675 * | |
| 676 * \since This function is available since SDL 3.2.0. | |
| 677 */ | |
| 678 extern SDL_DECLSPEC char ** SDLCALL SDL_GlobStorageDirectory(SDL_Storage *storage, const char *path, const char *pattern, SDL_GlobFlags flags, int *count); | |
| 679 | |
| 680 /* Ends C function definitions when using C++ */ | |
| 681 #ifdef __cplusplus | |
| 682 } | |
| 683 #endif | |
| 684 #include <SDL3/SDL_close_code.h> | |
| 685 | |
| 686 #endif /* SDL_storage_h_ */ |
