From dc400184388ae7d70bfc7b4f59de5c5c160bb039 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 9 Aug 2017 11:58:38 -0700 Subject: [PATCH] Added an API SDL_LoadFile_RW() to load all the data from an SDL data stream, and a convenience macro SDL_LoadFile() to load all the data from a file. --- include/SDL_rwops.h | 23 ++++++++++++++ src/dynapi/SDL_dynapi_overrides.h | 1 + src/dynapi/SDL_dynapi_procs.h | 1 + src/file/SDL_rwops.c | 53 +++++++++++++++++++++++++++++++ 4 files changed, 78 insertions(+) diff --git a/include/SDL_rwops.h b/include/SDL_rwops.h index 00d82a6d0..7f0cbdfd5 100644 --- a/include/SDL_rwops.h +++ b/include/SDL_rwops.h @@ -190,6 +190,29 @@ extern DECLSPEC void SDLCALL SDL_FreeRW(SDL_RWops * area); /* @} *//* Read/write macros */ +/** + * Load all the data from an SDL data stream. + * + * The data is allocated with a zero byte at the end (null terminated) + * + * If \c datasize is not NULL, it is filled with the size of the data read. + * + * If \c freesrc is non-zero, the stream will be closed after being read. + * + * The data should be freed with SDL_free(). + * + * \return the data, or NULL if there was an error. + */ +extern DECLSPEC void *SDLCALL SDL_LoadFile_RW(SDL_RWops * src, size_t *datasize, + int freesrc); + +/** + * Load an entire file. + * + * Convenience macro. + */ +#define SDL_LoadFile(file, datasize) SDL_LoadFile_RW(SDL_RWFromFile(file, "rb"), datasize, 1) + /** * \name Read endian functions * diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index c848a7f98..819e41052 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -625,3 +625,4 @@ #define SDL_MemoryBarrierAcquireFunction SDL_MemoryBarrierAcquireFunction_REAL #define SDL_JoystickGetDeviceInstanceID SDL_JoystickGetDeviceInstanceID_REAL #define SDL_utf8strlen SDL_utf8strlen_REAL +#define SDL_LoadFile_RW SDL_LoadFile_RW_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 9583a3490..4db52884b 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -657,3 +657,4 @@ SDL_DYNAPI_PROC(void,SDL_MemoryBarrierReleaseFunction,(void),(),) SDL_DYNAPI_PROC(void,SDL_MemoryBarrierAcquireFunction,(void),(),) SDL_DYNAPI_PROC(SDL_JoystickID,SDL_JoystickGetDeviceInstanceID,(int a),(a),return) SDL_DYNAPI_PROC(size_t,SDL_utf8strlen,(const char *a),(a),return) +SDL_DYNAPI_PROC(void*,SDL_LoadFile_RW,(SDL_RWops *a, size_t *b, int c),(a,b,c),return) diff --git a/src/file/SDL_rwops.c b/src/file/SDL_rwops.c index 2d3bff6c5..a3ca213c0 100644 --- a/src/file/SDL_rwops.c +++ b/src/file/SDL_rwops.c @@ -653,6 +653,59 @@ SDL_FreeRW(SDL_RWops * area) SDL_free(area); } +/* Load all the data from an SDL data stream */ +void * +SDL_LoadFile_RW(SDL_RWops * src, size_t *datasize, int freesrc) +{ + const int FILE_CHUNK_SIZE = 1024; + Sint64 size; + size_t size_read, size_total; + void *data = NULL, *newdata; + + if (!src) { + SDL_InvalidParamError("src"); + return NULL; + } + + size = SDL_RWsize(src); + if (size < 0) { + size = FILE_CHUNK_SIZE; + } + data = SDL_malloc(size+1); + + size_total = 0; + for (;;) { + if ((size_total + FILE_CHUNK_SIZE) > size) { + size = (size_total + FILE_CHUNK_SIZE); + newdata = SDL_realloc(data, size + 1); + if (!newdata) { + SDL_free(data); + data = NULL; + SDL_OutOfMemory(); + goto done; + } + data = newdata; + } + + size_read = SDL_RWread(src, (char *)data+size_total, 1, (size_t)(size-size_total)); + if (size_read == 0) { + break; + } + size_total += size_read; + } + + if (datasize) { + *datasize = size_total; + } + ((char *)data)[size_total] = '\0'; + +done: + if (freesrc && src) { + SDL_RWclose(src); + } + return data; +} + /* Functions for dynamically reading and writing endian-specific values */ Uint8