Sfoglia il codice sorgente

Added SDL_RWprintf() and SDL_RWvprintf() to do formatted printing to an SDL_rwops stream

Fixes https://github.com/libsdl-org/SDL/issues/2390
Sam Lantinga 1 anno fa
parent
commit
f9d11807c0

+ 45 - 0
include/SDL3/SDL_rwops.h

@@ -490,11 +490,56 @@ extern DECLSPEC size_t SDLCALL SDL_RWread(SDL_RWops *context, void *ptr, size_t
  * \sa SDL_RWFromConstMem
  * \sa SDL_RWFromFile
  * \sa SDL_RWFromMem
+ * \sa SDL_RWprint
  * \sa SDL_RWread
  * \sa SDL_RWseek
  */
 extern DECLSPEC size_t SDLCALL SDL_RWwrite(SDL_RWops *context, const void *ptr, size_t size);
 
+/**
+ * Print to an SDL_RWops data stream.
+ *
+ * This function does formatted printing to the stream.
+ *
+ * \param context a pointer to an SDL_RWops structure
+ * \param fmt a printf() style format string
+ * \param ... additional parameters matching % tokens in the `fmt` string, if any
+ * \returns the number of bytes written, or 0 on error; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 3.0.0.
+ *
+ * \sa SDL_RWclose
+ * \sa SDL_RWFromConstMem
+ * \sa SDL_RWFromFile
+ * \sa SDL_RWFromMem
+ * \sa SDL_RWread
+ * \sa SDL_RWseek
+ * \sa SDL_RWwrite
+ */
+extern DECLSPEC size_t SDLCALL SDL_RWprintf(SDL_RWops *context, SDL_PRINTF_FORMAT_STRING const char *fmt, ...);
+
+/**
+ * Print to an SDL_RWops data stream.
+ *
+ * This function does formatted printing to the stream.
+ *
+ * \param context a pointer to an SDL_RWops structure
+ * \param fmt a printf() style format string
+ * \param ap a variable argument list
+ * \returns the number of bytes written, or 0 on error; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 3.0.0.
+ *
+ * \sa SDL_RWclose
+ * \sa SDL_RWFromConstMem
+ * \sa SDL_RWFromFile
+ * \sa SDL_RWFromMem
+ * \sa SDL_RWread
+ * \sa SDL_RWseek
+ * \sa SDL_RWwrite
+ */
+extern DECLSPEC size_t SDLCALL SDL_RWvprintf(SDL_RWops *context, const char *fmt, va_list ap);
+
 /**
  * Close and free an allocated SDL_RWops structure.
  *

+ 20 - 0
src/dynapi/SDL_dynapi.c

@@ -144,6 +144,16 @@ static void SDL_InitDynamicAPI(void);
         va_end(ap);                                                                                                                       \
         return retval;                                                                                                                    \
     }                                                                                                                                     \
+    _static size_t SDLCALL SDL_RWprintf##name(SDL_RWops *context, SDL_PRINTF_FORMAT_STRING const char *fmt, ...)                          \
+    {                                                                                                                                     \
+        size_t retval;                                                                                                                    \
+        va_list ap;                                                                                                                       \
+        initcall;                                                                                                                         \
+        va_start(ap, fmt);                                                                                                                \
+        retval = jump_table.SDL_RWvprintf(context, fmt, ap);                                                                              \
+        va_end(ap);                                                                                                                       \
+        return retval;                                                                                                                    \
+    }                                                                                                                                     \
     _static void SDLCALL SDL_Log##name(SDL_PRINTF_FORMAT_STRING const char *fmt, ...)                                                     \
     {                                                                                                                                     \
         va_list ap;                                                                                                                       \
@@ -285,6 +295,16 @@ static int SDLCALL SDL_swprintf_LOGSDLCALLS(SDL_OUT_Z_CAP(maxlen) wchar_t *buf,
     va_end(ap);
     return retval;
 }
+_static size_t SDLCALL SDL_RWprintf_LOGSDLCALLS(SDL_RWops *context, SDL_PRINTF_FORMAT_STRING const char *fmt, ...)
+{
+    size_t retval;
+    va_list ap;
+    SDL_Log_REAL("SDL3CALL SDL_RWprintf");
+    va_start(ap, fmt);
+    retval = SDL_RWvprintf_REAL(context, fmt, ap);
+    va_end(ap);
+    return retval;
+}
 static void SDLCALL SDL_Log_LOGSDLCALLS(SDL_PRINTF_FORMAT_STRING const char *fmt, ...)
 {
     va_list ap;

+ 2 - 0
src/dynapi/SDL_dynapi.sym

@@ -922,6 +922,8 @@ SDL3_0.0.0 {
     SDL_ClearProperty;
     SDL_EnterAppMainCallbacks;
     SDL_CleanupEvent;
+    SDL_RWprintf;
+    SDL_RWvprintf;
     # extra symbols go here (don't modify this line)
   local: *;
 };

+ 2 - 0
src/dynapi/SDL_dynapi_overrides.h

@@ -947,3 +947,5 @@
 #define SDL_ClearProperty SDL_ClearProperty_REAL
 #define SDL_EnterAppMainCallbacks SDL_EnterAppMainCallbacks_REAL
 #define SDL_CleanupEvent SDL_CleanupEvent_REAL
+#define SDL_RWprintf SDL_RWprintf_REAL
+#define SDL_RWvprintf SDL_RWvprintf_REAL

+ 2 - 0
src/dynapi/SDL_dynapi_procs.h

@@ -43,6 +43,7 @@ SDL_DYNAPI_PROC(int,SDL_asprintf,(char **a, SDL_PRINTF_FORMAT_STRING const char
 SDL_DYNAPI_PROC(int,SDL_snprintf,(SDL_OUT_Z_CAP(b) char *a, size_t b, SDL_PRINTF_FORMAT_STRING const char *c, ...),(a,b,c),return)
 SDL_DYNAPI_PROC(int,SDL_swprintf,(SDL_OUT_Z_CAP(b) wchar_t *a, size_t b, SDL_PRINTF_FORMAT_STRING const wchar_t *c, ...),(a,b,c),return)
 SDL_DYNAPI_PROC(int,SDL_sscanf,(const char *a, SDL_SCANF_FORMAT_STRING const char *b, ...),(a,b),return)
+SDL_DYNAPI_PROC(size_t,SDL_RWprintf,(SDL_RWops *a, SDL_PRINTF_FORMAT_STRING const char *b, ...),(a,b),return)
 #endif
 
 #ifdef SDL_CreateThread
@@ -979,3 +980,4 @@ SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetWindowProperties,(SDL_Window *a),(a),ret
 SDL_DYNAPI_PROC(int,SDL_ClearProperty,(SDL_PropertiesID a, const char *b),(a,b),return)
 SDL_DYNAPI_PROC(int,SDL_EnterAppMainCallbacks,(int a, char *b[], SDL_AppInit_func c, SDL_AppIterate_func d, SDL_AppEvent_func e, SDL_AppQuit_func f),(a,b,c,d,e,f),return)
 SDL_DYNAPI_PROC(void,SDL_CleanupEvent,(SDL_Event *a),(a),)
+SDL_DYNAPI_PROC(size_t,SDL_RWvprintf,(SDL_RWops *a, const char *b, va_list c),(a,b,c),return)

+ 29 - 0
src/file/SDL_rwops.c

@@ -808,6 +808,35 @@ size_t SDL_RWwrite(SDL_RWops *context, const void *ptr, size_t size)
     return bytes;
 }
 
+size_t SDL_RWprintf(SDL_RWops *context, SDL_PRINTF_FORMAT_STRING const char *fmt, ...)
+{
+    va_list ap;
+    int size;
+    char *string = NULL;
+    size_t bytes;
+
+    va_start(ap, fmt);
+    size = SDL_vasprintf(&string, fmt, ap);
+    va_end(ap);
+
+    bytes = SDL_RWwrite(context, string, size);
+    SDL_free(string);
+    return bytes;
+}
+
+size_t SDL_RWvprintf(SDL_RWops *context, const char *fmt, va_list ap)
+{
+    int size;
+    char *string = NULL;
+    size_t bytes;
+
+    size = SDL_vasprintf(&string, fmt, ap);
+
+    bytes = SDL_RWwrite(context, string, size);
+    SDL_free(string);
+    return bytes;
+}
+
 int SDL_RWclose(SDL_RWops *context)
 {
     if (!context) {

+ 33 - 2
test/testautomation_rwops.c

@@ -110,11 +110,11 @@ static void testGenericRWopsValidations(SDL_RWops *rw, SDL_bool write)
     SDLTest_AssertPass("Call to SDL_RWseek succeeded");
     SDLTest_AssertCheck(i == (Sint64)0, "Verify seek to 0 with SDL_RWseek (SDL_RW_SEEK_SET), expected 0, got %" SDL_PRIs64, i);
 
-    /* Test write. */
+    /* Test write */
     s = SDL_RWwrite(rw, RWopsHelloWorldTestString, sizeof(RWopsHelloWorldTestString) - 1);
     SDLTest_AssertPass("Call to SDL_RWwrite succeeded");
     if (write) {
-        SDLTest_AssertCheck(s == sizeof(RWopsHelloWorldTestString) - 1, "Verify result of writing one byte with SDL_RWwrite, expected 1, got %i", (int)s);
+        SDLTest_AssertCheck(s == sizeof(RWopsHelloWorldTestString) - 1, "Verify result of writing with SDL_RWwrite, expected %i, got %i", (int)sizeof(RWopsHelloWorldTestString) - 1, (int)s);
     } else {
         SDLTest_AssertCheck(s == 0, "Verify result of writing with SDL_RWwrite, expected: 0, got %i", (int)s);
     }
@@ -129,6 +129,37 @@ static void testGenericRWopsValidations(SDL_RWops *rw, SDL_bool write)
     SDLTest_AssertPass("Call to SDL_RWseek succeeded");
     SDLTest_AssertCheck(i == (Sint64)0, "Verify seek to 0 with SDL_RWseek (SDL_RW_SEEK_SET), expected 0, got %" SDL_PRIs64, i);
 
+    /* Test read */
+    s = SDL_RWread(rw, buf, sizeof(RWopsHelloWorldTestString) - 1);
+    SDLTest_AssertPass("Call to SDL_RWread succeeded");
+    SDLTest_AssertCheck(
+        s == (sizeof(RWopsHelloWorldTestString) - 1),
+        "Verify result from SDL_RWread, expected %i, got %i",
+        (int)(sizeof(RWopsHelloWorldTestString) - 1),
+        (int)s);
+    SDLTest_AssertCheck(
+        SDL_memcmp(buf, RWopsHelloWorldTestString, sizeof(RWopsHelloWorldTestString) - 1) == 0,
+        "Verify read bytes match expected string, expected '%s', got '%s'", RWopsHelloWorldTestString, buf);
+
+    /* Test seek back to start */
+    i = SDL_RWseek(rw, 0, SDL_RW_SEEK_SET);
+    SDLTest_AssertPass("Call to SDL_RWseek succeeded");
+    SDLTest_AssertCheck(i == (Sint64)0, "Verify seek to 0 with SDL_RWseek (SDL_RW_SEEK_SET), expected 0, got %" SDL_PRIs64, i);
+
+    /* Test printf */
+    s = SDL_RWprintf(rw, "%s", RWopsHelloWorldTestString);
+    SDLTest_AssertPass("Call to SDL_RWprintf succeeded");
+    if (write) {
+        SDLTest_AssertCheck(s == sizeof(RWopsHelloWorldTestString) - 1, "Verify result of writing with SDL_RWprintf, expected %i, got %i", (int)sizeof(RWopsHelloWorldTestString) - 1, (int)s);
+    } else {
+        SDLTest_AssertCheck(s == 0, "Verify result of writing with SDL_RWwrite, expected: 0, got %i", (int)s);
+    }
+
+    /* Test seek back to start */
+    i = SDL_RWseek(rw, 0, SDL_RW_SEEK_SET);
+    SDLTest_AssertPass("Call to SDL_RWseek succeeded");
+    SDLTest_AssertCheck(i == (Sint64)0, "Verify seek to 0 with SDL_RWseek (SDL_RW_SEEK_SET), expected 0, got %" SDL_PRIs64, i);
+
     /* Test read */
     s = SDL_RWread(rw, buf, sizeof(RWopsHelloWorldTestString) - 1);
     SDLTest_AssertPass("Call to SDL_RWread succeeded");