SDL: SDL_rwops read/write functions return size_t again

From b903ccf945a75266ebcba2df68da3b796a71e75d Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Sun, 6 Aug 2023 13:51:03 -0700
Subject: [PATCH] SDL_rwops read/write functions return size_t again

The current status is stored in the SDL_rwops 'status' field to be able to determine whether a 0 return value is caused by end of file, an error, or a non-blocking source not being ready.

The functions to read sized datatypes now return SDL_bool so you can detect read errors.

Fixes https://github.com/libsdl-org/SDL/issues/6729
---
 build-scripts/SDL_migration.cocci |  60 ++++
 docs/README-migration.md          |  92 +++--
 include/SDL3/SDL_gamepad.h        |   5 +-
 include/SDL3/SDL_oldnames.h       |  24 ++
 include/SDL3/SDL_rwops.h          | 367 +++++++++++++-------
 include/SDL3/SDL_surface.h        |   5 +-
 src/audio/SDL_wave.c              |  39 ++-
 src/audio/disk/SDL_diskaudio.c    |   4 +-
 src/core/android/SDL_android.c    |  11 +-
 src/core/android/SDL_android.h    |   4 +-
 src/dynapi/SDL_dynapi.sym         |  35 +-
 src/dynapi/SDL_dynapi_overrides.h |  35 +-
 src/dynapi/SDL_dynapi_procs.h     |  47 ++-
 src/file/SDL_rwops.c              | 536 +++++++++++++++++++-----------
 src/joystick/SDL_gamepad.c        |  28 +-
 src/video/SDL_bmp.c               | 297 ++++++++++-------
 test/testautomation_rwops.c       | 104 +++---
 test/testfile.c                   | 120 +++----
 test/testime.c                    |  11 +-
 test/testresample.c               |  26 +-
 20 files changed, 1125 insertions(+), 725 deletions(-)

diff --git a/build-scripts/SDL_migration.cocci b/build-scripts/SDL_migration.cocci
index be10b4b17f0f..32e24084f028 100644
--- a/build-scripts/SDL_migration.cocci
+++ b/build-scripts/SDL_migration.cocci
@@ -2690,3 +2690,63 @@ typedef SDL_cond, SDL_Condition;
 - SDL_strtokr
 + SDL_strtok_r
   (...)
