From ff6f3ec70f1c04dc7c210aab17fd9787e50b6516 Mon Sep 17 00:00:00 2001
From: "Ryan C. Gordon" <[EMAIL REDACTED]>
Date: Fri, 25 Nov 2022 17:06:51 -0500
Subject: [PATCH] Implemented SDL_RWFromFP, removed from SDL3.
---
src/sdl2_compat.c | 126 +++++++++++++++++++++++++++++++++++++
src/sdl3_include_wrapper.h | 10 ---
src/sdl3_syms.h | 6 --
3 files changed, 126 insertions(+), 16 deletions(-)
diff --git a/src/sdl2_compat.c b/src/sdl2_compat.c
index d716573..f5c2255 100644
--- a/src/sdl2_compat.c
+++ b/src/sdl2_compat.c
@@ -49,10 +49,12 @@
#define WIN32_LEAN_AND_MEAN 1
#endif
#include <windows.h>
+#define HAVE_STDIO_H 0 /* !!! FIXME: we _currently_ don't include stdio.h on windows. Should we? */
#else
#include <stdio.h> /* fprintf(), etc. */
#include <stdlib.h> /* for abort() */
#include <string.h>
+#define HAVE_STDIO_H 1
#endif
/* mingw headers may define these ... */
@@ -509,6 +511,130 @@ SDL_snprintf(char *text, size_t maxlen, const char *fmt, ...)
return retval;
}
+
+#if !HAVE_STDIO_H
+DECLSPEC SDL_RWops * SDLCALL
+SDL_RWFromFP(void *fp, SDL_bool autoclose)
+{
+ SDL3_SetError("SDL not compiled with stdio support");
+ return NULL;
+}
+#else
+
+/* !!! FIXME: SDL2 has a bunch of macro salsa to try and use the most 64-bit
+fseek, etc, and I'm avoiding that for now; this can change if it becomes a
+problem. --ryan. */
+
+/* Functions to read/write stdio file pointers */
+
+static Sint64 SDLCALL
+stdio_size(SDL_RWops * context)
+{
+ Sint64 pos, size;
+
+ pos = SDL3_RWseek(context, 0, RW_SEEK_CUR);
+ if (pos < 0) {
+ return -1;
+ }
+ size = SDL3_RWseek(context, 0, RW_SEEK_END);
+
+ SDL3_RWseek(context, pos, RW_SEEK_SET);
+ return size;
+}
+
+static Sint64 SDLCALL
+stdio_seek(SDL_RWops * context, Sint64 offset, int whence)
+{
+ int stdiowhence;
+
+ switch (whence) {
+ case RW_SEEK_SET:
+ stdiowhence = SEEK_SET;
+ break;
+ case RW_SEEK_CUR:
+ stdiowhence = SEEK_CUR;
+ break;
+ case RW_SEEK_END:
+ stdiowhence = SEEK_END;
+ break;
+ default:
+ return SDL3_SetError("Unknown value for 'whence'");
+ }
+
+#if defined(FSEEK_OFF_MIN) && defined(FSEEK_OFF_MAX)
+ if (offset < (Sint64)(FSEEK_OFF_MIN) || offset > (Sint64)(FSEEK_OFF_MAX)) {
+ return SDL3_SetError("Seek offset out of range");
+ }
+#endif
+
+ if (fseek(context->hidden.stdio.fp, (long)offset, stdiowhence) == 0) {
+ Sint64 pos = ftell(context->hidden.stdio.fp);
+ if (pos < 0) {
+ return SDL3_SetError("Couldn't get stream offset");
+ }
+ return pos;
+ }
+ return SDL3_Error(SDL_EFSEEK);
+}
+
+static size_t SDLCALL
+stdio_read(SDL_RWops * context, void *ptr, size_t size, size_t maxnum)
+{
+ size_t nread;
+
+ nread = fread(ptr, size, maxnum, context->hidden.stdio.fp);
+ if (nread == 0 && ferror(context->hidden.stdio.fp)) {
+ SDL3_Error(SDL_EFREAD);
+ }
+ return nread;
+}
+
+static size_t SDLCALL
+stdio_write(SDL_RWops * context, const void *ptr, size_t size, size_t num)
+{
+ size_t nwrote;
+
+ nwrote = fwrite(ptr, size, num, context->hidden.stdio.fp);
+ if (nwrote == 0 && ferror(context->hidden.stdio.fp)) {
+ SDL3_Error(SDL_EFWRITE);
+ }
+ return nwrote;
+}
+
+static int SDLCALL
+stdio_close(SDL_RWops * context)
+{
+ int status = 0;
+ if (context) {
+ if (context->hidden.stdio.autoclose) {
+ /* WARNING: Check the return value here! */
+ if (fclose(context->hidden.stdio.fp) != 0) {
+ status = SDL3_Error(SDL_EFWRITE);
+ }
+ }
+ SDL3_FreeRW(context);
+ }
+ return status;
+}
+
+DECLSPEC SDL_RWops * SDLCALL
+SDL_RWFromFP(FILE *fp, SDL_bool autoclose)
+{
+ SDL_RWops *rwops = SDL3_AllocRW();
+ if (rwops != NULL) {
+ rwops->size = stdio_size;
+ rwops->seek = stdio_seek;
+ rwops->read = stdio_read;
+ rwops->write = stdio_write;
+ rwops->close = stdio_close;
+ rwops->hidden.stdio.fp = fp;
+ rwops->hidden.stdio.autoclose = autoclose;
+ rwops->type = SDL_RWOPS_STDFILE;
+ }
+ return rwops;
+}
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/src/sdl3_include_wrapper.h b/src/sdl3_include_wrapper.h
index 43121ab..6d78700 100644
--- a/src/sdl3_include_wrapper.h
+++ b/src/sdl3_include_wrapper.h
@@ -277,8 +277,6 @@
#define SDL_LoadFunction IGNORE_THIS_VERSION_OF_SDL_LoadFunction
#define SDL_UnloadObject IGNORE_THIS_VERSION_OF_SDL_UnloadObject
#define SDL_RWFromFile IGNORE_THIS_VERSION_OF_SDL_RWFromFile
-#define SDL_RWFromFP IGNORE_THIS_VERSION_OF_SDL_RWFromFP
-#define SDL_RWFromFP IGNORE_THIS_VERSION_OF_SDL_RWFromFP
#define SDL_RWFromMem IGNORE_THIS_VERSION_OF_SDL_RWFromMem
#define SDL_RWFromConstMem IGNORE_THIS_VERSION_OF_SDL_RWFromConstMem
#define SDL_AllocRW IGNORE_THIS_VERSION_OF_SDL_AllocRW
@@ -1927,14 +1925,6 @@ typedef void (__cdecl *pfnSDL_CurrentEndThread) (unsigned);
#undef SDL_RWFromFile
#endif
-#ifdef SDL_RWFromFP
-#undef SDL_RWFromFP
-#endif
-
-#ifdef SDL_RWFromFP
-#undef SDL_RWFromFP
-#endif
-
#ifdef SDL_RWFromMem
#undef SDL_RWFromMem
#endif
diff --git a/src/sdl3_syms.h b/src/sdl3_syms.h
index 64e1a48..c891aff 100644
--- a/src/sdl3_syms.h
+++ b/src/sdl3_syms.h
@@ -60,12 +60,6 @@ SDL3_SYM_PASSTHROUGH(SDL_Thread*,CreateThread,(SDL_ThreadFunction a, const char
SDL3_SYM_PASSTHROUGH(SDL_Thread*,CreateThread,(SDL_ThreadFunction a, const char *b, void *c),(a,b,c),return)
#endif
-#ifdef HAVE_STDIO_H
-SDL3_SYM_PASSTHROUGH(SDL_RWops*,RWFromFP,(FILE *a, SDL_bool b),(a,b),return)
-#else
-SDL3_SYM_PASSTHROUGH(SDL_RWops*,RWFromFP,(void *a, SDL_bool b),(a,b),return)
-#endif
-
#if defined(__WIN32__) || defined(__GDK__)
SDL3_SYM_PASSTHROUGH(int,RegisterApp,(const char *a, Uint32 b, void *c),(a,b,c),return)
SDL3_SYM_PASSTHROUGH(void,UnregisterApp,(void),(),)