diff --git a/include/SDL3/SDL_iostream.h b/include/SDL3/SDL_iostream.h index 76fdf0ad2d..433fd1fac6 100644 --- a/include/SDL3/SDL_iostream.h +++ b/include/SDL3/SDL_iostream.h @@ -664,6 +664,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_FlushIO(SDL_IOStream *context); * \since This function is available since SDL 3.1.3. * * \sa SDL_LoadFile + * \sa SDL_SaveFile_IO */ extern SDL_DECLSPEC void * SDLCALL SDL_LoadFile_IO(SDL_IOStream *src, size_t *datasize, bool closeio); @@ -684,9 +685,46 @@ extern SDL_DECLSPEC void * SDLCALL SDL_LoadFile_IO(SDL_IOStream *src, size_t *da * \since This function is available since SDL 3.1.3. * * \sa SDL_LoadFile_IO + * \sa SDL_SaveFile */ extern SDL_DECLSPEC void * SDLCALL SDL_LoadFile(const char *file, size_t *datasize); +/** + * Save all the data into an SDL data stream. + * + * \param src the SDL_IOStream to write all data to. + * \param data the data to be written. If datasize is 0, may be NULL or a + * invalid pointer. + * \param datasize the number of bytes to be written. + * \param closeio if true, calls SDL_CloseIO() on `src` before returning, even + * in the case of an error. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL 3.1.3. + * + * \sa SDL_SaveFile + * \sa SDL_LoadFile_IO + */ +extern SDL_DECLSPEC bool SDLCALL SDL_SaveFile_IO(SDL_IOStream *src, const void *data, size_t datasize, bool closeio); + +/** + * Save all the data into a file path. + * + * \param file the path to read all available data from. + * \param data the data to be written. If datasize is 0, may be NULL or a + * invalid pointer. + * \param datasize the number of bytes to be written. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL 3.1.3. + * + * \sa SDL_SaveFile_IO + * \sa SDL_LoadFile + */ +extern SDL_DECLSPEC bool SDLCALL SDL_SaveFile(const char *file, const void *data, size_t datasize); + /** * \name Read endian functions * diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index fcdb93b05f..e786d37002 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -1184,6 +1184,8 @@ SDL3_0.0.0 { SDL_RenderDebugText; SDL_GetSandbox; SDL_CancelGPUCommandBuffer; + SDL_SaveFile_IO; + SDL_SaveFile; # extra symbols go here (don't modify this line) local: *; }; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index c33efb30b8..215f471510 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -1209,3 +1209,5 @@ #define SDL_RenderDebugText SDL_RenderDebugText_REAL #define SDL_GetSandbox SDL_GetSandbox_REAL #define SDL_CancelGPUCommandBuffer SDL_CancelGPUCommandBuffer_REAL +#define SDL_SaveFile_IO SDL_SaveFile_IO_REAL +#define SDL_SaveFile SDL_SaveFile_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index cebdf0206e..05849f6ec3 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -1215,3 +1215,5 @@ SDL_DYNAPI_PROC(SDL_LogOutputFunction,SDL_GetDefaultLogOutputFunction,(void),(), SDL_DYNAPI_PROC(bool,SDL_RenderDebugText,(SDL_Renderer *a,float b,float c,const char *d),(a,b,c,d),return) SDL_DYNAPI_PROC(SDL_Sandbox,SDL_GetSandbox,(void),(),return) SDL_DYNAPI_PROC(bool,SDL_CancelGPUCommandBuffer,(SDL_GPUCommandBuffer *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_SaveFile_IO,(SDL_IOStream *a,const void *b,size_t c,bool d),(a,b,c,d),return) +SDL_DYNAPI_PROC(bool,SDL_SaveFile,(const char *a,const void *b,size_t c),(a,b,c),return) diff --git a/src/file/SDL_iostream.c b/src/file/SDL_iostream.c index 1fa652f893..7e70f5b931 100644 --- a/src/file/SDL_iostream.c +++ b/src/file/SDL_iostream.c @@ -1218,6 +1218,58 @@ void *SDL_LoadFile(const char *file, size_t *datasize) return SDL_LoadFile_IO(stream, datasize, true); } +bool SDL_SaveFile_IO(SDL_IOStream *src, const void *data, size_t datasize, bool closeio) +{ + size_t size_written = 0; + size_t size_total = 0; + bool success = true; + + if (!src) { + SDL_InvalidParamError("src"); + goto done; + } + + if (!data && datasize > 0) { + SDL_InvalidParamError("data"); + goto done; + } + + if (datasize > 0) { + while (size_total < datasize) { + size_written = SDL_WriteIO(src, ((const char *) data) + size_written, datasize - size_written); + + if (size_written <= 0) { + if (SDL_GetIOStatus(src) == SDL_IO_STATUS_NOT_READY) { + // Wait for the stream to be ready + SDL_Delay(1); + continue; + } else { + success = false; + goto done; + } + } + + size_total += size_written; + } + } + +done: + if (closeio && src) { + SDL_CloseIO(src); + } + + return success; +} + +bool SDL_SaveFile(const char *file, const void *data, size_t datasize) +{ + SDL_IOStream *stream = SDL_IOFromFile(file, "wb"); + if (!stream) { + return false; + } + return SDL_SaveFile_IO(stream, data, datasize, true); +} + SDL_PropertiesID SDL_GetIOProperties(SDL_IOStream *context) { if (!context) {