+@@
+@@
+- SDL_ReadLE16
++ SDL_ReadU16LE
+  (...)
+@@
+@@
+- SDL_ReadLE32
++ SDL_ReadU32LE
+  (...)
+@@
+@@
+- SDL_ReadBE32
++ SDL_ReadU32BE
+  (...)
+@@
+@@
+- SDL_ReadBE16
++ SDL_ReadU16BE
+  (...)
+@@
+@@
+- SDL_ReadLE64
++ SDL_ReadU64LE
+  (...)
+@@
+@@
+- SDL_ReadBE64
++ SDL_ReadU64BE
+  (...)
+@@
+@@
+- SDL_WriteLE16
++ SDL_WriteU16LE
+  (...)
+@@
+@@
+- SDL_WriteBE16
++ SDL_WriteU16BE
+  (...)
+@@
+@@
+- SDL_WriteLE32
++ SDL_WriteU32LE
+  (...)
+@@
+@@
+- SDL_WriteBE32
++ SDL_WriteU32BE
+  (...)
+@@
+@@
+- SDL_WriteLE64
++ SDL_WriteU64LE
+  (...)
+@@
+@@
+- SDL_WriteBE64
++ SDL_WriteU64BE
+  (...)
diff --git a/docs/README-migration.md b/docs/README-migration.md
index 70704d127abf..dc34559f9c25 100644
--- a/docs/README-migration.md
+++ b/docs/README-migration.md
@@ -910,33 +910,26 @@ size_t SDL_RWwrite(SDL_RWops *context, const void *ptr, size_t size, size_t maxn
 But now they look more like POSIX:
 
 ```c
-Sint64 SDL_RWread(SDL_RWops *context, void *ptr, Sint64 size);
-Sint64 SDL_RWwrite(SDL_RWops *context, const void *ptr, Sint64 size);
+size_t SDL_RWread(SDL_RWops *context, void *ptr, size_t size);
+size_t SDL_RWwrite(SDL_RWops *context, const void *ptr, size_t size);

-SDL_RWread() previously returned 0 at end of file or other error. Now it returns the number of bytes read, 0 for end of file, -1 for another error, or -2 for data not ready (in the case of a non-blocking context).

Code that used to look like this:

size_t custom_read(void *ptr, size_t size, size_t nitems, SDL_RWops *stream)
{
-    return (size_t)SDL_RWread(stream, ptr, size, nitems);
+    return SDL_RWread(stream, ptr, size, nitems);
}

should be changed to:

size_t custom_read(void *ptr, size_t size, size_t nitems, SDL_RWops *stream)
{
-    Sint64 amount = SDL_RWread(stream, ptr, size * nitems);
-    if (amount <= 0) {
-        return 0;
-    }
-    return (size_t)(amount / size);
+    size_t bytes = SDL_RWread(stream, ptr, size * nitems);
+    return (bytes / size);
}

-Similarly, SDL_RWwrite() can return -2 for data not ready in the case of a non-blocking context. There is currently no way to create a non-blocking context, we have simply defined the semantic for your own custom SDL_RWops object.

SDL_RWFromFP has been removed from the API, due to issues when the SDL library uses a different C runtime from the application.

You can implement this in your own code easily:
@@ -944,23 +937,7 @@ You can implement this in your own code easily:
#include <stdio.h>

-static Sint64 SDLCALL
-stdio_size(SDL_RWops * context)
-{

  • Sint64 pos, size;
  • pos = SDL_RWseek(context, 0, SDL_RW_SEEK_CUR);
  • if (pos < 0) {
  •    return -1;
    
  • }
  • size = SDL_RWseek(context, 0, SDL_RW_SEEK_END);
  • SDL_RWseek(context, pos, SDL_RW_SEEK_SET);
  • return size;
    -}

-static Sint64 SDLCALL
-stdio_seek(SDL_RWops * context, Sint64 offset, int whence)
+static Sint64 SDLCALL stdio_seek(SDL_RWops *context, Sint64 offset, int whence)
{
int stdiowhence;

@@ -988,54 +965,46 @@ stdio_seek(SDL_RWops * context, Sint64 offset, int whence)
return SDL_Error(SDL_EFSEEK);
}

-static Sint64 SDLCALL
-stdio_read(SDL_RWops * context, void *ptr, Sint64 size)
+static size_t SDLCALL stdio_read(SDL_RWops *context, void *ptr, size_t size)
{

  • size_t nread;
  • size_t bytes;
  • nread = fread(ptr, 1, (size_t) size, (FILE *)context->hidden.stdio.fp);
  • if (nread == 0 && ferror((FILE *)context->hidden.stdio.fp)) {
  •    return SDL_Error(SDL_EFREAD);
    
  • bytes = fread(ptr, 1, size, (FILE *)context->hidden.stdio.fp);
  • if (bytes == 0 && ferror((FILE *)context->hidden.stdio.fp)) {
  •    SDL_Error(SDL_EFREAD);
    
    }
  • return (Sint64) nread;
  • return bytes;
    }

-static Sint64 SDLCALL
-stdio_write(SDL_RWops * context, const void *ptr, Sint64 size)
+static size_t SDLCALL stdio_write(SDL_RWops *context, const void *ptr, size_t size)
{

  • size_t nwrote;
  • size_t bytes;
  • nwrote = fwrite(ptr, 1, (size_t) size, (FILE *)context->hidden.stdio.fp);
  • if (nwrote == 0 && ferror((FILE *)context->hidden.stdio.fp)) {
  •    return SDL_Error(SDL_EFWRITE);
    
  • bytes = fwrite(ptr, 1, size, (FILE *)context->hidden.stdio.fp);
  • if (bytes == 0 && ferror((FILE *)context->hidden.stdio.fp)) {
  •    SDL_Error(SDL_EFWRITE);
    
    }
  • return (Sint64) nwrote;
  • return bytes;
    }

-static int SDLCALL
-stdio_close(SDL_RWops * context)
+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((FILE *)context->hidden.stdio.fp) != 0) {
    
  •            status = SDL_Error(SDL_EFWRITE);
    
  •        }
    
  • if (context->hidden.stdio.autoclose) {
  •    if (fclose((FILE *)context->hidden.stdio.fp) != 0) {
    
  •        status = SDL_Error(SDL_EFWRITE);
       }
    
  •    SDL_DestroyRW(context);
    
    }
  • SDL_DestroyRW(context);
    return status;
    }

-SDL_RWops *
-SDL_RWFromFP(void *fp, SDL_bool autoclose)
+SDL_RWops *SDL_RWFromFP(void *fp, SDL_bool autoclose)
{
SDL_RWops *rwops = NULL;

 rwops = SDL_CreateRW();
 if (rwops != NULL) {
  •    rwops->size = stdio_size;
       rwops->seek = stdio_seek;
       rwops->read = stdio_read;
       rwops->write = stdio_write;
    

@@ -1048,10 +1017,23 @@ SDL_RWFromFP(void *fp, SDL_bool autoclose)
}


+The functions SDL_ReadU8(), SDL_ReadU16LE(), SDL_ReadU16BE(), SDL_ReadU32LE(), SDL_ReadU32BE(), SDL_ReadU64LE(), and SDL_ReadU64BE() now return SDL_TRUE if the read succeeded and SDL_FALSE if it didn't, and store the data in a pointer passed in as a parameter.

The following functions have been renamed:
* SDL_AllocRW() => SDL_CreateRW()
* SDL_FreeRW() => SDL_DestroyRW()
+* SDL_ReadBE16() => SDL_ReadU16BE()
+* SDL_ReadBE32() => SDL_ReadU32BE()
+* SDL_ReadBE64() => SDL_ReadU64BE()
+* SDL_ReadLE16() => SDL_ReadU16LE()
+* SDL_ReadLE32() => SDL_ReadU32LE()
+* SDL_ReadLE64() => SDL_ReadU64LE()
+* SDL_WriteBE16() => SDL_WriteU16BE()
+* SDL_WriteBE32() => SDL_WriteU32BE()
+* SDL_WriteBE64() => SDL_WriteU64BE()
+* SDL_WriteLE16() => SDL_WriteU16LE()
+* SDL_WriteLE32() => SDL_WriteU32LE()
+* SDL_WriteLE64() => SDL_WriteU64LE()

## SDL_sensor.h

diff --git a/include/SDL3/SDL_gamepad.h b/include/SDL3/SDL_gamepad.h
index e74160a17dd7..4e9caad822ac 100644
--- a/include/SDL3/SDL_gamepad.h
+++ b/include/SDL3/SDL_gamepad.h
@@ -176,7 +176,8 @@ extern DECLSPEC int SDLCALL SDL_AddGamepadMapping(const char *mapping);
 * constrained environment.
 *
 * \param src the data stream for the mappings to be added
- * \param freesrc non-zero to close the stream after being read
+ * \param freesrc if SDL_TRUE, calls SDL_RWclose() on `src` before returning,
+ *                even in the case of an error
 * \returns the number of mappings added or -1 on error; call SDL_GetError()
 *          for more information.
 *
@@ -186,7 +187,7 @@ extern DECLSPEC int SDLCALL SDL_AddGamepadMapping(const char *mapping);
 * \sa SDL_AddGamepadMappingsFromFile
 * \sa SDL_GetGamepadMappingForGUID
 */
-extern DECLSPEC int SDLCALL SDL_AddGamepadMappingsFromRW(SDL_RWops *src, int freesrc);
+extern DECLSPEC int SDLCALL SDL_AddGamepadMappingsFromRW(SDL_RWops *src, SDL_bool freesrc);

/**
 * Load a set of gamepad mappings from a file.
diff --git a/include/SDL3/SDL_oldnames.h b/include/SDL3/SDL_oldnames.h
index 494f5669f93d..ff5f888a8467 100644
--- a/include/SDL3/SDL_oldnames.h
+++ b/include/SDL3/SDL_oldnames.h
@@ -423,6 +423,18 @@
#define RW_SEEK_SET SDL_RW_SEEK_SET
#define SDL_AllocRW SDL_CreateRW
#define SDL_FreeRW SDL_DestroyRW
+#define SDL_ReadBE16 SDL_ReadU16BE
+#define SDL_ReadBE32 SDL_ReadU32BE
+#define SDL_ReadBE64 SDL_ReadU64BE
+#define SDL_ReadLE16 SDL_ReadU16LE
+#define SDL_ReadLE32 SDL_ReadU32LE
+#define SDL_ReadLE64 SDL_ReadU64LE
+#define SDL_WriteBE16 SDL_WriteU16BE
+#define SDL_WriteBE32 SDL_WriteU32BE
+#define SDL_WriteBE64 SDL_WriteU64BE
+#define SDL_WriteLE16 SDL_WriteU16LE
+#define SDL_WriteLE32 SDL_WriteU32LE
+#define SDL_WriteLE64 SDL_WriteU64LE

/* ##SDL_sensor.h */
#define SDL_SensorClose SDL_CloseSensor
@@ -863,6 +875,18 @@
#define RW_SEEK_SET RW_SEEK_SET_renamed_SDL_RW_SEEK_SET
#define SDL_AllocRW SDL_AllocRW_renamed_SDL_CreateRW
#define SDL_FreeRW SDL_FreeRW_renamed_SDL_DestroyRW
+#define SDL_ReadBE16 SDL_ReadBE16_renamed_SDL_ReadU16BE
+#define SDL_ReadBE32 SDL_ReadBE32_renamed_SDL_ReadU32BE
+#define SDL_ReadBE64 SDL_ReadBE64_renamed_SDL_ReadU64BE
+#define SDL_ReadLE16 SDL_ReadLE16_renamed_SDL_ReadU16LE
+#define SDL_ReadLE32 SDL_ReadLE32_renamed_SDL_ReadU32LE
+#define SDL_ReadLE64 SDL_ReadLE64_renamed_SDL_ReadU64LE
+#define SDL_WriteBE16 SDL_WriteBE16_renamed_SDL_WriteU16BE
+#define SDL_WriteBE32 SDL_WriteBE32_renamed_SDL_WriteU32BE
+#define SDL_WriteBE64 SDL_WriteBE64_renamed_SDL_WriteU64BE
+#define SDL_WriteLE16 SDL_WriteLE16_renamed_SDL_WriteU16LE
+#define SDL_WriteLE32 SDL_WriteLE32_renamed_SDL_WriteU32LE
+#define SDL_WriteLE64 SDL_WriteLE64_renamed_SDL_WriteU64LE

/* ##SDL_sensor.h */
#define SDL_SensorClose SDL_SensorClose_renamed_SDL_CloseSensor
diff --git a/include/SDL3/SDL_rwops.h b/include/SDL3/SDL_rwops.h
index b3bc41c19978..82b72dbb7ab1 100644
--- a/include/SDL3/SDL_rwops.h
+++ b/include/SDL3/SDL_rwops.h
@@ -38,13 +38,21 @@
extern "C" {
#endif

-/* RWops Types */
-#define SDL_RWOPS_UNKNOWN   0U  /**< Unknown stream type */
-#define SDL_RWOPS_WINFILE   1U  /**< Win32 file */
-#define SDL_RWOPS_STDFILE   2U  /**< Stdio file */
-#define SDL_RWOPS_JNIFILE   3U  /**< Android asset */
-#define SDL_RWOPS_MEMORY    4U  /**< Memory stream */
-#define SDL_RWOPS_MEMORY_RO 5U  /**< Read-Only memory stream */
+/* RWops types */
+#define SDL_RWOPS_UNKNOWN   0   /**< Unknown stream type */
+#define SDL_RWOPS_WINFILE   1   /**< Win32 file */
+#define SDL_RWOPS_STDFILE   2   /**< Stdio file */
+#define SDL_RWOPS_JNIFILE   3   /**< Android asset */
+#define SDL_RWOPS_MEMORY    4   /**< Memory stream */
+#define SDL_RWOPS_MEMORY_RO 5   /**< Read-Only memory stream */
+
+/* RWops status, set by a read or write operation */
+#define SDL_RWOPS_STATUS_READY          0   /**< Everything is ready */
+#define SDL_RWOPS_STATUS_ERROR          1   /**< Read or write I/O error */
+#define SDL_RWOPS_STATUS_EOF            2   /**< End of file */
+#define SDL_RWOPS_STATUS_NOT_READY      3   /**< Non blocking I/O, not ready */
+#define SDL_RWOPS_STATUS_READONLY       4   /**< Tried to write a read-only buffer */
+#define SDL_RWOPS_STATUS_WRITEONLY      5   /**< Tried to read a write-only buffer */

/**
 * This is the read/write operation structure -- very basic.
@@ -52,9 +60,11 @@ extern "C" {
typedef struct SDL_RWops
{
    /**
-     *  Return the size of the file in this rwops, or -1 if unknown
+     *  Return the number of bytes in this rwops
+     *
+     *  \return the total size of the data stream, or -1 on error.
     */
-    Sint64 (SDLCALL * size) (struct SDL_RWops * context);
+    Sint64 (SDLCALL *size)(struct SDL_RWops *context);

    /**
     *  Seek to \c offset relative to \c whence, one of stdio's whence values:
@@ -62,45 +72,33 @@ typedef struct SDL_RWops
     *
     *  \return the final offset in the data stream, or -1 on error.
     */
-    Sint64 (SDLCALL * seek) (struct SDL_RWops * context, Sint64 offset,
-                             int whence);
+    Sint64 (SDLCALL *seek)(struct SDL_RWops *context, Sint64 offset, int whence);

    /**
     *  Read up to \c size bytes from the data stream to the area pointed
     *  at by \c ptr.
     *
-     *  It is an error to use a negative \c size, but this parameter is
-     *  signed so you definitely cannot overflow the return value on a
-     *  successful run with enormous amounts of data.
-     *
-     *  \return the number of objects read, or 0 on end of file, or -1 on error.
+     *  \return the number of bytes read
     */
-    Sint64 (SDLCALL * read) (struct SDL_RWops * context, void *ptr,
-                             Sint64 size);
+    size_t (SDLCALL *read)(struct SDL_RWops *context, void *ptr, size_t size);

    /**
     *  Write exactly \c size bytes from the area pointed at by \c ptr
-     *  to data stream. May write less than requested (error, non-blocking i/o,
-     *  etc). Returns -1 on error when nothing was written.
-     *
-     *  It is an error to use a negative \c size, but this parameter is
-     *  signed so you definitely cannot overflow the return value on a
-     *  successful run with enormous amounts of data.
+     *  to data stream.
     *
-     *  \return the number of bytes written, which might be less than \c size,
-     *          and -1 on error.
+     *  \return the number of bytes written
     */
-    Sint64 (SDLCALL * write) (struct SDL_RWops * context, const void *ptr,
-                              Sint64 size);
+    size_t (SDLCALL *write)(struct SDL_RWops *context, const void *ptr, size_t size);

    /**
     *  Close and free an allocated SDL_RWops structure.
     *
     *  \return 0 if successful or -1 on write error when flushing data.
     */
-    int (SDLCALL * close) (struct SDL_RWops * context);
+    int (SDLCALL *close)(struct SDL_RWops *context);

    Uint32 type;
+    Uint32 status;
    union
    {
#ifdef __ANDROID__
@@ -213,8 +211,7 @@ typedef struct SDL_RWops
 * \sa SDL_RWtell
 * \sa SDL_RWwrite
 */
-extern DECLSPEC SDL_RWops *SDLCALL SDL_RWFromFile(const char *file,
-                                                  const char *mode);
+extern DECLSPEC SDL_RWops *SDLCALL SDL_RWFromFile(const char *file, const char *mode);

/**
 * Use this function to prepare a read-write memory buffer for use with
@@ -279,8 +276,7 @@ extern DECLSPEC SDL_RWops *SDLCALL SDL_RWFromMem(void *mem, size_t size);
 * \sa SDL_RWseek
 * \sa SDL_RWtell
 */
-extern DECLSPEC SDL_RWops *SDLCALL SDL_RWFromConstMem(const void *mem,
-                                                      size_t size);
+extern DECLSPEC SDL_RWops *SDLCALL SDL_RWFromConstMem(const void *mem, size_t size);

/* @} *//* RWFrom functions */

@@ -289,7 +285,7 @@ extern DECLSPEC SDL_RWops *SDLCALL SDL_RWFromConstMem(const void *mem,
 * Use this function to allocate an empty, unpopulated SDL_RWops structure.
 *
 * Applications do not need to use this function unless they are providing
- * their own SDL_RWops implementation. If you just need a SDL_RWops to
+ * their own SDL_RWops implementation. If you just need an SDL_RWops to
 * read/write a common data source, you should use the built-in
 * implementations in SDL, like SDL_RWFromFile() or SDL_RWFromMem(), etc.
 *
@@ -315,7 +311,7 @@ extern DECLSPEC SDL_RWops *SDLCALL SDL_CreateRW(void);
 * SDL_CreateRW().
 *
 * Applications do not need to use this function unless they are providing
- * their own SDL_RWops implementation. If you just need a SDL_RWops to
+ * their own SDL_RWops implementation. If you just need an SDL_RWops to
 * read/write a common data source, you should use the built-in
 * implementations in SDL, like SDL_RWFromFile() or SDL_RWFromMem(), etc, and
 * call the **close** method on those SDL_RWops pointers when you are done
@@ -327,13 +323,13 @@ extern DECLSPEC SDL_RWops *SDLCALL SDL_CreateRW(void);
 * the programmer must be responsible for managing that memory in their
 * **close** method.
 *
- * \param area the SDL_RWops structure to be freed
+ * \param context the SDL_RWops structure to be freed
 *
 * \since This function is available since SDL 3.0.0.
 *
 * \sa SDL_CreateRW
 */
-extern DECLSPEC void SDLCALL SDL_DestroyRW(SDL_RWops * area);
+extern DECLSPEC void SDLCALL SDL_DestroyRW(SDL_RWops *context);

#define SDL_RW_SEEK_SET 0       /**< Seek from the beginning of data */
#define SDL_RW_SEEK_CUR 1       /**< Seek relative to current read point */
@@ -342,12 +338,8 @@ extern DECLSPEC void SDLCALL SDL_DestroyRW(SDL_RWops * area);
/**
 * Use this function to get the size of the data stream in an SDL_RWops.
 *
- * Prior to SDL 2.0.10, this function was a macro.
- *
 * \param context the SDL_RWops to get the size of the data stream from
- * \returns the size of the data stream in the SDL_RWops on success, -1 if
- *          unknown or a negative error code on failure; call SDL_GetError()
- *          for more information.
+ * \returns the size of the data stream in the SDL_RWops on success or a negative error code on failure; call SDL_GetError() for more information.
 *
 * \since This function is available since SDL 3.0.0.
 */
@@ -369,14 +361,12 @@ extern DECLSPEC Sint64 SDLCALL SDL_RWsize(SDL_RWops *context);
 * SDL_RWseek() is actually a wrapper function that calls the SDL_RWops's
 * `seek` method appropriately, to simplify application development.
 *
- * Prior to SDL 2.0.10, this function was a macro.
- *
 * \param context a pointer to an SDL_RWops structure
 * \param offset an offset in bytes, relative to **whence** location; can be
 *               negative
 * \param whence any of `SDL_RW_SEEK_SET`, `SDL_RW_SEEK_CUR`,
 *               `SDL_RW_SEEK_END`
- * \returns the final offset in the data stream after the seek or -1 on error.
+ * \returns the final offset in the data stream after the seek or a negative error code on failure; call SDL_GetError() for more information.
 *
 * \since This function is available since SDL 3.0.0.
 *
@@ -388,8 +378,7 @@ extern DECLSPEC Sint64 SDLCALL SDL_RWsize(SDL_RWops *context);
 * \sa SDL_RWtell
 * \sa SDL_RWwrite
 */
-extern DECLSPEC Sint64 SDLCALL SDL_RWseek(SDL_RWops *context,
-                                          Sint64 offset, int whence);
+extern DECLSPEC Sint64 SDLCALL SDL_RWseek(SDL_RWops *context, Sint64 offset, int whence);

/**
 * Determine the current read/write offset in an SDL_RWops data stream.
@@ -398,9 +387,7 @@ extern DECLSPEC Sint64 SDLCALL SDL_RWseek(SDL_RWops *context,
 * method, with an offset of 0 bytes from `SDL_RW_SEEK_CUR`, to simplify
 * application development.
 *
- * Prior to SDL 2.0.10, this function was a macro.
- *
- * \param context a SDL_RWops data stream object from which to get the current
+ * \param context an SDL_RWops data stream object from which to get the current
 *                offset
 * \returns the current offset in the stream, or -1 if the information can not
 *          be determined.
@@ -438,8 +425,7 @@ extern DECLSPEC Sint64 SDLCALL SDL_RWtell(SDL_RWops *context);
 * \param context a pointer to an SDL_RWops structure
 * \param ptr a pointer to a buffer to read data into
 * \param size the number of bytes to read from the data source.
- * \returns the number of bytes read, 0 at end of file, -1 on error, and -2
- *          for data not ready with a non-blocking context.
+ * \returns the number of bytes read, or 0 on end of file or other error.
 *
 * \since This function is available since SDL 3.0.0.
 *
@@ -450,7 +436,7 @@ extern DECLSPEC Sint64 SDLCALL SDL_RWtell(SDL_RWops *context);
 * \sa SDL_RWseek
 * \sa SDL_RWwrite
 */
-extern DECLSPEC Sint64 SDLCALL SDL_RWread(SDL_RWops *context, void *ptr, Sint64 size);
+extern DECLSPEC size_t SDLCALL SDL_RWread(SDL_RWops *context, void *ptr, size_t size);

/**
 * Write to an SDL_RWops data stream.
@@ -488,8 +474,7 @@ extern DECLSPEC Sint64 SDLCALL SDL_RWread(SDL_RWops *context, void *ptr, Sint64
 * \sa SDL_RWread
 * \sa SDL_RWseek
 */
-extern DECLSPEC Sint64 SDLCALL SDL_RWwrite(SDL_RWops *context,
-                                           const void *ptr, Sint64 size);
+extern DECLSPEC size_t SDLCALL SDL_RWwrite(SDL_RWops *context, const void *ptr, size_t size);

/**
 * Close and free an allocated SDL_RWops structure.
@@ -502,8 +487,6 @@ extern DECLSPEC Sint64 SDLCALL SDL_RWwrite(SDL_RWops *context,
 * Note that if this fails to flush the stream to disk, this function reports
 * an error, but the SDL_RWops is still invalid once this function returns.
 *
- * Prior to SDL 2.0.10, this function was a macro.
- *
 * \param context SDL_RWops structure to close
 * \returns 0 on success or a negative error code on failure; call
 *          SDL_GetError() for more information.
@@ -536,9 +519,7 @@ extern DECLSPEC int SDLCALL SDL_RWclose(SDL_RWops *context);
 *
 * \since This function is available since SDL 3.0.0.
 */
-extern DECLSPEC void *SDLCALL SDL_LoadFile_RW(SDL_RWops *src,
-                                              size_t *datasize,
-                                              SDL_bool freesrc);
+extern DECLSPEC void *SDLCALL SDL_LoadFile_RW(SDL_RWops *src, size_t *datasize, SDL_bool freesrc);

/**
 * Load all the data from a file path.
@@ -549,9 +530,6 @@ extern DECLSPEC void *SDLCALL SDL_LoadFile_RW(SDL_RWops *src,
 *
 * The data should be freed with SDL_free().
 *
- * Prior to SDL 2.0.10, this function was a macro wrapping around
- * SDL_LoadFile_RW.
- *
 * \param file the path to read all available data from
 * \param datasize if not NULL, will store the number of bytes read
 * \returns the data, or NULL if there was an error.
@@ -571,14 +549,28 @@ extern DECLSPEC void *SDLCALL SDL_LoadFile(const char *file, size_t *datasize);
 * Use this function to read a byte from an SDL_RWops.
 *
 * \param src the SDL_RWops to read from
- * \returns the read byte on success or 0 on failure; call SDL_GetError() for
+ * \param value a pointer filled in with the data read
+ * \returns SDL_TRUE on success or SDL_FALSE on failure; call SDL_GetError() for
 *          more information.
 *
 * \since This function is available since SDL 3.0.0.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_ReadU8(SDL_RWops *src, Uint8 *value);
+
+/**
+ * Use this function to read 16 bits of little-endian data from an SDL_RWops
+ * and return in native format.
 *
- * \sa SDL_WriteU8
+ * SDL byteswaps the data only if necessary, so the data returned will be in
+ * the native byte order.
+ *
+ * \param src the stream from which to read data
+ * \param value a pointer filled in with the data read
+ * \returns SDL_TRUE on successful write, SDL_FALSE on failure; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 3.0.0.
 */
-extern DECLSPEC Uint8 SDLCALL SDL_ReadU8(SDL_RWops * src);
+extern DECLSPEC SDL_bool SDLCALL SDL_ReadU16LE(SDL_RWops *src, Uint16 *value);

/**
 * Use this function to read 16 bits of little-endian data from an SDL_RWops
@@ -588,13 +580,13 @@ extern DECLSPEC Uint8 SDLCALL SDL_ReadU8(SDL_RWops * src);
 * the native byte order.
 *
 * \param src the stream from which to read data
- * \returns 16 bits of data in the native byte order of the platform.
+ * \param value a pointer filled in with the data read
+ * \returns SDL_TRUE on successful write, SDL_FALSE on failure; call SDL_GetError() for more information.
 *
 * \since This function is available since SDL 3.0.0.
 *
- * \sa SDL_ReadBE16
 */
-extern DECLSPEC Uint16 SDLCALL SDL_ReadLE16(SDL_RWops * src);
+extern DECLSPEC SDL_bool SDLCALL SDL_ReadS16LE(SDL_RWops *src, Sint16 *value);

/**
 * Use this function to read 16 bits of big-endian data from an SDL_RWops and
@@ -604,13 +596,28 @@ extern DECLSPEC Uint16 SDLCALL SDL_ReadLE16(SDL_RWops * src);
 * the native byte order.
 *
 * \param src the stream from which to read data
- * \returns 16 bits of data in the native byte order of the platform.
+ * \param value a pointer filled in with the data read
+ * \returns SDL_TRUE on successful write, SDL_FALSE on failure; call SDL_GetError() for more information.
 *
 * \since This function is available since SDL 3.0.0.
 *
- * \sa SDL_ReadLE16
 */
-extern DECLSPEC Uint16 SDLCALL SDL_ReadBE16(SDL_RWops * src);
+extern DECLSPEC SDL_bool SDLCALL SDL_ReadU16BE(SDL_RWops *src, Uint16 *value);
+
+/**
+ * Use this function to read 16 bits of big-endian data from an SDL_RWops and
+ * return in native format.
+ *
+ * SDL byteswaps the data only if necessary, so the data returned will be in
+ * the native byte order.
+ *
+ * \param src the stream from which to read data
+ * \param value a pointer filled in with the data read
+ * \returns SDL_TRUE on successful write, SDL_FALSE on failure; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 3.0.0.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_ReadS16BE(SDL_RWops *src, Sint16 *value);

/**
 * Use this function to read 32 bits of little-endian data from an SDL_RWops
@@ -620,13 +627,27 @@ extern DECLSPEC Uint16 SDLCALL SDL_ReadBE16(SDL_RWops * src);
 * the native byte order.
 *
 * \param src the stream from which to read data
- * \returns 32 bits of data in the native byte order of the platform.
+ * \param value a pointer filled in with the data read
+ * \returns SDL_TRUE on successful write, SDL_FALSE on failure; call SDL_GetError() for more information.
 *
 * \since This function is available since SDL 3.0.0.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_ReadU32LE(SDL_RWops *src, Uint32 *value);
+
+/**
+ * Use this function to read 32 bits of little-endian data from an SDL_RWops
+ * and return in native format.
 *
- * \sa SDL_ReadBE32
+ * SDL byteswaps the data only if necessary, so the data returned will be in
+ * the native byte order.
+ *
+ * \param src the stream from which to read data
+ * \param value a pointer filled in with the data read
+ * \returns SDL_TRUE on successful write, SDL_FALSE on failure; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 3.0.0.
 */
-extern DECLSPEC Uint32 SDLCALL SDL_ReadLE32(SDL_RWops * src);
+extern DECLSPEC SDL_bool SDLCALL SDL_ReadS32LE(SDL_RWops *src, Sint32 *value);

/**
 * Use this function to read 32 bits of big-endian data from an SDL_RWops and
@@ -636,13 +657,27 @@ extern DECLSPEC Uint32 SDLCALL SDL_ReadLE32(SDL_RWops * src);
 * the native byte order.
 *
 * \param src the stream from which to read data
- * \returns 32 bits of data in the native byte order of the platform.
+ * \param value a pointer filled in with the data read
+ * \returns SDL_TRUE on successful write, SDL_FALSE on failure; call SDL_GetError() for more information.
 *
 * \since This function is available since SDL 3.0.0.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_ReadU32BE(SDL_RWops *src, Uint32 *value);
+
+/**
+ * Use this function to read 32 bits of big-endian data from an SDL_RWops and
+ * return in native format.
 *
- * \sa SDL_ReadLE32
+ * SDL byteswaps the data only if necessary, so the data returned will be in
+ * the native byte order.
+ *
+ * \param src the stream from which to read data
+ * \param value a pointer filled in with the data read
+ * \returns SDL_TRUE on successful write, SDL_FALSE on failure; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 3.0.0.
 */
-extern DECLSPEC Uint32 SDLCALL SDL_ReadBE32(SDL_RWops * src);
+extern DECLSPEC SDL_bool SDLCALL SDL_ReadS32BE(SDL_RWops *src, Sint32 *value);

/**
 * Use this function to read 64 bits of little-endian data from an SDL_RWops
@@ -652,13 +687,27 @@ extern DECLSPEC Uint32 SDLCALL SDL_ReadBE32(SDL_RWops * src);
 * the native byte order.
 *
 * \param src the stream from which to read data
- * \returns 64 bits of data in the native byte order of the platform.
+ * \param value a pointer filled in with the data read
+ * \returns SDL_TRUE on successful write, SDL_FALSE on failure; call SDL_GetError() for more information.
 *
 * \since This function is available since SDL 3.0.0.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_ReadU64LE(SDL_RWops *src, Uint64 *value);
+
+/**
+ * Use this function to read 64 bits of little-endian data from an SDL_RWops
+ * and return in native format.
 *
- * \sa SDL_ReadBE64
+ * SDL byteswaps the data only if necessary, so the data returned will be in
+ * the native byte order.
+ *
+ * \param src the stream from which to read data
+ * \param value a pointer filled in with the data read
+ * \returns SDL_TRUE on successful write, SDL_FALSE on failure; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 3.0.0.
 */
-extern DECLSPEC Uint64 SDLCALL SDL_ReadLE64(SDL_RWops * src);
+extern DECLSPEC SDL_bool SDLCALL SDL_ReadS64LE(SDL_RWops *src, Sint64 *value);

/**
 * Use this function to read 64 bits of big-endian data from an SDL_RWops and
@@ -668,13 +717,27 @@ extern DECLSPEC Uint64 SDLCALL SDL_ReadLE64(SDL_RWops * src);
 * the native byte order.
 *
 * \param src the stream from which to read data
- * \returns 64 bits of data in the native byte order of the platform.
+ * \param value a pointer filled in with the data read
+ * \returns SDL_TRUE on successful write, SDL_FALSE on failure; call SDL_GetError() for more information.
 *
 * \since This function is available since SDL 3.0.0.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_ReadU64BE(SDL_RWops *src, Uint64 *value);
+
+/**
+ * Use this function to read 64 bits of big-endian data from an SDL_RWops and
+ * return in native format.
 *
- * \sa SDL_ReadLE64
+ * SDL byteswaps the data only if necessary, so the data returned will be in
+ * the native byte order.
+ *
+ * \param src the stream from which to read data
+ * \param value a pointer filled in with the data read
+ * \returns SDL_TRUE on successful write, SDL_FALSE on failure; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 3.0.0.
 */
-extern DECLSPEC Uint64 SDLCALL SDL_ReadBE64(SDL_RWops * src);
+extern DECLSPEC SDL_bool SDLCALL SDL_ReadS64BE(SDL_RWops *src, Sint64 *value);
/* @} *//* Read endian functions */

/**
@@ -689,17 +752,14 @@ extern DECLSPEC Uint64 SDLCALL SDL_ReadBE64(SDL_RWops * src);
 *
 * \param dst the SDL_RWops to write to
 * \param value the 

(Patch may be truncated, please check the link at the top of this post.)