|
|
@@ -41,14 +41,21 @@
|
|
|
|
|
|
#include "SDL_iostream_c.h"
|
|
|
|
|
|
+
|
|
|
/* This file provides a general interface for SDL to read and write
|
|
|
data sources. It can easily be extended to files, memory, etc.
|
|
|
*/
|
|
|
|
|
|
+// IOStreams have various Properties. The first time SDL_GetIOProperties() is
|
|
|
+// called, it creates the SDL_PropertiesID and then uses this function
|
|
|
+// interface to fill in the appropriate props for the stream on-demand.
|
|
|
+typedef void (*SetIOPropertiesFn)(SDL_PropertiesID props, void *userdata);
|
|
|
+
|
|
|
struct SDL_IOStream
|
|
|
{
|
|
|
SDL_IOStreamInterface iface;
|
|
|
void *userdata;
|
|
|
+ SetIOPropertiesFn setioprops;
|
|
|
SDL_IOStatus status;
|
|
|
SDL_PropertiesID props;
|
|
|
};
|
|
|
@@ -425,6 +432,12 @@ static bool SDLCALL windows_file_close(void *userdata)
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
+static void windows_setioprops(SDL_PropertiesID props, void *userdata)
|
|
|
+{
|
|
|
+ const IOStreamWindowsData *iodata = (const IOStreamWindowsData *) userdata;
|
|
|
+ SDL_SetPointerProperty(props, SDL_PROP_IOSTREAM_WINDOWS_HANDLE_POINTER, iodata->h);
|
|
|
+}
|
|
|
+
|
|
|
SDL_IOStream *SDL_IOFromHandle(HANDLE handle, const char *mode, bool autoclose)
|
|
|
{
|
|
|
IOStreamWindowsData *iodata = (IOStreamWindowsData *) SDL_calloc(1, sizeof (*iodata));
|
|
|
@@ -470,10 +483,7 @@ SDL_IOStream *SDL_IOFromHandle(HANDLE handle, const char *mode, bool autoclose)
|
|
|
if (!iostr) {
|
|
|
iface.close(iodata);
|
|
|
} else {
|
|
|
- const SDL_PropertiesID props = SDL_GetIOProperties(iostr);
|
|
|
- if (props) {
|
|
|
- SDL_SetPointerProperty(props, SDL_PROP_IOSTREAM_WINDOWS_HANDLE_POINTER, iodata->h);
|
|
|
- }
|
|
|
+ iostr->setioprops = windows_setioprops;
|
|
|
}
|
|
|
|
|
|
return iostr;
|
|
|
@@ -636,6 +646,12 @@ static bool SDLCALL fd_close(void *userdata)
|
|
|
return status;
|
|
|
}
|
|
|
|
|
|
+static void fd_setioprops(SDL_PropertiesID props, void *userdata)
|
|
|
+{
|
|
|
+ const IOStreamFDData *iodata = (const IOStreamFDData *) userdata;
|
|
|
+ SDL_SetNumberProperty(props, SDL_PROP_IOSTREAM_FILE_DESCRIPTOR_NUMBER, iodata->fd);
|
|
|
+}
|
|
|
+
|
|
|
SDL_IOStream *SDL_IOFromFD(int fd, bool autoclose)
|
|
|
{
|
|
|
IOStreamFDData *iodata = (IOStreamFDData *) SDL_calloc(1, sizeof (*iodata));
|
|
|
@@ -662,10 +678,7 @@ SDL_IOStream *SDL_IOFromFD(int fd, bool autoclose)
|
|
|
if (!iostr) {
|
|
|
iface.close(iodata);
|
|
|
} else {
|
|
|
- const SDL_PropertiesID props = SDL_GetIOProperties(iostr);
|
|
|
- if (props) {
|
|
|
- SDL_SetNumberProperty(props, SDL_PROP_IOSTREAM_FILE_DESCRIPTOR_NUMBER, fd);
|
|
|
- }
|
|
|
+ iostr->setioprops = fd_setioprops;
|
|
|
}
|
|
|
|
|
|
return iostr;
|
|
|
@@ -834,6 +847,14 @@ static bool SDLCALL stdio_close(void *userdata)
|
|
|
return status;
|
|
|
}
|
|
|
|
|
|
+static void stdio_setioprops(SDL_PropertiesID props, void *userdata)
|
|
|
+{
|
|
|
+ const IOStreamStdioData *iodata = (const IOStreamStdioData *) userdata;
|
|
|
+ FILE *fp = iodata->fp;
|
|
|
+ SDL_SetPointerProperty(props, SDL_PROP_IOSTREAM_STDIO_FILE_POINTER, fp);
|
|
|
+ SDL_SetNumberProperty(props, SDL_PROP_IOSTREAM_FILE_DESCRIPTOR_NUMBER, fileno(fp));
|
|
|
+}
|
|
|
+
|
|
|
SDL_IOStream *SDL_IOFromFP(FILE *fp, bool autoclose)
|
|
|
{
|
|
|
IOStreamStdioData *iodata = (IOStreamStdioData *) SDL_calloc(1, sizeof (*iodata));
|
|
|
@@ -860,11 +881,7 @@ SDL_IOStream *SDL_IOFromFP(FILE *fp, bool autoclose)
|
|
|
if (!iostr) {
|
|
|
iface.close(iodata);
|
|
|
} else {
|
|
|
- const SDL_PropertiesID props = SDL_GetIOProperties(iostr);
|
|
|
- if (props) {
|
|
|
- SDL_SetPointerProperty(props, SDL_PROP_IOSTREAM_STDIO_FILE_POINTER, fp);
|
|
|
- SDL_SetNumberProperty(props, SDL_PROP_IOSTREAM_FILE_DESCRIPTOR_NUMBER, fileno(fp));
|
|
|
- }
|
|
|
+ iostr->setioprops = stdio_setioprops;
|
|
|
}
|
|
|
|
|
|
return iostr;
|
|
|
@@ -878,6 +895,7 @@ typedef struct IOStreamMemData
|
|
|
Uint8 *base;
|
|
|
Uint8 *here;
|
|
|
Uint8 *stop;
|
|
|
+ size_t size;
|
|
|
SDL_PropertiesID props;
|
|
|
} IOStreamMemData;
|
|
|
|
|
|
@@ -960,6 +978,15 @@ static bool SDLCALL mem_close(void *userdata)
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
+static void mem_setioprops(SDL_PropertiesID props, void *userdata)
|
|
|
+{
|
|
|
+ IOStreamMemData *iodata = (IOStreamMemData *) userdata;
|
|
|
+ SDL_SetPointerProperty(props, SDL_PROP_IOSTREAM_MEMORY_POINTER, iodata->base);
|
|
|
+ SDL_SetNumberProperty(props, SDL_PROP_IOSTREAM_MEMORY_SIZE_NUMBER, iodata->size);
|
|
|
+ SDL_assert(iodata->props == 0);
|
|
|
+ iodata->props = props;
|
|
|
+}
|
|
|
+
|
|
|
// Functions to create SDL_IOStream structures from various data sources
|
|
|
|
|
|
// private platforms might define SKIP_STDIO_DIR_TEST in their build configs, too.
|
|
|
@@ -977,6 +1004,13 @@ static bool IsStdioFileADirectory(FILE *f)
|
|
|
#define IsStdioFileADirectory(f) false
|
|
|
#endif
|
|
|
|
|
|
+#ifdef SDL_PLATFORM_ANDROID
|
|
|
+static void android_setioprops(SDL_PropertiesID props, void *userdata)
|
|
|
+{
|
|
|
+ SDL_SetPointerProperty(props, SDL_PROP_IOSTREAM_ANDROID_AASSET_POINTER, userdata);
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
SDL_IOStream *SDL_IOFromFile(const char *file, const char *mode)
|
|
|
{
|
|
|
SDL_IOStream *iostr = NULL;
|
|
|
@@ -1056,10 +1090,7 @@ SDL_IOStream *SDL_IOFromFile(const char *file, const char *mode)
|
|
|
if (!iostr) {
|
|
|
iface.close(iodata);
|
|
|
} else {
|
|
|
- const SDL_PropertiesID props = SDL_GetIOProperties(iostr);
|
|
|
- if (props) {
|
|
|
- SDL_SetPointerProperty(props, SDL_PROP_IOSTREAM_ANDROID_AASSET_POINTER, iodata);
|
|
|
- }
|
|
|
+ iostr->setioprops = android_setioprops;
|
|
|
}
|
|
|
|
|
|
#elif defined(SDL_PLATFORM_IOS)
|
|
|
@@ -1153,18 +1184,15 @@ SDL_IOStream *SDL_IOFromMem(void *mem, size_t size)
|
|
|
iodata->base = (Uint8 *)mem;
|
|
|
iodata->here = iodata->base;
|
|
|
iodata->stop = iodata->base + size;
|
|
|
+ iodata->size = size;
|
|
|
|
|
|
SDL_IOStream *iostr = SDL_OpenIO(&iface, iodata);
|
|
|
if (!iostr) {
|
|
|
SDL_free(iodata);
|
|
|
} else {
|
|
|
- const SDL_PropertiesID props = SDL_GetIOProperties(iostr);
|
|
|
- if (props) {
|
|
|
- iodata->props = props;
|
|
|
- SDL_SetPointerProperty(props, SDL_PROP_IOSTREAM_MEMORY_POINTER, mem);
|
|
|
- SDL_SetNumberProperty(props, SDL_PROP_IOSTREAM_MEMORY_SIZE_NUMBER, size);
|
|
|
- }
|
|
|
+ iostr->setioprops = mem_setioprops;
|
|
|
}
|
|
|
+
|
|
|
return iostr;
|
|
|
}
|
|
|
|
|
|
@@ -1196,19 +1224,15 @@ SDL_IOStream *SDL_IOFromConstMem(const void *mem, size_t size)
|
|
|
if (!iostr) {
|
|
|
SDL_free(iodata);
|
|
|
} else {
|
|
|
- const SDL_PropertiesID props = SDL_GetIOProperties(iostr);
|
|
|
- if (props) {
|
|
|
- iodata->props = props;
|
|
|
- SDL_SetPointerProperty(props, SDL_PROP_IOSTREAM_MEMORY_POINTER, (void *)mem);
|
|
|
- SDL_SetNumberProperty(props, SDL_PROP_IOSTREAM_MEMORY_SIZE_NUMBER, size);
|
|
|
- }
|
|
|
+ iostr->setioprops = mem_setioprops;
|
|
|
}
|
|
|
+
|
|
|
return iostr;
|
|
|
}
|
|
|
|
|
|
typedef struct IOStreamDynamicMemData
|
|
|
{
|
|
|
- SDL_IOStream *stream;
|
|
|
+ SDL_PropertiesID props;
|
|
|
IOStreamMemData data;
|
|
|
Uint8 *end;
|
|
|
} IOStreamDynamicMemData;
|
|
|
@@ -1237,7 +1261,7 @@ static size_t SDLCALL dynamic_mem_read(void *userdata, void *ptr, size_t size, S
|
|
|
|
|
|
static bool dynamic_mem_realloc(IOStreamDynamicMemData *iodata, size_t size)
|
|
|
{
|
|
|
- size_t chunksize = (size_t)SDL_GetNumberProperty(SDL_GetIOProperties(iodata->stream), SDL_PROP_IOSTREAM_DYNAMIC_CHUNKSIZE_NUMBER, 0);
|
|
|
+ size_t chunksize = (size_t)SDL_GetNumberProperty(iodata->props, SDL_PROP_IOSTREAM_DYNAMIC_CHUNKSIZE_NUMBER, 1024);
|
|
|
if (!chunksize) {
|
|
|
chunksize = 1024;
|
|
|
}
|
|
|
@@ -1256,7 +1280,7 @@ static bool dynamic_mem_realloc(IOStreamDynamicMemData *iodata, size_t size)
|
|
|
iodata->data.here = base + here_offset;
|
|
|
iodata->data.stop = base + stop_offset;
|
|
|
iodata->end = base + length;
|
|
|
- return SDL_SetPointerProperty(SDL_GetIOProperties(iodata->stream), SDL_PROP_IOSTREAM_DYNAMIC_MEMORY_POINTER, base);
|
|
|
+ return iodata->props ? SDL_SetPointerProperty(iodata->props, SDL_PROP_IOSTREAM_DYNAMIC_MEMORY_POINTER, base) : true;
|
|
|
}
|
|
|
|
|
|
static size_t SDLCALL dynamic_mem_write(void *userdata, const void *ptr, size_t size, SDL_IOStatus *status)
|
|
|
@@ -1279,12 +1303,20 @@ static size_t SDLCALL dynamic_mem_write(void *userdata, const void *ptr, size_t
|
|
|
static bool SDLCALL dynamic_mem_close(void *userdata)
|
|
|
{
|
|
|
const IOStreamDynamicMemData *iodata = (IOStreamDynamicMemData *) userdata;
|
|
|
- void *mem = SDL_GetPointerProperty(SDL_GetIOProperties(iodata->stream), SDL_PROP_IOSTREAM_DYNAMIC_MEMORY_POINTER, NULL);
|
|
|
+ void *mem = iodata->props ? SDL_GetPointerProperty(iodata->props, SDL_PROP_IOSTREAM_DYNAMIC_MEMORY_POINTER, NULL) : iodata->data.base;
|
|
|
SDL_free(mem);
|
|
|
SDL_free(userdata);
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
+static void dynamic_mem_setioprops(SDL_PropertiesID props, void *userdata)
|
|
|
+{
|
|
|
+ IOStreamDynamicMemData *iodata = (IOStreamDynamicMemData *) userdata;
|
|
|
+ SDL_SetPointerProperty(props, SDL_PROP_IOSTREAM_DYNAMIC_MEMORY_POINTER, iodata->data.base);
|
|
|
+ SDL_assert(iodata->props == 0);
|
|
|
+ iodata->props = props;
|
|
|
+}
|
|
|
+
|
|
|
SDL_IOStream *SDL_IOFromDynamicMem(void)
|
|
|
{
|
|
|
IOStreamDynamicMemData *iodata = (IOStreamDynamicMemData *) SDL_calloc(1, sizeof (*iodata));
|
|
|
@@ -1301,11 +1333,12 @@ SDL_IOStream *SDL_IOFromDynamicMem(void)
|
|
|
iface.close = dynamic_mem_close;
|
|
|
|
|
|
SDL_IOStream *iostr = SDL_OpenIO(&iface, iodata);
|
|
|
- if (iostr) {
|
|
|
- iodata->stream = iostr;
|
|
|
- } else {
|
|
|
+ if (!iostr) {
|
|
|
SDL_free(iodata);
|
|
|
+ } else {
|
|
|
+ iostr->setioprops = dynamic_mem_setioprops;
|
|
|
}
|
|
|
+
|
|
|
return iostr;
|
|
|
}
|
|
|
|
|
|
@@ -1496,6 +1529,10 @@ SDL_PropertiesID SDL_GetIOProperties(SDL_IOStream *context)
|
|
|
|
|
|
if (context->props == 0) {
|
|
|
context->props = SDL_CreateProperties();
|
|
|
+ if (context->props && context->setioprops) {
|
|
|
+ context->setioprops(context->props, context->userdata);
|
|
|
+ context->setioprops = NULL; // NULL so we don't try to set props again, just in case.
|
|
|
+ }
|
|
|
}
|
|
|
return context->props;
|
|
|
}
|