Browse Source

Merge pull request #9254 from icculus/sdl3-rwops-hidden-interface

rwops: Reworked RWops for SDL3. Now it's SDL_IOStream!
Ryan C. Gordon 1 year ago
parent
commit
ec6de7017c
55 changed files with 1959 additions and 1822 deletions
  1. 2 2
      VisualC-GDK/SDL/SDL.vcxproj
  2. 2 2
      VisualC-GDK/SDL/SDL.vcxproj.filters
  3. 2 2
      VisualC-WinRT/SDL-UWP.vcxproj
  4. 2 2
      VisualC-WinRT/SDL-UWP.vcxproj.filters
  5. 2 2
      VisualC/SDL/SDL.vcxproj
  6. 2 2
      VisualC/SDL/SDL.vcxproj.filters
  7. 1 1
      VisualC/tests/testautomation/testautomation.vcxproj
  8. 16 16
      Xcode/SDL/SDL.xcodeproj/project.pbxproj
  9. 4 4
      Xcode/SDLTest/SDLTest.xcodeproj/project.pbxproj
  10. 69 14
      build-scripts/SDL_migration.cocci
  11. 1 1
      docs/README-android.md
  12. 1 1
      docs/README-emscripten.md
  13. 92 46
      docs/README-migration.md
  14. 1 1
      docs/README-winrt.md
  15. 1 1
      include/SDL3/SDL.h
  16. 6 6
      include/SDL3/SDL_audio.h
  17. 4 4
      include/SDL3/SDL_gamepad.h
  18. 3 3
      include/SDL3/SDL_hints.h
  19. 1 1
      include/SDL3/SDL_init.h
  20. 284 318
      include/SDL3/SDL_iostream.h
  21. 34 12
      include/SDL3/SDL_oldnames.h
  22. 10 10
      include/SDL3/SDL_surface.h
  23. 25 25
      src/audio/SDL_wave.c
  24. 5 5
      src/audio/disk/SDL_diskaudio.c
  25. 1 1
      src/audio/disk/SDL_diskaudio.h
  26. 14 21
      src/core/android/SDL_android.c
  27. 6 6
      src/core/android/SDL_android.h
  28. 5 5
      src/dynapi/SDL_dynapi.c
  29. 19 19
      src/dynapi/SDL_dynapi.sym
  30. 19 19
      src/dynapi/SDL_dynapi_overrides.h
  31. 45 45
      src/dynapi/SDL_dynapi_procs.h
  32. 378 286
      src/file/SDL_iostream.c
  33. 2 2
      src/file/cocoa/SDL_iostreambundlesupport.h
  34. 1 1
      src/file/cocoa/SDL_iostreambundlesupport.m
  35. 1 1
      src/file/n3ds/SDL_iostreamromfs.c
  36. 3 3
      src/file/n3ds/SDL_iostreamromfs.h
  37. 3 3
      src/joystick/SDL_gamepad.c
  38. 9 9
      src/test/SDL_test_common.c
  39. 27 27
      src/video/SDL_bmp.c
  40. 1 1
      test/README
  41. 2 2
      test/gamepadutils.c
  42. 1 1
      test/testautomation.c
  43. 648 0
      test/testautomation_iostream.c
  44. 0 685
      test/testautomation_rwops.c
  45. 1 1
      test/testautomation_suites.h
  46. 2 2
      test/testffmpeg.c
  47. 173 173
      test/testfile.c
  48. 6 6
      test/testime.c
  49. 4 4
      test/testoverlay.c
  50. 6 6
      test/testresample.c
  51. 1 1
      test/testshape.c
  52. 2 2
      test/testspriteminimal.c
  53. 4 4
      test/teststreaming.c
  54. 3 3
      test/testutils.c
  55. 2 2
      test/testwaylandcustom.c

+ 2 - 2
VisualC-GDK/SDL/SDL.vcxproj

@@ -364,7 +364,7 @@
     <ClInclude Include="..\..\include\SDL3\SDL_rect.h" />
     <ClInclude Include="..\..\include\SDL3\SDL_render.h" />
     <ClInclude Include="..\..\include\SDL3\SDL_revision.h" />
-    <ClInclude Include="..\..\include\SDL3\SDL_rwops.h" />
+    <ClInclude Include="..\..\include\SDL3\SDL_iostream.h" />
     <ClInclude Include="..\..\include\SDL3\SDL_scancode.h" />
     <ClInclude Include="..\..\include\SDL3\SDL_sensor.h" />
     <ClInclude Include="..\..\include\SDL3\SDL_stdinc.h" />
@@ -629,7 +629,7 @@
     <ClCompile Include="..\..\src\events\SDL_quit.c" />
     <ClCompile Include="..\..\src\events\SDL_touch.c" />
     <ClCompile Include="..\..\src\events\SDL_windowevents.c" />
-    <ClCompile Include="..\..\src\file\SDL_rwops.c" />
+    <ClCompile Include="..\..\src\file\SDL_iostream.c" />
     <ClCompile Include="..\..\src\filesystem\gdk\SDL_sysfilesystem.cpp">
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Gaming.Desktop.x64'">true</ExcludedFromBuild>
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Gaming.Desktop.x64'">true</ExcludedFromBuild>

+ 2 - 2
VisualC-GDK/SDL/SDL.vcxproj.filters

@@ -43,7 +43,7 @@
     <ClCompile Include="..\..\src\events\SDL_quit.c" />
     <ClCompile Include="..\..\src\events\SDL_touch.c" />
     <ClCompile Include="..\..\src\events\SDL_windowevents.c" />
-    <ClCompile Include="..\..\src\file\SDL_rwops.c" />
+    <ClCompile Include="..\..\src\file\SDL_iostream.c" />
     <ClCompile Include="..\..\src\filesystem\gdk\SDL_sysfilesystem.cpp" />
     <ClCompile Include="..\..\src\haptic\dummy\SDL_syshaptic.c" />
     <ClCompile Include="..\..\src\haptic\SDL_haptic.c" />
@@ -258,7 +258,7 @@
     <ClInclude Include="..\..\include\SDL3\SDL_rect.h" />
     <ClInclude Include="..\..\include\SDL3\SDL_render.h" />
     <ClInclude Include="..\..\include\SDL3\SDL_revision.h" />
-    <ClInclude Include="..\..\include\SDL3\SDL_rwops.h" />
+    <ClInclude Include="..\..\include\SDL3\SDL_iostream.h" />
     <ClInclude Include="..\..\include\SDL3\SDL_scancode.h" />
     <ClInclude Include="..\..\include\SDL3\SDL_sensor.h" />
     <ClInclude Include="..\..\include\SDL3\SDL_stdinc.h" />

+ 2 - 2
VisualC-WinRT/SDL-UWP.vcxproj

@@ -78,7 +78,7 @@
     <ClInclude Include="..\include\SDL3\SDL_rect.h" />
     <ClInclude Include="..\include\SDL3\SDL_render.h" />
     <ClInclude Include="..\include\SDL3\SDL_revision.h" />
-    <ClInclude Include="..\include\SDL3\SDL_rwops.h" />
+    <ClInclude Include="..\include\SDL3\SDL_iostream.h" />
     <ClInclude Include="..\include\SDL3\SDL_scancode.h" />
     <ClInclude Include="..\include\SDL3\SDL_sensor.h" />
     <ClInclude Include="..\include\SDL3\SDL_stdinc.h" />
@@ -332,7 +332,7 @@
       <PrecompiledHeaderOutputFile Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(IntDir)$(TargetName)_cpp.pch</PrecompiledHeaderOutputFile>
       <PrecompiledHeaderOutputFile Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(IntDir)$(TargetName)_cpp.pch</PrecompiledHeaderOutputFile>
     </ClCompile>
-    <ClCompile Include="..\src\file\SDL_rwops.c" />
+    <ClCompile Include="..\src\file\SDL_iostream.c" />
     <ClCompile Include="..\src\haptic\dummy\SDL_syshaptic.c" />
     <ClCompile Include="..\src\haptic\SDL_haptic.c" />
     <ClCompile Include="..\src\haptic\windows\SDL_dinputhaptic.c" />

+ 2 - 2
VisualC-WinRT/SDL-UWP.vcxproj.filters

@@ -141,7 +141,7 @@
     <ClInclude Include="..\include\SDL3\SDL_revision.h">
       <Filter>Header Files</Filter>
     </ClInclude>
-    <ClInclude Include="..\include\SDL3\SDL_rwops.h">
+    <ClInclude Include="..\include\SDL3\SDL_iostream.h">
       <Filter>Header Files</Filter>
     </ClInclude>
     <ClInclude Include="..\include\SDL3\SDL_scancode.h">
@@ -582,7 +582,7 @@
     <ClCompile Include="..\src\filesystem\winrt\SDL_sysfilesystem.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
-    <ClCompile Include="..\src\file\SDL_rwops.c">
+    <ClCompile Include="..\src\file\SDL_iostream.c">
       <Filter>Source Files</Filter>
     </ClCompile>
     <ClCompile Include="..\src\haptic\dummy\SDL_syshaptic.c">

+ 2 - 2
VisualC/SDL/SDL.vcxproj

@@ -287,7 +287,7 @@
     <ClInclude Include="..\..\include\SDL3\SDL_rect.h" />
     <ClInclude Include="..\..\include\SDL3\SDL_render.h" />
     <ClInclude Include="..\..\include\SDL3\SDL_revision.h" />
-    <ClInclude Include="..\..\include\SDL3\SDL_rwops.h" />
+    <ClInclude Include="..\..\include\SDL3\SDL_iostream.h" />
     <ClInclude Include="..\..\include\SDL3\SDL_scancode.h" />
     <ClInclude Include="..\..\include\SDL3\SDL_sensor.h" />
     <ClInclude Include="..\..\include\SDL3\SDL_stdinc.h" />
@@ -521,7 +521,7 @@
     <ClCompile Include="..\..\src\events\SDL_quit.c" />
     <ClCompile Include="..\..\src\events\SDL_touch.c" />
     <ClCompile Include="..\..\src\events\SDL_windowevents.c" />
-    <ClCompile Include="..\..\src\file\SDL_rwops.c" />
+    <ClCompile Include="..\..\src\file\SDL_iostream.c" />
     <ClCompile Include="..\..\src\filesystem\windows\SDL_sysfilesystem.c" />
     <ClCompile Include="..\..\src\haptic\dummy\SDL_syshaptic.c" />
     <ClCompile Include="..\..\src\haptic\SDL_haptic.c" />

+ 2 - 2
VisualC/SDL/SDL.vcxproj.filters

@@ -342,7 +342,7 @@
     <ClInclude Include="..\..\include\SDL3\SDL_revision.h">
       <Filter>API Headers</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\include\SDL3\SDL_rwops.h">
+    <ClInclude Include="..\..\include\SDL3\SDL_iostream.h">
       <Filter>API Headers</Filter>
     </ClInclude>
     <ClInclude Include="..\..\include\SDL3\SDL_scancode.h">
@@ -973,7 +973,7 @@
     <ClCompile Include="..\..\src\events\SDL_windowevents.c">
       <Filter>events</Filter>
     </ClCompile>
-    <ClCompile Include="..\..\src\file\SDL_rwops.c">
+    <ClCompile Include="..\..\src\file\SDL_iostream.c">
       <Filter>file</Filter>
     </ClCompile>
     <ClCompile Include="..\..\src\filesystem\windows\SDL_sysfilesystem.c">

+ 1 - 1
VisualC/tests/testautomation/testautomation.vcxproj

@@ -221,7 +221,7 @@
     <ClCompile Include="..\..\..\test\testautomation_properties.c" />
     <ClCompile Include="..\..\..\test\testautomation_rect.c" />
     <ClCompile Include="..\..\..\test\testautomation_render.c" />
-    <ClCompile Include="..\..\..\test\testautomation_rwops.c" />
+    <ClCompile Include="..\..\..\test\testautomation_iostream.c" />
     <ClCompile Include="..\..\..\test\testautomation_sdltest.c" />
     <ClCompile Include="..\..\..\test\testautomation_stdlib.c" />
     <ClCompile Include="..\..\..\test\testautomation_surface.c" />

+ 16 - 16
Xcode/SDL/SDL.xcodeproj/project.pbxproj

@@ -224,9 +224,9 @@
 		A7D8B58123E2514300DCD162 /* SDL_sysjoystick.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A7CF23E2513E00DCD162 /* SDL_sysjoystick.h */; };
 		A7D8B58723E2514300DCD162 /* SDL_joystick_c.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A7D023E2513E00DCD162 /* SDL_joystick_c.h */; };
 		A7D8B5B723E2514300DCD162 /* controller_type.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A7D923E2513E00DCD162 /* controller_type.h */; };
-		A7D8B5BD23E2514300DCD162 /* SDL_rwops.c in Sources */ = {isa = PBXBuildFile; fileRef = A7D8A7DB23E2513F00DCD162 /* SDL_rwops.c */; };
-		A7D8B5C323E2514300DCD162 /* SDL_rwopsbundlesupport.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A7DD23E2513F00DCD162 /* SDL_rwopsbundlesupport.h */; };
-		A7D8B5C923E2514300DCD162 /* SDL_rwopsbundlesupport.m in Sources */ = {isa = PBXBuildFile; fileRef = A7D8A7DE23E2513F00DCD162 /* SDL_rwopsbundlesupport.m */; };
+		A7D8B5BD23E2514300DCD162 /* SDL_iostream.c in Sources */ = {isa = PBXBuildFile; fileRef = A7D8A7DB23E2513F00DCD162 /* SDL_iostream.c */; };
+		A7D8B5C323E2514300DCD162 /* SDL_iostreambundlesupport.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A7DD23E2513F00DCD162 /* SDL_iostreambundlesupport.h */; };
+		A7D8B5C923E2514300DCD162 /* SDL_iostreambundlesupport.m in Sources */ = {isa = PBXBuildFile; fileRef = A7D8A7DE23E2513F00DCD162 /* SDL_iostreambundlesupport.m */; };
 		A7D8B5CF23E2514300DCD162 /* SDL_syspower.m in Sources */ = {isa = PBXBuildFile; fileRef = A7D8A7E123E2513F00DCD162 /* SDL_syspower.m */; };
 		A7D8B5D523E2514300DCD162 /* SDL_syspower.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A7E223E2513F00DCD162 /* SDL_syspower.h */; };
 		A7D8B5E723E2514300DCD162 /* SDL_power.c in Sources */ = {isa = PBXBuildFile; fileRef = A7D8A7E723E2513F00DCD162 /* SDL_power.c */; };
@@ -458,7 +458,7 @@
 		F3F7D9592933074E00816151 /* SDL_video.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F7D8C52933074B00816151 /* SDL_video.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		F3F7D95D2933074E00816151 /* SDL_opengles.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F7D8C62933074B00816151 /* SDL_opengles.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		F3F7D9612933074E00816151 /* SDL_opengles2.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F7D8C72933074B00816151 /* SDL_opengles2.h */; settings = {ATTRIBUTES = (Public, ); }; };
-		F3F7D9652933074E00816151 /* SDL_rwops.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F7D8C82933074B00816151 /* SDL_rwops.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		F3F7D9652933074E00816151 /* SDL_iostream.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F7D8C82933074B00816151 /* SDL_iostream.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		F3F7D9692933074E00816151 /* SDL_opengles2_gl2platform.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F7D8C92933074B00816151 /* SDL_opengles2_gl2platform.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		F3F7D96D2933074E00816151 /* SDL_hidapi.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F7D8CA2933074B00816151 /* SDL_hidapi.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		F3F7D9712933074E00816151 /* SDL_events.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F7D8CB2933074B00816151 /* SDL_events.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -760,9 +760,9 @@
 		A7D8A7CF23E2513E00DCD162 /* SDL_sysjoystick.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_sysjoystick.h; sourceTree = "<group>"; };
 		A7D8A7D023E2513E00DCD162 /* SDL_joystick_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_joystick_c.h; sourceTree = "<group>"; };
 		A7D8A7D923E2513E00DCD162 /* controller_type.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = controller_type.h; sourceTree = "<group>"; };
-		A7D8A7DB23E2513F00DCD162 /* SDL_rwops.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_rwops.c; sourceTree = "<group>"; };
-		A7D8A7DD23E2513F00DCD162 /* SDL_rwopsbundlesupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_rwopsbundlesupport.h; sourceTree = "<group>"; };
-		A7D8A7DE23E2513F00DCD162 /* SDL_rwopsbundlesupport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_rwopsbundlesupport.m; sourceTree = "<group>"; };
+		A7D8A7DB23E2513F00DCD162 /* SDL_iostream.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_iostream.c; sourceTree = "<group>"; };
+		A7D8A7DD23E2513F00DCD162 /* SDL_iostreambundlesupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_iostreambundlesupport.h; sourceTree = "<group>"; };
+		A7D8A7DE23E2513F00DCD162 /* SDL_iostreambundlesupport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_iostreambundlesupport.m; sourceTree = "<group>"; };
 		A7D8A7E123E2513F00DCD162 /* SDL_syspower.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_syspower.m; sourceTree = "<group>"; };
 		A7D8A7E223E2513F00DCD162 /* SDL_syspower.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_syspower.h; sourceTree = "<group>"; };
 		A7D8A7E723E2513F00DCD162 /* SDL_power.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_power.c; sourceTree = "<group>"; };
@@ -983,7 +983,7 @@
 		F3F7D8C52933074B00816151 /* SDL_video.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_video.h; path = SDL3/SDL_video.h; sourceTree = "<group>"; };
 		F3F7D8C62933074B00816151 /* SDL_opengles.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_opengles.h; path = SDL3/SDL_opengles.h; sourceTree = "<group>"; };
 		F3F7D8C72933074B00816151 /* SDL_opengles2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_opengles2.h; path = SDL3/SDL_opengles2.h; sourceTree = "<group>"; };
-		F3F7D8C82933074B00816151 /* SDL_rwops.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_rwops.h; path = SDL3/SDL_rwops.h; sourceTree = "<group>"; };
+		F3F7D8C82933074B00816151 /* SDL_iostream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_iostream.h; path = SDL3/SDL_iostream.h; sourceTree = "<group>"; };
 		F3F7D8C92933074B00816151 /* SDL_opengles2_gl2platform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_opengles2_gl2platform.h; path = SDL3/SDL_opengles2_gl2platform.h; sourceTree = "<group>"; };
 		F3F7D8CA2933074B00816151 /* SDL_hidapi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_hidapi.h; path = SDL3/SDL_hidapi.h; sourceTree = "<group>"; };
 		F3F7D8CB2933074B00816151 /* SDL_events.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_events.h; path = SDL3/SDL_events.h; sourceTree = "<group>"; };
@@ -1158,7 +1158,7 @@
 				F3F7D8E22933074D00816151 /* SDL_rect.h */,
 				F3F7D8DE2933074D00816151 /* SDL_render.h */,
 				F3F7D8B42933074900816151 /* SDL_revision.h */,
-				F3F7D8C82933074B00816151 /* SDL_rwops.h */,
+				F3F7D8C82933074B00816151 /* SDL_iostream.h */,
 				F3F7D8C12933074B00816151 /* SDL_scancode.h */,
 				F3F7D8C22933074B00816151 /* SDL_sensor.h */,
 				F3F7D8AC2933074900816151 /* SDL_stdinc.h */,
@@ -1803,7 +1803,7 @@
 			isa = PBXGroup;
 			children = (
 				A7D8A7DC23E2513F00DCD162 /* cocoa */,
-				A7D8A7DB23E2513F00DCD162 /* SDL_rwops.c */,
+				A7D8A7DB23E2513F00DCD162 /* SDL_iostream.c */,
 			);
 			path = file;
 			sourceTree = "<group>";
@@ -1811,8 +1811,8 @@
 		A7D8A7DC23E2513F00DCD162 /* cocoa */ = {
 			isa = PBXGroup;
 			children = (
-				A7D8A7DD23E2513F00DCD162 /* SDL_rwopsbundlesupport.h */,
-				A7D8A7DE23E2513F00DCD162 /* SDL_rwopsbundlesupport.m */,
+				A7D8A7DD23E2513F00DCD162 /* SDL_iostreambundlesupport.h */,
+				A7D8A7DE23E2513F00DCD162 /* SDL_iostreambundlesupport.m */,
 			);
 			path = cocoa;
 			sourceTree = "<group>";
@@ -2320,8 +2320,8 @@
 				A7D8B9FB23E2514400DCD162 /* SDL_render_sw_c.h in Headers */,
 				F3F7D9152933074E00816151 /* SDL_revision.h in Headers */,
 				A7D8BA3123E2514400DCD162 /* SDL_rotate.h in Headers */,
-				F3F7D9652933074E00816151 /* SDL_rwops.h in Headers */,
-				A7D8B5C323E2514300DCD162 /* SDL_rwopsbundlesupport.h in Headers */,
+				F3F7D9652933074E00816151 /* SDL_iostream.h in Headers */,
+				A7D8B5C323E2514300DCD162 /* SDL_iostreambundlesupport.h in Headers */,
 				F3F7D9492933074E00816151 /* SDL_scancode.h in Headers */,
 				F3F7D94D2933074E00816151 /* SDL_sensor.h in Headers */,
 				A7D8A98D23E2514000DCD162 /* SDL_sensor_c.h in Headers */,
@@ -2638,7 +2638,7 @@
 				F32DDAD12AB795A30041EAA5 /* SDL_audioqueue.c in Sources */,
 				A7D8B8E423E2514400DCD162 /* SDL_error.c in Sources */,
 				A7D8AD6823E2514100DCD162 /* SDL_blit.c in Sources */,
-				A7D8B5BD23E2514300DCD162 /* SDL_rwops.c in Sources */,
+				A7D8B5BD23E2514300DCD162 /* SDL_iostream.c in Sources */,
 				A7D8BA9123E2514400DCD162 /* s_cos.c in Sources */,
 				A7D8B9D123E2514400DCD162 /* SDL_yuv_sw.c in Sources */,
 				A7D8B76A23E2514300DCD162 /* SDL_wave.c in Sources */,
@@ -2724,7 +2724,7 @@
 				A7D8AAB023E2514100DCD162 /* SDL_syshaptic.c in Sources */,
 				F3F07D5A269640160074468B /* SDL_hidapi_luna.c in Sources */,
 				A7D8BBD523E2574800DCD162 /* SDL_uikitclipboard.m in Sources */,
-				A7D8B5C923E2514300DCD162 /* SDL_rwopsbundlesupport.m in Sources */,
+				A7D8B5C923E2514300DCD162 /* SDL_iostreambundlesupport.m in Sources */,
 				F386F6F92884663E001840AA /* SDL_utils.c in Sources */,
 				E4F7981E2AD8D86A00669F54 /* SDL_render_unsupported.c in Sources */,
 				A7D8AC0F23E2514100DCD162 /* SDL_video.c in Sources */,

+ 4 - 4
Xcode/SDLTest/SDLTest.xcodeproj/project.pbxproj

@@ -137,7 +137,7 @@
 		F35E56CF2983130F00A43A5F /* testautomation_main.c in Sources */ = {isa = PBXBuildFile; fileRef = F35E56B62983130A00A43A5F /* testautomation_main.c */; };
 		F35E56D02983130F00A43A5F /* testautomation_hints.c in Sources */ = {isa = PBXBuildFile; fileRef = F35E56B72983130A00A43A5F /* testautomation_hints.c */; };
 		F35E56D12983130F00A43A5F /* testautomation_render.c in Sources */ = {isa = PBXBuildFile; fileRef = F35E56B82983130A00A43A5F /* testautomation_render.c */; };
-		F35E56D22983130F00A43A5F /* testautomation_rwops.c in Sources */ = {isa = PBXBuildFile; fileRef = F35E56B92983130B00A43A5F /* testautomation_rwops.c */; };
+		F35E56D22983130F00A43A5F /* testautomation_iostream.c in Sources */ = {isa = PBXBuildFile; fileRef = F35E56B92983130B00A43A5F /* testautomation_iostream.c */; };
 		F35E56D32983130F00A43A5F /* testautomation_math.c in Sources */ = {isa = PBXBuildFile; fileRef = F35E56BA2983130B00A43A5F /* testautomation_math.c */; };
 		F35E56D42983130F00A43A5F /* testautomation_events.c in Sources */ = {isa = PBXBuildFile; fileRef = F35E56BB2983130B00A43A5F /* testautomation_events.c */; };
 		F35E56D52983130F00A43A5F /* testautomation_clipboard.c in Sources */ = {isa = PBXBuildFile; fileRef = F35E56BC2983130B00A43A5F /* testautomation_clipboard.c */; };
@@ -1312,7 +1312,7 @@
 		F35E56B62983130A00A43A5F /* testautomation_main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testautomation_main.c; sourceTree = "<group>"; };
 		F35E56B72983130A00A43A5F /* testautomation_hints.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testautomation_hints.c; sourceTree = "<group>"; };
 		F35E56B82983130A00A43A5F /* testautomation_render.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testautomation_render.c; sourceTree = "<group>"; };
-		F35E56B92983130B00A43A5F /* testautomation_rwops.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testautomation_rwops.c; sourceTree = "<group>"; };
+		F35E56B92983130B00A43A5F /* testautomation_iostream.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testautomation_iostream.c; sourceTree = "<group>"; };
 		F35E56BA2983130B00A43A5F /* testautomation_math.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testautomation_math.c; sourceTree = "<group>"; };
 		F35E56BB2983130B00A43A5F /* testautomation_events.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testautomation_events.c; sourceTree = "<group>"; };
 		F35E56BC2983130B00A43A5F /* testautomation_clipboard.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testautomation_clipboard.c; sourceTree = "<group>"; };
@@ -1774,7 +1774,7 @@
 				F35E56C32983130D00A43A5F /* testautomation_platform.c */,
 				F35E56C52983130D00A43A5F /* testautomation_rect.c */,
 				F35E56B82983130A00A43A5F /* testautomation_render.c */,
-				F35E56B92983130B00A43A5F /* testautomation_rwops.c */,
+				F35E56B92983130B00A43A5F /* testautomation_iostream.c */,
 				F35E56C82983130E00A43A5F /* testautomation_sdltest.c */,
 				F35E56BE2983130C00A43A5F /* testautomation_stdlib.c */,
 				F35E56CB2983130F00A43A5F /* testautomation_surface.c */,
@@ -3355,7 +3355,7 @@
 			files = (
 				F35E56D12983130F00A43A5F /* testautomation_render.c in Sources */,
 				F399C6512A7892D800C86979 /* testautomation_intrinsics.c in Sources */,
-				F35E56D22983130F00A43A5F /* testautomation_rwops.c in Sources */,
+				F35E56D22983130F00A43A5F /* testautomation_iostream.c in Sources */,
 				F35E56E32983130F00A43A5F /* testautomation_surface.c in Sources */,
 				F35E56DB2983130F00A43A5F /* testautomation_platform.c in Sources */,
 				F35E56DD2983130F00A43A5F /* testautomation_rect.c in Sources */,

+ 69 - 14
build-scripts/SDL_migration.cocci

@@ -1051,7 +1051,7 @@ typedef SDL_GameController, SDL_Gamepad;
 @@
 @@
 - SDL_GameControllerAddMappingsFromRW
-+ SDL_AddGamepadMappingsFromRW
++ SDL_AddGamepadMappingsFromIO
   (...)
 @@
 typedef SDL_GameControllerAxis, SDL_GamepadAxis;
@@ -1804,25 +1804,15 @@ expression e2;
 @@
 @@
 - RW_SEEK_CUR
-+ SDL_RW_SEEK_CUR
++ SDL_IO_SEEK_CUR
 @@
 @@
 - RW_SEEK_END
-+ SDL_RW_SEEK_END
++ SDL_IO_SEEK_END
 @@
 @@
 - RW_SEEK_SET
-+ SDL_RW_SEEK_SET
-@@
-@@
-- SDL_AllocRW
-+ SDL_CreateRW
-  (...)
-@@
-@@
-- SDL_FreeRW
-+ SDL_DestroyRW
-  (...)
++ SDL_IO_SEEK_SET
 @@
 @@
 - SDL_SensorClose
@@ -3058,3 +3048,68 @@ typedef SDL_version, SDL_Version;
 - SDL_JoystickGetBall
 + SDL_GetJoystickBall
   (...)
+@@
+@@
+- SDL_RWclose
++ SDL_CloseIO
+  (...)
+@@
+@@
+- SDL_RWread
++ SDL_ReadIO
+  (...)
+@@
+@@
+- SDL_RWwrite
++ SDL_WriteIO
+  (...)
+@@
+@@
+- SDL_RWtell
++ SDL_TellIO
+  (...)
+@@
+@@
+- SDL_RWsize
++ SDL_SizeIO
+  (...)
+@@
+@@
+- SDL_RWseek
++ SDL_SeekIO
+  (...)
+@@
+@@
+- SDL_LoadBMP_RW
++ SDL_LoadBMP_IO
+  (...)
+@@
+@@
+- SDL_LoadWAV_RW
++ SDL_LoadWAV_IO
+  (...)
+@@
+@@
+- SDL_SaveBMP_RW
++ SDL_SaveBMP_IO
+  (...)
+@@
+@@
+- SDL_RWFromFile
++ SDL_IOFromFile
+  (...)
+@@
+@@
+- SDL_RWFromMem
++ SDL_IOFromMem
+  (...)
+@@
+@@
+- SDL_RWFromConstMem
++ SDL_IOFromConstMem
+  (...)
+@@
+typedef SDL_RWops, SDL_IOStream;
+@@
+- SDL_RWops
++ SDL_IOStream

+ 1 - 1
docs/README-android.md

@@ -165,7 +165,7 @@ Loading assets
 
 Any files you put in the "app/src/main/assets" directory of your project
 directory will get bundled into the application package and you can load
-them using the standard functions in SDL_rwops.h.
+them using the standard functions in SDL_iostream.h.
 
 There are also a few Android specific functions that allow you to get other
 useful paths for saving and loading data:

+ 1 - 1
docs/README-emscripten.md

@@ -301,7 +301,7 @@ Your game probably has data files. Here's how to access them.
 Filesystem access works like a Unix filesystem; you have a single directory
 tree, possibly interpolated from several mounted locations, no drive letters,
 '/' for a path separator. You can access them with standard file APIs like
-open() or fopen() or SDL_RWops. You can read or write from the filesystem.
+open() or fopen() or SDL_IOStream. You can read or write from the filesystem.
 
 By default, you probably have a "MEMFS" filesystem (all files are stored in
 memory, but access to them is immediate and doesn't need to block). There are

+ 92 - 46
docs/README-migration.md

@@ -191,7 +191,7 @@ SDL_FreeWAV has been removed and calls can be replaced with SDL_free.
 
 SDL_LoadWAV() is a proper function now and no longer a macro (but offers the same functionality otherwise).
 
-SDL_LoadWAV_RW() and SDL_LoadWAV() return an int now: zero on success, -1 on error, like most of SDL. They no longer return a pointer to an SDL_AudioSpec.
+SDL_LoadWAV_IO() and SDL_LoadWAV() return an int now: zero on success, -1 on error, like most of SDL. They no longer return a pointer to an SDL_AudioSpec.
 
 SDL_AudioCVT interface has been removed, the SDL_AudioStream interface (for audio supplied in pieces) or the new SDL_ConvertAudioSamples() function (for converting a complete audio buffer in one call) can be used instead.
 
@@ -253,6 +253,7 @@ The following functions have been renamed:
 * SDL_AudioStreamGet() => SDL_GetAudioStreamData()
 * SDL_AudioStreamPut() => SDL_PutAudioStreamData()
 * SDL_FreeAudioStream() => SDL_DestroyAudioStream()
+* SDL_LoadWAV_RW() => SDL_LoadWAV_IO()
 * SDL_NewAudioStream() => SDL_CreateAudioStream()
 
 
@@ -525,7 +526,7 @@ The following structures have been renamed:
 The following functions have been renamed:
 * SDL_GameControllerAddMapping() => SDL_AddGamepadMapping()
 * SDL_GameControllerAddMappingsFromFile() => SDL_AddGamepadMappingsFromFile()
-* SDL_GameControllerAddMappingsFromRW() => SDL_AddGamepadMappingsFromRW()
+* SDL_GameControllerAddMappingsFromRW() => SDL_AddGamepadMappingsFromIO()
 * SDL_GameControllerClose() => SDL_CloseGamepad()
 * SDL_GameControllerFromInstanceID() => SDL_GetGamepadFromInstanceID()
 * SDL_GameControllerFromPlayerIndex() => SDL_GetGamepadFromPlayerIndex()
@@ -1152,11 +1153,19 @@ The following symbols have been renamed:
 ## SDL_rwops.h
 
 The following symbols have been renamed:
-* RW_SEEK_CUR => SDL_RW_SEEK_CUR
-* RW_SEEK_END => SDL_RW_SEEK_END
-* RW_SEEK_SET => SDL_RW_SEEK_SET
+* RW_SEEK_CUR => SDL_IO_SEEK_CUR
+* RW_SEEK_END => SDL_IO_SEEK_END
+* RW_SEEK_SET => SDL_IO_SEEK_SET
 
-SDL_RWread and SDL_RWwrite (and SDL_RWops::read, SDL_RWops::write) have a different function signature in SDL3.
+SDL_rwops.h is now named SDL_iostream.h
+
+SDL_RWops is now an opaque structure, and has been renamed to SDL_IOStream. The SDL3 APIs to create an SDL_IOStream (SDL_IOFromFile, etc) are renamed but otherwise still function as they did in SDL2. However, to make a custom SDL_IOStream with app-provided function pointers, call SDL_OpenIO and provide the function pointers through there. To call into an SDL_IOStream's functionality, use the standard APIs (SDL_ReadIO, etc), as the function pointers are internal.
+
+SDL_IOStream is not to be confused with the unrelated standard C++ iostream class!
+
+The RWops function pointers are now in a separate structure called SDL_IOStreamInterface, which is provided to SDL_OpenIO when creating a custom SDL_IOStream implementation. All the functions now take a `void *` userdata argument for their first parameter instead of an SDL_IOStream, since that's now an opaque structure.
+
+SDL_RWread and SDL_RWwrite (and the read and write function pointers) have a different function signature in SDL3, in addition to being renamed.
 
 Previously they looked more like stdio:
 
@@ -1168,55 +1177,67 @@ size_t SDL_RWwrite(SDL_RWops *context, const void *ptr, size_t size, size_t maxn
 But now they look more like POSIX:
 
 ```c
-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);
+size_t SDL_ReadIO(void *userdata, void *ptr, size_t size);
+size_t SDL_WriteIO(void *userdata, const void *ptr, size_t size);
 ```
 
 Code that used to look like this:
-```
+```c
 size_t custom_read(void *ptr, size_t size, size_t nitems, SDL_RWops *stream)
 {
     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)
+```c
+size_t custom_read(void *ptr, size_t size, size_t nitems, SDL_IOStream *stream)
 {
     if (size > 0 && nitems > 0) {
-        return SDL_RWread(stream, ptr, size * nitems) / size;
+        return SDL_ReadIO(stream, ptr, size * nitems) / size;
     }
     return 0;
 }
 ```
 
+SDL_RWops::type was removed; it wasn't meaningful for app-provided implementations at all, and wasn't much use for SDL's internal implementations, either. If you _have_ to identify the type, you can examine the SDL_IOStream's properties to detect built-in implementations.
+
+SDL_IOStreamInterface::close implementations should clean up their own userdata, but not call SDL_CloseIO on themselves; now the contract is always that SDL_CloseIO is called, which calls `->close` before freeing the opaque object.
+
+SDL_AllocRW(), SDL_FreeRW(), SDL_RWclose() and direct access to the `->close` function pointer have been removed from the API, so there's only one path to manage RWops lifetimes now: SDL_OpenIO() and SDL_CloseIO().
+
 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:
 ```c
 #include <stdio.h>
 
+typedef struct IOStreamStdioFPData
+{
+    FILE *fp;
+    SDL_bool autoclose;
+} IOStreamStdioFPData;
 
-static Sint64 SDLCALL stdio_seek(SDL_RWops *context, Sint64 offset, int whence)
+static Sint64 SDLCALL stdio_seek(void *userdata, Sint64 offset, int whence)
 {
+    FILE *fp = ((IOStreamStdioFPData *) userdata)->fp;
     int stdiowhence;
 
     switch (whence) {
-    case SDL_RW_SEEK_SET:
+    case SDL_IO_SEEK_SET:
         stdiowhence = SEEK_SET;
         break;
-    case SDL_RW_SEEK_CUR:
+    case SDL_IO_SEEK_CUR:
         stdiowhence = SEEK_CUR;
         break;
-    case SDL_RW_SEEK_END:
+    case SDL_IO_SEEK_END:
         stdiowhence = SEEK_END;
         break;
     default:
         return SDL_SetError("Unknown value for 'whence'");
     }
 
-    if (fseek((FILE *)context->hidden.stdio.fp, (fseek_off_t)offset, stdiowhence) == 0) {
-        Sint64 pos = ftell((FILE *)context->hidden.stdio.fp);
+    if (fseek(fp, (fseek_off_t)offset, stdiowhence) == 0) {
+        const Sint64 pos = ftell(fp);
         if (pos < 0) {
             return SDL_SetError("Couldn't get stream offset");
         }
@@ -1225,63 +1246,82 @@ static Sint64 SDLCALL stdio_seek(SDL_RWops *context, Sint64 offset, int whence)
     return SDL_Error(SDL_EFSEEK);
 }
 
-static size_t SDLCALL stdio_read(SDL_RWops *context, void *ptr, size_t size)
+static size_t SDLCALL stdio_read(void *userdata, void *ptr, size_t size, SDL_IOStatus *status)
 {
-    size_t bytes;
-
-    bytes = fread(ptr, 1, size, (FILE *)context->hidden.stdio.fp);
-    if (bytes == 0 && ferror((FILE *)context->hidden.stdio.fp)) {
+    FILE *fp = ((IOStreamStdioFPData *) userdata)->fp;
+    const size_t bytes = fread(ptr, 1, size, fp);
+    if (bytes == 0 && ferror(fp)) {
         SDL_Error(SDL_EFREAD);
     }
     return bytes;
 }
 
-static size_t SDLCALL stdio_write(SDL_RWops *context, const void *ptr, size_t size)
+static size_t SDLCALL stdio_write(void *userdata, const void *ptr, size_t size, SDL_IOStatus *status)
 {
-    size_t bytes;
-
-    bytes = fwrite(ptr, 1, size, (FILE *)context->hidden.stdio.fp);
-    if (bytes == 0 && ferror((FILE *)context->hidden.stdio.fp)) {
+    FILE *fp = ((IOStreamStdioFPData *) userdata)->fp;
+    const size_t bytes = fwrite(ptr, 1, size, fp);
+    if (bytes == 0 && ferror(fp)) {
         SDL_Error(SDL_EFWRITE);
     }
     return bytes;
 }
 
-static int SDLCALL stdio_close(SDL_RWops *context)
+static int SDLCALL stdio_close(void *userdata)
 {
+    IOStreamStdioData *rwopsdata = (IOStreamStdioData *) userdata;
     int status = 0;
-    if (context->hidden.stdio.autoclose) {
-        if (fclose((FILE *)context->hidden.stdio.fp) != 0) {
+    if (rwopsdata->autoclose) {
+        if (fclose(rwopsdata->fp) != 0) {
             status = SDL_Error(SDL_EFWRITE);
         }
     }
-    SDL_DestroyRW(context);
     return status;
 }
 
-SDL_RWops *SDL_RWFromFP(void *fp, SDL_bool autoclose)
+SDL_IOStream *SDL_RWFromFP(FILE *fp, SDL_bool autoclose)
 {
-    SDL_RWops *rwops = NULL;
-
-    rwops = SDL_CreateRW();
-    if (rwops != NULL) {
-        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;
+    SDL_IOStreamInterface iface;
+    IOStreamStdioFPData *rwopsdata;
+    SDL_IOStream *rwops;
+
+    rwopsdata = (IOStreamStdioFPData *) SDL_malloc(sizeof (*rwopsdata));
+    if (!rwopsdata) {
+        return NULL;
+    }
+
+    SDL_zero(iface);
+    /* There's no stdio_size because SDL_SizeIO emulates it the same way we'd do it for stdio anyhow. */
+    iface.seek = stdio_seek;
+    iface.read = stdio_read;
+    iface.write = stdio_write;
+    iface.close = stdio_close;
+
+    rwopsdata->fp = fp;
+    rwopsdata->autoclose = autoclose;
+
+    rwops = SDL_OpenIO(&iface, rwopsdata);
+    if (!rwops) {
+        iface.close(rwopsdata);
     }
     return rwops;
 }
 ```
 
+The internal `FILE *` is available through a standard SDL_IOStream property, for streams made through SDL_IOFromFile() that use stdio behind the scenes; apps use this pointer at their own risk and should make sure that SDL and the app are using the same C runtime.
+
+
 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_RWFromConstMem() => SDL_IOFromConstMem()
+* SDL_RWFromFile() => SDL_IOFromFile()
+* SDL_RWFromMem() => SDL_IOFromMem()
+* SDL_RWclose() => SDL_CloseIO()
+* SDL_RWread() => SDL_ReadIO()
+* SDL_RWseek() => SDL_SeekIO()
+* SDL_RWsize() => SDL_SizeIO()
+* SDL_RWtell() => SDL_TellIO()
+* SDL_RWwrite() => SDL_WriteIO()
 * SDL_ReadBE16() => SDL_ReadU16BE()
 * SDL_ReadBE32() => SDL_ReadU32BE()
 * SDL_ReadBE64() => SDL_ReadU64BE()
@@ -1295,6 +1335,10 @@ The following functions have been renamed:
 * SDL_WriteLE32() => SDL_WriteU32LE()
 * SDL_WriteLE64() => SDL_WriteU64LE()
 
+
+The following structures have been renamed:
+* SDL_RWops => SDL_IOStream
+
 ## SDL_sensor.h
 
 SDL_SensorID has changed from Sint32 to Uint32, with an invalid ID being 0.
@@ -1418,8 +1462,10 @@ The following functions have been renamed:
 * SDL_GetColorKey() => SDL_GetSurfaceColorKey()
 * SDL_HasColorKey() => SDL_SurfaceHasColorKey()
 * SDL_HasSurfaceRLE() => SDL_SurfaceHasRLE()
+* SDL_LoadBMP_RW() => SDL_LoadBMP_IO()
 * SDL_LowerBlit() => SDL_BlitSurfaceUnchecked()
 * SDL_LowerBlitScaled() => SDL_BlitSurfaceUncheckedScaled()
+* SDL_SaveBMP_RW() => SDL_SaveBMP_IO()
 * SDL_SetClipRect() => SDL_SetSurfaceClipRect()
 * SDL_SetColorKey() => SDL_SetSurfaceColorKey()
 * SDL_UpperBlit() => SDL_BlitSurface()

+ 1 - 1
docs/README-winrt.md

@@ -42,7 +42,7 @@ Here is a rough list of what works, and what doesn't:
   * threads
   * timers (via SDL_GetTicks(), SDL_AddTimer(), SDL_GetPerformanceCounter(),
     SDL_GetPerformanceFrequency(), etc.)
-  * file I/O via SDL_RWops
+  * file I/O via SDL_IOStream
   * mouse input  (unsupported on Windows Phone)
   * audio, via SDL's WASAPI backend (if you want to record, your app must
     have "Microphone" capabilities enabled in its manifest, and the user must

+ 1 - 1
include/SDL3/SDL.h

@@ -68,7 +68,7 @@
 #include <SDL3/SDL_quit.h>
 #include <SDL3/SDL_rect.h>
 #include <SDL3/SDL_render.h>
-#include <SDL3/SDL_rwops.h>
+#include <SDL3/SDL_iostream.h>
 #include <SDL3/SDL_scancode.h>
 #include <SDL3/SDL_sensor.h>
 #include <SDL3/SDL_surface.h>

+ 6 - 6
include/SDL3/SDL_audio.h

@@ -33,7 +33,7 @@
 #include <SDL3/SDL_error.h>
 #include <SDL3/SDL_mutex.h>
 #include <SDL3/SDL_properties.h>
-#include <SDL3/SDL_rwops.h>
+#include <SDL3/SDL_iostream.h>
 #include <SDL3/SDL_thread.h>
 
 #include <SDL3/SDL_begin_code.h>
@@ -1306,7 +1306,7 @@ extern DECLSPEC int SDLCALL SDL_SetAudioPostmixCallback(SDL_AudioDeviceID devid,
  * Example:
  *
  * ```c
- * SDL_LoadWAV_RW(SDL_RWFromFile("sample.wav", "rb"), 1, &spec, &buf, &len);
+ * SDL_LoadWAV_IO(SDL_IOFromFile("sample.wav", "rb"), 1, &spec, &buf, &len);
  * ```
  *
  * Note that the SDL_LoadWAV function does this same thing for you, but in a
@@ -1317,7 +1317,7 @@ extern DECLSPEC int SDLCALL SDL_SetAudioPostmixCallback(SDL_AudioDeviceID devid,
  * ```
  *
  * \param src The data source for the WAVE data
- * \param freesrc If SDL_TRUE, calls SDL_RWclose() on `src` before returning,
+ * \param closeio If SDL_TRUE, calls SDL_CloseIO() on `src` before returning,
  *                even in the case of an error
  * \param spec A pointer to an SDL_AudioSpec that will be set to the WAVE
  *             data's format details on successful return
@@ -1344,7 +1344,7 @@ extern DECLSPEC int SDLCALL SDL_SetAudioPostmixCallback(SDL_AudioDeviceID devid,
  * \sa SDL_free
  * \sa SDL_LoadWAV
  */
-extern DECLSPEC int SDLCALL SDL_LoadWAV_RW(SDL_RWops * src, SDL_bool freesrc,
+extern DECLSPEC int SDLCALL SDL_LoadWAV_IO(SDL_IOStream * src, SDL_bool closeio,
                                            SDL_AudioSpec * spec, Uint8 ** audio_buf,
                                            Uint32 * audio_len);
 
@@ -1354,7 +1354,7 @@ extern DECLSPEC int SDLCALL SDL_LoadWAV_RW(SDL_RWops * src, SDL_bool freesrc,
  * This is a convenience function that is effectively the same as:
  *
  * ```c
- * SDL_LoadWAV_RW(SDL_RWFromFile(path, "rb"), 1, spec, audio_buf, audio_len);
+ * SDL_LoadWAV_IO(SDL_IOFromFile(path, "rb"), 1, spec, audio_buf, audio_len);
  * ```
  *
  * Note that in SDL2, this was a preprocessor macro and not a real function.
@@ -1383,7 +1383,7 @@ extern DECLSPEC int SDLCALL SDL_LoadWAV_RW(SDL_RWops * src, SDL_bool freesrc,
  * \since This function is available since SDL 3.0.0.
  *
  * \sa SDL_free
- * \sa SDL_LoadWAV_RW
+ * \sa SDL_LoadWAV_IO
  */
 extern DECLSPEC int SDLCALL SDL_LoadWAV(const char *path, SDL_AudioSpec * spec,
                                         Uint8 ** audio_buf, Uint32 * audio_len);

+ 4 - 4
include/SDL3/SDL_gamepad.h

@@ -32,7 +32,7 @@
 #include <SDL3/SDL_error.h>
 #include <SDL3/SDL_joystick.h>
 #include <SDL3/SDL_properties.h>
-#include <SDL3/SDL_rwops.h>
+#include <SDL3/SDL_iostream.h>
 #include <SDL3/SDL_sensor.h>
 
 #include <SDL3/SDL_begin_code.h>
@@ -268,7 +268,7 @@ extern DECLSPEC int SDLCALL SDL_AddGamepadMapping(const char *mapping);
  * constrained environment.
  *
  * \param src the data stream for the mappings to be added
- * \param freesrc if SDL_TRUE, calls SDL_RWclose() on `src` before returning,
+ * \param closeio if SDL_TRUE, calls SDL_CloseIO() 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.
@@ -279,7 +279,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, SDL_bool freesrc);
+extern DECLSPEC int SDLCALL SDL_AddGamepadMappingsFromIO(SDL_IOStream *src, SDL_bool closeio);
 
 /**
  * Load a set of gamepad mappings from a file.
@@ -301,7 +301,7 @@ extern DECLSPEC int SDLCALL SDL_AddGamepadMappingsFromRW(SDL_RWops *src, SDL_boo
  * \since This function is available since SDL 3.0.0.
  *
  * \sa SDL_AddGamepadMapping
- * \sa SDL_AddGamepadMappingsFromRW
+ * \sa SDL_AddGamepadMappingsFromIO
  * \sa SDL_GetGamepadMappingForGUID
  */
 extern DECLSPEC int SDLCALL SDL_AddGamepadMappingsFromFile(const char *file);

+ 3 - 3
include/SDL3/SDL_hints.h

@@ -2261,7 +2261,7 @@ extern "C" {
  *   "ignorezero"  - Like "truncate", but ignore fact chunk if the number of samples is zero.
  *   "ignore"      - Ignore fact chunk entirely. (default)
  *
- * This hint should be set before calling SDL_LoadWAV() or SDL_LoadWAV_RW()
+ * This hint should be set before calling SDL_LoadWAV() or SDL_LoadWAV_IO()
  */
 #define SDL_HINT_WAVE_FACT_CHUNK   "SDL_WAVE_FACT_CHUNK"
 
@@ -2278,7 +2278,7 @@ extern "C" {
  *   "ignore"       - Ignore the RIFF chunk size and always search up to 4 GiB.
  *   "maximum"      - Search for chunks until the end of file. (not recommended)
  *
- * This hint should be set before calling SDL_LoadWAV() or SDL_LoadWAV_RW()
+ * This hint should be set before calling SDL_LoadWAV() or SDL_LoadWAV_IO()
  */
 #define SDL_HINT_WAVE_RIFF_CHUNK_SIZE   "SDL_WAVE_RIFF_CHUNK_SIZE"
 
@@ -2293,7 +2293,7 @@ extern "C" {
  *   "dropframe"  - Decode until the first incomplete sample frame.
  *   "dropblock"  - Decode until the first incomplete block. (default)
  *
- * This hint should be set before calling SDL_LoadWAV() or SDL_LoadWAV_RW()
+ * This hint should be set before calling SDL_LoadWAV() or SDL_LoadWAV_IO()
  */
 #define SDL_HINT_WAVE_TRUNCATION   "SDL_WAVE_TRUNCATION"
 

+ 1 - 1
include/SDL3/SDL_init.h

@@ -70,7 +70,7 @@ typedef enum
  * two may be used interchangeably. Though for readability of your code
  * SDL_InitSubSystem() might be preferred.
  *
- * The file I/O (for example: SDL_RWFromFile) and threading (SDL_CreateThread)
+ * The file I/O (for example: SDL_IOFromFile) and threading (SDL_CreateThread)
  * subsystems are initialized by default. Message boxes
  * (SDL_ShowSimpleMessageBox) also attempt to work without initializing the
  * video subsystem, in hopes of being useful in showing an error dialog when

+ 284 - 318
include/SDL3/SDL_rwops.h → include/SDL3/SDL_iostream.h

@@ -20,14 +20,17 @@
 */
 
 /**
- *  \file SDL_rwops.h
+ *  \file SDL_iostream.h
  *
  *  This file provides a general interface for SDL to read and write
  *  data streams.  It can easily be extended to files, memory, etc.
+ *
+ *  SDL_IOStream is not related to the standard C++ iostream class, other
+ *  than both are abstract interfaces to read/write data.
  */
 
-#ifndef SDL_rwops_h_
-#define SDL_rwops_h_
+#ifndef SDL_iostream_h_
+#define SDL_iostream_h_
 
 #include <SDL3/SDL_stdinc.h>
 #include <SDL3/SDL_error.h>
@@ -39,122 +42,85 @@
 extern "C" {
 #endif
 
-/* 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.
- */
-typedef struct SDL_RWops
+/* SDL_IOStream status, set by a read or write operation */
+typedef enum SDL_IOStatus
+{
+    SDL_IO_STATUS_READY,     /**< Everything is ready */
+    SDL_IO_STATUS_ERROR,     /**< Read or write I/O error */
+    SDL_IO_STATUS_EOF,       /**< End of file */
+    SDL_IO_STATUS_NOT_READY, /**< Non blocking I/O, not ready */
+    SDL_IO_STATUS_READONLY,  /**< Tried to write a read-only buffer */
+    SDL_IO_STATUS_WRITEONLY  /**< Tried to read a write-only buffer */
+} SDL_IOStatus;
+
+typedef struct SDL_IOStreamInterface
 {
     /**
-     *  Return the number of bytes in this rwops
+     *  Return the number of bytes in this SDL_IOStream
      *
      *  \return the total size of the data stream, or -1 on error.
      */
-    Sint64 (SDLCALL *size)(struct SDL_RWops *context);
+    Sint64 (SDLCALL *size)(void *userdata);
 
     /**
      *  Seek to \c offset relative to \c whence, one of stdio's whence values:
-     *  SDL_RW_SEEK_SET, SDL_RW_SEEK_CUR, SDL_RW_SEEK_END
+     *  SDL_IO_SEEK_SET, SDL_IO_SEEK_CUR, SDL_IO_SEEK_END
      *
      *  \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)(void *userdata, Sint64 offset, int whence);
 
     /**
      *  Read up to \c size bytes from the data stream to the area pointed
      *  at by \c ptr.
      *
+     *  On an incomplete read, you should set `*status` to a value from the
+     *  SDL_IOStatus enum. You do not have to explicitly set this on
+     *  a complete, successful read.
+     *
      *  \return the number of bytes read
      */
-    size_t (SDLCALL *read)(struct SDL_RWops *context, void *ptr, size_t size);
+    size_t (SDLCALL *read)(void *userdata, void *ptr, size_t size, SDL_IOStatus *status);
 
     /**
      *  Write exactly \c size bytes from the area pointed at by \c ptr
      *  to data stream.
      *
+     *  On an incomplete write, you should set `*status` to a value from the
+     *  SDL_IOStatus enum. You do not have to explicitly set this on
+     *  a complete, successful write.
+     *
      *  \return the number of bytes written
      */
-    size_t (SDLCALL *write)(struct SDL_RWops *context, const void *ptr, size_t size);
+    size_t (SDLCALL *write)(void *userdata, const void *ptr, size_t size, SDL_IOStatus *status);
 
     /**
-     *  Close and free an allocated SDL_RWops structure.
+     *  Close and free any allocated resources.
+     *
+     *  The SDL_IOStream is still destroyed even if this fails, so clean up anything
+     *  even if flushing to disk returns an error.
      *
      *  \return 0 if successful or -1 on write error when flushing data.
      */
-    int (SDLCALL *close)(struct SDL_RWops *context);
-
-    Uint32 type;
-    Uint32 status;
-    SDL_PropertiesID props;
-    union
-    {
-#ifdef SDL_PLATFORM_ANDROID
-        struct
-        {
-            void *asset;
-        } androidio;
-
-#elif defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK) || defined(SDL_PLATFORM_WINRT)
-        struct
-        {
-            SDL_bool append;
-            void *h;
-            struct
-            {
-                void *data;
-                size_t size;
-                size_t left;
-            } buffer;
-        } windowsio;
-#endif
-
-        struct
-        {
-            SDL_bool autoclose;
-            void *fp;
-        } stdio;
-
-        struct
-        {
-            Uint8 *base;
-            Uint8 *here;
-            Uint8 *stop;
-        } mem;
+    int (SDLCALL *close)(void *userdata);
+} SDL_IOStreamInterface;
 
-        struct
-        {
-            void *data1;
-            void *data2;
-        } unknown;
-    } hidden;
 
-} SDL_RWops;
+/**
+ * This is the read/write operation structure -- opaque, as of SDL3!
+ */
+typedef struct SDL_IOStream SDL_IOStream;
 
 
 /**
- *  \name RWFrom functions
+ *  \name IOFrom functions
  *
- *  Functions to create SDL_RWops structures from various data streams.
+ *  Functions to create SDL_IOStream structures from various data streams.
  */
 /* @{ */
 
 /**
- * Use this function to create a new SDL_RWops structure for reading from
+ * Use this function to create a new SDL_IOStream structure for reading from
  * and/or writing to a named file.
  *
  * The `mode` string is treated roughly the same as in a call to the C
@@ -192,151 +158,171 @@ typedef struct SDL_RWops
  * This function supports Unicode filenames, but they must be encoded in UTF-8
  * format, regardless of the underlying operating system.
  *
- * As a fallback, SDL_RWFromFile() will transparently open a matching filename
+ * As a fallback, SDL_IOFromFile() will transparently open a matching filename
  * in an Android app's `assets`.
  *
- * Closing the SDL_RWops will close the file handle SDL is holding internally.
+ * Closing the SDL_IOStream will close SDL's internal file handle.
+ *
+ * The following properties may be set at creation time by SDL:
+ *
+ * - `SDL_PROP_IOSTREAM_WINDOWS_HANDLE_POINTER`: a pointer, that can be cast
+ *   to a win32 `HANDLE`, that this SDL_IOStream is using to access the filesystem.
+ *   If the program isn't running on Windows, or SDL used some other method
+ *   to access the filesystem, this property will not be set.
+ * - `SDL_PROP_IOSTREAM_STDIO_HANDLE_POINTER`: a pointer, that can be cast
+ *   to a stdio `FILE *`, that this SDL_IOStream is using to access the filesystem.
+ *   If SDL used some other method to access the filesystem, this property
+ *   will not be set. PLEASE NOTE that if SDL is using a different C runtime
+ *   than your app, trying to use this pointer will almost certainly result
+ *   in a crash! This is mostly a problem on Windows; make sure you build SDL
+ *   and your app with the same compiler and settings to avoid it.
+ * - `SDL_PROP_IOSTREAM_ANDROID_AASSET_POINTER`: a pointer, that can be cast
+ *   to an Android NDK `AAsset *`, that this SDL_IOStream is using to access the
+ *   filesystem. If SDL used some other method to access the filesystem, this
+ *   property will not be set.
  *
  * \param file a UTF-8 string representing the filename to open
  * \param mode an ASCII string representing the mode to be used for opening
  *             the file.
- * \returns a pointer to the SDL_RWops structure that is created, or NULL on
+ * \returns a pointer to the SDL_IOStream structure that is created, or NULL on
  *          failure; call SDL_GetError() for more information.
  *
  * \since This function is available since SDL 3.0.0.
  *
- * \sa SDL_RWclose
- * \sa SDL_RWFromConstMem
- * \sa SDL_RWFromMem
- * \sa SDL_RWread
- * \sa SDL_RWseek
- * \sa SDL_RWtell
- * \sa SDL_RWwrite
+ * \sa SDL_IOFromConstMem
+ * \sa SDL_IOFromMem
+ * \sa SDL_CloseIO
+ * \sa SDL_ReadIO
+ * \sa SDL_SeekIO
+ * \sa SDL_TellIO
+ * \sa SDL_WriteIO
  */
-extern DECLSPEC SDL_RWops *SDLCALL SDL_RWFromFile(const char *file, const char *mode);
+extern DECLSPEC SDL_IOStream *SDLCALL SDL_IOFromFile(const char *file, const char *mode);
+
+#define SDL_PROP_IOSTREAM_WINDOWS_HANDLE_POINTER "SDL.iostream.windows.handle"
+#define SDL_PROP_IOSTREAM_STDIO_HANDLE_POINTER "SDL.iostream.stdio.handle"
+#define SDL_PROP_IOSTREAM_ANDROID_AASSET_POINTER "SDL.opstream.android.aasset"
 
 /**
  * Use this function to prepare a read-write memory buffer for use with
- * SDL_RWops.
+ * SDL_IOStream.
  *
- * This function sets up an SDL_RWops struct based on a memory area of a
+ * This function sets up an SDL_IOStream struct based on a memory area of a
  * certain size, for both read and write access.
  *
- * This memory buffer is not copied by the RWops; the pointer you provide must
+ * This memory buffer is not copied by the SDL_IOStream; the pointer you provide must
  * remain valid until you close the stream. Closing the stream will not free
  * the original buffer.
  *
- * If you need to make sure the RWops never writes to the memory buffer, you
- * should use SDL_RWFromConstMem() with a read-only buffer of memory instead.
+ * If you need to make sure the SDL_IOStream never writes to the memory buffer, you
+ * should use SDL_IOFromConstMem() with a read-only buffer of memory instead.
  *
- * \param mem a pointer to a buffer to feed an SDL_RWops stream
+ * \param mem a pointer to a buffer to feed an SDL_IOStream stream
  * \param size the buffer size, in bytes
- * \returns a pointer to a new SDL_RWops structure, or NULL if it fails; call
+ * \returns a pointer to a new SDL_IOStream structure, or NULL if it fails; 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_RWtell
- * \sa SDL_RWwrite
+ * \sa SDL_IOFromConstMem
+ * \sa SDL_IOFromFile
+ * \sa SDL_IOFromMem
+ * \sa SDL_CloseIO
+ * \sa SDL_ReadIO
+ * \sa SDL_SeekIO
+ * \sa SDL_TellIO
+ * \sa SDL_WriteIO
  */
-extern DECLSPEC SDL_RWops *SDLCALL SDL_RWFromMem(void *mem, size_t size);
+extern DECLSPEC SDL_IOStream *SDLCALL SDL_IOFromMem(void *mem, size_t size);
 
 /**
- * Use this function to prepare a read-only memory buffer for use with RWops.
+ * Use this function to prepare a read-only memory buffer for use with SDL_IOStream.
  *
- * This function sets up an SDL_RWops struct based on a memory area of a
+ * This function sets up an SDL_IOStream struct based on a memory area of a
  * certain size. It assumes the memory area is not writable.
  *
- * Attempting to write to this RWops stream will report an error without
+ * Attempting to write to this SDL_IOStream stream will report an error without
  * writing to the memory buffer.
  *
- * This memory buffer is not copied by the RWops; the pointer you provide must
+ * This memory buffer is not copied by the SDL_IOStream; the pointer you provide must
  * remain valid until you close the stream. Closing the stream will not free
  * the original buffer.
  *
- * If you need to write to a memory buffer, you should use SDL_RWFromMem()
+ * If you need to write to a memory buffer, you should use SDL_IOFromMem()
  * with a writable buffer of memory instead.
  *
- * \param mem a pointer to a read-only buffer to feed an SDL_RWops stream
+ * \param mem a pointer to a read-only buffer to feed an SDL_IOStream stream
  * \param size the buffer size, in bytes
- * \returns a pointer to a new SDL_RWops structure, or NULL if it fails; call
+ * \returns a pointer to a new SDL_IOStream structure, or NULL if it fails; 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_RWtell
+ * \sa SDL_IOFromConstMem
+ * \sa SDL_IOFromFile
+ * \sa SDL_IOFromMem
+ * \sa SDL_CloseIO
+ * \sa SDL_ReadIO
+ * \sa SDL_SeekIO
+ * \sa SDL_TellIO
  */
-extern DECLSPEC SDL_RWops *SDLCALL SDL_RWFromConstMem(const void *mem, size_t size);
+extern DECLSPEC SDL_IOStream *SDLCALL SDL_IOFromConstMem(const void *mem, size_t size);
 
-/* @} *//* RWFrom functions */
+/* @} *//* IOFrom functions */
 
 
 /**
- * Use this function to allocate an empty, unpopulated SDL_RWops structure.
+ * Create a custom SDL_IOStream.
  *
  * Applications do not need to use this function unless they are providing
- * their own SDL_RWops implementation. If you just need an SDL_RWops to
+ * their own SDL_IOStream implementation. If you just need an SDL_IOStream to
  * read/write a common data source, you should use the built-in
- * implementations in SDL, like SDL_RWFromFile() or SDL_RWFromMem(), etc.
+ * implementations in SDL, like SDL_IOFromFile() or SDL_IOFromMem(), etc.
  *
- * You must free the returned pointer with SDL_DestroyRW(). Depending on your
- * operating system and compiler, there may be a difference between the
- * malloc() and free() your program uses and the versions SDL calls
- * internally. Trying to mix the two can cause crashing such as segmentation
- * faults. Since all SDL_RWops must free themselves when their **close**
- * method is called, all SDL_RWops must be allocated through this function, so
- * they can all be freed correctly with SDL_DestroyRW().
+ * You must free the returned pointer with SDL_CloseIO().
  *
+ *
+ * \param iface The function pointers that implement this SDL_IOStream.
+ * \param userdata The app-controlled pointer that is passed to iface's functions when called.
  * \returns a pointer to the allocated memory on success, or NULL on failure;
  *          call SDL_GetError() for more information.
  *
  * \since This function is available since SDL 3.0.0.
  *
- * \sa SDL_DestroyRW
+ * \sa SDL_CloseIO
  */
-extern DECLSPEC SDL_RWops *SDLCALL SDL_CreateRW(void);
+extern DECLSPEC SDL_IOStream *SDLCALL SDL_OpenIO(const SDL_IOStreamInterface *iface, void *userdata);
 
 /**
- * Use this function to free an SDL_RWops structure allocated by
- * SDL_CreateRW().
+ * Close and free an allocated SDL_IOStream structure.
  *
- * Applications do not need to use this function unless they are providing
- * 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
- * with them.
+ * SDL_CloseIO() closes and cleans up the SDL_IOStream stream. It releases
+ * any resources used by the stream and frees the SDL_IOStream itself. This
+ * returns 0 on success, or -1 if the stream failed to flush to its output
+ * (e.g. to disk).
  *
- * Only use SDL_DestroyRW() on pointers returned by SDL_CreateRW(). The
- * pointer is invalid as soon as this function returns. Any extra memory
- * allocated during creation of the SDL_RWops is not freed by SDL_DestroyRW();
- * the programmer must be responsible for managing that memory in their
- * **close** method.
+ * Note that if this fails to flush the stream to disk, this function reports
+ * an error, but the SDL_IOStream is still invalid once this function returns.
  *
- * \param context the SDL_RWops structure to be freed
+ * \param context SDL_IOStream structure to close
+ * \returns 0 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.
  *
- * \sa SDL_CreateRW
+ * \sa SDL_IOFromConstMem
+ * \sa SDL_IOFromFile
+ * \sa SDL_IOFromMem
+ * \sa SDL_ReadIO
+ * \sa SDL_SeekIO
+ * \sa SDL_WriteIO
  */
-extern DECLSPEC void SDLCALL SDL_DestroyRW(SDL_RWops *context);
+extern DECLSPEC int SDLCALL SDL_CloseIO(SDL_IOStream *context);
 
 /**
- * Get the properties associated with an SDL_RWops.
+ * Get the properties associated with an SDL_IOStream.
  *
- * \param context a pointer to an SDL_RWops structure
+ * \param context a pointer to an SDL_IOStream structure
  * \returns a valid property ID on success or 0 on failure; call
  *          SDL_GetError() for more information.
  *
@@ -345,83 +331,99 @@ extern DECLSPEC void SDLCALL SDL_DestroyRW(SDL_RWops *context);
  * \sa SDL_GetProperty
  * \sa SDL_SetProperty
  */
-extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetRWProperties(SDL_RWops *context);
+extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetIOProperties(SDL_IOStream *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 */
-#define SDL_RW_SEEK_END 2       /**< Seek relative to the end of data */
+#define SDL_IO_SEEK_SET 0       /**< Seek from the beginning of data */
+#define SDL_IO_SEEK_CUR 1       /**< Seek relative to current read point */
+#define SDL_IO_SEEK_END 2       /**< Seek relative to the end of data */
+
+/**
+ * Query the stream status of an SDL_IOStream.
+ *
+ * This information can be useful to decide if a short read or write was
+ * due to an error, an EOF, or a non-blocking operation that isn't yet
+ * ready to complete.
+ *
+ * An SDL_IOStream's status is only expected to change after a SDL_ReadIO or
+ * SDL_WriteIO call; don't expect it to change if you just call this
+ * query function in a tight loop.
+ *
+ * \param context the SDL_IOStream to query.
+ * \returns an SDL_IOStatus enum with the current state.
+ *
+ * \threadsafety This function should not be called at the same time that
+ *               another thread is operating on the same SDL_IOStream.
+ *
+ * \since This function is available since SDL 3.0.0.
+ */
+extern DECLSPEC SDL_IOStatus SDLCALL SDL_GetIOStatus(SDL_IOStream *context);
 
 /**
- * Use this function to get the size of the data stream in an SDL_RWops.
+ * Use this function to get the size of the data stream in an SDL_IOStream.
  *
- * \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 or a
+ * \param context the SDL_IOStream to get the size of the data stream from
+ * \returns the size of the data stream in the SDL_IOStream 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.
  */
-extern DECLSPEC Sint64 SDLCALL SDL_RWsize(SDL_RWops *context);
+extern DECLSPEC Sint64 SDLCALL SDL_SizeIO(SDL_IOStream *context);
 
 /**
- * Seek within an SDL_RWops data stream.
+ * Seek within an SDL_IOStream data stream.
  *
  * This function seeks to byte `offset`, relative to `whence`.
  *
  * `whence` may be any of the following values:
  *
- * - `SDL_RW_SEEK_SET`: seek from the beginning of data
- * - `SDL_RW_SEEK_CUR`: seek relative to current read point
- * - `SDL_RW_SEEK_END`: seek relative to the end of data
+ * - `SDL_IO_SEEK_SET`: seek from the beginning of data
+ * - `SDL_IO_SEEK_CUR`: seek relative to current read point
+ * - `SDL_IO_SEEK_END`: seek relative to the end of data
  *
  * If this stream can not seek, it will return -1.
  *
- * SDL_RWseek() is actually a wrapper function that calls the SDL_RWops's
- * `seek` method appropriately, to simplify application development.
- *
- * \param context a pointer to an SDL_RWops structure
+ * \param context a pointer to an SDL_IOStream 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`
+ * \param whence any of `SDL_IO_SEEK_SET`, `SDL_IO_SEEK_CUR`,
+ *               `SDL_IO_SEEK_END`
  * \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.
  *
- * \sa SDL_RWclose
- * \sa SDL_RWFromConstMem
- * \sa SDL_RWFromFile
- * \sa SDL_RWFromMem
- * \sa SDL_RWread
- * \sa SDL_RWtell
- * \sa SDL_RWwrite
+ * \sa SDL_IOFromConstMem
+ * \sa SDL_IOFromFile
+ * \sa SDL_IOFromMem
+ * \sa SDL_ReadIO
+ * \sa SDL_TellIO
+ * \sa SDL_WriteIO
  */
-extern DECLSPEC Sint64 SDLCALL SDL_RWseek(SDL_RWops *context, Sint64 offset, int whence);
+extern DECLSPEC Sint64 SDLCALL SDL_SeekIO(SDL_IOStream *context, Sint64 offset, int whence);
 
 /**
- * Determine the current read/write offset in an SDL_RWops data stream.
+ * Determine the current read/write offset in an SDL_IOStream data stream.
  *
- * SDL_RWtell is actually a wrapper function that calls the SDL_RWops's `seek`
- * method, with an offset of 0 bytes from `SDL_RW_SEEK_CUR`, to simplify
+ * SDL_TellIO is actually a wrapper function that calls the SDL_IOStream's `seek`
+ * method, with an offset of 0 bytes from `SDL_IO_SEEK_CUR`, to simplify
  * application development.
  *
- * \param context an SDL_RWops data stream object from which to get the
+ * \param context an SDL_IOStream 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.
  *
  * \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
+ * \sa SDL_IOFromConstMem
+ * \sa SDL_IOFromFile
+ * \sa SDL_IOFromMem
+ * \sa SDL_ReadIO
+ * \sa SDL_SeekIO
+ * \sa SDL_WriteIO
  */
-extern DECLSPEC Sint64 SDLCALL SDL_RWtell(SDL_RWops *context);
+extern DECLSPEC Sint64 SDLCALL SDL_TellIO(SDL_IOStream *context);
 
 /**
  * Read from a data source.
@@ -434,27 +436,23 @@ extern DECLSPEC Sint64 SDLCALL SDL_RWtell(SDL_RWops *context);
  * that this is not an error or end-of-file, and the caller can try again
  * later.
  *
- * SDL_RWread() is actually a function wrapper that calls the SDL_RWops's
- * `read` method appropriately, to simplify application development.
- *
- * \param context a pointer to an SDL_RWops structure
+ * \param context a pointer to an SDL_IOStream 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, or 0 on end of file or other error.
  *
  * \since This function is available since SDL 3.0.0.
  *
- * \sa SDL_RWclose
- * \sa SDL_RWFromConstMem
- * \sa SDL_RWFromFile
- * \sa SDL_RWFromMem
- * \sa SDL_RWseek
- * \sa SDL_RWwrite
+ * \sa SDL_IOFromConstMem
+ * \sa SDL_IOFromFile
+ * \sa SDL_IOFromMem
+ * \sa SDL_SeekIO
+ * \sa SDL_WriteIO
  */
-extern DECLSPEC size_t SDLCALL SDL_RWread(SDL_RWops *context, void *ptr, size_t size);
+extern DECLSPEC size_t SDLCALL SDL_ReadIO(SDL_IOStream *context, void *ptr, size_t size);
 
 /**
- * Write to an SDL_RWops data stream.
+ * Write to an SDL_IOStream data stream.
  *
  * This function writes exactly `size` bytes from the area pointed at by `ptr`
  * to the stream. If this fails for any reason, it'll return less than `size`
@@ -467,14 +465,11 @@ extern DECLSPEC size_t SDLCALL SDL_RWread(SDL_RWops *context, void *ptr, size_t
  * written because it would require blocking, this function returns -2 to
  * distinguish that this is not an error and the caller can try again later.
  *
- * SDL_RWwrite is actually a function wrapper that calls the SDL_RWops's
- * `write` method appropriately, to simplify application development.
- *
  * It is an error to specify a negative `size`, but this parameter is signed
  * so you definitely cannot overflow the return value on a successful run with
  * enormous amounts of data.
  *
- * \param context a pointer to an SDL_RWops structure
+ * \param context a pointer to an SDL_IOStream structure
  * \param ptr a pointer to a buffer containing data to write
  * \param size the number of bytes to write
  * \returns the number of bytes written, which will be less than `num` on
@@ -482,22 +477,21 @@ extern DECLSPEC size_t SDLCALL SDL_RWread(SDL_RWops *context, void *ptr, size_t
  *
  * \since This function is available since SDL 3.0.0.
  *
- * \sa SDL_RWclose
- * \sa SDL_RWFromConstMem
- * \sa SDL_RWFromFile
- * \sa SDL_RWFromMem
- * \sa SDL_RWprint
- * \sa SDL_RWread
- * \sa SDL_RWseek
+ * \sa SDL_IOFromConstMem
+ * \sa SDL_IOFromFile
+ * \sa SDL_IOFromMem
+ * \sa SDL_IOprintf
+ * \sa SDL_ReadIO
+ * \sa SDL_SeekIO
  */
-extern DECLSPEC size_t SDLCALL SDL_RWwrite(SDL_RWops *context, const void *ptr, size_t size);
+extern DECLSPEC size_t SDLCALL SDL_WriteIO(SDL_IOStream *context, const void *ptr, size_t size);
 
 /**
- * Print to an SDL_RWops data stream.
+ * Print to an SDL_IOStream data stream.
  *
  * This function does formatted printing to the stream.
  *
- * \param context a pointer to an SDL_RWops structure
+ * \param context a pointer to an SDL_IOStream structure
  * \param fmt a printf() style format string
  * \param ... additional parameters matching % tokens in the `fmt` string, if
  *            any
@@ -506,22 +500,21 @@ extern DECLSPEC size_t SDLCALL SDL_RWwrite(SDL_RWops *context, const void *ptr,
  *
  * \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
+ * \sa SDL_IOFromConstMem
+ * \sa SDL_IOFromFile
+ * \sa SDL_IOFromMem
+ * \sa SDL_ReadIO
+ * \sa SDL_SeekIO
+ * \sa SDL_WriteIO
  */
-extern DECLSPEC size_t SDLCALL SDL_RWprintf(SDL_RWops *context, SDL_PRINTF_FORMAT_STRING const char *fmt, ...)  SDL_PRINTF_VARARG_FUNC(2);
+extern DECLSPEC size_t SDLCALL SDL_IOprintf(SDL_IOStream *context, SDL_PRINTF_FORMAT_STRING const char *fmt, ...)  SDL_PRINTF_VARARG_FUNC(2);
 
 /**
- * Print to an SDL_RWops data stream.
+ * Print to an SDL_IOStream data stream.
  *
  * This function does formatted printing to the stream.
  *
- * \param context a pointer to an SDL_RWops structure
+ * \param context a pointer to an SDL_IOStream 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()
@@ -529,41 +522,14 @@ extern DECLSPEC size_t SDLCALL SDL_RWprintf(SDL_RWops *context, SDL_PRINTF_FORMA
  *
  * \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, SDL_PRINTF_FORMAT_STRING const char *fmt, va_list ap) SDL_PRINTF_VARARG_FUNCV(2);
-
-/**
- * Close and free an allocated SDL_RWops structure.
- *
- * SDL_RWclose() closes and cleans up the SDL_RWops stream. It releases any
- * resources used by the stream and frees the SDL_RWops itself with
- * SDL_DestroyRW(). This returns 0 on success, or -1 if the stream failed to
- * flush to its output (e.g. to disk).
- *
- * 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.
- *
- * \param context SDL_RWops structure to close
- * \returns 0 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.
- *
- * \sa SDL_RWFromConstMem
- * \sa SDL_RWFromFile
- * \sa SDL_RWFromMem
- * \sa SDL_RWread
- * \sa SDL_RWseek
- * \sa SDL_RWwrite
+ * \sa SDL_IOFromConstMem
+ * \sa SDL_IOFromFile
+ * \sa SDL_IOFromMem
+ * \sa SDL_ReadIO
+ * \sa SDL_SeekIO
+ * \sa SDL_WriteIO
  */
-extern DECLSPEC int SDLCALL SDL_RWclose(SDL_RWops *context);
+extern DECLSPEC size_t SDLCALL SDL_IOvprintf(SDL_IOStream *context, SDL_PRINTF_FORMAT_STRING const char *fmt, va_list ap) SDL_PRINTF_VARARG_FUNCV(2);
 
 /**
  * Load all the data from an SDL data stream.
@@ -574,15 +540,15 @@ extern DECLSPEC int SDLCALL SDL_RWclose(SDL_RWops *context);
  *
  * The data should be freed with SDL_free().
  *
- * \param src the SDL_RWops to read all available data from
+ * \param src the SDL_IOStream to read all available data from
  * \param datasize if not NULL, will store the number of bytes read
- * \param freesrc if SDL_TRUE, calls SDL_RWclose() on `src` before returning,
+ * \param closeio if SDL_TRUE, calls SDL_CloseIO() on `src` before returning,
  *                even in the case of an error
  * \returns the data, or NULL if there was an error.
  *
  * \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_IO(SDL_IOStream *src, size_t *datasize, SDL_bool closeio);
 
 /**
  * Load all the data from a file path.
@@ -609,19 +575,19 @@ extern DECLSPEC void *SDLCALL SDL_LoadFile(const char *file, size_t *datasize);
 /* @{ */
 
 /**
- * Use this function to read a byte from an SDL_RWops.
+ * Use this function to read a byte from an SDL_IOStream.
  *
- * \param src the SDL_RWops to read from
+ * \param src the SDL_IOStream to read from
  * \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);
+extern DECLSPEC SDL_bool SDLCALL SDL_ReadU8(SDL_IOStream *src, Uint8 *value);
 
 /**
- * Use this function to read 16 bits of little-endian data from an SDL_RWops
+ * Use this function to read 16 bits of little-endian data from an SDL_IOStream
  * and return in native format.
  *
  * SDL byteswaps the data only if necessary, so the data returned will be in
@@ -634,10 +600,10 @@ extern DECLSPEC SDL_bool SDLCALL SDL_ReadU8(SDL_RWops *src, Uint8 *value);
  *
  * \since This function is available since SDL 3.0.0.
  */
-extern DECLSPEC SDL_bool SDLCALL SDL_ReadU16LE(SDL_RWops *src, Uint16 *value);
+extern DECLSPEC SDL_bool SDLCALL SDL_ReadU16LE(SDL_IOStream *src, Uint16 *value);
 
 /**
- * Use this function to read 16 bits of little-endian data from an SDL_RWops
+ * Use this function to read 16 bits of little-endian data from an SDL_IOStream
  * and return in native format.
  *
  * SDL byteswaps the data only if necessary, so the data returned will be in
@@ -650,10 +616,10 @@ extern DECLSPEC SDL_bool SDLCALL SDL_ReadU16LE(SDL_RWops *src, Uint16 *value);
  *
  * \since This function is available since SDL 3.0.0.
  */
-extern DECLSPEC SDL_bool SDLCALL SDL_ReadS16LE(SDL_RWops *src, Sint16 *value);
+extern DECLSPEC SDL_bool SDLCALL SDL_ReadS16LE(SDL_IOStream *src, Sint16 *value);
 
 /**
- * Use this function to read 16 bits of big-endian data from an SDL_RWops and
+ * Use this function to read 16 bits of big-endian data from an SDL_IOStream and
  * return in native format.
  *
  * SDL byteswaps the data only if necessary, so the data returned will be in
@@ -666,10 +632,10 @@ extern DECLSPEC SDL_bool SDLCALL SDL_ReadS16LE(SDL_RWops *src, Sint16 *value);
  *
  * \since This function is available since SDL 3.0.0.
  */
-extern DECLSPEC SDL_bool SDLCALL SDL_ReadU16BE(SDL_RWops *src, Uint16 *value);
+extern DECLSPEC SDL_bool SDLCALL SDL_ReadU16BE(SDL_IOStream *src, Uint16 *value);
 
 /**
- * Use this function to read 16 bits of big-endian data from an SDL_RWops and
+ * Use this function to read 16 bits of big-endian data from an SDL_IOStream and
  * return in native format.
  *
  * SDL byteswaps the data only if necessary, so the data returned will be in
@@ -682,10 +648,10 @@ extern DECLSPEC SDL_bool SDLCALL SDL_ReadU16BE(SDL_RWops *src, Uint16 *value);
  *
  * \since This function is available since SDL 3.0.0.
  */
-extern DECLSPEC SDL_bool SDLCALL SDL_ReadS16BE(SDL_RWops *src, Sint16 *value);
+extern DECLSPEC SDL_bool SDLCALL SDL_ReadS16BE(SDL_IOStream *src, Sint16 *value);
 
 /**
- * Use this function to read 32 bits of little-endian data from an SDL_RWops
+ * Use this function to read 32 bits of little-endian data from an SDL_IOStream
  * and return in native format.
  *
  * SDL byteswaps the data only if necessary, so the data returned will be in
@@ -698,10 +664,10 @@ extern DECLSPEC SDL_bool SDLCALL SDL_ReadS16BE(SDL_RWops *src, Sint16 *value);
  *
  * \since This function is available since SDL 3.0.0.
  */
-extern DECLSPEC SDL_bool SDLCALL SDL_ReadU32LE(SDL_RWops *src, Uint32 *value);
+extern DECLSPEC SDL_bool SDLCALL SDL_ReadU32LE(SDL_IOStream *src, Uint32 *value);
 
 /**
- * Use this function to read 32 bits of little-endian data from an SDL_RWops
+ * Use this function to read 32 bits of little-endian data from an SDL_IOStream
  * and return in native format.
  *
  * SDL byteswaps the data only if necessary, so the data returned will be in
@@ -714,10 +680,10 @@ extern DECLSPEC SDL_bool SDLCALL SDL_ReadU32LE(SDL_RWops *src, Uint32 *value);
  *
  * \since This function is available since SDL 3.0.0.
  */
-extern DECLSPEC SDL_bool SDLCALL SDL_ReadS32LE(SDL_RWops *src, Sint32 *value);
+extern DECLSPEC SDL_bool SDLCALL SDL_ReadS32LE(SDL_IOStream *src, Sint32 *value);
 
 /**
- * Use this function to read 32 bits of big-endian data from an SDL_RWops and
+ * Use this function to read 32 bits of big-endian data from an SDL_IOStream and
  * return in native format.
  *
  * SDL byteswaps the data only if necessary, so the data returned will be in
@@ -730,10 +696,10 @@ extern DECLSPEC SDL_bool SDLCALL SDL_ReadS32LE(SDL_RWops *src, Sint32 *value);
  *
  * \since This function is available since SDL 3.0.0.
  */
-extern DECLSPEC SDL_bool SDLCALL SDL_ReadU32BE(SDL_RWops *src, Uint32 *value);
+extern DECLSPEC SDL_bool SDLCALL SDL_ReadU32BE(SDL_IOStream *src, Uint32 *value);
 
 /**
- * Use this function to read 32 bits of big-endian data from an SDL_RWops and
+ * Use this function to read 32 bits of big-endian data from an SDL_IOStream and
  * return in native format.
  *
  * SDL byteswaps the data only if necessary, so the data returned will be in
@@ -746,10 +712,10 @@ extern DECLSPEC SDL_bool SDLCALL SDL_ReadU32BE(SDL_RWops *src, Uint32 *value);
  *
  * \since This function is available since SDL 3.0.0.
  */
-extern DECLSPEC SDL_bool SDLCALL SDL_ReadS32BE(SDL_RWops *src, Sint32 *value);
+extern DECLSPEC SDL_bool SDLCALL SDL_ReadS32BE(SDL_IOStream *src, Sint32 *value);
 
 /**
- * Use this function to read 64 bits of little-endian data from an SDL_RWops
+ * Use this function to read 64 bits of little-endian data from an SDL_IOStream
  * and return in native format.
  *
  * SDL byteswaps the data only if necessary, so the data returned will be in
@@ -762,10 +728,10 @@ extern DECLSPEC SDL_bool SDLCALL SDL_ReadS32BE(SDL_RWops *src, Sint32 *value);
  *
  * \since This function is available since SDL 3.0.0.
  */
-extern DECLSPEC SDL_bool SDLCALL SDL_ReadU64LE(SDL_RWops *src, Uint64 *value);
+extern DECLSPEC SDL_bool SDLCALL SDL_ReadU64LE(SDL_IOStream *src, Uint64 *value);
 
 /**
- * Use this function to read 64 bits of little-endian data from an SDL_RWops
+ * Use this function to read 64 bits of little-endian data from an SDL_IOStream
  * and return in native format.
  *
  * SDL byteswaps the data only if necessary, so the data returned will be in
@@ -778,10 +744,10 @@ extern DECLSPEC SDL_bool SDLCALL SDL_ReadU64LE(SDL_RWops *src, Uint64 *value);
  *
  * \since This function is available since SDL 3.0.0.
  */
-extern DECLSPEC SDL_bool SDLCALL SDL_ReadS64LE(SDL_RWops *src, Sint64 *value);
+extern DECLSPEC SDL_bool SDLCALL SDL_ReadS64LE(SDL_IOStream *src, Sint64 *value);
 
 /**
- * Use this function to read 64 bits of big-endian data from an SDL_RWops and
+ * Use this function to read 64 bits of big-endian data from an SDL_IOStream and
  * return in native format.
  *
  * SDL byteswaps the data only if necessary, so the data returned will be in
@@ -794,10 +760,10 @@ extern DECLSPEC SDL_bool SDLCALL SDL_ReadS64LE(SDL_RWops *src, Sint64 *value);
  *
  * \since This function is available since SDL 3.0.0.
  */
-extern DECLSPEC SDL_bool SDLCALL SDL_ReadU64BE(SDL_RWops *src, Uint64 *value);
+extern DECLSPEC SDL_bool SDLCALL SDL_ReadU64BE(SDL_IOStream *src, Uint64 *value);
 
 /**
- * Use this function to read 64 bits of big-endian data from an SDL_RWops and
+ * Use this function to read 64 bits of big-endian data from an SDL_IOStream and
  * return in native format.
  *
  * SDL byteswaps the data only if necessary, so the data returned will be in
@@ -810,7 +776,7 @@ extern DECLSPEC SDL_bool SDLCALL SDL_ReadU64BE(SDL_RWops *src, Uint64 *value);
  *
  * \since This function is available since SDL 3.0.0.
  */
-extern DECLSPEC SDL_bool SDLCALL SDL_ReadS64BE(SDL_RWops *src, Sint64 *value);
+extern DECLSPEC SDL_bool SDLCALL SDL_ReadS64BE(SDL_IOStream *src, Sint64 *value);
 /* @} *//* Read endian functions */
 
 /**
@@ -821,19 +787,19 @@ extern DECLSPEC SDL_bool SDLCALL SDL_ReadS64BE(SDL_RWops *src, Sint64 *value);
 /* @{ */
 
 /**
- * Use this function to write a byte to an SDL_RWops.
+ * Use this function to write a byte to an SDL_IOStream.
  *
- * \param dst the SDL_RWops to write to
+ * \param dst the SDL_IOStream to write to
  * \param value the byte value to write
  * \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_WriteU8(SDL_RWops *dst, Uint8 value);
+extern DECLSPEC SDL_bool SDLCALL SDL_WriteU8(SDL_IOStream *dst, Uint8 value);
 
 /**
- * Use this function to write 16 bits in native format to an SDL_RWops as
+ * Use this function to write 16 bits in native format to an SDL_IOStream as
  * little-endian data.
  *
  * SDL byteswaps the data only if necessary, so the application always
@@ -847,10 +813,10 @@ extern DECLSPEC SDL_bool SDLCALL SDL_WriteU8(SDL_RWops *dst, Uint8 value);
  *
  * \since This function is available since SDL 3.0.0.
  */
-extern DECLSPEC SDL_bool SDLCALL SDL_WriteU16LE(SDL_RWops *dst, Uint16 value);
+extern DECLSPEC SDL_bool SDLCALL SDL_WriteU16LE(SDL_IOStream *dst, Uint16 value);
 
 /**
- * Use this function to write 16 bits in native format to an SDL_RWops as
+ * Use this function to write 16 bits in native format to an SDL_IOStream as
  * little-endian data.
  *
  * SDL byteswaps the data only if necessary, so the application always
@@ -864,10 +830,10 @@ extern DECLSPEC SDL_bool SDLCALL SDL_WriteU16LE(SDL_RWops *dst, Uint16 value);
  *
  * \since This function is available since SDL 3.0.0.
  */
-extern DECLSPEC SDL_bool SDLCALL SDL_WriteS16LE(SDL_RWops *dst, Sint16 value);
+extern DECLSPEC SDL_bool SDLCALL SDL_WriteS16LE(SDL_IOStream *dst, Sint16 value);
 
 /**
- * Use this function to write 16 bits in native format to an SDL_RWops as
+ * Use this function to write 16 bits in native format to an SDL_IOStream as
  * big-endian data.
  *
  * SDL byteswaps the data only if necessary, so the application always
@@ -880,10 +846,10 @@ extern DECLSPEC SDL_bool SDLCALL SDL_WriteS16LE(SDL_RWops *dst, Sint16 value);
  *
  * \since This function is available since SDL 3.0.0.
  */
-extern DECLSPEC SDL_bool SDLCALL SDL_WriteU16BE(SDL_RWops *dst, Uint16 value);
+extern DECLSPEC SDL_bool SDLCALL SDL_WriteU16BE(SDL_IOStream *dst, Uint16 value);
 
 /**
- * Use this function to write 16 bits in native format to an SDL_RWops as
+ * Use this function to write 16 bits in native format to an SDL_IOStream as
  * big-endian data.
  *
  * SDL byteswaps the data only if necessary, so the application always
@@ -896,10 +862,10 @@ extern DECLSPEC SDL_bool SDLCALL SDL_WriteU16BE(SDL_RWops *dst, Uint16 value);
  *
  * \since This function is available since SDL 3.0.0.
  */
-extern DECLSPEC SDL_bool SDLCALL SDL_WriteS16BE(SDL_RWops *dst, Sint16 value);
+extern DECLSPEC SDL_bool SDLCALL SDL_WriteS16BE(SDL_IOStream *dst, Sint16 value);
 
 /**
- * Use this function to write 32 bits in native format to an SDL_RWops as
+ * Use this function to write 32 bits in native format to an SDL_IOStream as
  * little-endian data.
  *
  * SDL byteswaps the data only if necessary, so the application always
@@ -913,10 +879,10 @@ extern DECLSPEC SDL_bool SDLCALL SDL_WriteS16BE(SDL_RWops *dst, Sint16 value);
  *
  * \since This function is available since SDL 3.0.0.
  */
-extern DECLSPEC SDL_bool SDLCALL SDL_WriteU32LE(SDL_RWops *dst, Uint32 value);
+extern DECLSPEC SDL_bool SDLCALL SDL_WriteU32LE(SDL_IOStream *dst, Uint32 value);
 
 /**
- * Use this function to write 32 bits in native format to an SDL_RWops as
+ * Use this function to write 32 bits in native format to an SDL_IOStream as
  * little-endian data.
  *
  * SDL byteswaps the data only if necessary, so the application always
@@ -930,10 +896,10 @@ extern DECLSPEC SDL_bool SDLCALL SDL_WriteU32LE(SDL_RWops *dst, Uint32 value);
  *
  * \since This function is available since SDL 3.0.0.
  */
-extern DECLSPEC SDL_bool SDLCALL SDL_WriteS32LE(SDL_RWops *dst, Sint32 value);
+extern DECLSPEC SDL_bool SDLCALL SDL_WriteS32LE(SDL_IOStream *dst, Sint32 value);
 
 /**
- * Use this function to write 32 bits in native format to an SDL_RWops as
+ * Use this function to write 32 bits in native format to an SDL_IOStream as
  * big-endian data.
  *
  * SDL byteswaps the data only if necessary, so the application always
@@ -946,10 +912,10 @@ extern DECLSPEC SDL_bool SDLCALL SDL_WriteS32LE(SDL_RWops *dst, Sint32 value);
  *
  * \since This function is available since SDL 3.0.0.
  */
-extern DECLSPEC SDL_bool SDLCALL SDL_WriteU32BE(SDL_RWops *dst, Uint32 value);
+extern DECLSPEC SDL_bool SDLCALL SDL_WriteU32BE(SDL_IOStream *dst, Uint32 value);
 
 /**
- * Use this function to write 32 bits in native format to an SDL_RWops as
+ * Use this function to write 32 bits in native format to an SDL_IOStream as
  * big-endian data.
  *
  * SDL byteswaps the data only if necessary, so the application always
@@ -962,10 +928,10 @@ extern DECLSPEC SDL_bool SDLCALL SDL_WriteU32BE(SDL_RWops *dst, Uint32 value);
  *
  * \since This function is available since SDL 3.0.0.
  */
-extern DECLSPEC SDL_bool SDLCALL SDL_WriteS32BE(SDL_RWops *dst, Sint32 value);
+extern DECLSPEC SDL_bool SDLCALL SDL_WriteS32BE(SDL_IOStream *dst, Sint32 value);
 
 /**
- * Use this function to write 64 bits in native format to an SDL_RWops as
+ * Use this function to write 64 bits in native format to an SDL_IOStream as
  * little-endian data.
  *
  * SDL byteswaps the data only if necessary, so the application always
@@ -979,10 +945,10 @@ extern DECLSPEC SDL_bool SDLCALL SDL_WriteS32BE(SDL_RWops *dst, Sint32 value);
  *
  * \since This function is available since SDL 3.0.0.
  */
-extern DECLSPEC SDL_bool SDLCALL SDL_WriteU64LE(SDL_RWops *dst, Uint64 value);
+extern DECLSPEC SDL_bool SDLCALL SDL_WriteU64LE(SDL_IOStream *dst, Uint64 value);
 
 /**
- * Use this function to write 64 bits in native format to an SDL_RWops as
+ * Use this function to write 64 bits in native format to an SDL_IOStream as
  * little-endian data.
  *
  * SDL byteswaps the data only if necessary, so the application always
@@ -996,10 +962,10 @@ extern DECLSPEC SDL_bool SDLCALL SDL_WriteU64LE(SDL_RWops *dst, Uint64 value);
  *
  * \since This function is available since SDL 3.0.0.
  */
-extern DECLSPEC SDL_bool SDLCALL SDL_WriteS64LE(SDL_RWops *dst, Sint64 value);
+extern DECLSPEC SDL_bool SDLCALL SDL_WriteS64LE(SDL_IOStream *dst, Sint64 value);
 
 /**
- * Use this function to write 64 bits in native format to an SDL_RWops as
+ * Use this function to write 64 bits in native format to an SDL_IOStream as
  * big-endian data.
  *
  * SDL byteswaps the data only if necessary, so the application always
@@ -1012,10 +978,10 @@ extern DECLSPEC SDL_bool SDLCALL SDL_WriteS64LE(SDL_RWops *dst, Sint64 value);
  *
  * \since This function is available since SDL 3.0.0.
  */
-extern DECLSPEC SDL_bool SDLCALL SDL_WriteU64BE(SDL_RWops *dst, Uint64 value);
+extern DECLSPEC SDL_bool SDLCALL SDL_WriteU64BE(SDL_IOStream *dst, Uint64 value);
 
 /**
- * Use this function to write 64 bits in native format to an SDL_RWops as
+ * Use this function to write 64 bits in native format to an SDL_IOStream as
  * big-endian data.
  *
  * SDL byteswaps the data only if necessary, so the application always
@@ -1028,7 +994,7 @@ extern DECLSPEC SDL_bool SDLCALL SDL_WriteU64BE(SDL_RWops *dst, Uint64 value);
  *
  * \since This function is available since SDL 3.0.0.
  */
-extern DECLSPEC SDL_bool SDLCALL SDL_WriteS64BE(SDL_RWops *dst, Sint64 value);
+extern DECLSPEC SDL_bool SDLCALL SDL_WriteS64BE(SDL_IOStream *dst, Sint64 value);
 
 /* @} *//* Write endian functions */
 
@@ -1038,4 +1004,4 @@ extern DECLSPEC SDL_bool SDLCALL SDL_WriteS64BE(SDL_RWops *dst, Sint64 value);
 #endif
 #include <SDL3/SDL_close_code.h>
 
-#endif /* SDL_rwops_h_ */
+#endif /* SDL_iostream_h_ */

+ 34 - 12
include/SDL3/SDL_oldnames.h

@@ -69,6 +69,7 @@
 #define SDL_AudioStreamPut SDL_PutAudioStreamData
 #define SDL_FreeAudioStream SDL_DestroyAudioStream
 #define SDL_FreeWAV SDL_free
+#define SDL_LoadWAV_RW SDL_LoadWAV_IO
 #define SDL_NewAudioStream SDL_CreateAudioStream
 
 /* ##SDL_events.h */
@@ -204,7 +205,7 @@
 #define SDL_GameController SDL_Gamepad
 #define SDL_GameControllerAddMapping SDL_AddGamepadMapping
 #define SDL_GameControllerAddMappingsFromFile SDL_AddGamepadMappingsFromFile
-#define SDL_GameControllerAddMappingsFromRW SDL_AddGamepadMappingsFromRW
+#define SDL_GameControllerAddMappingsFromRW SDL_AddGamepadMappingsFromIO
 #define SDL_GameControllerAxis SDL_GamepadAxis
 #define SDL_GameControllerBindType SDL_GamepadBindingType
 #define SDL_GameControllerButton SDL_GamepadButton
@@ -449,11 +450,19 @@
 #define SDL_ScaleModeNearest SDL_SCALEMODE_NEAREST
 
 /* ##SDL_rwops.h */
-#define RW_SEEK_CUR SDL_RW_SEEK_CUR
-#define RW_SEEK_END SDL_RW_SEEK_END
-#define RW_SEEK_SET SDL_RW_SEEK_SET
-#define SDL_AllocRW SDL_CreateRW
-#define SDL_FreeRW SDL_DestroyRW
+#define RW_SEEK_CUR SDL_IO_SEEK_CUR
+#define RW_SEEK_END SDL_IO_SEEK_END
+#define RW_SEEK_SET SDL_IO_SEEK_SET
+#define SDL_RWFromConstMem SDL_IOFromConstMem
+#define SDL_RWFromFile SDL_IOFromFile
+#define SDL_RWFromMem SDL_IOFromMem
+#define SDL_RWclose SDL_CloseIO
+#define SDL_RWops SDL_IOStream
+#define SDL_RWread SDL_ReadIO
+#define SDL_RWseek SDL_SeekIO
+#define SDL_RWsize SDL_SizeIO
+#define SDL_RWtell SDL_TellIO
+#define SDL_RWwrite SDL_WriteIO
 #define SDL_ReadBE16 SDL_ReadU16BE
 #define SDL_ReadBE32 SDL_ReadU32BE
 #define SDL_ReadBE64 SDL_ReadU64BE
@@ -489,8 +498,10 @@
 #define SDL_GetColorKey SDL_GetSurfaceColorKey
 #define SDL_HasColorKey SDL_SurfaceHasColorKey
 #define SDL_HasSurfaceRLE SDL_SurfaceHasRLE
+#define SDL_LoadBMP_RW SDL_LoadBMP_IO
 #define SDL_LowerBlit SDL_BlitSurfaceUnchecked
 #define SDL_LowerBlitScaled SDL_BlitSurfaceUncheckedScaled
+#define SDL_SaveBMP_RW SDL_SaveBMP_IO
 #define SDL_SetClipRect SDL_SetSurfaceClipRect
 #define SDL_SetColorKey SDL_SetSurfaceColorKey
 #define SDL_UpperBlit SDL_BlitSurface
@@ -554,6 +565,7 @@
 #define SDL_AudioStreamPut SDL_AudioStreamPut_renamed_SDL_PutAudioStreamData
 #define SDL_FreeAudioStream SDL_FreeAudioStream_renamed_SDL_DestroyAudioStream
 #define SDL_FreeWAV SDL_FreeWAV_renamed_SDL_free
+#define SDL_LoadWAV_RW SDL_LoadWAV_RW_renamed_SDL_LoadWAV_IO
 #define SDL_NewAudioStream SDL_NewAudioStream_renamed_SDL_CreateAudioStream
 
 /* ##SDL_events.h */
@@ -689,7 +701,7 @@
 #define SDL_GameController SDL_GameController_renamed_SDL_Gamepad
 #define SDL_GameControllerAddMapping SDL_GameControllerAddMapping_renamed_SDL_AddGamepadMapping
 #define SDL_GameControllerAddMappingsFromFile SDL_GameControllerAddMappingsFromFile_renamed_SDL_AddGamepadMappingsFromFile
-#define SDL_GameControllerAddMappingsFromRW SDL_GameControllerAddMappingsFromRW_renamed_SDL_AddGamepadMappingsFromRW
+#define SDL_GameControllerAddMappingsFromRW SDL_GameControllerAddMappingsFromRW_renamed_SDL_AddGamepadMappingsFromIO
 #define SDL_GameControllerAxis SDL_GameControllerAxis_renamed_SDL_GamepadAxis
 #define SDL_GameControllerBindType SDL_GameControllerBindType_renamed_SDL_GamepadBindingType
 #define SDL_GameControllerButton SDL_GameControllerButton_renamed_SDL_GamepadButton
@@ -935,11 +947,19 @@
 #define SDL_ScaleModeNearest SDL_ScaleModeNearest_renamed_SDL_SCALEMODE_NEAREST
 
 /* ##SDL_rwops.h */
-#define RW_SEEK_CUR RW_SEEK_CUR_renamed_SDL_RW_SEEK_CUR
-#define RW_SEEK_END RW_SEEK_END_renamed_SDL_RW_SEEK_END
-#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 RW_SEEK_CUR RW_SEEK_CUR_renamed_SDL_IO_SEEK_CUR
+#define RW_SEEK_END RW_SEEK_END_renamed_SDL_IO_SEEK_END
+#define RW_SEEK_SET RW_SEEK_SET_renamed_SDL_IO_SEEK_SET
+#define SDL_RWFromConstMem SDL_RWFromConstMem_renamed_SDL_IOFromConstMem
+#define SDL_RWFromFile SDL_RWFromFile_renamed_SDL_IOFromFile
+#define SDL_RWFromMem SDL_RWFromMem_renamed_SDL_IOFromMem
+#define SDL_RWclose SDL_RWclose_renamed_SDL_CloseIO
+#define SDL_RWops SDL_RWops_renamed_SDL_IOStream
+#define SDL_RWread SDL_RWread_renamed_SDL_ReadIO
+#define SDL_RWseek SDL_RWseek_renamed_SDL_SeekIO
+#define SDL_RWsize SDL_RWsize_renamed_SDL_SizeIO
+#define SDL_RWtell SDL_RWtell_renamed_SDL_TellIO
+#define SDL_RWwrite SDL_RWwrite_renamed_SDL_WriteIO
 #define SDL_ReadBE16 SDL_ReadBE16_renamed_SDL_ReadU16BE
 #define SDL_ReadBE32 SDL_ReadBE32_renamed_SDL_ReadU32BE
 #define SDL_ReadBE64 SDL_ReadBE64_renamed_SDL_ReadU64BE
@@ -975,8 +995,10 @@
 #define SDL_GetColorKey SDL_GetColorKey_renamed_SDL_GetSurfaceColorKey
 #define SDL_HasColorKey SDL_HasColorKey_renamed_SDL_SurfaceHasColorKey
 #define SDL_HasSurfaceRLE SDL_HasSurfaceRLE_renamed_SDL_SurfaceHasRLE
+#define SDL_LoadBMP_RW SDL_LoadBMP_RW_renamed_SDL_LoadBMP_IO
 #define SDL_LowerBlit SDL_LowerBlit_renamed_SDL_BlitSurfaceUnchecked
 #define SDL_LowerBlitScaled SDL_LowerBlitScaled_renamed_SDL_BlitSurfaceUncheckedScaled
+#define SDL_SaveBMP_RW SDL_SaveBMP_RW_renamed_SDL_SaveBMP_IO
 #define SDL_SetClipRect SDL_SetClipRect_renamed_SDL_SetSurfaceClipRect
 #define SDL_SetColorKey SDL_SetColorKey_renamed_SDL_SetSurfaceColorKey
 #define SDL_UpperBlit SDL_UpperBlit_renamed_SDL_BlitSurface

+ 10 - 10
include/SDL3/SDL_surface.h

@@ -33,7 +33,7 @@
 #include <SDL3/SDL_pixels.h>
 #include <SDL3/SDL_properties.h>
 #include <SDL3/SDL_rect.h>
-#include <SDL3/SDL_rwops.h>
+#include <SDL3/SDL_iostream.h>
 
 #include <SDL3/SDL_begin_code.h>
 /* Set up for C function definitions, even when using C++ */
@@ -196,7 +196,7 @@ extern DECLSPEC SDL_Surface *SDLCALL SDL_CreateSurfaceFrom
  * \sa SDL_CreateSurface
  * \sa SDL_CreateSurfaceFrom
  * \sa SDL_LoadBMP
- * \sa SDL_LoadBMP_RW
+ * \sa SDL_LoadBMP_IO
  */
 extern DECLSPEC void SDLCALL SDL_DestroySurface(SDL_Surface *surface);
 
@@ -328,7 +328,7 @@ extern DECLSPEC void SDLCALL SDL_UnlockSurface(SDL_Surface *surface);
  * will result in a memory leak.
  *
  * \param src the data stream for the surface
- * \param freesrc if SDL_TRUE, calls SDL_RWclose() on `src` before returning,
+ * \param closeio if SDL_TRUE, calls SDL_CloseIO() on `src` before returning,
  *                even in the case of an error
  * \returns a pointer to a new SDL_Surface structure or NULL if there was an
  *          error; call SDL_GetError() for more information.
@@ -337,9 +337,9 @@ extern DECLSPEC void SDLCALL SDL_UnlockSurface(SDL_Surface *surface);
  *
  * \sa SDL_DestroySurface
  * \sa SDL_LoadBMP
- * \sa SDL_SaveBMP_RW
+ * \sa SDL_SaveBMP_IO
  */
-extern DECLSPEC SDL_Surface *SDLCALL SDL_LoadBMP_RW(SDL_RWops *src, SDL_bool freesrc);
+extern DECLSPEC SDL_Surface *SDLCALL SDL_LoadBMP_IO(SDL_IOStream *src, SDL_bool closeio);
 
 /**
  * Load a BMP image from a file.
@@ -354,7 +354,7 @@ extern DECLSPEC SDL_Surface *SDLCALL SDL_LoadBMP_RW(SDL_RWops *src, SDL_bool fre
  * \since This function is available since SDL 3.0.0.
  *
  * \sa SDL_DestroySurface
- * \sa SDL_LoadBMP_RW
+ * \sa SDL_LoadBMP_IO
  * \sa SDL_SaveBMP
  */
 extern DECLSPEC SDL_Surface *SDLCALL SDL_LoadBMP(const char *file);
@@ -370,17 +370,17 @@ extern DECLSPEC SDL_Surface *SDLCALL SDL_LoadBMP(const char *file);
  *
  * \param surface the SDL_Surface structure containing the image to be saved
  * \param dst a data stream to save to
- * \param freedst if SDL_TRUE, calls SDL_RWclose() on `dst` before returning,
+ * \param closeio if SDL_TRUE, calls SDL_CloseIO() on `dst` before returning,
  *                even in the case of an error
  * \returns 0 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.
  *
- * \sa SDL_LoadBMP_RW
+ * \sa SDL_LoadBMP_IO
  * \sa SDL_SaveBMP
  */
-extern DECLSPEC int SDLCALL SDL_SaveBMP_RW(SDL_Surface *surface, SDL_RWops *dst, SDL_bool freedst);
+extern DECLSPEC int SDLCALL SDL_SaveBMP_IO(SDL_Surface *surface, SDL_IOStream *dst, SDL_bool closeio);
 
 /**
  * Save a surface to a file.
@@ -399,7 +399,7 @@ extern DECLSPEC int SDLCALL SDL_SaveBMP_RW(SDL_Surface *surface, SDL_RWops *dst,
  * \since This function is available since SDL 3.0.0.
  *
  * \sa SDL_LoadBMP
- * \sa SDL_SaveBMP_RW
+ * \sa SDL_SaveBMP_IO
  */
 extern DECLSPEC int SDLCALL SDL_SaveBMP(SDL_Surface *surface, const char *file);
 

+ 25 - 25
src/audio/SDL_wave.c

@@ -1502,7 +1502,7 @@ static void WaveFreeChunkData(WaveChunk *chunk)
     chunk->size = 0;
 }
 
-static int WaveNextChunk(SDL_RWops *src, WaveChunk *chunk)
+static int WaveNextChunk(SDL_IOStream *src, WaveChunk *chunk)
 {
     Uint32 chunkheader[2];
     Sint64 nextposition = chunk->position + chunk->length;
@@ -1520,10 +1520,10 @@ static int WaveNextChunk(SDL_RWops *src, WaveChunk *chunk)
         nextposition++;
     }
 
-    if (SDL_RWseek(src, nextposition, SDL_RW_SEEK_SET) != nextposition) {
+    if (SDL_SeekIO(src, nextposition, SDL_IO_SEEK_SET) != nextposition) {
         /* Not sure how we ended up here. Just abort. */
         return -2;
-    } else if (SDL_RWread(src, chunkheader, sizeof(Uint32) * 2) != (sizeof(Uint32) * 2)) {
+    } else if (SDL_ReadIO(src, chunkheader, sizeof(Uint32) * 2) != (sizeof(Uint32) * 2)) {
         return -1;
     }
 
@@ -1534,7 +1534,7 @@ static int WaveNextChunk(SDL_RWops *src, WaveChunk *chunk)
     return 0;
 }
 
-static int WaveReadPartialChunkData(SDL_RWops *src, WaveChunk *chunk, size_t length)
+static int WaveReadPartialChunkData(SDL_IOStream *src, WaveChunk *chunk, size_t length)
 {
     WaveFreeChunkData(chunk);
 
@@ -1548,12 +1548,12 @@ static int WaveReadPartialChunkData(SDL_RWops *src, WaveChunk *chunk, size_t len
             return -1;
         }
 
-        if (SDL_RWseek(src, chunk->position, SDL_RW_SEEK_SET) != chunk->position) {
+        if (SDL_SeekIO(src, chunk->position, SDL_IO_SEEK_SET) != chunk->position) {
             /* Not sure how we ended up here. Just abort. */
             return -2;
         }
 
-        chunk->size = SDL_RWread(src, chunk->data, length);
+        chunk->size = SDL_ReadIO(src, chunk->data, length);
         if (chunk->size != length) {
             /* Expected to be handled by the caller. */
         }
@@ -1562,7 +1562,7 @@ static int WaveReadPartialChunkData(SDL_RWops *src, WaveChunk *chunk, size_t len
     return 0;
 }
 
-static int WaveReadChunkData(SDL_RWops *src, WaveChunk *chunk)
+static int WaveReadChunkData(SDL_IOStream *src, WaveChunk *chunk)
 {
     return WaveReadPartialChunkData(src, chunk, chunk->length);
 }
@@ -1602,14 +1602,14 @@ static int WaveReadFormat(WaveFile *file)
 {
     WaveChunk *chunk = &file->chunk;
     WaveFormat *format = &file->format;
-    SDL_RWops *fmtsrc;
+    SDL_IOStream *fmtsrc;
     size_t fmtlen = chunk->size;
 
     if (fmtlen > SDL_MAX_SINT32) {
-        /* Limit given by SDL_RWFromConstMem. */
+        /* Limit given by SDL_IOFromConstMem. */
         return SDL_SetError("Data of WAVE fmt chunk too big");
     }
-    fmtsrc = SDL_RWFromConstMem(chunk->data, (int)chunk->size);
+    fmtsrc = SDL_IOFromConstMem(chunk->data, (int)chunk->size);
     if (!fmtsrc) {
         return -1;
     }
@@ -1629,7 +1629,7 @@ static int WaveReadFormat(WaveFile *file)
             return -1;
         }
     } else if (format->encoding == PCM_CODE) {
-        SDL_RWclose(fmtsrc);
+        SDL_CloseIO(fmtsrc);
         return SDL_SetError("Missing wBitsPerSample field in WAVE fmt chunk");
     }
 
@@ -1649,19 +1649,19 @@ static int WaveReadFormat(WaveFile *file)
 
         /* Extensible header must be at least 22 bytes. */
         if (fmtlen < 40 || format->extsize < 22) {
-            SDL_RWclose(fmtsrc);
+            SDL_CloseIO(fmtsrc);
             return SDL_SetError("Extensible WAVE header too small");
         }
 
         if (!SDL_ReadU16LE(fmtsrc, &format->validsamplebits) ||
             !SDL_ReadU32LE(fmtsrc, &format->channelmask) ||
-            SDL_RWread(fmtsrc, format->subformat, 16) != 16) {
+            SDL_ReadIO(fmtsrc, format->subformat, 16) != 16) {
         }
         format->samplesperblock = format->validsamplebits;
         format->encoding = WaveGetFormatGUIDEncoding(format);
     }
 
-    SDL_RWclose(fmtsrc);
+    SDL_CloseIO(fmtsrc);
 
     return 0;
 }
@@ -1769,7 +1769,7 @@ static int WaveCheckFormat(WaveFile *file, size_t datalength)
     return 0;
 }
 
-static int WaveLoad(SDL_RWops *src, WaveFile *file, SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len)
+static int WaveLoad(SDL_IOStream *src, WaveFile *file, SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len)
 {
     int result;
     Uint32 chunkcount = 0;
@@ -1795,7 +1795,7 @@ static int WaveLoad(SDL_RWops *src, WaveFile *file, SDL_AudioSpec *spec, Uint8 *
         }
     }
 
-    RIFFstart = SDL_RWtell(src);
+    RIFFstart = SDL_TellIO(src);
     if (RIFFstart < 0) {
         return SDL_SetError("Could not seek in file");
     }
@@ -1897,7 +1897,7 @@ static int WaveLoad(SDL_RWops *src, WaveFile *file, SDL_AudioSpec *spec, Uint8 *
                     file->fact.status = -1;
                 } else {
                     /* Let's use src directly, it's just too convenient. */
-                    Sint64 position = SDL_RWseek(src, chunk->position, SDL_RW_SEEK_SET);
+                    Sint64 position = SDL_SeekIO(src, chunk->position, SDL_IO_SEEK_SET);
                     if (position == chunk->position && SDL_ReadU32LE(src, &file->fact.samplelength)) {
                         file->fact.status = 1;
                     } else {
@@ -1940,7 +1940,7 @@ static int WaveLoad(SDL_RWops *src, WaveFile *file, SDL_AudioSpec *spec, Uint8 *
         if (chunk->fourcc != DATA && chunk->length > 0) {
             Uint8 tmp;
             Uint64 position = (Uint64)chunk->position + chunk->length - 1;
-            if (position > SDL_MAX_SINT64 || SDL_RWseek(src, (Sint64)position, SDL_RW_SEEK_SET) != (Sint64)position) {
+            if (position > SDL_MAX_SINT64 || SDL_SeekIO(src, (Sint64)position, SDL_IO_SEEK_SET) != (Sint64)position) {
                 return SDL_SetError("Could not seek to WAVE chunk data");
             } else if (!SDL_ReadU8(src, &tmp)) {
                 return SDL_SetError("RIFF size truncates chunk");
@@ -2075,14 +2075,14 @@ static int WaveLoad(SDL_RWops *src, WaveFile *file, SDL_AudioSpec *spec, Uint8 *
     return 0;
 }
 
-int SDL_LoadWAV_RW(SDL_RWops *src, SDL_bool freesrc, SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len)
+int SDL_LoadWAV_IO(SDL_IOStream *src, SDL_bool closeio, SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len)
 {
     int result = -1;
     WaveFile file;
 
     /* Make sure we are passed a valid data source */
     if (!src) {
-        goto done;  /* Error may come from RWops. */
+        goto done;  /* Error may come from SDL_IOStream. */
     } else if (!spec) {
         SDL_InvalidParamError("spec");
         goto done;
@@ -2110,20 +2110,20 @@ int SDL_LoadWAV_RW(SDL_RWops *src, SDL_bool freesrc, SDL_AudioSpec *spec, Uint8
     }
 
     /* Cleanup */
-    if (!freesrc) {
-        SDL_RWseek(src, file.chunk.position, SDL_RW_SEEK_SET);
+    if (!closeio) {
+        SDL_SeekIO(src, file.chunk.position, SDL_IO_SEEK_SET);
     }
     WaveFreeChunkData(&file.chunk);
     SDL_free(file.decoderdata);
 done:
-    if (freesrc && src) {
-        SDL_RWclose(src);
+    if (closeio && src) {
+        SDL_CloseIO(src);
     }
     return result;
 }
 
 int SDL_LoadWAV(const char *path, SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len)
 {
-    return SDL_LoadWAV_RW(SDL_RWFromFile(path, "rb"), 1, spec, audio_buf, audio_len);
+    return SDL_LoadWAV_IO(SDL_IOFromFile(path, "rb"), 1, spec, audio_buf, audio_len);
 }
 

+ 5 - 5
src/audio/disk/SDL_diskaudio.c

@@ -43,7 +43,7 @@ static int DISKAUDIO_WaitDevice(SDL_AudioDevice *device)
 
 static int DISKAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buffer_size)
 {
-    const int written = (int)SDL_RWwrite(device->hidden->io, buffer, (size_t)buffer_size);
+    const int written = (int)SDL_WriteIO(device->hidden->io, buffer, (size_t)buffer_size);
     if (written != buffer_size) { // If we couldn't write, assume fatal error for now
         return -1;
     }
@@ -64,11 +64,11 @@ static int DISKAUDIO_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, in
     const int origbuflen = buflen;
 
     if (h->io) {
-        const int br = (int)SDL_RWread(h->io, buffer, (size_t)buflen);
+        const int br = (int)SDL_ReadIO(h->io, buffer, (size_t)buflen);
         buflen -= br;
         buffer = ((Uint8 *)buffer) + br;
         if (buflen > 0) { // EOF (or error, but whatever).
-            SDL_RWclose(h->io);
+            SDL_CloseIO(h->io);
             h->io = NULL;
         }
     }
@@ -88,7 +88,7 @@ static void DISKAUDIO_CloseDevice(SDL_AudioDevice *device)
 {
     if (device->hidden) {
         if (device->hidden->io) {
-            SDL_RWclose(device->hidden->io);
+            SDL_CloseIO(device->hidden->io);
         }
         SDL_free(device->hidden->mixbuf);
         SDL_free(device->hidden);
@@ -123,7 +123,7 @@ static int DISKAUDIO_OpenDevice(SDL_AudioDevice *device)
     }
 
     // Open the "audio device"
-    device->hidden->io = SDL_RWFromFile(fname, iscapture ? "rb" : "wb");
+    device->hidden->io = SDL_IOFromFile(fname, iscapture ? "rb" : "wb");
     if (!device->hidden->io) {
         return -1;
     }

+ 1 - 1
src/audio/disk/SDL_diskaudio.h

@@ -28,7 +28,7 @@
 struct SDL_PrivateAudioData
 {
     // The file descriptor for the audio device
-    SDL_RWops *io;
+    SDL_IOStream *io;
     Uint32 io_delay;
     Uint8 *mixbuf;
 };

+ 14 - 21
src/core/android/SDL_android.c

@@ -1956,11 +1956,12 @@ static void Internal_Android_Destroy_AssetManager()
     }
 }
 
-int Android_JNI_FileOpen(SDL_RWops *ctx,
-                         const char *fileName, const char *mode)
+int Android_JNI_FileOpen(void **puserdata, const char *fileName, const char *mode)
 {
+    SDL_assert(puserdata != NULL);
+
     AAsset *asset = NULL;
-    ctx->hidden.androidio.asset = NULL;
+    *puserdata = NULL;
 
     if (!asset_manager) {
         Internal_Android_Create_AssetManager();
@@ -1975,14 +1976,13 @@ int Android_JNI_FileOpen(SDL_RWops *ctx,
         return SDL_SetError("Couldn't open asset '%s'", fileName);
     }
 
-    ctx->hidden.androidio.asset = (void *)asset;
+    *puserdata = (void *)asset;
     return 0;
 }
 
-size_t Android_JNI_FileRead(SDL_RWops *ctx, void *buffer, size_t size)
+size_t Android_JNI_FileRead(void *userdata, void *buffer, size_t size, SDL_IOStatus *status)
 {
-    AAsset *asset = (AAsset *)ctx->hidden.androidio.asset;
-    int bytes = AAsset_read(asset, buffer, size);
+    const int bytes = AAsset_read((AAsset *)userdata, buffer, size);
     if (bytes < 0) {
         SDL_SetError("AAsset_read() failed");
         return 0;
@@ -1990,31 +1990,24 @@ size_t Android_JNI_FileRead(SDL_RWops *ctx, void *buffer, size_t size)
     return (size_t)bytes;
 }
 
-size_t Android_JNI_FileWrite(SDL_RWops *ctx, const void *buffer, size_t size)
+size_t Android_JNI_FileWrite(void *userdata, const void *buffer, size_t size, SDL_IOStatus *status)
 {
     return SDL_SetError("Cannot write to Android package filesystem");
 }
 
-Sint64 Android_JNI_FileSize(SDL_RWops *ctx)
+Sint64 Android_JNI_FileSize(void *userdata)
 {
-    off64_t result;
-    AAsset *asset = (AAsset *)ctx->hidden.androidio.asset;
-    result = AAsset_getLength64(asset);
-    return result;
+    return (Sint64) AAsset_getLength64((AAsset *)userdata);
 }
 
-Sint64 Android_JNI_FileSeek(SDL_RWops *ctx, Sint64 offset, int whence)
+Sint64 Android_JNI_FileSeek(void *userdata, Sint64 offset, int whence)
 {
-    off64_t result;
-    AAsset *asset = (AAsset *)ctx->hidden.androidio.asset;
-    result = AAsset_seek64(asset, offset, whence);
-    return result;
+    return (Sint64) AAsset_seek64((AAsset *)userdata, offset, whence);
 }
 
-int Android_JNI_FileClose(SDL_RWops *ctx)
+int Android_JNI_FileClose(void *userdata)
 {
-    AAsset *asset = (AAsset *)ctx->hidden.androidio.asset;
-    AAsset_close(asset);
+    AAsset_close((AAsset *)userdata);
     return 0;
 }
 

+ 6 - 6
src/core/android/SDL_android.h

@@ -66,12 +66,12 @@ extern void Android_JNI_CloseAudioDevice(const int iscapture);
 extern SDL_bool Android_IsDeXMode(void);
 extern SDL_bool Android_IsChromebook(void);
 
-int Android_JNI_FileOpen(SDL_RWops *ctx, const char *fileName, const char *mode);
-Sint64 Android_JNI_FileSize(SDL_RWops *ctx);
-Sint64 Android_JNI_FileSeek(SDL_RWops *ctx, Sint64 offset, int whence);
-size_t Android_JNI_FileRead(SDL_RWops *ctx, void *buffer, size_t size);
-size_t Android_JNI_FileWrite(SDL_RWops *ctx, const void *buffer, size_t size);
-int Android_JNI_FileClose(SDL_RWops *ctx);
+int Android_JNI_FileOpen(void **puserdata, const char *fileName, const char *mode);
+Sint64 Android_JNI_FileSize(void *userdata);
+Sint64 Android_JNI_FileSeek(void *userdata, Sint64 offset, int whence);
+size_t Android_JNI_FileRead(void *userdata, void *buffer, size_t size, SDL_IOStatus *status);
+size_t Android_JNI_FileWrite(void *userdata, const void *buffer, size_t size, SDL_IOStatus *status);
+int Android_JNI_FileClose(void *userdata);
 
 /* Environment support */
 void Android_JNI_GetManifestEnvironmentVariables(void);

+ 5 - 5
src/dynapi/SDL_dynapi.c

@@ -146,13 +146,13 @@ 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, ...)                          \
+    _static size_t SDLCALL SDL_IOprintf##name(SDL_IOStream *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);                                                                              \
+        retval = jump_table.SDL_IOvprintf(context, fmt, ap);                                                                              \
         va_end(ap);                                                                                                                       \
         return retval;                                                                                                                    \
     }                                                                                                                                     \
@@ -297,13 +297,13 @@ 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, ...)
+_static size_t SDLCALL SDL_IOprintf_LOGSDLCALLS(SDL_IOStream *context, SDL_PRINTF_FORMAT_STRING const char *fmt, ...)
 {
     size_t retval;
     va_list ap;
-    SDL_Log_REAL("SDL3CALL SDL_RWprintf");
+    SDL_Log_REAL("SDL3CALL SDL_IOprintf");
     va_start(ap, fmt);
-    retval = SDL_RWvprintf_REAL(context, fmt, ap);
+    retval = SDL_IOvprintf_REAL(context, fmt, ap);
     va_end(ap);
     return retval;
 }

+ 19 - 19
src/dynapi/SDL_dynapi.sym

@@ -4,7 +4,7 @@ SDL3_0.0.0 {
     SDL_DYNAPI_entry;
     SDL_AddEventWatch;
     SDL_AddGamepadMapping;
-    SDL_AddGamepadMappingsFromRW;
+    SDL_AddGamepadMappingsFromIO;
     SDL_AddHintCallback;
     SDL_AddTimer;
     SDL_AndroidBackButton;
@@ -52,7 +52,6 @@ SDL3_0.0.0 {
     SDL_CreatePalette;
     SDL_CreatePixelFormat;
     SDL_CreatePopupWindow;
-    SDL_CreateRW;
     SDL_CreateRWLock;
     SDL_CreateRenderer;
     SDL_CreateSemaphore;
@@ -79,7 +78,6 @@ SDL3_0.0.0 {
     SDL_DestroyMutex;
     SDL_DestroyPalette;
     SDL_DestroyPixelFormat;
-    SDL_DestroyRW;
     SDL_DestroyRWLock;
     SDL_DestroyRenderer;
     SDL_DestroySemaphore;
@@ -409,9 +407,9 @@ SDL3_0.0.0 {
     SDL_LinuxSetThreadPriority;
     SDL_LinuxSetThreadPriorityAndPolicy;
     SDL_LoadBMP;
-    SDL_LoadBMP_RW;
+    SDL_LoadBMP_IO;
     SDL_LoadFile;
-    SDL_LoadFile_RW;
+    SDL_LoadFile_IO;
     SDL_LoadFunction;
     SDL_LoadObject;
     SDL_LockJoysticks;
@@ -466,15 +464,14 @@ SDL3_0.0.0 {
     SDL_QueryTexture;
     SDL_Quit;
     SDL_QuitSubSystem;
-    SDL_RWFromConstMem;
-    SDL_RWFromFile;
-    SDL_RWFromMem;
-    SDL_RWclose;
-    SDL_RWread;
-    SDL_RWseek;
-    SDL_RWsize;
-    SDL_RWtell;
-    SDL_RWwrite;
+    SDL_IOFromConstMem;
+    SDL_IOFromFile;
+    SDL_IOFromMem;
+    SDL_ReadIO;
+    SDL_SeekIO;
+    SDL_SizeIO;
+    SDL_TellIO;
+    SDL_WriteIO;
     SDL_RaiseWindow;
     SDL_ReadU16BE;
     SDL_ReadU32BE;
@@ -517,7 +514,7 @@ SDL3_0.0.0 {
     SDL_RunApp;
     SDL_SIMDGetAlignment;
     SDL_SaveBMP;
-    SDL_SaveBMP_RW;
+    SDL_SaveBMP_IO;
     SDL_ScreenKeyboardShown;
     SDL_ScreenSaverEnabled;
     SDL_SendGamepadEffect;
@@ -842,7 +839,7 @@ SDL3_0.0.0 {
     SDL_SetAudioStreamPutCallback;
     SDL_DestroyAudioStream;
     SDL_OpenAudioDeviceStream;
-    SDL_LoadWAV_RW;
+    SDL_LoadWAV_IO;
     SDL_LoadWAV;
     SDL_MixAudioFormat;
     SDL_ConvertAudioSamples;
@@ -881,14 +878,14 @@ SDL3_0.0.0 {
     SDL_GetJoystickProperties;
     SDL_GetRendererProperties;
     SDL_GetTextureProperties;
-    SDL_GetRWProperties;
+    SDL_GetIOProperties;
     SDL_GetSensorProperties;
     SDL_GetSurfaceProperties;
     SDL_GetWindowProperties;
     SDL_ClearProperty;
     SDL_EnterAppMainCallbacks;
-    SDL_RWprintf;
-    SDL_RWvprintf;
+    SDL_IOprintf;
+    SDL_IOvprintf;
     SDL_AllocateEventMemory;
     SDL_GetDisplayProperties;
     SDL_SetPropertyWithCleanup;
@@ -979,6 +976,9 @@ SDL3_0.0.0 {
     SDL_ShowOpenFileDialog;
     SDL_ShowSaveFileDialog;
     SDL_ShowOpenFolderDialog;
+    SDL_OpenIO;
+    SDL_CloseIO;
+    SDL_GetIOStatus;
     # extra symbols go here (don't modify this line)
   local: *;
 };

+ 19 - 19
src/dynapi/SDL_dynapi_overrides.h

@@ -28,7 +28,7 @@
 
 #define SDL_AddEventWatch SDL_AddEventWatch_REAL
 #define SDL_AddGamepadMapping SDL_AddGamepadMapping_REAL
-#define SDL_AddGamepadMappingsFromRW SDL_AddGamepadMappingsFromRW_REAL
+#define SDL_AddGamepadMappingsFromIO SDL_AddGamepadMappingsFromIO_REAL
 #define SDL_AddHintCallback SDL_AddHintCallback_REAL
 #define SDL_AddTimer SDL_AddTimer_REAL
 #define SDL_AndroidBackButton   SDL_AndroidBackButton_REAL
@@ -76,7 +76,6 @@
 #define SDL_CreatePalette SDL_CreatePalette_REAL
 #define SDL_CreatePixelFormat SDL_CreatePixelFormat_REAL
 #define SDL_CreatePopupWindow SDL_CreatePopupWindow_REAL
-#define SDL_CreateRW SDL_CreateRW_REAL
 #define SDL_CreateRWLock SDL_CreateRWLock_REAL
 #define SDL_CreateRenderer SDL_CreateRenderer_REAL
 #define SDL_CreateSemaphore SDL_CreateSemaphore_REAL
@@ -103,7 +102,6 @@
 #define SDL_DestroyMutex SDL_DestroyMutex_REAL
 #define SDL_DestroyPalette SDL_DestroyPalette_REAL
 #define SDL_DestroyPixelFormat SDL_DestroyPixelFormat_REAL
-#define SDL_DestroyRW SDL_DestroyRW_REAL
 #define SDL_DestroyRWLock SDL_DestroyRWLock_REAL
 #define SDL_DestroyRenderer SDL_DestroyRenderer_REAL
 #define SDL_DestroySemaphore SDL_DestroySemaphore_REAL
@@ -433,9 +431,9 @@
 #define SDL_LinuxSetThreadPriority  SDL_LinuxSetThreadPriority_REAL
 #define SDL_LinuxSetThreadPriorityAndPolicy SDL_LinuxSetThreadPriorityAndPolicy_REAL
 #define SDL_LoadBMP SDL_LoadBMP_REAL
-#define SDL_LoadBMP_RW SDL_LoadBMP_RW_REAL
+#define SDL_LoadBMP_IO SDL_LoadBMP_IO_REAL
 #define SDL_LoadFile SDL_LoadFile_REAL
-#define SDL_LoadFile_RW SDL_LoadFile_RW_REAL
+#define SDL_LoadFile_IO SDL_LoadFile_IO_REAL
 #define SDL_LoadFunction SDL_LoadFunction_REAL
 #define SDL_LoadObject SDL_LoadObject_REAL
 #define SDL_LockJoysticks SDL_LockJoysticks_REAL
@@ -490,15 +488,14 @@
 #define SDL_QueryTexture SDL_QueryTexture_REAL
 #define SDL_Quit SDL_Quit_REAL
 #define SDL_QuitSubSystem SDL_QuitSubSystem_REAL
-#define SDL_RWFromConstMem SDL_RWFromConstMem_REAL
-#define SDL_RWFromFile SDL_RWFromFile_REAL
-#define SDL_RWFromMem SDL_RWFromMem_REAL
-#define SDL_RWclose SDL_RWclose_REAL
-#define SDL_RWread SDL_RWread_REAL
-#define SDL_RWseek SDL_RWseek_REAL
-#define SDL_RWsize SDL_RWsize_REAL
-#define SDL_RWtell SDL_RWtell_REAL
-#define SDL_RWwrite SDL_RWwrite_REAL
+#define SDL_IOFromConstMem SDL_IOFromConstMem_REAL
+#define SDL_IOFromFile SDL_IOFromFile_REAL
+#define SDL_IOFromMem SDL_IOFromMem_REAL
+#define SDL_ReadIO SDL_ReadIO_REAL
+#define SDL_SeekIO SDL_SeekIO_REAL
+#define SDL_SizeIO SDL_SizeIO_REAL
+#define SDL_TellIO SDL_TellIO_REAL
+#define SDL_WriteIO SDL_WriteIO_REAL
 #define SDL_RaiseWindow SDL_RaiseWindow_REAL
 #define SDL_ReadU16BE SDL_ReadU16BE_REAL
 #define SDL_ReadU32BE SDL_ReadU32BE_REAL
@@ -541,7 +538,7 @@
 #define SDL_RunApp SDL_RunApp_REAL
 #define SDL_SIMDGetAlignment SDL_SIMDGetAlignment_REAL
 #define SDL_SaveBMP SDL_SaveBMP_REAL
-#define SDL_SaveBMP_RW SDL_SaveBMP_RW_REAL
+#define SDL_SaveBMP_IO SDL_SaveBMP_IO_REAL
 #define SDL_ScreenKeyboardShown SDL_ScreenKeyboardShown_REAL
 #define SDL_ScreenSaverEnabled SDL_ScreenSaverEnabled_REAL
 #define SDL_SendGamepadEffect SDL_SendGamepadEffect_REAL
@@ -867,7 +864,7 @@
 #define SDL_SetAudioStreamPutCallback SDL_SetAudioStreamPutCallback_REAL
 #define SDL_DestroyAudioStream SDL_DestroyAudioStream_REAL
 #define SDL_OpenAudioDeviceStream SDL_OpenAudioDeviceStream_REAL
-#define SDL_LoadWAV_RW SDL_LoadWAV_RW_REAL
+#define SDL_LoadWAV_IO SDL_LoadWAV_IO_REAL
 #define SDL_LoadWAV SDL_LoadWAV_REAL
 #define SDL_MixAudioFormat SDL_MixAudioFormat_REAL
 #define SDL_ConvertAudioSamples SDL_ConvertAudioSamples_REAL
@@ -906,14 +903,14 @@
 #define SDL_GetJoystickProperties SDL_GetJoystickProperties_REAL
 #define SDL_GetRendererProperties SDL_GetRendererProperties_REAL
 #define SDL_GetTextureProperties SDL_GetTextureProperties_REAL
-#define SDL_GetRWProperties SDL_GetRWProperties_REAL
+#define SDL_GetIOProperties SDL_GetIOProperties_REAL
 #define SDL_GetSensorProperties SDL_GetSensorProperties_REAL
 #define SDL_GetSurfaceProperties SDL_GetSurfaceProperties_REAL
 #define SDL_GetWindowProperties SDL_GetWindowProperties_REAL
 #define SDL_ClearProperty SDL_ClearProperty_REAL
 #define SDL_EnterAppMainCallbacks SDL_EnterAppMainCallbacks_REAL
-#define SDL_RWprintf SDL_RWprintf_REAL
-#define SDL_RWvprintf SDL_RWvprintf_REAL
+#define SDL_IOprintf SDL_IOprintf_REAL
+#define SDL_IOvprintf SDL_IOvprintf_REAL
 #define SDL_AllocateEventMemory SDL_AllocateEventMemory_REAL
 #define SDL_GetDisplayProperties SDL_GetDisplayProperties_REAL
 #define SDL_SetPropertyWithCleanup SDL_SetPropertyWithCleanup_REAL
@@ -1004,3 +1001,6 @@
 #define SDL_ShowOpenFileDialog SDL_ShowOpenFileDialog_REAL
 #define SDL_ShowSaveFileDialog SDL_ShowSaveFileDialog_REAL
 #define SDL_ShowOpenFolderDialog SDL_ShowOpenFolderDialog_REAL
+#define SDL_OpenIO SDL_OpenIO_REAL
+#define SDL_CloseIO SDL_CloseIO_REAL
+#define SDL_GetIOStatus SDL_GetIOStatus_REAL

+ 45 - 45
src/dynapi/SDL_dynapi_procs.h

@@ -43,7 +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)
+SDL_DYNAPI_PROC(size_t,SDL_IOprintf,(SDL_IOStream *a, SDL_PRINTF_FORMAT_STRING const char *b, ...),(a,b),return)
 #endif
 
 #ifdef SDL_CreateThread
@@ -103,7 +103,7 @@ SDL_DYNAPI_PROC(SDL_bool,SDL_IsDeXMode,(void),(),return)
 
 SDL_DYNAPI_PROC(int,SDL_AddEventWatch,(SDL_EventFilter a, void *b),(a,b),return)
 SDL_DYNAPI_PROC(int,SDL_AddGamepadMapping,(const char *a),(a),return)
-SDL_DYNAPI_PROC(int,SDL_AddGamepadMappingsFromRW,(SDL_RWops *a, SDL_bool b),(a,b),return)
+SDL_DYNAPI_PROC(int,SDL_AddGamepadMappingsFromIO,(SDL_IOStream *a, SDL_bool b),(a,b),return)
 SDL_DYNAPI_PROC(int,SDL_AddHintCallback,(const char *a, SDL_HintCallback b, void *c),(a,b,c),return)
 SDL_DYNAPI_PROC(SDL_TimerID,SDL_AddTimer,(Uint32 a, SDL_TimerCallback b, void *c),(a,b,c),return)
 SDL_DYNAPI_PROC(int,SDL_AtomicAdd,(SDL_AtomicInt *a, int b),(a,b),return)
@@ -142,7 +142,6 @@ SDL_DYNAPI_PROC(SDL_Mutex*,SDL_CreateMutex,(void),(),return)
 SDL_DYNAPI_PROC(SDL_Palette*,SDL_CreatePalette,(int a),(a),return)
 SDL_DYNAPI_PROC(SDL_PixelFormat*,SDL_CreatePixelFormat,(SDL_PixelFormatEnum a),(a),return)
 SDL_DYNAPI_PROC(SDL_Window*,SDL_CreatePopupWindow,(SDL_Window *a, int b, int c, int d, int e, Uint32 f),(a,b,c,d,e,f),return)
-SDL_DYNAPI_PROC(SDL_RWops*,SDL_CreateRW,(void),(),return)
 SDL_DYNAPI_PROC(SDL_RWLock*,SDL_CreateRWLock,(void),(),return)
 SDL_DYNAPI_PROC(SDL_Renderer*,SDL_CreateRenderer,(SDL_Window *a, const char *b, Uint32 c),(a,b,c),return)
 SDL_DYNAPI_PROC(SDL_Semaphore*,SDL_CreateSemaphore,(Uint32 a),(a),return)
@@ -166,7 +165,6 @@ SDL_DYNAPI_PROC(void,SDL_DestroyCursor,(SDL_Cursor *a),(a),)
 SDL_DYNAPI_PROC(void,SDL_DestroyMutex,(SDL_Mutex *a),(a),)
 SDL_DYNAPI_PROC(void,SDL_DestroyPalette,(SDL_Palette *a),(a),)
 SDL_DYNAPI_PROC(void,SDL_DestroyPixelFormat,(SDL_PixelFormat *a),(a),)
-SDL_DYNAPI_PROC(void,SDL_DestroyRW,(SDL_RWops *a),(a),)
 SDL_DYNAPI_PROC(void,SDL_DestroyRWLock,(SDL_RWLock *a),(a),)
 SDL_DYNAPI_PROC(void,SDL_DestroyRenderer,(SDL_Renderer *a),(a),)
 SDL_DYNAPI_PROC(void,SDL_DestroySemaphore,(SDL_Semaphore *a),(a),)
@@ -487,9 +485,9 @@ SDL_DYNAPI_PROC(SDL_bool,SDL_JoystickConnected,(SDL_Joystick *a),(a),return)
 SDL_DYNAPI_PROC(SDL_bool,SDL_JoystickEventsEnabled,(void),(),return)
 SDL_DYNAPI_PROC(SDL_bool,SDL_IsJoystickHaptic,(SDL_Joystick *a),(a),return)
 SDL_DYNAPI_PROC(SDL_Surface*,SDL_LoadBMP,(const char *a),(a),return)
-SDL_DYNAPI_PROC(SDL_Surface*,SDL_LoadBMP_RW,(SDL_RWops *a, SDL_bool b),(a,b),return)
+SDL_DYNAPI_PROC(SDL_Surface*,SDL_LoadBMP_IO,(SDL_IOStream *a, SDL_bool b),(a,b),return)
 SDL_DYNAPI_PROC(void*,SDL_LoadFile,(const char *a, size_t *b),(a,b),return)
-SDL_DYNAPI_PROC(void*,SDL_LoadFile_RW,(SDL_RWops *a, size_t *b, SDL_bool c),(a,b,c),return)
+SDL_DYNAPI_PROC(void*,SDL_LoadFile_IO,(SDL_IOStream *a, size_t *b, SDL_bool c),(a,b,c),return)
 SDL_DYNAPI_PROC(SDL_FunctionPointer,SDL_LoadFunction,(void *a, const char *b),(a,b),return)
 SDL_DYNAPI_PROC(void*,SDL_LoadObject,(const char *a),(a),return)
 SDL_DYNAPI_PROC(void,SDL_LockJoysticks,(void),(),)
@@ -535,23 +533,22 @@ SDL_DYNAPI_PROC(int,SDL_PushEvent,(SDL_Event *a),(a),return)
 SDL_DYNAPI_PROC(int,SDL_QueryTexture,(SDL_Texture *a, Uint32 *b, int *c, int *d, int *e),(a,b,c,d,e),return)
 SDL_DYNAPI_PROC(void,SDL_Quit,(void),(),)
 SDL_DYNAPI_PROC(void,SDL_QuitSubSystem,(Uint32 a),(a),)
-SDL_DYNAPI_PROC(SDL_RWops*,SDL_RWFromConstMem,(const void *a, size_t b),(a,b),return)
-SDL_DYNAPI_PROC(SDL_RWops*,SDL_RWFromFile,(const char *a, const char *b),(a,b),return)
-SDL_DYNAPI_PROC(SDL_RWops*,SDL_RWFromMem,(void *a, size_t b),(a,b),return)
-SDL_DYNAPI_PROC(int,SDL_RWclose,(SDL_RWops *a),(a),return)
-SDL_DYNAPI_PROC(size_t,SDL_RWread,(SDL_RWops *a, void *b, size_t c),(a,b,c),return)
-SDL_DYNAPI_PROC(Sint64,SDL_RWseek,(SDL_RWops *a, Sint64 b, int c),(a,b,c),return)
-SDL_DYNAPI_PROC(Sint64,SDL_RWsize,(SDL_RWops *a),(a),return)
-SDL_DYNAPI_PROC(Sint64,SDL_RWtell,(SDL_RWops *a),(a),return)
-SDL_DYNAPI_PROC(size_t,SDL_RWwrite,(SDL_RWops *a, const void *b, size_t c),(a,b,c),return)
+SDL_DYNAPI_PROC(SDL_IOStream*,SDL_IOFromConstMem,(const void *a, size_t b),(a,b),return)
+SDL_DYNAPI_PROC(SDL_IOStream*,SDL_IOFromFile,(const char *a, const char *b),(a,b),return)
+SDL_DYNAPI_PROC(SDL_IOStream*,SDL_IOFromMem,(void *a, size_t b),(a,b),return)
+SDL_DYNAPI_PROC(size_t,SDL_ReadIO,(SDL_IOStream *a, void *b, size_t c),(a,b,c),return)
+SDL_DYNAPI_PROC(Sint64,SDL_SeekIO,(SDL_IOStream *a, Sint64 b, int c),(a,b,c),return)
+SDL_DYNAPI_PROC(Sint64,SDL_SizeIO,(SDL_IOStream *a),(a),return)
+SDL_DYNAPI_PROC(Sint64,SDL_TellIO,(SDL_IOStream *a),(a),return)
+SDL_DYNAPI_PROC(size_t,SDL_WriteIO,(SDL_IOStream *a, const void *b, size_t c),(a,b,c),return)
 SDL_DYNAPI_PROC(int,SDL_RaiseWindow,(SDL_Window *a),(a),return)
-SDL_DYNAPI_PROC(SDL_bool,SDL_ReadU16BE,(SDL_RWops *a, Uint16 *b),(a,b),return)
-SDL_DYNAPI_PROC(SDL_bool,SDL_ReadU32BE,(SDL_RWops *a, Uint32 *b),(a,b),return)
-SDL_DYNAPI_PROC(SDL_bool,SDL_ReadU64BE,(SDL_RWops *a, Uint64 *b),(a,b),return)
-SDL_DYNAPI_PROC(SDL_bool,SDL_ReadU16LE,(SDL_RWops *a, Uint16 *b),(a,b),return)
-SDL_DYNAPI_PROC(SDL_bool,SDL_ReadU32LE,(SDL_RWops *a, Uint32 *b),(a,b),return)
-SDL_DYNAPI_PROC(SDL_bool,SDL_ReadU64LE,(SDL_RWops *a, Uint64 *b),(a,b),return)
-SDL_DYNAPI_PROC(SDL_bool,SDL_ReadU8,(SDL_RWops *a, Uint8 *b),(a,b),return)
+SDL_DYNAPI_PROC(SDL_bool,SDL_ReadU16BE,(SDL_IOStream *a, Uint16 *b),(a,b),return)
+SDL_DYNAPI_PROC(SDL_bool,SDL_ReadU32BE,(SDL_IOStream *a, Uint32 *b),(a,b),return)
+SDL_DYNAPI_PROC(SDL_bool,SDL_ReadU64BE,(SDL_IOStream *a, Uint64 *b),(a,b),return)
+SDL_DYNAPI_PROC(SDL_bool,SDL_ReadU16LE,(SDL_IOStream *a, Uint16 *b),(a,b),return)
+SDL_DYNAPI_PROC(SDL_bool,SDL_ReadU32LE,(SDL_IOStream *a, Uint32 *b),(a,b),return)
+SDL_DYNAPI_PROC(SDL_bool,SDL_ReadU64LE,(SDL_IOStream *a, Uint64 *b),(a,b),return)
+SDL_DYNAPI_PROC(SDL_bool,SDL_ReadU8,(SDL_IOStream *a, Uint8 *b),(a,b),return)
 SDL_DYNAPI_PROC(Uint32,SDL_RegisterEvents,(int a),(a),return)
 SDL_DYNAPI_PROC(SDL_bool,SDL_RemoveTimer,(SDL_TimerID a),(a),return)
 SDL_DYNAPI_PROC(int,SDL_RenderClear,(SDL_Renderer *a),(a),return)
@@ -585,7 +582,7 @@ SDL_DYNAPI_PROC(int,SDL_RumbleJoystickTriggers,(SDL_Joystick *a, Uint16 b, Uint1
 SDL_DYNAPI_PROC(int,SDL_RunApp,(int a, char *b[], SDL_main_func c, void *d),(a,b,c,d),return)
 SDL_DYNAPI_PROC(size_t,SDL_SIMDGetAlignment,(void),(),return)
 SDL_DYNAPI_PROC(int,SDL_SaveBMP,(SDL_Surface *a, const char *b),(a,b),return)
-SDL_DYNAPI_PROC(int,SDL_SaveBMP_RW,(SDL_Surface *a, SDL_RWops *b, SDL_bool c),(a,b,c),return)
+SDL_DYNAPI_PROC(int,SDL_SaveBMP_IO,(SDL_Surface *a, SDL_IOStream *b, SDL_bool c),(a,b,c),return)
 SDL_DYNAPI_PROC(SDL_bool,SDL_ScreenKeyboardShown,(SDL_Window *a),(a),return)
 SDL_DYNAPI_PROC(SDL_bool,SDL_ScreenSaverEnabled,(void),(),return)
 SDL_DYNAPI_PROC(int,SDL_SendGamepadEffect,(SDL_Gamepad *a, const void *b, int c),(a,b,c),return)
@@ -702,13 +699,13 @@ SDL_DYNAPI_PROC(void,SDL_WaitThread,(SDL_Thread *a, int *b),(a,b),)
 SDL_DYNAPI_PROC(int,SDL_WarpMouseGlobal,(float a, float b),(a,b),return)
 SDL_DYNAPI_PROC(void,SDL_WarpMouseInWindow,(SDL_Window *a, float b, float c),(a,b,c),)
 SDL_DYNAPI_PROC(Uint32,SDL_WasInit,(Uint32 a),(a),return)
-SDL_DYNAPI_PROC(SDL_bool,SDL_WriteU16BE,(SDL_RWops *a, Uint16 b),(a,b),return)
-SDL_DYNAPI_PROC(SDL_bool,SDL_WriteU32BE,(SDL_RWops *a, Uint32 b),(a,b),return)
-SDL_DYNAPI_PROC(SDL_bool,SDL_WriteU64BE,(SDL_RWops *a, Uint64 b),(a,b),return)
-SDL_DYNAPI_PROC(SDL_bool,SDL_WriteU16LE,(SDL_RWops *a, Uint16 b),(a,b),return)
-SDL_DYNAPI_PROC(SDL_bool,SDL_WriteU32LE,(SDL_RWops *a, Uint32 b),(a,b),return)
-SDL_DYNAPI_PROC(SDL_bool,SDL_WriteU64LE,(SDL_RWops *a, Uint64 b),(a,b),return)
-SDL_DYNAPI_PROC(SDL_bool,SDL_WriteU8,(SDL_RWops *a, Uint8 b),(a,b),return)
+SDL_DYNAPI_PROC(SDL_bool,SDL_WriteU16BE,(SDL_IOStream *a, Uint16 b),(a,b),return)
+SDL_DYNAPI_PROC(SDL_bool,SDL_WriteU32BE,(SDL_IOStream *a, Uint32 b),(a,b),return)
+SDL_DYNAPI_PROC(SDL_bool,SDL_WriteU64BE,(SDL_IOStream *a, Uint64 b),(a,b),return)
+SDL_DYNAPI_PROC(SDL_bool,SDL_WriteU16LE,(SDL_IOStream *a, Uint16 b),(a,b),return)
+SDL_DYNAPI_PROC(SDL_bool,SDL_WriteU32LE,(SDL_IOStream *a, Uint32 b),(a,b),return)
+SDL_DYNAPI_PROC(SDL_bool,SDL_WriteU64LE,(SDL_IOStream *a, Uint64 b),(a,b),return)
+SDL_DYNAPI_PROC(SDL_bool,SDL_WriteU8,(SDL_IOStream *a, Uint8 b),(a,b),return)
 SDL_DYNAPI_PROC(int,SDL_abs,(int a),(a),return)
 SDL_DYNAPI_PROC(double,SDL_acos,(double a),(a),return)
 SDL_DYNAPI_PROC(float,SDL_acosf,(float a),(a),return)
@@ -899,7 +896,7 @@ SDL_DYNAPI_PROC(int,SDL_SetAudioStreamGetCallback,(SDL_AudioStream *a, SDL_Audio
 SDL_DYNAPI_PROC(int,SDL_SetAudioStreamPutCallback,(SDL_AudioStream *a, SDL_AudioStreamCallback b, void *c),(a,b,c),return)
 SDL_DYNAPI_PROC(void,SDL_DestroyAudioStream,(SDL_AudioStream *a),(a),)
 SDL_DYNAPI_PROC(SDL_AudioStream*,SDL_OpenAudioDeviceStream,(SDL_AudioDeviceID a, const SDL_AudioSpec *b, SDL_AudioStreamCallback c, void *d),(a,b,c,d),return)
-SDL_DYNAPI_PROC(int,SDL_LoadWAV_RW,(SDL_RWops *a, SDL_bool b, SDL_AudioSpec *c, Uint8 **d, Uint32 *e),(a,b,c,d,e),return)
+SDL_DYNAPI_PROC(int,SDL_LoadWAV_IO,(SDL_IOStream *a, SDL_bool b, SDL_AudioSpec *c, Uint8 **d, Uint32 *e),(a,b,c,d,e),return)
 SDL_DYNAPI_PROC(int,SDL_LoadWAV,(const char *a, SDL_AudioSpec *b, Uint8 **c, Uint32 *d),(a,b,c,d),return)
 SDL_DYNAPI_PROC(int,SDL_MixAudioFormat,(Uint8 *a, const Uint8 *b, SDL_AudioFormat c, Uint32 d, int e),(a,b,c,d,e),return)
 SDL_DYNAPI_PROC(int,SDL_ConvertAudioSamples,(const SDL_AudioSpec *a, const Uint8 *b, int c, const SDL_AudioSpec *d, Uint8 **e, int *f),(a,b,c,d,e,f),return)
@@ -909,18 +906,18 @@ SDL_DYNAPI_PROC(int,SDL_ResumeAudioDevice,(SDL_AudioDeviceID a),(a),return)
 SDL_DYNAPI_PROC(SDL_bool,SDL_AudioDevicePaused,(SDL_AudioDeviceID a),(a),return)
 SDL_DYNAPI_PROC(SDL_AudioDeviceID,SDL_GetAudioStreamDevice,(SDL_AudioStream *a),(a),return)
 SDL_DYNAPI_PROC(int,SDL_ShowWindowSystemMenu,(SDL_Window *a, int b, int c),(a,b,c),return)
-SDL_DYNAPI_PROC(SDL_bool,SDL_ReadS16LE,(SDL_RWops *a, Sint16 *b),(a,b),return)
-SDL_DYNAPI_PROC(SDL_bool,SDL_ReadS16BE,(SDL_RWops *a, Sint16 *b),(a,b),return)
-SDL_DYNAPI_PROC(SDL_bool,SDL_ReadS32LE,(SDL_RWops *a, Sint32 *b),(a,b),return)
-SDL_DYNAPI_PROC(SDL_bool,SDL_ReadS32BE,(SDL_RWops *a, Sint32 *b),(a,b),return)
-SDL_DYNAPI_PROC(SDL_bool,SDL_ReadS64LE,(SDL_RWops *a, Sint64 *b),(a,b),return)
-SDL_DYNAPI_PROC(SDL_bool,SDL_ReadS64BE,(SDL_RWops *a, Sint64 *b),(a,b),return)
-SDL_DYNAPI_PROC(SDL_bool,SDL_WriteS16LE,(SDL_RWops *a, Sint16 b),(a,b),return)
-SDL_DYNAPI_PROC(SDL_bool,SDL_WriteS16BE,(SDL_RWops *a, Sint16 b),(a,b),return)
-SDL_DYNAPI_PROC(SDL_bool,SDL_WriteS32LE,(SDL_RWops *a, Sint32 b),(a,b),return)
-SDL_DYNAPI_PROC(SDL_bool,SDL_WriteS32BE,(SDL_RWops *a, Sint32 b),(a,b),return)
-SDL_DYNAPI_PROC(SDL_bool,SDL_WriteS64LE,(SDL_RWops *a, Sint64 b),(a,b),return)
-SDL_DYNAPI_PROC(SDL_bool,SDL_WriteS64BE,(SDL_RWops *a, Sint64 b),(a,b),return)
+SDL_DYNAPI_PROC(SDL_bool,SDL_ReadS16LE,(SDL_IOStream *a, Sint16 *b),(a,b),return)
+SDL_DYNAPI_PROC(SDL_bool,SDL_ReadS16BE,(SDL_IOStream *a, Sint16 *b),(a,b),return)
+SDL_DYNAPI_PROC(SDL_bool,SDL_ReadS32LE,(SDL_IOStream *a, Sint32 *b),(a,b),return)
+SDL_DYNAPI_PROC(SDL_bool,SDL_ReadS32BE,(SDL_IOStream *a, Sint32 *b),(a,b),return)
+SDL_DYNAPI_PROC(SDL_bool,SDL_ReadS64LE,(SDL_IOStream *a, Sint64 *b),(a,b),return)
+SDL_DYNAPI_PROC(SDL_bool,SDL_ReadS64BE,(SDL_IOStream *a, Sint64 *b),(a,b),return)
+SDL_DYNAPI_PROC(SDL_bool,SDL_WriteS16LE,(SDL_IOStream *a, Sint16 b),(a,b),return)
+SDL_DYNAPI_PROC(SDL_bool,SDL_WriteS16BE,(SDL_IOStream *a, Sint16 b),(a,b),return)
+SDL_DYNAPI_PROC(SDL_bool,SDL_WriteS32LE,(SDL_IOStream *a, Sint32 b),(a,b),return)
+SDL_DYNAPI_PROC(SDL_bool,SDL_WriteS32BE,(SDL_IOStream *a, Sint32 b),(a,b),return)
+SDL_DYNAPI_PROC(SDL_bool,SDL_WriteS64LE,(SDL_IOStream *a, Sint64 b),(a,b),return)
+SDL_DYNAPI_PROC(SDL_bool,SDL_WriteS64BE,(SDL_IOStream *a, Sint64 b),(a,b),return)
 
 SDL_DYNAPI_PROC(int,SDL_GDKGetDefaultUser,(XUserHandle *a),(a),return)
 
@@ -940,13 +937,13 @@ SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetGamepadProperties,(SDL_Gamepad *a),(a),r
 SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetJoystickProperties,(SDL_Joystick *a),(a),return)
 SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetRendererProperties,(SDL_Renderer *a),(a),return)
 SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetTextureProperties,(SDL_Texture *a),(a),return)
-SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetRWProperties,(SDL_RWops *a),(a),return)
+SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetIOProperties,(SDL_IOStream *a),(a),return)
 SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetSensorProperties,(SDL_Sensor *a),(a),return)
 SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetSurfaceProperties,(SDL_Surface *a),(a),return)
 SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetWindowProperties,(SDL_Window *a),(a),return)
 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(size_t,SDL_RWvprintf,(SDL_RWops *a, SDL_PRINTF_FORMAT_STRING const char *b, va_list c),(a,b,c),return)
+SDL_DYNAPI_PROC(size_t,SDL_IOvprintf,(SDL_IOStream *a, SDL_PRINTF_FORMAT_STRING const char *b, va_list c),(a,b,c),return)
 SDL_DYNAPI_PROC(void*,SDL_AllocateEventMemory,(size_t a),(a),return)
 SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetDisplayProperties,(SDL_DisplayID a),(a),return)
 SDL_DYNAPI_PROC(int,SDL_SetPropertyWithCleanup,(SDL_PropertiesID a, const char *b, void *c, void (SDLCALL *d)(void *userdata, void *value), void *e),(a,b,c,d,e),return)
@@ -1029,3 +1026,6 @@ SDL_DYNAPI_PROC(int,SDL_GetJoystickBall,(SDL_Joystick *a, int b, int *c, int *d)
 SDL_DYNAPI_PROC(void,SDL_ShowOpenFileDialog,(SDL_DialogFileCallback a, void *b, SDL_Window *c, const SDL_DialogFileFilter *d, const char *e, int f),(a,b,c,d,e,f),)
 SDL_DYNAPI_PROC(void,SDL_ShowSaveFileDialog,(SDL_DialogFileCallback a, void *b, SDL_Window *c, const SDL_DialogFileFilter *d, const char *e),(a,b,c,d,e),)
 SDL_DYNAPI_PROC(void,SDL_ShowOpenFolderDialog,(SDL_DialogFileCallback a, void *b, SDL_Window *c, const char *d, int e),(a,b,c,d,e),)
+SDL_DYNAPI_PROC(SDL_IOStream*,SDL_OpenIO,(const SDL_IOStreamInterface *a, void *b),(a,b),return)
+SDL_DYNAPI_PROC(int,SDL_CloseIO,(SDL_IOStream *a),(a),return)
+SDL_DYNAPI_PROC(SDL_IOStatus,SDL_GetIOStatus,(SDL_IOStream *a),(a),return)

+ 378 - 286
src/file/SDL_rwops.c → src/file/SDL_iostream.c

@@ -36,12 +36,21 @@
    data sources.  It can easily be extended to files, memory, etc.
 */
 
+struct SDL_IOStream
+{
+    SDL_IOStreamInterface iface;
+    void *userdata;
+    SDL_IOStatus status;
+    SDL_PropertiesID props;
+};
+
+
 #ifdef SDL_PLATFORM_APPLE
-#include "cocoa/SDL_rwopsbundlesupport.h"
+#include "cocoa/SDL_iostreambundlesupport.h"
 #endif /* SDL_PLATFORM_APPLE */
 
 #ifdef SDL_PLATFORM_3DS
-#include "n3ds/SDL_rwopsromfs.h"
+#include "n3ds/SDL_iostreamromfs.h"
 #endif /* SDL_PLATFORM_3DS */
 
 #ifdef SDL_PLATFORM_ANDROID
@@ -50,6 +59,16 @@
 
 #if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK) || defined(SDL_PLATFORM_WINRT)
 
+typedef struct IOStreamWindowsData
+{
+    SDL_bool append;
+    HANDLE h;
+    void *data;
+    size_t size;
+    size_t left;
+} IOStreamWindowsData;
+
+
 /* Functions to read/write Win32 API file pointers */
 #ifndef INVALID_SET_FILE_POINTER
 #define INVALID_SET_FILE_POINTER 0xFFFFFFFF
@@ -57,7 +76,7 @@
 
 #define READAHEAD_BUFFER_SIZE 1024
 
-static int SDLCALL windows_file_open(SDL_RWops *context, const char *filename, const char *mode)
+static int SDLCALL windows_file_open(IOStreamWindowsData *iodata, const char *filename, const char *mode)
 {
 #if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES) && !defined(SDL_PLATFORM_WINRT)
     UINT old_error_mode;
@@ -67,10 +86,8 @@ static int SDLCALL windows_file_open(SDL_RWops *context, const char *filename, c
     DWORD must_exist, truncate;
     int a_mode;
 
-    context->hidden.windowsio.h = INVALID_HANDLE_VALUE; /* mark this as unusable */
-    context->hidden.windowsio.buffer.data = NULL;
-    context->hidden.windowsio.buffer.size = 0;
-    context->hidden.windowsio.buffer.left = 0;
+    SDL_zerop(iodata);
+    iodata->h = INVALID_HANDLE_VALUE; /* mark this as unusable */
 
     /* "r" = reading, file must exist */
     /* "w" = writing, truncate existing, file may not exist */
@@ -90,9 +107,8 @@ static int SDLCALL windows_file_open(SDL_RWops *context, const char *filename, c
     }
     /* failed (invalid call) */
 
-    context->hidden.windowsio.buffer.data =
-        (char *)SDL_malloc(READAHEAD_BUFFER_SIZE);
-    if (!context->hidden.windowsio.buffer.data) {
+    iodata->data = (char *)SDL_malloc(READAHEAD_BUFFER_SIZE);
+    if (!iodata->data) {
         return -1;
     }
 #if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES) && !defined(SDL_PLATFORM_WINRT)
@@ -131,47 +147,49 @@ static int SDLCALL windows_file_open(SDL_RWops *context, const char *filename, c
 #endif
 
     if (h == INVALID_HANDLE_VALUE) {
-        SDL_free(context->hidden.windowsio.buffer.data);
-        context->hidden.windowsio.buffer.data = NULL;
+        SDL_free(iodata->data);
+        iodata->data = NULL;
         SDL_SetError("Couldn't open %s", filename);
         return -2; /* failed (CreateFile) */
     }
-    context->hidden.windowsio.h = h;
-    context->hidden.windowsio.append = a_mode ? SDL_TRUE : SDL_FALSE;
+    iodata->h = h;
+    iodata->append = a_mode ? SDL_TRUE : SDL_FALSE;
 
     return 0; /* ok */
 }
 
-static Sint64 SDLCALL windows_file_size(SDL_RWops *context)
+static Sint64 SDLCALL windows_file_size(void *userdata)
 {
+    IOStreamWindowsData *iodata = (IOStreamWindowsData *) userdata;
     LARGE_INTEGER size;
 
-    if (!GetFileSizeEx(context->hidden.windowsio.h, &size)) {
+    if (!GetFileSizeEx(iodata->h, &size)) {
         return WIN_SetError("windows_file_size");
     }
 
     return size.QuadPart;
 }
 
-static Sint64 SDLCALL windows_file_seek(SDL_RWops *context, Sint64 offset, int whence)
+static Sint64 SDLCALL windows_file_seek(void *userdata, Sint64 offset, int whence)
 {
+    IOStreamWindowsData *iodata = (IOStreamWindowsData *) userdata;
     DWORD windowswhence;
     LARGE_INTEGER windowsoffset;
 
-    /* FIXME: We may be able to satisfy the seek within buffered data */
-    if (whence == SDL_RW_SEEK_CUR && context->hidden.windowsio.buffer.left) {
-        offset -= context->hidden.windowsio.buffer.left;
+    // FIXME: We may be able to satisfy the seek within buffered data
+    if ((whence == SDL_IO_SEEK_CUR) && (iodata->left)) {
+        offset -= iodata->left;
     }
-    context->hidden.windowsio.buffer.left = 0;
+    iodata->left = 0;
 
     switch (whence) {
-    case SDL_RW_SEEK_SET:
+    case SDL_IO_SEEK_SET:
         windowswhence = FILE_BEGIN;
         break;
-    case SDL_RW_SEEK_CUR:
+    case SDL_IO_SEEK_CUR:
         windowswhence = FILE_CURRENT;
         break;
-    case SDL_RW_SEEK_END:
+    case SDL_IO_SEEK_END:
         windowswhence = FILE_END;
         break;
     default:
@@ -179,26 +197,27 @@ static Sint64 SDLCALL windows_file_seek(SDL_RWops *context, Sint64 offset, int w
     }
 
     windowsoffset.QuadPart = offset;
-    if (!SetFilePointerEx(context->hidden.windowsio.h, windowsoffset, &windowsoffset, windowswhence)) {
+    if (!SetFilePointerEx(iodata->h, windowsoffset, &windowsoffset, windowswhence)) {
         return WIN_SetError("windows_file_seek");
     }
     return windowsoffset.QuadPart;
 }
 
-static size_t SDLCALL windows_file_read(SDL_RWops *context, void *ptr, size_t size)
+static size_t SDLCALL windows_file_read(void *userdata, void *ptr, size_t size, SDL_IOStatus *status)
 {
+    IOStreamWindowsData *iodata = (IOStreamWindowsData *) userdata;
     size_t total_need = size;
     size_t total_read = 0;
     size_t read_ahead;
     DWORD bytes;
 
-    if (context->hidden.windowsio.buffer.left > 0) {
-        void *data = (char *)context->hidden.windowsio.buffer.data +
-                     context->hidden.windowsio.buffer.size -
-                     context->hidden.windowsio.buffer.left;
-        read_ahead = SDL_min(total_need, context->hidden.windowsio.buffer.left);
+    if (iodata->left > 0) {
+        void *data = (char *)iodata->data +
+                     iodata->size -
+                     iodata->left;
+        read_ahead = SDL_min(total_need, iodata->left);
         SDL_memcpy(ptr, data, read_ahead);
-        context->hidden.windowsio.buffer.left -= read_ahead;
+        iodata->left -= read_ahead;
 
         if (read_ahead == total_need) {
             return size;
@@ -209,18 +228,17 @@ static size_t SDLCALL windows_file_read(SDL_RWops *context, void *ptr, size_t si
     }
 
     if (total_need < READAHEAD_BUFFER_SIZE) {
-        if (!ReadFile(context->hidden.windowsio.h, context->hidden.windowsio.buffer.data,
-                      READAHEAD_BUFFER_SIZE, &bytes, NULL)) {
+        if (!ReadFile(iodata->h, iodata->data, READAHEAD_BUFFER_SIZE, &bytes, NULL)) {
             SDL_Error(SDL_EFREAD);
             return 0;
         }
         read_ahead = SDL_min(total_need, bytes);
-        SDL_memcpy(ptr, context->hidden.windowsio.buffer.data, read_ahead);
-        context->hidden.windowsio.buffer.size = bytes;
-        context->hidden.windowsio.buffer.left = bytes - read_ahead;
+        SDL_memcpy(ptr, iodata->data, read_ahead);
+        iodata->size = bytes;
+        iodata->left = bytes - read_ahead;
         total_read += read_ahead;
     } else {
-        if (!ReadFile(context->hidden.windowsio.h, ptr, (DWORD)total_need, &bytes, NULL)) {
+        if (!ReadFile(iodata->h, ptr, (DWORD)total_need, &bytes, NULL)) {
             SDL_Error(SDL_EFREAD);
             return 0;
         }
@@ -229,32 +247,31 @@ static size_t SDLCALL windows_file_read(SDL_RWops *context, void *ptr, size_t si
     return total_read;
 }
 
-static size_t SDLCALL windows_file_write(SDL_RWops *context, const void *ptr, size_t size)
+static size_t SDLCALL windows_file_write(void *userdata, const void *ptr, size_t size, SDL_IOStatus *status)
 {
+    IOStreamWindowsData *iodata = (IOStreamWindowsData *) userdata;
     const size_t total_bytes = size;
     DWORD bytes;
 
-    if (context->hidden.windowsio.buffer.left) {
-        if (!SetFilePointer(context->hidden.windowsio.h,
-                       -(LONG)context->hidden.windowsio.buffer.left, NULL,
-                       FILE_CURRENT)) {
+    if (iodata->left) {
+        if (!SetFilePointer(iodata->h, -(LONG)iodata->left, NULL, FILE_CURRENT)) {
             SDL_Error(SDL_EFSEEK);
             return 0;
         }
-        context->hidden.windowsio.buffer.left = 0;
+        iodata->left = 0;
     }
 
     /* if in append mode, we must go to the EOF before write */
-    if (context->hidden.windowsio.append) {
+    if (iodata->append) {
         LARGE_INTEGER windowsoffset;
         windowsoffset.QuadPart = 0;
-        if (!SetFilePointerEx(context->hidden.windowsio.h, windowsoffset, &windowsoffset, FILE_END)) {
+        if (!SetFilePointerEx(iodata->h, windowsoffset, &windowsoffset, FILE_END)) {
             SDL_Error(SDL_EFSEEK);
             return 0;
         }
     }
 
-    if (!WriteFile(context->hidden.windowsio.h, ptr, (DWORD)total_bytes, &bytes, NULL)) {
+    if (!WriteFile(iodata->h, ptr, (DWORD)total_bytes, &bytes, NULL)) {
         SDL_Error(SDL_EFWRITE);
         return 0;
     }
@@ -262,17 +279,15 @@ static size_t SDLCALL windows_file_write(SDL_RWops *context, const void *ptr, si
     return bytes;
 }
 
-static int SDLCALL windows_file_close(SDL_RWops *context)
+static int SDLCALL windows_file_close(void *userdata)
 {
-    if (context->hidden.windowsio.h != INVALID_HANDLE_VALUE) {
-        CloseHandle(context->hidden.windowsio.h);
-        context->hidden.windowsio.h = INVALID_HANDLE_VALUE; /* to be sure */
-    }
-    if (context->hidden.windowsio.buffer.data) {
-        SDL_free(context->hidden.windowsio.buffer.data);
-        context->hidden.windowsio.buffer.data = NULL;
+    IOStreamWindowsData *iodata = (IOStreamWindowsData *) userdata;
+    if (iodata->h != INVALID_HANDLE_VALUE) {
+        CloseHandle(iodata->h);
+        iodata->h = INVALID_HANDLE_VALUE; /* to be sure */
     }
-    SDL_DestroyRW(context);
+    SDL_free(iodata->data);
+    SDL_free(iodata);
     return 0;
 }
 #endif /* defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK) */
@@ -281,6 +296,12 @@ static int SDLCALL windows_file_close(SDL_RWops *context)
 
 /* Functions to read/write stdio file pointers. Not used for windows. */
 
+typedef struct IOStreamStdioData
+{
+    FILE *fp;
+    SDL_bool autoclose;
+} IOStreamStdioData;
+
 #ifdef HAVE_FOPEN64
 #define fopen fopen64
 #endif
@@ -317,18 +338,19 @@ static int SDLCALL windows_file_close(SDL_RWops *context)
 #define fseek_off_t long
 #endif
 
-static Sint64 SDLCALL stdio_seek(SDL_RWops *context, Sint64 offset, int whence)
+static Sint64 SDLCALL stdio_seek(void *userdata, Sint64 offset, int whence)
 {
+    IOStreamStdioData *iodata = (IOStreamStdioData *) userdata;
     int stdiowhence;
 
     switch (whence) {
-    case SDL_RW_SEEK_SET:
+    case SDL_IO_SEEK_SET:
         stdiowhence = SEEK_SET;
         break;
-    case SDL_RW_SEEK_CUR:
+    case SDL_IO_SEEK_CUR:
         stdiowhence = SEEK_CUR;
         break;
-    case SDL_RW_SEEK_END:
+    case SDL_IO_SEEK_END:
         stdiowhence = SEEK_END;
         break;
     default:
@@ -341,8 +363,8 @@ static Sint64 SDLCALL stdio_seek(SDL_RWops *context, Sint64 offset, int whence)
     }
 #endif
 
-    if (fseek((FILE *)context->hidden.stdio.fp, (fseek_off_t)offset, stdiowhence) == 0) {
-        Sint64 pos = ftell((FILE *)context->hidden.stdio.fp);
+    if (fseek(iodata->fp, (fseek_off_t)offset, stdiowhence) == 0) {
+        const Sint64 pos = ftell(iodata->fp);
         if (pos < 0) {
             return SDL_SetError("Couldn't get stream offset");
         }
@@ -351,114 +373,139 @@ static Sint64 SDLCALL stdio_seek(SDL_RWops *context, Sint64 offset, int whence)
     return SDL_Error(SDL_EFSEEK);
 }
 
-static size_t SDLCALL stdio_read(SDL_RWops *context, void *ptr, size_t size)
+static size_t SDLCALL stdio_read(void *userdata, void *ptr, size_t size, SDL_IOStatus *status)
 {
-    size_t bytes;
-
-    bytes = fread(ptr, 1, size, (FILE *)context->hidden.stdio.fp);
-    if (bytes == 0 && ferror((FILE *)context->hidden.stdio.fp)) {
+    IOStreamStdioData *iodata = (IOStreamStdioData *) userdata;
+    const size_t bytes = fread(ptr, 1, size, iodata->fp);
+    if (bytes == 0 && ferror(iodata->fp)) {
         SDL_Error(SDL_EFREAD);
     }
     return bytes;
 }
 
-static size_t SDLCALL stdio_write(SDL_RWops *context, const void *ptr, size_t size)
+static size_t SDLCALL stdio_write(void *userdata, const void *ptr, size_t size, SDL_IOStatus *status)
 {
-    size_t bytes;
-
-    bytes = fwrite(ptr, 1, size, (FILE *)context->hidden.stdio.fp);
-    if (bytes == 0 && ferror((FILE *)context->hidden.stdio.fp)) {
+    IOStreamStdioData *iodata = (IOStreamStdioData *) userdata;
+    const size_t bytes = fwrite(ptr, 1, size, iodata->fp);
+    if (bytes == 0 && ferror(iodata->fp)) {
         SDL_Error(SDL_EFWRITE);
     }
     return bytes;
 }
 
-static int SDLCALL stdio_close(SDL_RWops *context)
+static int SDLCALL stdio_close(void *userdata)
 {
+    IOStreamStdioData *iodata = (IOStreamStdioData *) userdata;
     int status = 0;
-    if (context->hidden.stdio.autoclose) {
-        if (fclose((FILE *)context->hidden.stdio.fp) != 0) {
+    if (iodata->autoclose) {
+        if (fclose(iodata->fp) != 0) {
             status = SDL_Error(SDL_EFWRITE);
         }
     }
-    SDL_DestroyRW(context);
+    SDL_free(iodata);
     return status;
 }
 
-static SDL_RWops *SDL_RWFromFP(void *fp, SDL_bool autoclose)
+static SDL_IOStream *SDL_IOFromFP(FILE *fp, SDL_bool autoclose)
 {
-    SDL_RWops *rwops = NULL;
-
-    rwops = SDL_CreateRW();
-    if (rwops) {
-        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;
+    IOStreamStdioData *iodata = (IOStreamStdioData *) SDL_malloc(sizeof (*iodata));
+    if (!iodata) {
+        return NULL;
+    }
+
+    SDL_IOStreamInterface iface;
+    SDL_zero(iface);
+    // There's no stdio_size because SDL_SizeIO emulates it the same way we'd do it for stdio anyhow.
+    iface.seek = stdio_seek;
+    iface.read = stdio_read;
+    iface.write = stdio_write;
+    iface.close = stdio_close;
+
+    iodata->fp = fp;
+    iodata->autoclose = autoclose;
+
+    SDL_IOStream *iostr = SDL_OpenIO(&iface, iodata);
+    if (!iostr) {
+        iface.close(iodata);
+    } else {
+        const SDL_PropertiesID props = SDL_GetIOProperties(iostr);
+        if (props) {
+            SDL_SetProperty(props, SDL_PROP_IOSTREAM_STDIO_HANDLE_POINTER, fp);
+        }
+    }
+
+    return iostr;
 }
 #endif /* !HAVE_STDIO_H && !(SDL_PLATFORM_WIN32 || SDL_PLATFORM_GDK) */
 
 /* Functions to read/write memory pointers */
 
-static Sint64 SDLCALL mem_size(SDL_RWops *context)
+typedef struct IOStreamMemData
 {
-    return (context->hidden.mem.stop - context->hidden.mem.base);
+    Uint8 *base;
+    Uint8 *here;
+    Uint8 *stop;
+} IOStreamMemData;
+
+static Sint64 SDLCALL mem_size(void *userdata)
+{
+    const IOStreamMemData *iodata = (IOStreamMemData *) userdata;
+    return (iodata->stop - iodata->base);
 }
 
-static Sint64 SDLCALL mem_seek(SDL_RWops *context, Sint64 offset, int whence)
+static Sint64 SDLCALL mem_seek(void *userdata, Sint64 offset, int whence)
 {
+    IOStreamMemData *iodata = (IOStreamMemData *) userdata;
     Uint8 *newpos;
 
     switch (whence) {
-    case SDL_RW_SEEK_SET:
-        newpos = context->hidden.mem.base + offset;
+    case SDL_IO_SEEK_SET:
+        newpos = iodata->base + offset;
         break;
-    case SDL_RW_SEEK_CUR:
-        newpos = context->hidden.mem.here + offset;
+    case SDL_IO_SEEK_CUR:
+        newpos = iodata->here + offset;
         break;
-    case SDL_RW_SEEK_END:
-        newpos = context->hidden.mem.stop + offset;
+    case SDL_IO_SEEK_END:
+        newpos = iodata->stop + offset;
         break;
     default:
         return SDL_SetError("Unknown value for 'whence'");
     }
-    if (newpos < context->hidden.mem.base) {
-        newpos = context->hidden.mem.base;
+    if (newpos < iodata->base) {
+        newpos = iodata->base;
     }
-    if (newpos > context->hidden.mem.stop) {
-        newpos = context->hidden.mem.stop;
+    if (newpos > iodata->stop) {
+        newpos = iodata->stop;
     }
-    context->hidden.mem.here = newpos;
-    return (Sint64)(context->hidden.mem.here - context->hidden.mem.base);
+    iodata->here = newpos;
+    return (Sint64)(iodata->here - iodata->base);
 }
 
-static size_t mem_io(SDL_RWops *context, void *dst, const void *src, size_t size)
+static size_t mem_io(void *userdata, void *dst, const void *src, size_t size)
 {
-    const size_t mem_available = (context->hidden.mem.stop - context->hidden.mem.here);
+    IOStreamMemData *iodata = (IOStreamMemData *) userdata;
+    const size_t mem_available = (iodata->stop - iodata->here);
     if (size > mem_available) {
         size = mem_available;
     }
     SDL_memcpy(dst, src, size);
-    context->hidden.mem.here += size;
+    iodata->here += size;
     return size;
 }
 
-static size_t SDLCALL mem_read(SDL_RWops *context, void *ptr, size_t size)
+static size_t SDLCALL mem_read(void *userdata, void *ptr, size_t size, SDL_IOStatus *status)
 {
-    return mem_io(context, ptr, context->hidden.mem.here, size);
+    const IOStreamMemData *iodata = (IOStreamMemData *) userdata;
+    return mem_io(userdata, ptr, iodata->here, size);
 }
 
-static size_t SDLCALL mem_write(SDL_RWops *context, const void *ptr, size_t size)
+static size_t SDLCALL mem_write(void *userdata, const void *ptr, size_t size, SDL_IOStatus *status)
 {
-    return mem_io(context, context->hidden.mem.here, ptr, size);
+    const IOStreamMemData *iodata = (IOStreamMemData *) userdata;
+    return mem_io(userdata, iodata->here, ptr, size);
 }
 
-/* Functions to create SDL_RWops structures from various data sources */
+/* Functions to create SDL_IOStream structures from various data sources */
 
 #if defined(HAVE_STDIO_H) && !defined(SDL_PLATFORM_WINDOWS)
 static SDL_bool IsRegularFileOrPipe(FILE *f)
@@ -479,11 +526,11 @@ static SDL_bool IsRegularFileOrPipe(FILE *f)
 }
 #endif
 
-SDL_RWops *SDL_RWFromFile(const char *file, const char *mode)
+SDL_IOStream *SDL_IOFromFile(const char *file, const char *mode)
 {
-    SDL_RWops *rwops = NULL;
+    SDL_IOStream *iostr = NULL;
     if (!file || !*file || !mode || !*mode) {
-        SDL_SetError("SDL_RWFromFile(): No file or no mode specified");
+        SDL_SetError("SDL_IOFromFile(): No file or no mode specified");
         return NULL;
     }
 #ifdef SDL_PLATFORM_ANDROID
@@ -497,19 +544,16 @@ SDL_RWops *SDL_RWFromFile(const char *file, const char *mode)
                 SDL_SetError("%s is not a regular file or pipe", file);
                 return NULL;
             }
-            return SDL_RWFromFP(fp, 1);
+            return SDL_IOFromFP(fp, 1);
         }
     } else {
         /* Try opening it from internal storage if it's a relative path */
-        char *path;
-        FILE *fp;
-
-        /* !!! FIXME: why not just "char path[PATH_MAX];" ? */
-        path = SDL_stack_alloc(char, PATH_MAX);
+        // !!! FIXME: why not just "char path[PATH_MAX];"
+        char *path = SDL_stack_alloc(char, PATH_MAX);
         if (path) {
             SDL_snprintf(path, PATH_MAX, "%s/%s",
                          SDL_AndroidGetInternalStoragePath(), file);
-            fp = fopen(path, mode);
+            FILE *fp = fopen(path, mode);
             SDL_stack_free(path);
             if (fp) {
                 if (!IsRegularFileOrPipe(fp)) {
@@ -517,57 +561,85 @@ SDL_RWops *SDL_RWFromFile(const char *file, const char *mode)
                     SDL_SetError("%s is not a regular file or pipe", path);
                     return NULL;
                 }
-                return SDL_RWFromFP(fp, 1);
+                return SDL_IOFromFP(fp, 1);
             }
         }
     }
 #endif /* HAVE_STDIO_H */
 
     /* Try to open the file from the asset system */
-    rwops = SDL_CreateRW();
-    if (!rwops) {
-        return NULL; /* SDL_SetError already setup by SDL_CreateRW() */
-    }
 
-    if (Android_JNI_FileOpen(rwops, file, mode) < 0) {
-        SDL_DestroyRW(rwops);
+    void *iodata = NULL;
+    if (Android_JNI_FileOpen(&iodata, file, mode) < 0) {
+        SDL_CloseIO(iostr);
         return NULL;
     }
-    rwops->size = Android_JNI_FileSize;
-    rwops->seek = Android_JNI_FileSeek;
-    rwops->read = Android_JNI_FileRead;
-    rwops->write = Android_JNI_FileWrite;
-    rwops->close = Android_JNI_FileClose;
-    rwops->type = SDL_RWOPS_JNIFILE;
+
+    SDL_IOStreamInterface iface;
+    SDL_zero(iface);
+    iface.size = Android_JNI_FileSize;
+    iface.seek = Android_JNI_FileSeek;
+    iface.read = Android_JNI_FileRead;
+    iface.write = Android_JNI_FileWrite;
+    iface.close = Android_JNI_FileClose;
+
+    iostr = SDL_OpenIO(&iface, iodata);
+    if (!iostr) {
+        iface.close(iodata);
+    } else {
+        const SDL_PropertiesID props = SDL_GetIOProperties(iostr);
+        if (props) {
+            SDL_SetProperty(props, SDL_PROP_IOSTREAM_ANDROID_AASSET_POINTER, iodata);
+        }
+    }
+
+    return iostr;
+
 
 #elif defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK) || defined(SDL_PLATFORM_WINRT)
-    rwops = SDL_CreateRW();
-    if (!rwops) {
-        return NULL; /* SDL_SetError already setup by SDL_CreateRW() */
+    IOStreamWindowsData *iodata = (IOStreamWindowsData *) SDL_malloc(sizeof (*iodata));
+    if (!iodata) {
+        return NULL;
     }
 
-    if (windows_file_open(rwops, file, mode) < 0) {
-        SDL_DestroyRW(rwops);
+    if (windows_file_open(iodata, file, mode) < 0) {
+        SDL_CloseIO(iostr);
         return NULL;
     }
-    rwops->size = windows_file_size;
-    rwops->seek = windows_file_seek;
-    rwops->read = windows_file_read;
-    rwops->write = windows_file_write;
-    rwops->close = windows_file_close;
-    rwops->type = SDL_RWOPS_WINFILE;
+
+    SDL_IOStreamInterface iface;
+    SDL_zero(iface);
+    iface.size = windows_file_size;
+    iface.seek = windows_file_seek;
+    iface.read = windows_file_read;
+    iface.write = windows_file_write;
+    iface.close = windows_file_close;
+
+    iostr = SDL_OpenIO(&iface, iodata);
+    if (!iostr) {
+        windows_file_close(iodata);
+    } else {
+        const SDL_PropertiesID props = SDL_GetIOProperties(iostr);
+        if (props) {
+            SDL_SetProperty(props, SDL_PROP_IOSTREAM_WINDOWS_HANDLE_POINTER, iodata->h);
+        }
+    }
+
+    return iostr;
+
 #elif defined(HAVE_STDIO_H)
     {
-#if defined(SDL_PLATFORM_APPLE)
+        #if defined(SDL_PLATFORM_APPLE)
         FILE *fp = SDL_OpenFPFromBundleOrFallback(file, mode);
-#elif defined(SDL_PLATFORM_WINRT)
+        #elif defined(SDL_PLATFORM_WINRT)
         FILE *fp = NULL;
         fopen_s(&fp, file, mode);
-#elif defined(SDL_PLATFORM_3DS)
+        #elif defined(SDL_PLATFORM_3DS)
         FILE *fp = N3DS_FileOpen(file, mode);
-#else
+        #else
         FILE *fp = fopen(file, mode);
-#endif
+        #endif
+
         if (!fp) {
             SDL_SetError("Couldn't open %s", file);
         } else if (!IsRegularFileOrPipe(fp)) {
@@ -575,88 +647,123 @@ SDL_RWops *SDL_RWFromFile(const char *file, const char *mode)
             fp = NULL;
             SDL_SetError("%s is not a regular file or pipe", file);
         } else {
-            rwops = SDL_RWFromFP(fp, SDL_TRUE);
+            iostr = SDL_IOFromFP(fp, SDL_TRUE);
         }
     }
+
 #else
     SDL_SetError("SDL not compiled with stdio support");
 #endif /* !HAVE_STDIO_H */
 
-    return rwops;
+    return iostr;
 }
 
-SDL_RWops *SDL_RWFromMem(void *mem, size_t size)
+SDL_IOStream *SDL_IOFromMem(void *mem, size_t size)
 {
-    SDL_RWops *rwops = NULL;
-
     if (!mem) {
         SDL_InvalidParamError("mem");
         return NULL;
-    }
-    if (!size) {
+    } else if (!size) {
         SDL_InvalidParamError("size");
         return NULL;
     }
 
-    rwops = SDL_CreateRW();
-    if (rwops) {
-        rwops->size = mem_size;
-        rwops->seek = mem_seek;
-        rwops->read = mem_read;
-        rwops->write = mem_write;
-        rwops->hidden.mem.base = (Uint8 *)mem;
-        rwops->hidden.mem.here = rwops->hidden.mem.base;
-        rwops->hidden.mem.stop = rwops->hidden.mem.base + size;
-        rwops->type = SDL_RWOPS_MEMORY;
+    IOStreamMemData *iodata = (IOStreamMemData *) SDL_malloc(sizeof (*iodata));
+    if (!iodata) {
+        return NULL;
     }
-    return rwops;
+
+    SDL_IOStreamInterface iface;
+    SDL_zero(iface);
+    iface.size = mem_size;
+    iface.seek = mem_seek;
+    iface.read = mem_read;
+    iface.write = mem_write;
+
+    iodata->base = (Uint8 *)mem;
+    iodata->here = iodata->base;
+    iodata->stop = iodata->base + size;
+
+    SDL_IOStream *iostr = SDL_OpenIO(&iface, iodata);
+    if (!iostr) {
+        SDL_free(iodata);
+    }
+    return iostr;
 }
 
-SDL_RWops *SDL_RWFromConstMem(const void *mem, size_t size)
+SDL_IOStream *SDL_IOFromConstMem(const void *mem, size_t size)
 {
-    SDL_RWops *rwops = NULL;
-
     if (!mem) {
         SDL_InvalidParamError("mem");
         return NULL;
-    }
-    if (!size) {
+    } else if (!size) {
         SDL_InvalidParamError("size");
         return NULL;
     }
 
-    rwops = SDL_CreateRW();
-    if (rwops) {
-        rwops->size = mem_size;
-        rwops->seek = mem_seek;
-        rwops->read = mem_read;
-        rwops->hidden.mem.base = (Uint8 *)mem;
-        rwops->hidden.mem.here = rwops->hidden.mem.base;
-        rwops->hidden.mem.stop = rwops->hidden.mem.base + size;
-        rwops->type = SDL_RWOPS_MEMORY_RO;
+    IOStreamMemData *iodata = (IOStreamMemData *) SDL_malloc(sizeof (*iodata));
+    if (!iodata) {
+        return NULL;
+    }
+
+    SDL_IOStreamInterface iface;
+    SDL_zero(iface);
+    iface.size = mem_size;
+    iface.seek = mem_seek;
+    iface.read = mem_read;
+    // leave iface.write as NULL.
+
+    iodata->base = (Uint8 *)mem;
+    iodata->here = iodata->base;
+    iodata->stop = iodata->base + size;
+
+    SDL_IOStream *iostr = SDL_OpenIO(&iface, iodata);
+    if (!iostr) {
+        SDL_free(iodata);
     }
-    return rwops;
+    return iostr;
 }
 
-SDL_RWops *SDL_CreateRW(void)
+SDL_IOStatus SDL_GetIOStatus(SDL_IOStream *context)
 {
-    SDL_RWops *context;
+    if (!context) {
+        SDL_InvalidParamError("context");
+        return SDL_IO_STATUS_ERROR;
+    }
+    return context->status;
+}
+
+
+SDL_IOStream *SDL_OpenIO(const SDL_IOStreamInterface *iface, void *userdata)
+{
+    if (!iface) {
+        SDL_InvalidParamError("iface");
+        return NULL;
+    }
 
-    context = (SDL_RWops *)SDL_calloc(1, sizeof(*context));
-    if (context) {
-        context->type = SDL_RWOPS_UNKNOWN;
+    SDL_IOStream *iostr = (SDL_IOStream *)SDL_calloc(1, sizeof(*iostr));
+    if (iostr) {
+        SDL_copyp(&iostr->iface, iface);
+        iostr->userdata = userdata;
     }
-    return context;
+    return iostr;
 }
 
-void SDL_DestroyRW(SDL_RWops *context)
+int SDL_CloseIO(SDL_IOStream *iostr)
 {
-    SDL_DestroyProperties(context->props);
-    SDL_free(context);
+    int retval = 0;
+    if (iostr) {
+        if (iostr->iface.close) {
+            retval = iostr->iface.close(iostr->userdata);
+        }
+        SDL_DestroyProperties(iostr->props);
+        SDL_free(iostr);
+    }
+    return retval;
 }
 
 /* Load all the data from an SDL data stream */
-void *SDL_LoadFile_RW(SDL_RWops *src, size_t *datasize, SDL_bool freesrc)
+void *SDL_LoadFile_IO(SDL_IOStream *src, size_t *datasize, SDL_bool closeio)
 {
     const int FILE_CHUNK_SIZE = 1024;
     Sint64 size, size_total = 0;
@@ -669,7 +776,7 @@ void *SDL_LoadFile_RW(SDL_RWops *src, size_t *datasize, SDL_bool freesrc)
         goto done;
     }
 
-    size = SDL_RWsize(src);
+    size = SDL_SizeIO(src);
     if (size < 0) {
         size = FILE_CHUNK_SIZE;
         loading_chunks = SDL_TRUE;
@@ -701,7 +808,7 @@ void *SDL_LoadFile_RW(SDL_RWops *src, size_t *datasize, SDL_bool freesrc)
             }
         }
 
-        size_read = SDL_RWread(src, data + size_total, (size_t)(size - size_total));
+        size_read = SDL_ReadIO(src, data + size_total, (size_t)(size - size_total));
         if (size_read > 0) {
             size_total += size_read;
             continue;
@@ -717,18 +824,18 @@ done:
     if (datasize) {
         *datasize = (size_t)size_total;
     }
-    if (freesrc && src) {
-        SDL_RWclose(src);
+    if (closeio && src) {
+        SDL_CloseIO(src);
     }
     return data;
 }
 
 void *SDL_LoadFile(const char *file, size_t *datasize)
 {
-    return SDL_LoadFile_RW(SDL_RWFromFile(file, "rb"), datasize, SDL_TRUE);
+    return SDL_LoadFile_IO(SDL_IOFromFile(file, "rb"), datasize, SDL_TRUE);
 }
 
-SDL_PropertiesID SDL_GetRWProperties(SDL_RWops *context)
+SDL_PropertiesID SDL_GetIOProperties(SDL_IOStream *context)
 {
     if (!context) {
         SDL_InvalidParamError("context");
@@ -741,103 +848,100 @@ SDL_PropertiesID SDL_GetRWProperties(SDL_RWops *context)
     return context->props;
 }
 
-Sint64 SDL_RWsize(SDL_RWops *context)
+Sint64 SDL_SizeIO(SDL_IOStream *context)
 {
     if (!context) {
         return SDL_InvalidParamError("context");
     }
-    if (!context->size) {
+    if (!context->iface.size) {
         Sint64 pos, size;
 
-        pos = SDL_RWseek(context, 0, SDL_RW_SEEK_CUR);
+        pos = SDL_SeekIO(context, 0, SDL_IO_SEEK_CUR);
         if (pos < 0) {
             return -1;
         }
-        size = SDL_RWseek(context, 0, SDL_RW_SEEK_END);
+        size = SDL_SeekIO(context, 0, SDL_IO_SEEK_END);
 
-        SDL_RWseek(context, pos, SDL_RW_SEEK_SET);
+        SDL_SeekIO(context, pos, SDL_IO_SEEK_SET);
         return size;
     }
-    return context->size(context);
+    return context->iface.size(context->userdata);
 }
 
-Sint64 SDL_RWseek(SDL_RWops *context, Sint64 offset, int whence)
+Sint64 SDL_SeekIO(SDL_IOStream *context, Sint64 offset, int whence)
 {
     if (!context) {
         return SDL_InvalidParamError("context");
-    }
-    if (!context->seek) {
+    } else if (!context->iface.seek) {
         return SDL_Unsupported();
     }
-    return context->seek(context, offset, whence);
+    return context->iface.seek(context->userdata, offset, whence);
 }
 
-Sint64 SDL_RWtell(SDL_RWops *context)
+Sint64 SDL_TellIO(SDL_IOStream *context)
 {
-    return SDL_RWseek(context, 0, SDL_RW_SEEK_CUR);
+    return SDL_SeekIO(context, 0, SDL_IO_SEEK_CUR);
 }
 
-size_t SDL_RWread(SDL_RWops *context, void *ptr, size_t size)
+size_t SDL_ReadIO(SDL_IOStream *context, void *ptr, size_t size)
 {
     size_t bytes;
 
     if (!context) {
         SDL_InvalidParamError("context");
         return 0;
-    }
-    if (!context->read) {
-        context->status = SDL_RWOPS_STATUS_WRITEONLY;
+    } else if (!context->iface.read) {
+        context->status = SDL_IO_STATUS_WRITEONLY;
         SDL_Unsupported();
         return 0;
     }
 
-    context->status = SDL_RWOPS_STATUS_READY;
+    context->status = SDL_IO_STATUS_READY;
     SDL_ClearError();
 
     if (size == 0) {
         return 0;
     }
 
-    bytes = context->read(context, ptr, size);
-    if (bytes == 0 && context->status == SDL_RWOPS_STATUS_READY) {
+    bytes = context->iface.read(context->userdata, ptr, size, &context->status);
+    if (bytes == 0 && context->status == SDL_IO_STATUS_READY) {
         if (*SDL_GetError()) {
-            context->status = SDL_RWOPS_STATUS_ERROR;
+            context->status = SDL_IO_STATUS_ERROR;
         } else {
-            context->status = SDL_RWOPS_STATUS_EOF;
+            context->status = SDL_IO_STATUS_EOF;
         }
     }
     return bytes;
 }
 
-size_t SDL_RWwrite(SDL_RWops *context, const void *ptr, size_t size)
+size_t SDL_WriteIO(SDL_IOStream *context, const void *ptr, size_t size)
 {
     size_t bytes;
 
     if (!context) {
         SDL_InvalidParamError("context");
         return 0;
-    }
-    if (!context->write) {
-        context->status = SDL_RWOPS_STATUS_READONLY;
+    } else if (!context->iface.write) {
+        context->status = SDL_IO_STATUS_READONLY;
         SDL_Unsupported();
         return 0;
     }
 
-    context->status = SDL_RWOPS_STATUS_READY;
+    context->status = SDL_IO_STATUS_READY;
     SDL_ClearError();
 
     if (size == 0) {
         return 0;
     }
 
-    bytes = context->write(context, ptr, size);
-    if (bytes == 0 && context->status == SDL_RWOPS_STATUS_READY) {
-        context->status = SDL_RWOPS_STATUS_ERROR;
+    bytes = context->iface.write(context->userdata, ptr, size, &context->status);
+    if ((bytes == 0) && (context->status == SDL_IO_STATUS_READY)) {
+        context->status = SDL_IO_STATUS_ERROR;
     }
     return bytes;
 }
 
-size_t SDL_RWprintf(SDL_RWops *context, SDL_PRINTF_FORMAT_STRING const char *fmt, ...)
+size_t SDL_IOprintf(SDL_IOStream *context, SDL_PRINTF_FORMAT_STRING const char *fmt, ...)
 {
     va_list ap;
     int size;
@@ -851,12 +955,12 @@ size_t SDL_RWprintf(SDL_RWops *context, SDL_PRINTF_FORMAT_STRING const char *fmt
         return 0;
     }
 
-    bytes = SDL_RWwrite(context, string, (size_t)size);
+    bytes = SDL_WriteIO(context, string, (size_t)size);
     SDL_free(string);
     return bytes;
 }
 
-size_t SDL_RWvprintf(SDL_RWops *context, SDL_PRINTF_FORMAT_STRING const char *fmt, va_list ap)
+size_t SDL_IOvprintf(SDL_IOStream *context, SDL_PRINTF_FORMAT_STRING const char *fmt, va_list ap)
 {
     int size;
     char *string;
@@ -867,31 +971,19 @@ size_t SDL_RWvprintf(SDL_RWops *context, SDL_PRINTF_FORMAT_STRING const char *fm
         return 0;
     }
 
-    bytes = SDL_RWwrite(context, string, (size_t)size);
+    bytes = SDL_WriteIO(context, string, (size_t)size);
     SDL_free(string);
     return bytes;
 }
 
-int SDL_RWclose(SDL_RWops *context)
-{
-    if (!context) {
-        return SDL_InvalidParamError("context");
-    }
-    if (!context->close) {
-        SDL_DestroyRW(context);
-        return 0;
-    }
-    return context->close(context);
-}
-
 /* Functions for dynamically reading and writing endian-specific values */
 
-SDL_bool SDL_ReadU8(SDL_RWops *src, Uint8 *value)
+SDL_bool SDL_ReadU8(SDL_IOStream *src, Uint8 *value)
 {
     Uint8 data = 0;
     SDL_bool result = SDL_FALSE;
 
-    if (SDL_RWread(src, &data, sizeof(data)) == sizeof(data)) {
+    if (SDL_ReadIO(src, &data, sizeof(data)) == sizeof(data)) {
         result = SDL_TRUE;
     }
     if (value) {
@@ -900,12 +992,12 @@ SDL_bool SDL_ReadU8(SDL_RWops *src, Uint8 *value)
     return result;
 }
 
-SDL_bool SDL_ReadU16LE(SDL_RWops *src, Uint16 *value)
+SDL_bool SDL_ReadU16LE(SDL_IOStream *src, Uint16 *value)
 {
     Uint16 data = 0;
     SDL_bool result = SDL_FALSE;
 
-    if (SDL_RWread(src, &data, sizeof(data)) == sizeof(data)) {
+    if (SDL_ReadIO(src, &data, sizeof(data)) == sizeof(data)) {
         result = SDL_TRUE;
     }
     if (value) {
@@ -914,17 +1006,17 @@ SDL_bool SDL_ReadU16LE(SDL_RWops *src, Uint16 *value)
     return result;
 }
 
-SDL_bool SDL_ReadS16LE(SDL_RWops *src, Sint16 *value)
+SDL_bool SDL_ReadS16LE(SDL_IOStream *src, Sint16 *value)
 {
     return SDL_ReadU16LE(src, (Uint16 *)value);
 }
 
-SDL_bool SDL_ReadU16BE(SDL_RWops *src, Uint16 *value)
+SDL_bool SDL_ReadU16BE(SDL_IOStream *src, Uint16 *value)
 {
     Uint16 data = 0;
     SDL_bool result = SDL_FALSE;
 
-    if (SDL_RWread(src, &data, sizeof(data)) == sizeof(data)) {
+    if (SDL_ReadIO(src, &data, sizeof(data)) == sizeof(data)) {
         result = SDL_TRUE;
     }
     if (value) {
@@ -933,17 +1025,17 @@ SDL_bool SDL_ReadU16BE(SDL_RWops *src, Uint16 *value)
     return result;
 }
 
-SDL_bool SDL_ReadS16BE(SDL_RWops *src, Sint16 *value)
+SDL_bool SDL_ReadS16BE(SDL_IOStream *src, Sint16 *value)
 {
     return SDL_ReadU16BE(src, (Uint16 *)value);
 }
 
-SDL_bool SDL_ReadU32LE(SDL_RWops *src, Uint32 *value)
+SDL_bool SDL_ReadU32LE(SDL_IOStream *src, Uint32 *value)
 {
     Uint32 data = 0;
     SDL_bool result = SDL_FALSE;
 
-    if (SDL_RWread(src, &data, sizeof(data)) == sizeof(data)) {
+    if (SDL_ReadIO(src, &data, sizeof(data)) == sizeof(data)) {
         result = SDL_TRUE;
     }
     if (value) {
@@ -952,17 +1044,17 @@ SDL_bool SDL_ReadU32LE(SDL_RWops *src, Uint32 *value)
     return result;
 }
 
-SDL_bool SDL_ReadS32LE(SDL_RWops *src, Sint32 *value)
+SDL_bool SDL_ReadS32LE(SDL_IOStream *src, Sint32 *value)
 {
     return SDL_ReadU32LE(src, (Uint32 *)value);
 }
 
-SDL_bool SDL_ReadU32BE(SDL_RWops *src, Uint32 *value)
+SDL_bool SDL_ReadU32BE(SDL_IOStream *src, Uint32 *value)
 {
     Uint32 data = 0;
     SDL_bool result = SDL_FALSE;
 
-    if (SDL_RWread(src, &data, sizeof(data)) == sizeof(data)) {
+    if (SDL_ReadIO(src, &data, sizeof(data)) == sizeof(data)) {
         result = SDL_TRUE;
     }
     if (value) {
@@ -971,17 +1063,17 @@ SDL_bool SDL_ReadU32BE(SDL_RWops *src, Uint32 *value)
     return result;
 }
 
-SDL_bool SDL_ReadS32BE(SDL_RWops *src, Sint32 *value)
+SDL_bool SDL_ReadS32BE(SDL_IOStream *src, Sint32 *value)
 {
     return SDL_ReadU32BE(src, (Uint32 *)value);
 }
 
-SDL_bool SDL_ReadU64LE(SDL_RWops *src, Uint64 *value)
+SDL_bool SDL_ReadU64LE(SDL_IOStream *src, Uint64 *value)
 {
     Uint64 data = 0;
     SDL_bool result = SDL_FALSE;
 
-    if (SDL_RWread(src, &data, sizeof(data)) == sizeof(data)) {
+    if (SDL_ReadIO(src, &data, sizeof(data)) == sizeof(data)) {
         result = SDL_TRUE;
     }
     if (value) {
@@ -990,17 +1082,17 @@ SDL_bool SDL_ReadU64LE(SDL_RWops *src, Uint64 *value)
     return result;
 }
 
-SDL_bool SDL_ReadS64LE(SDL_RWops *src, Sint64 *value)
+SDL_bool SDL_ReadS64LE(SDL_IOStream *src, Sint64 *value)
 {
     return SDL_ReadU64LE(src, (Uint64 *)value);
 }
 
-SDL_bool SDL_ReadU64BE(SDL_RWops *src, Uint64 *value)
+SDL_bool SDL_ReadU64BE(SDL_IOStream *src, Uint64 *value)
 {
     Uint64 data = 0;
     SDL_bool result = SDL_FALSE;
 
-    if (SDL_RWread(src, &data, sizeof(data)) == sizeof(data)) {
+    if (SDL_ReadIO(src, &data, sizeof(data)) == sizeof(data)) {
         result = SDL_TRUE;
     }
     if (value) {
@@ -1009,78 +1101,78 @@ SDL_bool SDL_ReadU64BE(SDL_RWops *src, Uint64 *value)
     return result;
 }
 
-SDL_bool SDL_ReadS64BE(SDL_RWops *src, Sint64 *value)
+SDL_bool SDL_ReadS64BE(SDL_IOStream *src, Sint64 *value)
 {
     return SDL_ReadU64BE(src, (Uint64 *)value);
 }
 
-SDL_bool SDL_WriteU8(SDL_RWops *dst, Uint8 value)
+SDL_bool SDL_WriteU8(SDL_IOStream *dst, Uint8 value)
 {
-    return (SDL_RWwrite(dst, &value, sizeof(value)) == sizeof(value));
+    return (SDL_WriteIO(dst, &value, sizeof(value)) == sizeof(value));
 }
 
-SDL_bool SDL_WriteU16LE(SDL_RWops *dst, Uint16 value)
+SDL_bool SDL_WriteU16LE(SDL_IOStream *dst, Uint16 value)
 {
     const Uint16 swapped = SDL_SwapLE16(value);
-    return (SDL_RWwrite(dst, &swapped, sizeof(swapped)) == sizeof(swapped));
+    return (SDL_WriteIO(dst, &swapped, sizeof(swapped)) == sizeof(swapped));
 }
 
-SDL_bool SDL_WriteS16LE(SDL_RWops *dst, Sint16 value)
+SDL_bool SDL_WriteS16LE(SDL_IOStream *dst, Sint16 value)
 {
     return SDL_WriteU16LE(dst, (Uint16)value);
 }
 
-SDL_bool SDL_WriteU16BE(SDL_RWops *dst, Uint16 value)
+SDL_bool SDL_WriteU16BE(SDL_IOStream *dst, Uint16 value)
 {
     const Uint16 swapped = SDL_SwapBE16(value);
-    return (SDL_RWwrite(dst, &swapped, sizeof(swapped)) == sizeof(swapped));
+    return (SDL_WriteIO(dst, &swapped, sizeof(swapped)) == sizeof(swapped));
 }
 
-SDL_bool SDL_WriteS16BE(SDL_RWops *dst, Sint16 value)
+SDL_bool SDL_WriteS16BE(SDL_IOStream *dst, Sint16 value)
 {
     return SDL_WriteU16BE(dst, (Uint16)value);
 }
 
-SDL_bool SDL_WriteU32LE(SDL_RWops *dst, Uint32 value)
+SDL_bool SDL_WriteU32LE(SDL_IOStream *dst, Uint32 value)
 {
     const Uint32 swapped = SDL_SwapLE32(value);
-    return (SDL_RWwrite(dst, &swapped, sizeof(swapped)) == sizeof(swapped));
+    return (SDL_WriteIO(dst, &swapped, sizeof(swapped)) == sizeof(swapped));
 }
 
-SDL_bool SDL_WriteS32LE(SDL_RWops *dst, Sint32 value)
+SDL_bool SDL_WriteS32LE(SDL_IOStream *dst, Sint32 value)
 {
     return SDL_WriteU32LE(dst, (Uint32)value);
 }
 
-SDL_bool SDL_WriteU32BE(SDL_RWops *dst, Uint32 value)
+SDL_bool SDL_WriteU32BE(SDL_IOStream *dst, Uint32 value)
 {
     const Uint32 swapped = SDL_SwapBE32(value);
-    return (SDL_RWwrite(dst, &swapped, sizeof(swapped)) == sizeof(swapped));
+    return (SDL_WriteIO(dst, &swapped, sizeof(swapped)) == sizeof(swapped));
 }
 
-SDL_bool SDL_WriteS32BE(SDL_RWops *dst, Sint32 value)
+SDL_bool SDL_WriteS32BE(SDL_IOStream *dst, Sint32 value)
 {
     return SDL_WriteU32BE(dst, (Uint32)value);
 }
 
-SDL_bool SDL_WriteU64LE(SDL_RWops *dst, Uint64 value)
+SDL_bool SDL_WriteU64LE(SDL_IOStream *dst, Uint64 value)
 {
     const Uint64 swapped = SDL_SwapLE64(value);
-    return (SDL_RWwrite(dst, &swapped, sizeof(swapped)) == sizeof(swapped));
+    return (SDL_WriteIO(dst, &swapped, sizeof(swapped)) == sizeof(swapped));
 }
 
-SDL_bool SDL_WriteS64LE(SDL_RWops *dst, Sint64 value)
+SDL_bool SDL_WriteS64LE(SDL_IOStream *dst, Sint64 value)
 {
     return SDL_WriteU64LE(dst, (Uint64)value);
 }
 
-SDL_bool SDL_WriteU64BE(SDL_RWops *dst, Uint64 value)
+SDL_bool SDL_WriteU64BE(SDL_IOStream *dst, Uint64 value)
 {
     const Uint64 swapped = SDL_SwapBE64(value);
-    return (SDL_RWwrite(dst, &swapped, sizeof(swapped)) == sizeof(swapped));
+    return (SDL_WriteIO(dst, &swapped, sizeof(swapped)) == sizeof(swapped));
 }
 
-SDL_bool SDL_WriteS64BE(SDL_RWops *dst, Sint64 value)
+SDL_bool SDL_WriteS64BE(SDL_IOStream *dst, Sint64 value)
 {
     return SDL_WriteU64BE(dst, (Uint64)value);
 }

+ 2 - 2
src/file/cocoa/SDL_rwopsbundlesupport.h → src/file/cocoa/SDL_iostreambundlesupport.h

@@ -23,8 +23,8 @@
 
 #include <stdio.h>
 
-#ifndef SDL_rwopsbundlesupport_h
-#define SDL_rwopsbundlesupport_h
+#ifndef SDL_iostreambundlesupport_h
+#define SDL_iostreambundlesupport_h
 FILE *SDL_OpenFPFromBundleOrFallback(const char *file, const char *mode);
 #endif
 #endif

+ 1 - 1
src/file/cocoa/SDL_rwopsbundlesupport.m → src/file/cocoa/SDL_iostreambundlesupport.m

@@ -23,7 +23,7 @@
 #ifdef SDL_PLATFORM_APPLE
 #import <Foundation/Foundation.h>
 
-#include "SDL_rwopsbundlesupport.h"
+#include "SDL_iostreambundlesupport.h"
 
 /* For proper macOS applications, the resources are contained inside the application bundle.
  So the strategy is to first check the application bundle for the file, then fallback to the current working directory.

+ 1 - 1
src/file/n3ds/SDL_rwopsromfs.c → src/file/n3ds/SDL_iostreamromfs.c

@@ -19,7 +19,7 @@
   3. This notice may not be removed or altered from any source distribution.
 */
 
-#include "SDL_rwopsromfs.h"
+#include "SDL_iostreamromfs.h"
 
 /* Checks if the mode is a kind of reading */
 static SDL_bool IsReadMode(const char *mode);

+ 3 - 3
src/file/n3ds/SDL_rwopsromfs.h → src/file/n3ds/SDL_iostreamromfs.h

@@ -20,9 +20,9 @@
 */
 #include "SDL_internal.h"
 
-#ifndef SDL_rwopsromfs_h_
-#define SDL_rwopsromfs_h_
+#ifndef SDL_iostreamromfs_h_
+#define SDL_iostreamromfs_h_
 
 FILE *N3DS_FileOpen(const char *file, const char *mode);
 
-#endif /* SDL_rwopsromfs_h_ */
+#endif /* SDL_iostreamromfs_h_ */

+ 3 - 3
src/joystick/SDL_gamepad.c

@@ -1789,7 +1789,7 @@ static GamepadMapping_t *SDL_PrivateGetGamepadMapping(SDL_JoystickID instance_id
 /*
  * Add or update an entry into the Mappings Database
  */
-int SDL_AddGamepadMappingsFromRW(SDL_RWops *src, SDL_bool freesrc)
+int SDL_AddGamepadMappingsFromIO(SDL_IOStream *src, SDL_bool closeio)
 {
     const char *platform = SDL_GetPlatform();
     int gamepads = 0;
@@ -1797,7 +1797,7 @@ int SDL_AddGamepadMappingsFromRW(SDL_RWops *src, SDL_bool freesrc)
     size_t db_size;
     size_t platform_len;
 
-    buf = (char *)SDL_LoadFile_RW(src, &db_size, freesrc);
+    buf = (char *)SDL_LoadFile_IO(src, &db_size, closeio);
     if (!buf) {
         return SDL_SetError("Could not allocate space to read DB into memory");
     }
@@ -1845,7 +1845,7 @@ int SDL_AddGamepadMappingsFromRW(SDL_RWops *src, SDL_bool freesrc)
 
 int SDL_AddGamepadMappingsFromFile(const char *file)
 {
-    return SDL_AddGamepadMappingsFromRW(SDL_RWFromFile(file, "rb"), 1);
+    return SDL_AddGamepadMappingsFromIO(SDL_IOFromFile(file, "rb"), 1);
 }
 
 int SDL_ReloadGamepadMappings(void)

+ 9 - 9
src/test/SDL_test_common.c

@@ -1900,20 +1900,20 @@ static const void *SDLTest_ScreenShotClipboardProvider(void *context, const char
     SDL_Log("Providing screenshot image to clipboard!\n");
 
     if (!data->image) {
-        SDL_RWops *file;
+        SDL_IOStream *file;
 
-        file = SDL_RWFromFile(SCREENSHOT_FILE, "r");
+        file = SDL_IOFromFile(SCREENSHOT_FILE, "r");
         if (file) {
-            size_t length = (size_t)SDL_RWsize(file);
+            size_t length = (size_t)SDL_SizeIO(file);
             void *image = SDL_malloc(length);
             if (image) {
-                if (SDL_RWread(file, image, length) != length) {
+                if (SDL_ReadIO(file, image, length) != length) {
                     SDL_Log("Couldn't read %s: %s\n", SCREENSHOT_FILE, SDL_GetError());
                     SDL_free(image);
                     image = NULL;
                 }
             }
-            SDL_RWclose(file);
+            SDL_CloseIO(file);
 
             if (image) {
                 data->image = image;
@@ -1977,14 +1977,14 @@ static void SDLTest_PasteScreenShot(void)
         void *data = SDL_GetClipboardData(image_formats[i], &size);
         if (data) {
             char filename[16];
-            SDL_RWops *file;
+            SDL_IOStream *file;
 
             SDL_snprintf(filename, sizeof(filename), "clipboard.%s", image_formats[i] + 6);
-            file = SDL_RWFromFile(filename, "w");
+            file = SDL_IOFromFile(filename, "w");
             if (file) {
                 SDL_Log("Writing clipboard image to %s", filename);
-                SDL_RWwrite(file, data, size);
-                SDL_RWclose(file);
+                SDL_WriteIO(file, data, size);
+                SDL_CloseIO(file);
             }
             SDL_free(data);
             return;

+ 27 - 27
src/video/SDL_bmp.c

@@ -50,7 +50,7 @@
 #define LCS_WINDOWS_COLOR_SPACE 0x57696E20
 #endif
 
-static SDL_bool readRlePixels(SDL_Surface *surface, SDL_RWops *src, int isRle8)
+static SDL_bool readRlePixels(SDL_Surface *surface, SDL_IOStream *src, int isRle8)
 {
     /*
     | Sets the surface pixels from src.  A bmp image is upside down.
@@ -193,7 +193,7 @@ static void CorrectAlphaChannel(SDL_Surface *surface)
     }
 }
 
-SDL_Surface *SDL_LoadBMP_RW(SDL_RWops *src, SDL_bool freesrc)
+SDL_Surface *SDL_LoadBMP_IO(SDL_IOStream *src, SDL_bool closeio)
 {
     SDL_bool was_error = SDL_TRUE;
     Sint64 fp_offset = 0;
@@ -239,12 +239,12 @@ SDL_Surface *SDL_LoadBMP_RW(SDL_RWops *src, SDL_bool freesrc)
     }
 
     /* Read in the BMP file header */
-    fp_offset = SDL_RWtell(src);
+    fp_offset = SDL_TellIO(src);
     if (fp_offset < 0) {
         goto done;
     }
     SDL_ClearError();
-    if (SDL_RWread(src, magic, 2) != 2) {
+    if (SDL_ReadIO(src, magic, 2) != 2) {
         goto done;
     }
     if (SDL_strncmp(magic, "BM", 2) != 0) {
@@ -340,9 +340,9 @@ SDL_Surface *SDL_LoadBMP_RW(SDL_RWops *src, SDL_bool freesrc)
         }
 
         /* skip any header bytes we didn't handle... */
-        headerSize = (Uint32)(SDL_RWtell(src) - (fp_offset + 14));
+        headerSize = (Uint32)(SDL_TellIO(src) - (fp_offset + 14));
         if (biSize > headerSize) {
-            if (SDL_RWseek(src, (biSize - headerSize), SDL_RW_SEEK_CUR) < 0) {
+            if (SDL_SeekIO(src, (biSize - headerSize), SDL_IO_SEEK_CUR) < 0) {
                 goto done;
             }
         }
@@ -441,7 +441,7 @@ SDL_Surface *SDL_LoadBMP_RW(SDL_RWops *src, SDL_bool freesrc)
     /* Load the palette, if any */
     palette = (surface->format)->palette;
     if (palette) {
-        if (SDL_RWseek(src, fp_offset + 14 + biSize, SDL_RW_SEEK_SET) < 0) {
+        if (SDL_SeekIO(src, fp_offset + 14 + biSize, SDL_IO_SEEK_SET) < 0) {
             SDL_Error(SDL_EFSEEK);
             goto done;
         }
@@ -492,7 +492,7 @@ SDL_Surface *SDL_LoadBMP_RW(SDL_RWops *src, SDL_bool freesrc)
     }
 
     /* Read the surface pixels.  Note that the bmp image is upside down */
-    if (SDL_RWseek(src, fp_offset + bfOffBits, SDL_RW_SEEK_SET) < 0) {
+    if (SDL_SeekIO(src, fp_offset + bfOffBits, SDL_IO_SEEK_SET) < 0) {
         SDL_Error(SDL_EFSEEK);
         goto done;
     }
@@ -512,7 +512,7 @@ SDL_Surface *SDL_LoadBMP_RW(SDL_RWops *src, SDL_bool freesrc)
         bits = end - surface->pitch;
     }
     while (bits >= top && bits < end) {
-        if (SDL_RWread(src, bits, surface->pitch) != (size_t)surface->pitch) {
+        if (SDL_ReadIO(src, bits, surface->pitch) != (size_t)surface->pitch) {
             goto done;
         }
         if (biBitCount == 8 && palette && biClrUsed < (1u << biBitCount)) {
@@ -572,23 +572,23 @@ SDL_Surface *SDL_LoadBMP_RW(SDL_RWops *src, SDL_bool freesrc)
 done:
     if (was_error) {
         if (src) {
-            SDL_RWseek(src, fp_offset, SDL_RW_SEEK_SET);
+            SDL_SeekIO(src, fp_offset, SDL_IO_SEEK_SET);
         }
         SDL_DestroySurface(surface);
         surface = NULL;
     }
-    if (freesrc && src) {
-        SDL_RWclose(src);
+    if (closeio && src) {
+        SDL_CloseIO(src);
     }
     return surface;
 }
 
 SDL_Surface *SDL_LoadBMP(const char *file)
 {
-    return SDL_LoadBMP_RW(SDL_RWFromFile(file, "rb"), 1);
+    return SDL_LoadBMP_IO(SDL_IOFromFile(file, "rb"), 1);
 }
 
-int SDL_SaveBMP_RW(SDL_Surface *surface, SDL_RWops *dst, SDL_bool freedst)
+int SDL_SaveBMP_IO(SDL_Surface *surface, SDL_IOStream *dst, SDL_bool closeio)
 {
     SDL_bool was_error = SDL_TRUE;
     Sint64 fp_offset, new_offset;
@@ -685,7 +685,7 @@ int SDL_SaveBMP_RW(SDL_Surface *surface, SDL_RWops *dst, SDL_bool freedst)
         }
     } else {
         /* Set no error here because it may overwrite a more useful message from
-           SDL_RWFromFile() if SDL_SaveBMP_RW() is called from SDL_SaveBMP(). */
+           SDL_IOFromFile() if SDL_SaveBMP_IO() is called from SDL_SaveBMP(). */
         goto done;
     }
 
@@ -703,11 +703,11 @@ int SDL_SaveBMP_RW(SDL_Surface *surface, SDL_RWops *dst, SDL_bool freedst)
         bfOffBits = 0; /* We'll write this when we're done */
 
         /* Write the BMP file header values */
-        fp_offset = SDL_RWtell(dst);
+        fp_offset = SDL_TellIO(dst);
         if (fp_offset < 0) {
             goto done;
         }
-        if (SDL_RWwrite(dst, magic, 2) != 2 ||
+        if (SDL_WriteIO(dst, magic, 2) != 2 ||
             !SDL_WriteU32LE(dst, bfSize) ||
             !SDL_WriteU16LE(dst, bfReserved1) ||
             !SDL_WriteU16LE(dst, bfReserved2) ||
@@ -801,14 +801,14 @@ int SDL_SaveBMP_RW(SDL_Surface *surface, SDL_RWops *dst, SDL_bool freedst)
         }
 
         /* Write the bitmap offset */
-        bfOffBits = (Uint32)(SDL_RWtell(dst) - fp_offset);
-        if (SDL_RWseek(dst, fp_offset + 10, SDL_RW_SEEK_SET) < 0) {
+        bfOffBits = (Uint32)(SDL_TellIO(dst) - fp_offset);
+        if (SDL_SeekIO(dst, fp_offset + 10, SDL_IO_SEEK_SET) < 0) {
             goto done;
         }
         if (!SDL_WriteU32LE(dst, bfOffBits)) {
             goto done;
         }
-        if (SDL_RWseek(dst, fp_offset + bfOffBits, SDL_RW_SEEK_SET) < 0) {
+        if (SDL_SeekIO(dst, fp_offset + bfOffBits, SDL_IO_SEEK_SET) < 0) {
             goto done;
         }
 
@@ -817,7 +817,7 @@ int SDL_SaveBMP_RW(SDL_Surface *surface, SDL_RWops *dst, SDL_bool freedst)
         pad = ((bw % 4) ? (4 - (bw % 4)) : 0);
         while (bits > (Uint8 *)intermediate_surface->pixels) {
             bits -= intermediate_surface->pitch;
-            if (SDL_RWwrite(dst, bits, bw) != bw) {
+            if (SDL_WriteIO(dst, bits, bw) != bw) {
                 goto done;
             }
             if (pad) {
@@ -831,18 +831,18 @@ int SDL_SaveBMP_RW(SDL_Surface *surface, SDL_RWops *dst, SDL_bool freedst)
         }
 
         /* Write the BMP file size */
-        new_offset = SDL_RWtell(dst);
+        new_offset = SDL_TellIO(dst);
         if (new_offset < 0) {
             goto done;
         }
         bfSize = (Uint32)(new_offset - fp_offset);
-        if (SDL_RWseek(dst, fp_offset + 2, SDL_RW_SEEK_SET) < 0) {
+        if (SDL_SeekIO(dst, fp_offset + 2, SDL_IO_SEEK_SET) < 0) {
             goto done;
         }
         if (!SDL_WriteU32LE(dst, bfSize)) {
             goto done;
         }
-        if (SDL_RWseek(dst, fp_offset + bfSize, SDL_RW_SEEK_SET) < 0) {
+        if (SDL_SeekIO(dst, fp_offset + bfSize, SDL_IO_SEEK_SET) < 0) {
             goto done;
         }
 
@@ -856,8 +856,8 @@ done:
     if (intermediate_surface && intermediate_surface != surface) {
         SDL_DestroySurface(intermediate_surface);
     }
-    if (freedst && dst) {
-        if (SDL_RWclose(dst) < 0) {
+    if (closeio && dst) {
+        if (SDL_CloseIO(dst) < 0) {
             was_error = SDL_TRUE;
         }
     }
@@ -869,5 +869,5 @@ done:
 
 int SDL_SaveBMP(SDL_Surface *surface, const char *file)
 {
-    return SDL_SaveBMP_RW(surface, SDL_RWFromFile(file, "wb"), 1);
+    return SDL_SaveBMP_IO(surface, SDL_IOFromFile(file, "wb"), 1);
 }

+ 1 - 1
test/README

@@ -6,7 +6,7 @@ These are test programs for the SDL library:
 	testsurround	Audio test -- play test tone on each audio channel
 	testaudioinfo	Lists audio device capabilities
 	testerror	Tests multi-threaded error handling
-	testfile	Tests RWops layer
+	testfile	Tests SDL_IOStream layer
 	testgl		A very simple example of using OpenGL with SDL
 	testiconv	Tests international string conversion
 	testkeys	List the available keyboard keys

+ 2 - 2
test/gamepadutils.c

@@ -135,9 +135,9 @@ static SDL_Texture *CreateTexture(SDL_Renderer *renderer, unsigned char *data, u
 {
     SDL_Texture *texture = NULL;
     SDL_Surface *surface;
-    SDL_RWops *src = SDL_RWFromConstMem(data, len);
+    SDL_IOStream *src = SDL_IOFromConstMem(data, len);
     if (src) {
-        surface = SDL_LoadBMP_RW(src, SDL_TRUE);
+        surface = SDL_LoadBMP_IO(src, SDL_TRUE);
         if (surface) {
             texture = SDL_CreateTextureFromSurface(renderer, surface);
             SDL_DestroySurface(surface);

+ 1 - 1
test/testautomation.c

@@ -40,7 +40,7 @@ static SDLTest_TestSuiteReference *testSuites[] = {
     &propertiesTestSuite,
     &rectTestSuite,
     &renderTestSuite,
-    &rwopsTestSuite,
+    &iostrmTestSuite,
     &sdltestTestSuite,
     &stdlibTestSuite,
     &surfaceTestSuite,

+ 648 - 0
test/testautomation_iostream.c

@@ -0,0 +1,648 @@
+
+/**
+ * Automated SDL_IOStream test.
+ *
+ * Original code written by Edgar Simo "bobbens"
+ * Ported by Markus Kauppila (markus.kauppila@gmail.com)
+ * Updated and extended for SDL_test by aschiffler at ferzkopp dot net
+ *
+ * Released under Public Domain.
+ */
+
+/* quiet windows compiler warnings */
+#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
+#define _CRT_SECURE_NO_WARNINGS
+#endif
+
+#include <stdio.h>
+
+#include <SDL3/SDL.h>
+#include <SDL3/SDL_test.h>
+#include "testautomation_suites.h"
+
+/* ================= Test Case Implementation ================== */
+
+static const char *IOStreamReadTestFilename = "iostrm_read";
+static const char *IOStreamWriteTestFilename = "iostrm_write";
+static const char *IOStreamAlphabetFilename = "iostrm_alphabet";
+
+static const char IOStreamHelloWorldTestString[] = "Hello World!";
+static const char IOStreamHelloWorldCompString[] = "Hello World!";
+static const char IOStreamAlphabetString[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+/* Fixture */
+
+static void IOStreamSetUp(void *arg)
+{
+    size_t fileLen;
+    FILE *handle;
+    size_t writtenLen;
+    int result;
+
+    /* Clean up from previous runs (if any); ignore errors */
+    (void)remove(IOStreamReadTestFilename);
+    (void)remove(IOStreamWriteTestFilename);
+    (void)remove(IOStreamAlphabetFilename);
+
+    /* Create a test file */
+    handle = fopen(IOStreamReadTestFilename, "w");
+    SDLTest_AssertCheck(handle != NULL, "Verify creation of file '%s' returned non NULL handle", IOStreamReadTestFilename);
+    if (handle == NULL) {
+        return;
+    }
+
+    /* Write some known text into it */
+    fileLen = SDL_strlen(IOStreamHelloWorldTestString);
+    writtenLen = fwrite(IOStreamHelloWorldTestString, 1, fileLen, handle);
+    SDLTest_AssertCheck(fileLen == writtenLen, "Verify number of written bytes, expected %i, got %i", (int)fileLen, (int)writtenLen);
+    result = fclose(handle);
+    SDLTest_AssertCheck(result == 0, "Verify result from fclose, expected 0, got %i", result);
+
+    /* Create a second test file */
+    handle = fopen(IOStreamAlphabetFilename, "w");
+    SDLTest_AssertCheck(handle != NULL, "Verify creation of file '%s' returned non NULL handle", IOStreamAlphabetFilename);
+    if (handle == NULL) {
+        return;
+    }
+
+    /* Write alphabet text into it */
+    fileLen = SDL_strlen(IOStreamAlphabetString);
+    writtenLen = fwrite(IOStreamAlphabetString, 1, fileLen, handle);
+    SDLTest_AssertCheck(fileLen == writtenLen, "Verify number of written bytes, expected %i, got %i", (int)fileLen, (int)writtenLen);
+    result = fclose(handle);
+    SDLTest_AssertCheck(result == 0, "Verify result from fclose, expected 0, got %i", result);
+
+    SDLTest_AssertPass("Creation of test file completed");
+}
+
+static void IOStreamTearDown(void *arg)
+{
+    int result;
+
+    /* Remove the created files to clean up; ignore errors for write filename */
+    result = remove(IOStreamReadTestFilename);
+    SDLTest_AssertCheck(result == 0, "Verify result from remove(%s), expected 0, got %i", IOStreamReadTestFilename, result);
+    (void)remove(IOStreamWriteTestFilename);
+    result = remove(IOStreamAlphabetFilename);
+    SDLTest_AssertCheck(result == 0, "Verify result from remove(%s), expected 0, got %i", IOStreamAlphabetFilename, result);
+
+    SDLTest_AssertPass("Cleanup of test files completed");
+}
+
+/**
+ * Makes sure parameters work properly. Local helper function.
+ *
+ * \sa SDL_SeekIO
+ * \sa SDL_ReadIO
+ */
+static void testGenericIOStreamValidations(SDL_IOStream *rw, SDL_bool write)
+{
+    char buf[sizeof(IOStreamHelloWorldTestString)];
+    Sint64 i;
+    size_t s;
+    int seekPos = SDLTest_RandomIntegerInRange(4, 8);
+
+    /* Clear buffer */
+    SDL_zeroa(buf);
+
+    /* Set to start. */
+    i = SDL_SeekIO(rw, 0, SDL_IO_SEEK_SET);
+    SDLTest_AssertPass("Call to SDL_SeekIO succeeded");
+    SDLTest_AssertCheck(i == (Sint64)0, "Verify seek to 0 with SDL_SeekIO (SDL_IO_SEEK_SET), expected 0, got %" SDL_PRIs64, i);
+
+    /* Test write */
+    s = SDL_WriteIO(rw, IOStreamHelloWorldTestString, sizeof(IOStreamHelloWorldTestString) - 1);
+    SDLTest_AssertPass("Call to SDL_WriteIO succeeded");
+    if (write) {
+        SDLTest_AssertCheck(s == sizeof(IOStreamHelloWorldTestString) - 1, "Verify result of writing with SDL_WriteIO, expected %i, got %i", (int)sizeof(IOStreamHelloWorldTestString) - 1, (int)s);
+    } else {
+        SDLTest_AssertCheck(s == 0, "Verify result of writing with SDL_WriteIO, expected: 0, got %i", (int)s);
+    }
+
+    /* Test seek to random position */
+    i = SDL_SeekIO(rw, seekPos, SDL_IO_SEEK_SET);
+    SDLTest_AssertPass("Call to SDL_SeekIO succeeded");
+    SDLTest_AssertCheck(i == (Sint64)seekPos, "Verify seek to %i with SDL_SeekIO (SDL_IO_SEEK_SET), expected %i, got %" SDL_PRIs64, seekPos, seekPos, i);
+
+    /* Test seek back to start */
+    i = SDL_SeekIO(rw, 0, SDL_IO_SEEK_SET);
+    SDLTest_AssertPass("Call to SDL_SeekIO succeeded");
+    SDLTest_AssertCheck(i == (Sint64)0, "Verify seek to 0 with SDL_SeekIO (SDL_IO_SEEK_SET), expected 0, got %" SDL_PRIs64, i);
+
+    /* Test read */
+    s = SDL_ReadIO(rw, buf, sizeof(IOStreamHelloWorldTestString) - 1);
+    SDLTest_AssertPass("Call to SDL_ReadIO succeeded");
+    SDLTest_AssertCheck(
+        s == (sizeof(IOStreamHelloWorldTestString) - 1),
+        "Verify result from SDL_ReadIO, expected %i, got %i",
+        (int)(sizeof(IOStreamHelloWorldTestString) - 1),
+        (int)s);
+    SDLTest_AssertCheck(
+        SDL_memcmp(buf, IOStreamHelloWorldTestString, sizeof(IOStreamHelloWorldTestString) - 1) == 0,
+        "Verify read bytes match expected string, expected '%s', got '%s'", IOStreamHelloWorldTestString, buf);
+
+    /* Test seek back to start */
+    i = SDL_SeekIO(rw, 0, SDL_IO_SEEK_SET);
+    SDLTest_AssertPass("Call to SDL_SeekIO succeeded");
+    SDLTest_AssertCheck(i == (Sint64)0, "Verify seek to 0 with SDL_SeekIO (SDL_IO_SEEK_SET), expected 0, got %" SDL_PRIs64, i);
+
+    /* Test printf */
+    s = SDL_IOprintf(rw, "%s", IOStreamHelloWorldTestString);
+    SDLTest_AssertPass("Call to SDL_IOprintf succeeded");
+    if (write) {
+        SDLTest_AssertCheck(s == sizeof(IOStreamHelloWorldTestString) - 1, "Verify result of writing with SDL_IOprintf, expected %i, got %i", (int)sizeof(IOStreamHelloWorldTestString) - 1, (int)s);
+    } else {
+        SDLTest_AssertCheck(s == 0, "Verify result of writing with SDL_WriteIO, expected: 0, got %i", (int)s);
+    }
+
+    /* Test seek back to start */
+    i = SDL_SeekIO(rw, 0, SDL_IO_SEEK_SET);
+    SDLTest_AssertPass("Call to SDL_SeekIO succeeded");
+    SDLTest_AssertCheck(i == (Sint64)0, "Verify seek to 0 with SDL_SeekIO (SDL_IO_SEEK_SET), expected 0, got %" SDL_PRIs64, i);
+
+    /* Test read */
+    s = SDL_ReadIO(rw, buf, sizeof(IOStreamHelloWorldTestString) - 1);
+    SDLTest_AssertPass("Call to SDL_ReadIO succeeded");
+    SDLTest_AssertCheck(
+        s == (sizeof(IOStreamHelloWorldTestString) - 1),
+        "Verify result from SDL_ReadIO, expected %i, got %i",
+        (int)(sizeof(IOStreamHelloWorldTestString) - 1),
+        (int)s);
+    SDLTest_AssertCheck(
+        SDL_memcmp(buf, IOStreamHelloWorldTestString, sizeof(IOStreamHelloWorldTestString) - 1) == 0,
+        "Verify read bytes match expected string, expected '%s', got '%s'", IOStreamHelloWorldTestString, buf);
+
+    /* More seek tests. */
+    i = SDL_SeekIO(rw, -4, SDL_IO_SEEK_CUR);
+    SDLTest_AssertPass("Call to SDL_SeekIO(...,-4,SDL_IO_SEEK_CUR) succeeded");
+    SDLTest_AssertCheck(
+        i == (Sint64)(sizeof(IOStreamHelloWorldTestString) - 5),
+        "Verify seek to -4 with SDL_SeekIO (SDL_IO_SEEK_CUR), expected %i, got %i",
+        (int)(sizeof(IOStreamHelloWorldTestString) - 5),
+        (int)i);
+
+    i = SDL_SeekIO(rw, -1, SDL_IO_SEEK_END);
+    SDLTest_AssertPass("Call to SDL_SeekIO(...,-1,SDL_IO_SEEK_END) succeeded");
+    SDLTest_AssertCheck(
+        i == (Sint64)(sizeof(IOStreamHelloWorldTestString) - 2),
+        "Verify seek to -1 with SDL_SeekIO (SDL_IO_SEEK_END), expected %i, got %i",
+        (int)(sizeof(IOStreamHelloWorldTestString) - 2),
+        (int)i);
+
+    /* Invalid whence seek */
+    i = SDL_SeekIO(rw, 0, 999);
+    SDLTest_AssertPass("Call to SDL_SeekIO(...,0,invalid_whence) succeeded");
+    SDLTest_AssertCheck(
+        i == (Sint64)(-1),
+        "Verify seek with SDL_SeekIO (invalid_whence); expected: -1, got %i",
+        (int)i);
+}
+
+/**
+ * Negative test for SDL_IOFromFile parameters
+ *
+ * \sa SDL_IOFromFile
+ *
+ */
+static int iostrm_testParamNegative(void *arg)
+{
+    SDL_IOStream *iostrm;
+
+    /* These should all fail. */
+    iostrm = SDL_IOFromFile(NULL, NULL);
+    SDLTest_AssertPass("Call to SDL_IOFromFile(NULL, NULL) succeeded");
+    SDLTest_AssertCheck(iostrm == NULL, "Verify SDL_IOFromFile(NULL, NULL) returns NULL");
+
+    iostrm = SDL_IOFromFile(NULL, "ab+");
+    SDLTest_AssertPass("Call to SDL_IOFromFile(NULL, \"ab+\") succeeded");
+    SDLTest_AssertCheck(iostrm == NULL, "Verify SDL_IOFromFile(NULL, \"ab+\") returns NULL");
+
+    iostrm = SDL_IOFromFile(NULL, "sldfkjsldkfj");
+    SDLTest_AssertPass("Call to SDL_IOFromFile(NULL, \"sldfkjsldkfj\") succeeded");
+    SDLTest_AssertCheck(iostrm == NULL, "Verify SDL_IOFromFile(NULL, \"sldfkjsldkfj\") returns NULL");
+
+    iostrm = SDL_IOFromFile("something", "");
+    SDLTest_AssertPass("Call to SDL_IOFromFile(\"something\", \"\") succeeded");
+    SDLTest_AssertCheck(iostrm == NULL, "Verify SDL_IOFromFile(\"something\", \"\") returns NULL");
+
+    iostrm = SDL_IOFromFile("something", NULL);
+    SDLTest_AssertPass("Call to SDL_IOFromFile(\"something\", NULL) succeeded");
+    SDLTest_AssertCheck(iostrm == NULL, "Verify SDL_IOFromFile(\"something\", NULL) returns NULL");
+
+    iostrm = SDL_IOFromMem(NULL, 10);
+    SDLTest_AssertPass("Call to SDL_IOFromMem(NULL, 10) succeeded");
+    SDLTest_AssertCheck(iostrm == NULL, "Verify SDL_IOFromMem(NULL, 10) returns NULL");
+
+    iostrm = SDL_IOFromMem((void *)IOStreamAlphabetString, 0);
+    SDLTest_AssertPass("Call to SDL_IOFromMem(data, 0) succeeded");
+    SDLTest_AssertCheck(iostrm == NULL, "Verify SDL_IOFromMem(data, 0) returns NULL");
+
+    iostrm = SDL_IOFromConstMem((const void *)IOStreamAlphabetString, 0);
+    SDLTest_AssertPass("Call to SDL_IOFromConstMem(data, 0) succeeded");
+    SDLTest_AssertCheck(iostrm == NULL, "Verify SDL_IOFromConstMem(data, 0) returns NULL");
+
+    return TEST_COMPLETED;
+}
+
+/**
+ * Tests opening from memory.
+ *
+ * \sa SDL_IOFromMem
+ * \sa SDL_CloseIO
+ */
+static int iostrm_testMem(void *arg)
+{
+    char mem[sizeof(IOStreamHelloWorldTestString)];
+    SDL_IOStream *rw;
+    int result;
+
+    /* Clear buffer */
+    SDL_zeroa(mem);
+
+    /* Open */
+    rw = SDL_IOFromMem(mem, sizeof(IOStreamHelloWorldTestString) - 1);
+    SDLTest_AssertPass("Call to SDL_IOFromMem() succeeded");
+    SDLTest_AssertCheck(rw != NULL, "Verify opening memory with SDL_IOFromMem does not return NULL");
+
+    /* Bail out if NULL */
+    if (rw == NULL) {
+        return TEST_ABORTED;
+    }
+
+    /* Run generic tests */
+    testGenericIOStreamValidations(rw, SDL_TRUE);
+
+    /* Close */
+    result = SDL_CloseIO(rw);
+    SDLTest_AssertPass("Call to SDL_CloseIO() succeeded");
+    SDLTest_AssertCheck(result == 0, "Verify result value is 0; got: %d", result);
+
+    return TEST_COMPLETED;
+}
+
+/**
+ * Tests opening from memory.
+ *
+ * \sa SDL_IOFromConstMem
+ * \sa SDL_CloseIO
+ */
+static int iostrm_testConstMem(void *arg)
+{
+    SDL_IOStream *rw;
+    int result;
+
+    /* Open handle */
+    rw = SDL_IOFromConstMem(IOStreamHelloWorldCompString, sizeof(IOStreamHelloWorldCompString) - 1);
+    SDLTest_AssertPass("Call to SDL_IOFromConstMem() succeeded");
+    SDLTest_AssertCheck(rw != NULL, "Verify opening memory with SDL_IOFromConstMem does not return NULL");
+
+    /* Bail out if NULL */
+    if (rw == NULL) {
+        return TEST_ABORTED;
+    }
+
+    /* Run generic tests */
+    testGenericIOStreamValidations(rw, SDL_FALSE);
+
+    /* Close handle */
+    result = SDL_CloseIO(rw);
+    SDLTest_AssertPass("Call to SDL_CloseIO() succeeded");
+    SDLTest_AssertCheck(result == 0, "Verify result value is 0; got: %d", result);
+
+    return TEST_COMPLETED;
+}
+
+/**
+ * Tests reading from file.
+ *
+ * \sa SDL_IOFromFile
+ * \sa SDL_CloseIO
+ */
+static int iostrm_testFileRead(void *arg)
+{
+    SDL_IOStream *rw;
+    int result;
+
+    /* Read test. */
+    rw = SDL_IOFromFile(IOStreamReadTestFilename, "r");
+    SDLTest_AssertPass("Call to SDL_IOFromFile(..,\"r\") succeeded");
+    SDLTest_AssertCheck(rw != NULL, "Verify opening file with SDL_IOFromFile in read mode does not return NULL");
+
+    /* Bail out if NULL */
+    if (rw == NULL) {
+        return TEST_ABORTED;
+    }
+
+    /* Run generic tests */
+    testGenericIOStreamValidations(rw, SDL_FALSE);
+
+    /* Close handle */
+    result = SDL_CloseIO(rw);
+    SDLTest_AssertPass("Call to SDL_CloseIO() succeeded");
+    SDLTest_AssertCheck(result == 0, "Verify result value is 0; got: %d", result);
+
+    return TEST_COMPLETED;
+}
+
+/**
+ * Tests writing from file.
+ *
+ * \sa SDL_IOFromFile
+ * \sa SDL_CloseIO
+ */
+static int iostrm_testFileWrite(void *arg)
+{
+    SDL_IOStream *rw;
+    int result;
+
+    /* Write test. */
+    rw = SDL_IOFromFile(IOStreamWriteTestFilename, "w+");
+    SDLTest_AssertPass("Call to SDL_IOFromFile(..,\"w+\") succeeded");
+    SDLTest_AssertCheck(rw != NULL, "Verify opening file with SDL_IOFromFile in write mode does not return NULL");
+
+    /* Bail out if NULL */
+    if (rw == NULL) {
+        return TEST_ABORTED;
+    }
+
+    /* Run generic tests */
+    testGenericIOStreamValidations(rw, SDL_TRUE);
+
+    /* Close handle */
+    result = SDL_CloseIO(rw);
+    SDLTest_AssertPass("Call to SDL_CloseIO() succeeded");
+    SDLTest_AssertCheck(result == 0, "Verify result value is 0; got: %d", result);
+
+    return TEST_COMPLETED;
+}
+
+/**
+ * Tests alloc and free RW context.
+ *
+ * \sa SDL_OpenIO
+ * \sa SDL_CloseIO
+ */
+static int iostrm_testAllocFree(void *arg)
+{
+    /* Allocate context */
+    SDL_IOStreamInterface iface;
+    SDL_IOStream *rw;
+
+    SDL_zero(iface);
+    rw = SDL_OpenIO(&iface, NULL);
+    SDLTest_AssertPass("Call to SDL_OpenIO() succeeded");
+    SDLTest_AssertCheck(rw != NULL, "Validate result from SDL_OpenIO() is not NULL");
+    if (rw == NULL) {
+        return TEST_ABORTED;
+    }
+
+    /* Free context again */
+    SDL_CloseIO(rw);
+    SDLTest_AssertPass("Call to SDL_CloseIO() succeeded");
+
+    return TEST_COMPLETED;
+}
+
+/**
+ * Compare memory and file reads
+ *
+ * \sa SDL_IOFromMem
+ * \sa SDL_IOFromFile
+ */
+static int iostrm_testCompareRWFromMemWithRWFromFile(void *arg)
+{
+    int slen = 26;
+    char buffer_file[27];
+    char buffer_mem[27];
+    size_t rv_file;
+    size_t rv_mem;
+    Uint64 sv_file;
+    Uint64 sv_mem;
+    SDL_IOStream *iostrm_file;
+    SDL_IOStream *iostrm_mem;
+    int size;
+    int result;
+
+    for (size = 5; size < 10; size++) {
+        /* Terminate buffer */
+        buffer_file[slen] = 0;
+        buffer_mem[slen] = 0;
+
+        /* Read/seek from memory */
+        iostrm_mem = SDL_IOFromMem((void *)IOStreamAlphabetString, slen);
+        SDLTest_AssertPass("Call to SDL_IOFromMem()");
+        rv_mem = SDL_ReadIO(iostrm_mem, buffer_mem, size * 6);
+        SDLTest_AssertPass("Call to SDL_ReadIO(mem, size=%d)", size * 6);
+        sv_mem = SDL_SeekIO(iostrm_mem, 0, SEEK_END);
+        SDLTest_AssertPass("Call to SDL_SeekIO(mem,SEEK_END)");
+        result = SDL_CloseIO(iostrm_mem);
+        SDLTest_AssertPass("Call to SDL_CloseIO(mem)");
+        SDLTest_AssertCheck(result == 0, "Verify result value is 0; got: %d", result);
+
+        /* Read/see from file */
+        iostrm_file = SDL_IOFromFile(IOStreamAlphabetFilename, "r");
+        SDLTest_AssertPass("Call to SDL_IOFromFile()");
+        rv_file = SDL_ReadIO(iostrm_file, buffer_file, size * 6);
+        SDLTest_AssertPass("Call to SDL_ReadIO(file, size=%d)", size * 6);
+        sv_file = SDL_SeekIO(iostrm_file, 0, SEEK_END);
+        SDLTest_AssertPass("Call to SDL_SeekIO(file,SEEK_END)");
+        result = SDL_CloseIO(iostrm_file);
+        SDLTest_AssertPass("Call to SDL_CloseIO(file)");
+        SDLTest_AssertCheck(result == 0, "Verify result value is 0; got: %d", result);
+
+        /* Compare */
+        SDLTest_AssertCheck(rv_mem == rv_file, "Verify returned read blocks matches for mem and file reads; got: rv_mem=%d rv_file=%d", (int)rv_mem, (int)rv_file);
+        SDLTest_AssertCheck(sv_mem == sv_file, "Verify SEEK_END position matches for mem and file seeks; got: sv_mem=%d sv_file=%d", (int)sv_mem, (int)sv_file);
+        SDLTest_AssertCheck(buffer_mem[slen] == 0, "Verify mem buffer termination; expected: 0, got: %d", buffer_mem[slen]);
+        SDLTest_AssertCheck(buffer_file[slen] == 0, "Verify file buffer termination; expected: 0, got: %d", buffer_file[slen]);
+        SDLTest_AssertCheck(
+            SDL_strncmp(buffer_mem, IOStreamAlphabetString, slen) == 0,
+            "Verify mem buffer contain alphabet string; expected: %s, got: %s", IOStreamAlphabetString, buffer_mem);
+        SDLTest_AssertCheck(
+            SDL_strncmp(buffer_file, IOStreamAlphabetString, slen) == 0,
+            "Verify file buffer contain alphabet string; expected: %s, got: %s", IOStreamAlphabetString, buffer_file);
+    }
+
+    return TEST_COMPLETED;
+}
+
+/**
+ * Tests writing and reading from file using endian aware functions.
+ *
+ * \sa SDL_IOFromFile
+ * \sa SDL_CloseIO
+ * \sa SDL_ReadU16BE
+ * \sa SDL_WriteU16BE
+ */
+static int iostrm_testFileWriteReadEndian(void *arg)
+{
+    SDL_IOStream *rw;
+    Sint64 result;
+    int mode;
+    Uint16 BE16value;
+    Uint32 BE32value;
+    Uint64 BE64value;
+    Uint16 LE16value;
+    Uint32 LE32value;
+    Uint64 LE64value;
+    Uint16 BE16test;
+    Uint32 BE32test;
+    Uint64 BE64test;
+    Uint16 LE16test;
+    Uint32 LE32test;
+    Uint64 LE64test;
+    SDL_bool bresult;
+    int cresult;
+
+    for (mode = 0; mode < 3; mode++) {
+
+        /* Create test data */
+        switch (mode) {
+        default:
+        case 0:
+            SDLTest_Log("All 0 values");
+            BE16value = 0;
+            BE32value = 0;
+            BE64value = 0;
+            LE16value = 0;
+            LE32value = 0;
+            LE64value = 0;
+            break;
+        case 1:
+            SDLTest_Log("All 1 values");
+            BE16value = 1;
+            BE32value = 1;
+            BE64value = 1;
+            LE16value = 1;
+            LE32value = 1;
+            LE64value = 1;
+            break;
+        case 2:
+            SDLTest_Log("Random values");
+            BE16value = SDLTest_RandomUint16();
+            BE32value = SDLTest_RandomUint32();
+            BE64value = SDLTest_RandomUint64();
+            LE16value = SDLTest_RandomUint16();
+            LE32value = SDLTest_RandomUint32();
+            LE64value = SDLTest_RandomUint64();
+            break;
+        }
+
+        /* Write test. */
+        rw = SDL_IOFromFile(IOStreamWriteTestFilename, "w+");
+        SDLTest_AssertPass("Call to SDL_IOFromFile(..,\"w+\")");
+        SDLTest_AssertCheck(rw != NULL, "Verify opening file with SDL_IOFromFile in write mode does not return NULL");
+
+        /* Bail out if NULL */
+        if (rw == NULL) {
+            return TEST_ABORTED;
+        }
+
+        /* Write test data */
+        bresult = SDL_WriteU16BE(rw, BE16value);
+        SDLTest_AssertPass("Call to SDL_WriteU16BE()");
+        SDLTest_AssertCheck(bresult == SDL_TRUE, "Validate object written, expected: SDL_TRUE, got: SDL_FALSE");
+        bresult = SDL_WriteU32BE(rw, BE32value);
+        SDLTest_AssertPass("Call to SDL_WriteU32BE()");
+        SDLTest_AssertCheck(bresult == SDL_TRUE, "Validate object written, expected: SDL_TRUE, got: SDL_FALSE");
+        bresult = SDL_WriteU64BE(rw, BE64value);
+        SDLTest_AssertPass("Call to SDL_WriteU64BE()");
+        SDLTest_AssertCheck(bresult == SDL_TRUE, "Validate object written, expected: SDL_TRUE, got: SDL_FALSE");
+        bresult = SDL_WriteU16LE(rw, LE16value);
+        SDLTest_AssertPass("Call to SDL_WriteU16LE()");
+        SDLTest_AssertCheck(bresult == SDL_TRUE, "Validate object written, expected: SDL_TRUE, got: SDL_FALSE");
+        bresult = SDL_WriteU32LE(rw, LE32value);
+        SDLTest_AssertPass("Call to SDL_WriteU32LE()");
+        SDLTest_AssertCheck(bresult == SDL_TRUE, "Validate object written, expected: SDL_TRUE, got: SDL_FALSE");
+        bresult = SDL_WriteU64LE(rw, LE64value);
+        SDLTest_AssertPass("Call to SDL_WriteU64LE()");
+        SDLTest_AssertCheck(bresult == SDL_TRUE, "Validate object written, expected: SDL_TRUE, got: SDL_FALSE");
+
+        /* Test seek to start */
+        result = SDL_SeekIO(rw, 0, SDL_IO_SEEK_SET);
+        SDLTest_AssertPass("Call to SDL_SeekIO succeeded");
+        SDLTest_AssertCheck(result == 0, "Verify result from position 0 with SDL_SeekIO, expected 0, got %i", (int)result);
+
+        /* Read test data */
+        bresult = SDL_ReadU16BE(rw, &BE16test);
+        SDLTest_AssertPass("Call to SDL_ReadU16BE()");
+        SDLTest_AssertCheck(bresult == SDL_TRUE, "Validate object read, expected: SDL_TRUE, got: SDL_FALSE");
+        SDLTest_AssertCheck(BE16test == BE16value, "Validate object read from SDL_ReadU16BE, expected: %hu, got: %hu", BE16value, BE16test);
+        bresult = SDL_ReadU32BE(rw, &BE32test);
+        SDLTest_AssertPass("Call to SDL_ReadU32BE()");
+        SDLTest_AssertCheck(bresult == SDL_TRUE, "Validate object read, expected: SDL_TRUE, got: SDL_FALSE");
+        SDLTest_AssertCheck(BE32test == BE32value, "Validate object read from SDL_ReadU32BE, expected: %" SDL_PRIu32 ", got: %" SDL_PRIu32, BE32value, BE32test);
+        bresult = SDL_ReadU64BE(rw, &BE64test);
+        SDLTest_AssertPass("Call to SDL_ReadU64BE()");
+        SDLTest_AssertCheck(bresult == SDL_TRUE, "Validate object read, expected: SDL_TRUE, got: SDL_FALSE");
+        SDLTest_AssertCheck(BE64test == BE64value, "Validate object read from SDL_ReadU64BE, expected: %" SDL_PRIu64 ", got: %" SDL_PRIu64, BE64value, BE64test);
+        bresult = SDL_ReadU16LE(rw, &LE16test);
+        SDLTest_AssertPass("Call to SDL_ReadU16LE()");
+        SDLTest_AssertCheck(bresult == SDL_TRUE, "Validate object read, expected: SDL_TRUE, got: SDL_FALSE");
+        SDLTest_AssertCheck(LE16test == LE16value, "Validate object read from SDL_ReadU16LE, expected: %hu, got: %hu", LE16value, LE16test);
+        bresult = SDL_ReadU32LE(rw, &LE32test);
+        SDLTest_AssertPass("Call to SDL_ReadU32LE()");
+        SDLTest_AssertCheck(bresult == SDL_TRUE, "Validate object read, expected: SDL_TRUE, got: SDL_FALSE");
+        SDLTest_AssertCheck(LE32test == LE32value, "Validate object read from SDL_ReadU32LE, expected: %" SDL_PRIu32 ", got: %" SDL_PRIu32, LE32value, LE32test);
+        bresult = SDL_ReadU64LE(rw, &LE64test);
+        SDLTest_AssertPass("Call to SDL_ReadU64LE()");
+        SDLTest_AssertCheck(bresult == SDL_TRUE, "Validate object read, expected: SDL_TRUE, got: SDL_FALSE");
+        SDLTest_AssertCheck(LE64test == LE64value, "Validate object read from SDL_ReadU64LE, expected: %" SDL_PRIu64 ", got: %" SDL_PRIu64, LE64value, LE64test);
+
+        /* Close handle */
+        cresult = SDL_CloseIO(rw);
+        SDLTest_AssertPass("Call to SDL_CloseIO() succeeded");
+        SDLTest_AssertCheck(cresult == 0, "Verify result value is 0; got: %d", cresult);
+    }
+
+    return TEST_COMPLETED;
+}
+
+/* ================= Test References ================== */
+
+/* IOStream test cases */
+static const SDLTest_TestCaseReference iostrmTest1 = {
+    (SDLTest_TestCaseFp)iostrm_testParamNegative, "iostrm_testParamNegative", "Negative test for SDL_IOFromFile parameters", TEST_ENABLED
+};
+
+static const SDLTest_TestCaseReference iostrmTest2 = {
+    (SDLTest_TestCaseFp)iostrm_testMem, "iostrm_testMem", "Tests opening from memory", TEST_ENABLED
+};
+
+static const SDLTest_TestCaseReference iostrmTest3 = {
+    (SDLTest_TestCaseFp)iostrm_testConstMem, "iostrm_testConstMem", "Tests opening from (const) memory", TEST_ENABLED
+};
+
+static const SDLTest_TestCaseReference iostrmTest4 = {
+    (SDLTest_TestCaseFp)iostrm_testFileRead, "iostrm_testFileRead", "Tests reading from a file", TEST_ENABLED
+};
+
+static const SDLTest_TestCaseReference iostrmTest5 = {
+    (SDLTest_TestCaseFp)iostrm_testFileWrite, "iostrm_testFileWrite", "Test writing to a file", TEST_ENABLED
+};
+
+static const SDLTest_TestCaseReference iostrmTest6 = {
+    (SDLTest_TestCaseFp)iostrm_testAllocFree, "iostrm_testAllocFree", "Test alloc and free of RW context", TEST_ENABLED
+};
+
+static const SDLTest_TestCaseReference iostrmTest7 = {
+    (SDLTest_TestCaseFp)iostrm_testFileWriteReadEndian, "iostrm_testFileWriteReadEndian", "Test writing and reading via the Endian aware functions", TEST_ENABLED
+};
+
+static const SDLTest_TestCaseReference iostrmTest8 = {
+    (SDLTest_TestCaseFp)iostrm_testCompareRWFromMemWithRWFromFile, "iostrm_testCompareRWFromMemWithRWFromFile", "Compare RWFromMem and RWFromFile IOStream for read and seek", TEST_ENABLED
+};
+
+/* Sequence of IOStream test cases */
+static const SDLTest_TestCaseReference *iostrmTests[] = {
+    &iostrmTest1, &iostrmTest2, &iostrmTest3, &iostrmTest4, &iostrmTest5, &iostrmTest6,
+    &iostrmTest7, &iostrmTest8, NULL
+};
+
+/* IOStream test suite (global) */
+SDLTest_TestSuiteReference iostrmTestSuite = {
+    "IOStream",
+    IOStreamSetUp,
+    iostrmTests,
+    IOStreamTearDown
+};

+ 0 - 685
test/testautomation_rwops.c

@@ -1,685 +0,0 @@
-
-/**
- * Automated SDL_RWops test.
- *
- * Original code written by Edgar Simo "bobbens"
- * Ported by Markus Kauppila (markus.kauppila@gmail.com)
- * Updated and extended for SDL_test by aschiffler at ferzkopp dot net
- *
- * Released under Public Domain.
- */
-
-/* quiet windows compiler warnings */
-#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
-#define _CRT_SECURE_NO_WARNINGS
-#endif
-
-#include <stdio.h>
-
-#include <SDL3/SDL.h>
-#include <SDL3/SDL_test.h>
-#include "testautomation_suites.h"
-
-/* ================= Test Case Implementation ================== */
-
-static const char *RWopsReadTestFilename = "rwops_read";
-static const char *RWopsWriteTestFilename = "rwops_write";
-static const char *RWopsAlphabetFilename = "rwops_alphabet";
-
-static const char RWopsHelloWorldTestString[] = "Hello World!";
-static const char RWopsHelloWorldCompString[] = "Hello World!";
-static const char RWopsAlphabetString[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
-
-/* Fixture */
-
-static void RWopsSetUp(void *arg)
-{
-    size_t fileLen;
-    FILE *handle;
-    size_t writtenLen;
-    int result;
-
-    /* Clean up from previous runs (if any); ignore errors */
-    (void)remove(RWopsReadTestFilename);
-    (void)remove(RWopsWriteTestFilename);
-    (void)remove(RWopsAlphabetFilename);
-
-    /* Create a test file */
-    handle = fopen(RWopsReadTestFilename, "w");
-    SDLTest_AssertCheck(handle != NULL, "Verify creation of file '%s' returned non NULL handle", RWopsReadTestFilename);
-    if (handle == NULL) {
-        return;
-    }
-
-    /* Write some known text into it */
-    fileLen = SDL_strlen(RWopsHelloWorldTestString);
-    writtenLen = fwrite(RWopsHelloWorldTestString, 1, fileLen, handle);
-    SDLTest_AssertCheck(fileLen == writtenLen, "Verify number of written bytes, expected %i, got %i", (int)fileLen, (int)writtenLen);
-    result = fclose(handle);
-    SDLTest_AssertCheck(result == 0, "Verify result from fclose, expected 0, got %i", result);
-
-    /* Create a second test file */
-    handle = fopen(RWopsAlphabetFilename, "w");
-    SDLTest_AssertCheck(handle != NULL, "Verify creation of file '%s' returned non NULL handle", RWopsAlphabetFilename);
-    if (handle == NULL) {
-        return;
-    }
-
-    /* Write alphabet text into it */
-    fileLen = SDL_strlen(RWopsAlphabetString);
-    writtenLen = fwrite(RWopsAlphabetString, 1, fileLen, handle);
-    SDLTest_AssertCheck(fileLen == writtenLen, "Verify number of written bytes, expected %i, got %i", (int)fileLen, (int)writtenLen);
-    result = fclose(handle);
-    SDLTest_AssertCheck(result == 0, "Verify result from fclose, expected 0, got %i", result);
-
-    SDLTest_AssertPass("Creation of test file completed");
-}
-
-static void RWopsTearDown(void *arg)
-{
-    int result;
-
-    /* Remove the created files to clean up; ignore errors for write filename */
-    result = remove(RWopsReadTestFilename);
-    SDLTest_AssertCheck(result == 0, "Verify result from remove(%s), expected 0, got %i", RWopsReadTestFilename, result);
-    (void)remove(RWopsWriteTestFilename);
-    result = remove(RWopsAlphabetFilename);
-    SDLTest_AssertCheck(result == 0, "Verify result from remove(%s), expected 0, got %i", RWopsAlphabetFilename, result);
-
-    SDLTest_AssertPass("Cleanup of test files completed");
-}
-
-/**
- * Makes sure parameters work properly. Local helper function.
- *
- * \sa SDL_RWseek
- * \sa SDL_RWread
- */
-static void testGenericRWopsValidations(SDL_RWops *rw, SDL_bool write)
-{
-    char buf[sizeof(RWopsHelloWorldTestString)];
-    Sint64 i;
-    size_t s;
-    int seekPos = SDLTest_RandomIntegerInRange(4, 8);
-
-    /* Clear buffer */
-    SDL_zeroa(buf);
-
-    /* Set 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 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 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);
-    }
-
-    /* Test seek to random position */
-    i = SDL_RWseek(rw, seekPos, SDL_RW_SEEK_SET);
-    SDLTest_AssertPass("Call to SDL_RWseek succeeded");
-    SDLTest_AssertCheck(i == (Sint64)seekPos, "Verify seek to %i with SDL_RWseek (SDL_RW_SEEK_SET), expected %i, got %" SDL_PRIs64, seekPos, seekPos, i);
-
-    /* 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");
-    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");
-    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);
-
-    /* More seek tests. */
-    i = SDL_RWseek(rw, -4, SDL_RW_SEEK_CUR);
-    SDLTest_AssertPass("Call to SDL_RWseek(...,-4,SDL_RW_SEEK_CUR) succeeded");
-    SDLTest_AssertCheck(
-        i == (Sint64)(sizeof(RWopsHelloWorldTestString) - 5),
-        "Verify seek to -4 with SDL_RWseek (SDL_RW_SEEK_CUR), expected %i, got %i",
-        (int)(sizeof(RWopsHelloWorldTestString) - 5),
-        (int)i);
-
-    i = SDL_RWseek(rw, -1, SDL_RW_SEEK_END);
-    SDLTest_AssertPass("Call to SDL_RWseek(...,-1,SDL_RW_SEEK_END) succeeded");
-    SDLTest_AssertCheck(
-        i == (Sint64)(sizeof(RWopsHelloWorldTestString) - 2),
-        "Verify seek to -1 with SDL_RWseek (SDL_RW_SEEK_END), expected %i, got %i",
-        (int)(sizeof(RWopsHelloWorldTestString) - 2),
-        (int)i);
-
-    /* Invalid whence seek */
-    i = SDL_RWseek(rw, 0, 999);
-    SDLTest_AssertPass("Call to SDL_RWseek(...,0,invalid_whence) succeeded");
-    SDLTest_AssertCheck(
-        i == (Sint64)(-1),
-        "Verify seek with SDL_RWseek (invalid_whence); expected: -1, got %i",
-        (int)i);
-}
-
-/**
- * Negative test for SDL_RWFromFile parameters
- *
- * \sa SDL_RWFromFile
- *
- */
-static int rwops_testParamNegative(void *arg)
-{
-    SDL_RWops *rwops;
-
-    /* These should all fail. */
-    rwops = SDL_RWFromFile(NULL, NULL);
-    SDLTest_AssertPass("Call to SDL_RWFromFile(NULL, NULL) succeeded");
-    SDLTest_AssertCheck(rwops == NULL, "Verify SDL_RWFromFile(NULL, NULL) returns NULL");
-
-    rwops = SDL_RWFromFile(NULL, "ab+");
-    SDLTest_AssertPass("Call to SDL_RWFromFile(NULL, \"ab+\") succeeded");
-    SDLTest_AssertCheck(rwops == NULL, "Verify SDL_RWFromFile(NULL, \"ab+\") returns NULL");
-
-    rwops = SDL_RWFromFile(NULL, "sldfkjsldkfj");
-    SDLTest_AssertPass("Call to SDL_RWFromFile(NULL, \"sldfkjsldkfj\") succeeded");
-    SDLTest_AssertCheck(rwops == NULL, "Verify SDL_RWFromFile(NULL, \"sldfkjsldkfj\") returns NULL");
-
-    rwops = SDL_RWFromFile("something", "");
-    SDLTest_AssertPass("Call to SDL_RWFromFile(\"something\", \"\") succeeded");
-    SDLTest_AssertCheck(rwops == NULL, "Verify SDL_RWFromFile(\"something\", \"\") returns NULL");
-
-    rwops = SDL_RWFromFile("something", NULL);
-    SDLTest_AssertPass("Call to SDL_RWFromFile(\"something\", NULL) succeeded");
-    SDLTest_AssertCheck(rwops == NULL, "Verify SDL_RWFromFile(\"something\", NULL) returns NULL");
-
-    rwops = SDL_RWFromMem(NULL, 10);
-    SDLTest_AssertPass("Call to SDL_RWFromMem(NULL, 10) succeeded");
-    SDLTest_AssertCheck(rwops == NULL, "Verify SDL_RWFromMem(NULL, 10) returns NULL");
-
-    rwops = SDL_RWFromMem((void *)RWopsAlphabetString, 0);
-    SDLTest_AssertPass("Call to SDL_RWFromMem(data, 0) succeeded");
-    SDLTest_AssertCheck(rwops == NULL, "Verify SDL_RWFromMem(data, 0) returns NULL");
-
-    rwops = SDL_RWFromConstMem((const void *)RWopsAlphabetString, 0);
-    SDLTest_AssertPass("Call to SDL_RWFromConstMem(data, 0) succeeded");
-    SDLTest_AssertCheck(rwops == NULL, "Verify SDL_RWFromConstMem(data, 0) returns NULL");
-
-    return TEST_COMPLETED;
-}
-
-/**
- * Tests opening from memory.
- *
- * \sa SDL_RWFromMem
- * \sa SDL_RWClose
- */
-static int rwops_testMem(void *arg)
-{
-    char mem[sizeof(RWopsHelloWorldTestString)];
-    SDL_RWops *rw;
-    int result;
-
-    /* Clear buffer */
-    SDL_zeroa(mem);
-
-    /* Open */
-    rw = SDL_RWFromMem(mem, sizeof(RWopsHelloWorldTestString) - 1);
-    SDLTest_AssertPass("Call to SDL_RWFromMem() succeeded");
-    SDLTest_AssertCheck(rw != NULL, "Verify opening memory with SDL_RWFromMem does not return NULL");
-
-    /* Bail out if NULL */
-    if (rw == NULL) {
-        return TEST_ABORTED;
-    }
-
-    /* Check type */
-    SDLTest_AssertCheck(rw->type == SDL_RWOPS_MEMORY, "Verify RWops type is SDL_RWOPS_MEMORY; expected: %d, got: %" SDL_PRIu32, SDL_RWOPS_MEMORY, rw->type);
-
-    /* Run generic tests */
-    testGenericRWopsValidations(rw, SDL_TRUE);
-
-    /* Close */
-    result = SDL_RWclose(rw);
-    SDLTest_AssertPass("Call to SDL_RWclose() succeeded");
-    SDLTest_AssertCheck(result == 0, "Verify result value is 0; got: %d", result);
-
-    return TEST_COMPLETED;
-}
-
-/**
- * Tests opening from memory.
- *
- * \sa SDL_RWFromConstMem
- * \sa SDL_RWClose
- */
-static int rwops_testConstMem(void *arg)
-{
-    SDL_RWops *rw;
-    int result;
-
-    /* Open handle */
-    rw = SDL_RWFromConstMem(RWopsHelloWorldCompString, sizeof(RWopsHelloWorldCompString) - 1);
-    SDLTest_AssertPass("Call to SDL_RWFromConstMem() succeeded");
-    SDLTest_AssertCheck(rw != NULL, "Verify opening memory with SDL_RWFromConstMem does not return NULL");
-
-    /* Bail out if NULL */
-    if (rw == NULL) {
-        return TEST_ABORTED;
-    }
-
-    /* Check type */
-    SDLTest_AssertCheck(rw->type == SDL_RWOPS_MEMORY_RO, "Verify RWops type is SDL_RWOPS_MEMORY_RO; expected: %d, got: %" SDL_PRIu32, SDL_RWOPS_MEMORY_RO, rw->type);
-
-    /* Run generic tests */
-    testGenericRWopsValidations(rw, SDL_FALSE);
-
-    /* Close handle */
-    result = SDL_RWclose(rw);
-    SDLTest_AssertPass("Call to SDL_RWclose() succeeded");
-    SDLTest_AssertCheck(result == 0, "Verify result value is 0; got: %d", result);
-
-    return TEST_COMPLETED;
-}
-
-/**
- * Tests reading from file.
- *
- * \sa SDL_RWFromFile
- * \sa SDL_RWClose
- */
-static int rwops_testFileRead(void *arg)
-{
-    SDL_RWops *rw;
-    int result;
-
-    /* Read test. */
-    rw = SDL_RWFromFile(RWopsReadTestFilename, "r");
-    SDLTest_AssertPass("Call to SDL_RWFromFile(..,\"r\") succeeded");
-    SDLTest_AssertCheck(rw != NULL, "Verify opening file with SDL_RWFromFile in read mode does not return NULL");
-
-    /* Bail out if NULL */
-    if (rw == NULL) {
-        return TEST_ABORTED;
-    }
-
-    /* Check type */
-#ifdef SDL_PLATFORM_ANDROID
-    SDLTest_AssertCheck(
-        rw->type == SDL_RWOPS_STDFILE || rw->type == SDL_RWOPS_JNIFILE,
-        "Verify RWops type is SDL_RWOPS_STDFILE or SDL_RWOPS_JNIFILE; expected: %d|%d, got: %d", SDL_RWOPS_STDFILE, SDL_RWOPS_JNIFILE, rw->type);
-#elif defined(SDL_PLATFORM_WIN32)
-    SDLTest_AssertCheck(
-        rw->type == SDL_RWOPS_WINFILE,
-        "Verify RWops type is SDL_RWOPS_WINFILE; expected: %d, got: %d", SDL_RWOPS_WINFILE, rw->type);
-#else
-    SDLTest_AssertCheck(
-        rw->type == SDL_RWOPS_STDFILE,
-        "Verify RWops type is SDL_RWOPS_STDFILE; expected: %d, got: %" SDL_PRIu32, SDL_RWOPS_STDFILE, rw->type);
-#endif
-
-    /* Run generic tests */
-    testGenericRWopsValidations(rw, SDL_FALSE);
-
-    /* Close handle */
-    result = SDL_RWclose(rw);
-    SDLTest_AssertPass("Call to SDL_RWclose() succeeded");
-    SDLTest_AssertCheck(result == 0, "Verify result value is 0; got: %d", result);
-
-    return TEST_COMPLETED;
-}
-
-/**
- * Tests writing from file.
- *
- * \sa SDL_RWFromFile
- * \sa SDL_RWClose
- */
-static int rwops_testFileWrite(void *arg)
-{
-    SDL_RWops *rw;
-    int result;
-
-    /* Write test. */
-    rw = SDL_RWFromFile(RWopsWriteTestFilename, "w+");
-    SDLTest_AssertPass("Call to SDL_RWFromFile(..,\"w+\") succeeded");
-    SDLTest_AssertCheck(rw != NULL, "Verify opening file with SDL_RWFromFile in write mode does not return NULL");
-
-    /* Bail out if NULL */
-    if (rw == NULL) {
-        return TEST_ABORTED;
-    }
-
-    /* Check type */
-#ifdef SDL_PLATFORM_ANDROID
-    SDLTest_AssertCheck(
-        rw->type == SDL_RWOPS_STDFILE || rw->type == SDL_RWOPS_JNIFILE,
-        "Verify RWops type is SDL_RWOPS_STDFILE or SDL_RWOPS_JNIFILE; expected: %d|%d, got: %d", SDL_RWOPS_STDFILE, SDL_RWOPS_JNIFILE, rw->type);
-#elif defined(SDL_PLATFORM_WIN32)
-    SDLTest_AssertCheck(
-        rw->type == SDL_RWOPS_WINFILE,
-        "Verify RWops type is SDL_RWOPS_WINFILE; expected: %d, got: %d", SDL_RWOPS_WINFILE, rw->type);
-#else
-    SDLTest_AssertCheck(
-        rw->type == SDL_RWOPS_STDFILE,
-        "Verify RWops type is SDL_RWOPS_STDFILE; expected: %d, got: %" SDL_PRIu32, SDL_RWOPS_STDFILE, rw->type);
-#endif
-
-    /* Run generic tests */
-    testGenericRWopsValidations(rw, SDL_TRUE);
-
-    /* Close handle */
-    result = SDL_RWclose(rw);
-    SDLTest_AssertPass("Call to SDL_RWclose() succeeded");
-    SDLTest_AssertCheck(result == 0, "Verify result value is 0; got: %d", result);
-
-    return TEST_COMPLETED;
-}
-
-/**
- * Tests alloc and free RW context.
- *
- * \sa SDL_CreateRW
- * \sa SDL_DestroyRW
- */
-static int rwops_testAllocFree(void *arg)
-{
-    /* Allocate context */
-    SDL_RWops *rw = SDL_CreateRW();
-    SDLTest_AssertPass("Call to SDL_CreateRW() succeeded");
-    SDLTest_AssertCheck(rw != NULL, "Validate result from SDL_CreateRW() is not NULL");
-    if (rw == NULL) {
-        return TEST_ABORTED;
-    }
-
-    /* Check type */
-    SDLTest_AssertCheck(
-        rw->type == SDL_RWOPS_UNKNOWN,
-        "Verify RWops type is SDL_RWOPS_UNKNOWN; expected: %d, got: %" SDL_PRIu32, SDL_RWOPS_UNKNOWN, rw->type);
-
-    /* Free context again */
-    SDL_DestroyRW(rw);
-    SDLTest_AssertPass("Call to SDL_DestroyRW() succeeded");
-
-    return TEST_COMPLETED;
-}
-
-/**
- * Compare memory and file reads
- *
- * \sa SDL_RWFromMem
- * \sa SDL_RWFromFile
- */
-static int rwops_testCompareRWFromMemWithRWFromFile(void *arg)
-{
-    int slen = 26;
-    char buffer_file[27];
-    char buffer_mem[27];
-    size_t rv_file;
-    size_t rv_mem;
-    Uint64 sv_file;
-    Uint64 sv_mem;
-    SDL_RWops *rwops_file;
-    SDL_RWops *rwops_mem;
-    int size;
-    int result;
-
-    for (size = 5; size < 10; size++) {
-        /* Terminate buffer */
-        buffer_file[slen] = 0;
-        buffer_mem[slen] = 0;
-
-        /* Read/seek from memory */
-        rwops_mem = SDL_RWFromMem((void *)RWopsAlphabetString, slen);
-        SDLTest_AssertPass("Call to SDL_RWFromMem()");
-        rv_mem = SDL_RWread(rwops_mem, buffer_mem, size * 6);
-        SDLTest_AssertPass("Call to SDL_RWread(mem, size=%d)", size * 6);
-        sv_mem = SDL_RWseek(rwops_mem, 0, SEEK_END);
-        SDLTest_AssertPass("Call to SDL_RWseek(mem,SEEK_END)");
-        result = SDL_RWclose(rwops_mem);
-        SDLTest_AssertPass("Call to SDL_RWclose(mem)");
-        SDLTest_AssertCheck(result == 0, "Verify result value is 0; got: %d", result);
-
-        /* Read/see from file */
-        rwops_file = SDL_RWFromFile(RWopsAlphabetFilename, "r");
-        SDLTest_AssertPass("Call to SDL_RWFromFile()");
-        rv_file = SDL_RWread(rwops_file, buffer_file, size * 6);
-        SDLTest_AssertPass("Call to SDL_RWread(file, size=%d)", size * 6);
-        sv_file = SDL_RWseek(rwops_file, 0, SEEK_END);
-        SDLTest_AssertPass("Call to SDL_RWseek(file,SEEK_END)");
-        result = SDL_RWclose(rwops_file);
-        SDLTest_AssertPass("Call to SDL_RWclose(file)");
-        SDLTest_AssertCheck(result == 0, "Verify result value is 0; got: %d", result);
-
-        /* Compare */
-        SDLTest_AssertCheck(rv_mem == rv_file, "Verify returned read blocks matches for mem and file reads; got: rv_mem=%d rv_file=%d", (int)rv_mem, (int)rv_file);
-        SDLTest_AssertCheck(sv_mem == sv_file, "Verify SEEK_END position matches for mem and file seeks; got: sv_mem=%d sv_file=%d", (int)sv_mem, (int)sv_file);
-        SDLTest_AssertCheck(buffer_mem[slen] == 0, "Verify mem buffer termination; expected: 0, got: %d", buffer_mem[slen]);
-        SDLTest_AssertCheck(buffer_file[slen] == 0, "Verify file buffer termination; expected: 0, got: %d", buffer_file[slen]);
-        SDLTest_AssertCheck(
-            SDL_strncmp(buffer_mem, RWopsAlphabetString, slen) == 0,
-            "Verify mem buffer contain alphabet string; expected: %s, got: %s", RWopsAlphabetString, buffer_mem);
-        SDLTest_AssertCheck(
-            SDL_strncmp(buffer_file, RWopsAlphabetString, slen) == 0,
-            "Verify file buffer contain alphabet string; expected: %s, got: %s", RWopsAlphabetString, buffer_file);
-    }
-
-    return TEST_COMPLETED;
-}
-
-/**
- * Tests writing and reading from file using endian aware functions.
- *
- * \sa SDL_RWFromFile
- * \sa SDL_RWClose
- * \sa SDL_ReadU16BE
- * \sa SDL_WriteU16BE
- */
-static int rwops_testFileWriteReadEndian(void *arg)
-{
-    SDL_RWops *rw;
-    Sint64 result;
-    int mode;
-    Uint16 BE16value;
-    Uint32 BE32value;
-    Uint64 BE64value;
-    Uint16 LE16value;
-    Uint32 LE32value;
-    Uint64 LE64value;
-    Uint16 BE16test;
-    Uint32 BE32test;
-    Uint64 BE64test;
-    Uint16 LE16test;
-    Uint32 LE32test;
-    Uint64 LE64test;
-    SDL_bool bresult;
-    int cresult;
-
-    for (mode = 0; mode < 3; mode++) {
-
-        /* Create test data */
-        switch (mode) {
-        default:
-        case 0:
-            SDLTest_Log("All 0 values");
-            BE16value = 0;
-            BE32value = 0;
-            BE64value = 0;
-            LE16value = 0;
-            LE32value = 0;
-            LE64value = 0;
-            break;
-        case 1:
-            SDLTest_Log("All 1 values");
-            BE16value = 1;
-            BE32value = 1;
-            BE64value = 1;
-            LE16value = 1;
-            LE32value = 1;
-            LE64value = 1;
-            break;
-        case 2:
-            SDLTest_Log("Random values");
-            BE16value = SDLTest_RandomUint16();
-            BE32value = SDLTest_RandomUint32();
-            BE64value = SDLTest_RandomUint64();
-            LE16value = SDLTest_RandomUint16();
-            LE32value = SDLTest_RandomUint32();
-            LE64value = SDLTest_RandomUint64();
-            break;
-        }
-
-        /* Write test. */
-        rw = SDL_RWFromFile(RWopsWriteTestFilename, "w+");
-        SDLTest_AssertPass("Call to SDL_RWFromFile(..,\"w+\")");
-        SDLTest_AssertCheck(rw != NULL, "Verify opening file with SDL_RWFromFile in write mode does not return NULL");
-
-        /* Bail out if NULL */
-        if (rw == NULL) {
-            return TEST_ABORTED;
-        }
-
-        /* Write test data */
-        bresult = SDL_WriteU16BE(rw, BE16value);
-        SDLTest_AssertPass("Call to SDL_WriteU16BE()");
-        SDLTest_AssertCheck(bresult == SDL_TRUE, "Validate object written, expected: SDL_TRUE, got: SDL_FALSE");
-        bresult = SDL_WriteU32BE(rw, BE32value);
-        SDLTest_AssertPass("Call to SDL_WriteU32BE()");
-        SDLTest_AssertCheck(bresult == SDL_TRUE, "Validate object written, expected: SDL_TRUE, got: SDL_FALSE");
-        bresult = SDL_WriteU64BE(rw, BE64value);
-        SDLTest_AssertPass("Call to SDL_WriteU64BE()");
-        SDLTest_AssertCheck(bresult == SDL_TRUE, "Validate object written, expected: SDL_TRUE, got: SDL_FALSE");
-        bresult = SDL_WriteU16LE(rw, LE16value);
-        SDLTest_AssertPass("Call to SDL_WriteU16LE()");
-        SDLTest_AssertCheck(bresult == SDL_TRUE, "Validate object written, expected: SDL_TRUE, got: SDL_FALSE");
-        bresult = SDL_WriteU32LE(rw, LE32value);
-        SDLTest_AssertPass("Call to SDL_WriteU32LE()");
-        SDLTest_AssertCheck(bresult == SDL_TRUE, "Validate object written, expected: SDL_TRUE, got: SDL_FALSE");
-        bresult = SDL_WriteU64LE(rw, LE64value);
-        SDLTest_AssertPass("Call to SDL_WriteU64LE()");
-        SDLTest_AssertCheck(bresult == SDL_TRUE, "Validate object written, expected: SDL_TRUE, got: SDL_FALSE");
-
-        /* Test seek to start */
-        result = SDL_RWseek(rw, 0, SDL_RW_SEEK_SET);
-        SDLTest_AssertPass("Call to SDL_RWseek succeeded");
-        SDLTest_AssertCheck(result == 0, "Verify result from position 0 with SDL_RWseek, expected 0, got %i", (int)result);
-
-        /* Read test data */
-        bresult = SDL_ReadU16BE(rw, &BE16test);
-        SDLTest_AssertPass("Call to SDL_ReadU16BE()");
-        SDLTest_AssertCheck(bresult == SDL_TRUE, "Validate object read, expected: SDL_TRUE, got: SDL_FALSE");
-        SDLTest_AssertCheck(BE16test == BE16value, "Validate object read from SDL_ReadU16BE, expected: %hu, got: %hu", BE16value, BE16test);
-        bresult = SDL_ReadU32BE(rw, &BE32test);
-        SDLTest_AssertPass("Call to SDL_ReadU32BE()");
-        SDLTest_AssertCheck(bresult == SDL_TRUE, "Validate object read, expected: SDL_TRUE, got: SDL_FALSE");
-        SDLTest_AssertCheck(BE32test == BE32value, "Validate object read from SDL_ReadU32BE, expected: %" SDL_PRIu32 ", got: %" SDL_PRIu32, BE32value, BE32test);
-        bresult = SDL_ReadU64BE(rw, &BE64test);
-        SDLTest_AssertPass("Call to SDL_ReadU64BE()");
-        SDLTest_AssertCheck(bresult == SDL_TRUE, "Validate object read, expected: SDL_TRUE, got: SDL_FALSE");
-        SDLTest_AssertCheck(BE64test == BE64value, "Validate object read from SDL_ReadU64BE, expected: %" SDL_PRIu64 ", got: %" SDL_PRIu64, BE64value, BE64test);
-        bresult = SDL_ReadU16LE(rw, &LE16test);
-        SDLTest_AssertPass("Call to SDL_ReadU16LE()");
-        SDLTest_AssertCheck(bresult == SDL_TRUE, "Validate object read, expected: SDL_TRUE, got: SDL_FALSE");
-        SDLTest_AssertCheck(LE16test == LE16value, "Validate object read from SDL_ReadU16LE, expected: %hu, got: %hu", LE16value, LE16test);
-        bresult = SDL_ReadU32LE(rw, &LE32test);
-        SDLTest_AssertPass("Call to SDL_ReadU32LE()");
-        SDLTest_AssertCheck(bresult == SDL_TRUE, "Validate object read, expected: SDL_TRUE, got: SDL_FALSE");
-        SDLTest_AssertCheck(LE32test == LE32value, "Validate object read from SDL_ReadU32LE, expected: %" SDL_PRIu32 ", got: %" SDL_PRIu32, LE32value, LE32test);
-        bresult = SDL_ReadU64LE(rw, &LE64test);
-        SDLTest_AssertPass("Call to SDL_ReadU64LE()");
-        SDLTest_AssertCheck(bresult == SDL_TRUE, "Validate object read, expected: SDL_TRUE, got: SDL_FALSE");
-        SDLTest_AssertCheck(LE64test == LE64value, "Validate object read from SDL_ReadU64LE, expected: %" SDL_PRIu64 ", got: %" SDL_PRIu64, LE64value, LE64test);
-
-        /* Close handle */
-        cresult = SDL_RWclose(rw);
-        SDLTest_AssertPass("Call to SDL_RWclose() succeeded");
-        SDLTest_AssertCheck(cresult == 0, "Verify result value is 0; got: %d", cresult);
-    }
-
-    return TEST_COMPLETED;
-}
-
-/* ================= Test References ================== */
-
-/* RWops test cases */
-static const SDLTest_TestCaseReference rwopsTest1 = {
-    (SDLTest_TestCaseFp)rwops_testParamNegative, "rwops_testParamNegative", "Negative test for SDL_RWFromFile parameters", TEST_ENABLED
-};
-
-static const SDLTest_TestCaseReference rwopsTest2 = {
-    (SDLTest_TestCaseFp)rwops_testMem, "rwops_testMem", "Tests opening from memory", TEST_ENABLED
-};
-
-static const SDLTest_TestCaseReference rwopsTest3 = {
-    (SDLTest_TestCaseFp)rwops_testConstMem, "rwops_testConstMem", "Tests opening from (const) memory", TEST_ENABLED
-};
-
-static const SDLTest_TestCaseReference rwopsTest4 = {
-    (SDLTest_TestCaseFp)rwops_testFileRead, "rwops_testFileRead", "Tests reading from a file", TEST_ENABLED
-};
-
-static const SDLTest_TestCaseReference rwopsTest5 = {
-    (SDLTest_TestCaseFp)rwops_testFileWrite, "rwops_testFileWrite", "Test writing to a file", TEST_ENABLED
-};
-
-static const SDLTest_TestCaseReference rwopsTest6 = {
-    (SDLTest_TestCaseFp)rwops_testAllocFree, "rwops_testAllocFree", "Test alloc and free of RW context", TEST_ENABLED
-};
-
-static const SDLTest_TestCaseReference rwopsTest7 = {
-    (SDLTest_TestCaseFp)rwops_testFileWriteReadEndian, "rwops_testFileWriteReadEndian", "Test writing and reading via the Endian aware functions", TEST_ENABLED
-};
-
-static const SDLTest_TestCaseReference rwopsTest8 = {
-    (SDLTest_TestCaseFp)rwops_testCompareRWFromMemWithRWFromFile, "rwops_testCompareRWFromMemWithRWFromFile", "Compare RWFromMem and RWFromFile RWops for read and seek", TEST_ENABLED
-};
-
-/* Sequence of RWops test cases */
-static const SDLTest_TestCaseReference *rwopsTests[] = {
-    &rwopsTest1, &rwopsTest2, &rwopsTest3, &rwopsTest4, &rwopsTest5, &rwopsTest6,
-    &rwopsTest7, &rwopsTest8, NULL
-};
-
-/* RWops test suite (global) */
-SDLTest_TestSuiteReference rwopsTestSuite = {
-    "RWops",
-    RWopsSetUp,
-    rwopsTests,
-    RWopsTearDown
-};

+ 1 - 1
test/testautomation_suites.h

@@ -27,7 +27,7 @@ extern SDLTest_TestSuiteReference platformTestSuite;
 extern SDLTest_TestSuiteReference propertiesTestSuite;
 extern SDLTest_TestSuiteReference rectTestSuite;
 extern SDLTest_TestSuiteReference renderTestSuite;
-extern SDLTest_TestSuiteReference rwopsTestSuite;
+extern SDLTest_TestSuiteReference iostrmTestSuite;
 extern SDLTest_TestSuiteReference sdltestTestSuite;
 extern SDLTest_TestSuiteReference stdlibTestSuite;
 extern SDLTest_TestSuiteReference subsystemsTestSuite;

+ 2 - 2
test/testffmpeg.c

@@ -237,9 +237,9 @@ static SDL_bool CreateWindowAndRenderer(SDL_WindowFlags window_flags, const char
 static SDL_Texture *CreateTexture(SDL_Renderer *r, unsigned char *data, unsigned int len, int *w, int *h) {
     SDL_Texture *texture = NULL;
     SDL_Surface *surface;
-    SDL_RWops *src = SDL_RWFromConstMem(data, len);
+    SDL_IOStream *src = SDL_IOFromConstMem(data, len);
     if (src) {
-        surface = SDL_LoadBMP_RW(src, SDL_TRUE);
+        surface = SDL_LoadBMP_IO(src, SDL_TRUE);
         if (surface) {
             /* Treat white as transparent */
             SDL_SetSurfaceColorKey(surface, SDL_TRUE, SDL_MapRGB(surface->format, 255, 255, 255));

+ 173 - 173
test/testfile.c

@@ -10,7 +10,7 @@
   freely.
 */
 
-/* sanity tests on SDL_rwops.c (useful for alternative implementations of stdio rwops) */
+/* sanity tests on SDL_iostream.c (useful for alternative implementations of stdio iostream) */
 
 /* quiet windows compiler warnings */
 #if defined(_MSC_VER) && !defined(_CRT_NONSTDC_NO_WARNINGS)
@@ -51,22 +51,22 @@ cleanup(void)
 }
 
 static void
-rwops_error_quit(unsigned line, SDL_RWops *rwops)
+iostrm_error_quit(unsigned line, SDL_IOStream *iostrm)
 {
     SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "testfile.c(%d): failed\n", line);
-    if (rwops) {
-        SDL_RWclose(rwops); /* This calls SDL_DestroyRW(rwops); */
+    if (iostrm) {
+        SDL_CloseIO(iostrm);
     }
     cleanup();
     SDLTest_CommonDestroyState(state);
-    exit(1); /* quit with rwops error (test failed) */
+    exit(1); /* quit with iostrm error (test failed) */
 }
 
-#define RWOP_ERR_QUIT(x) rwops_error_quit(__LINE__, (x))
+#define RWOP_ERR_QUIT(x) iostrm_error_quit(__LINE__, (x))
 
 int main(int argc, char *argv[])
 {
-    SDL_RWops *rwops = NULL;
+    SDL_IOStream *iostrm = NULL;
     char test_buf[30];
 
     /* Initialize test framework */
@@ -85,27 +85,27 @@ int main(int argc, char *argv[])
 
     cleanup();
 
-    /* test 1 : basic argument test: all those calls to SDL_RWFromFile should fail */
+    /* test 1 : basic argument test: all those calls to SDL_IOFromFile should fail */
 
-    rwops = SDL_RWFromFile(NULL, NULL);
-    if (rwops) {
-        RWOP_ERR_QUIT(rwops);
+    iostrm = SDL_IOFromFile(NULL, NULL);
+    if (iostrm) {
+        RWOP_ERR_QUIT(iostrm);
     }
-    rwops = SDL_RWFromFile(NULL, "ab+");
-    if (rwops) {
-        RWOP_ERR_QUIT(rwops);
+    iostrm = SDL_IOFromFile(NULL, "ab+");
+    if (iostrm) {
+        RWOP_ERR_QUIT(iostrm);
     }
-    rwops = SDL_RWFromFile(NULL, "sldfkjsldkfj");
-    if (rwops) {
-        RWOP_ERR_QUIT(rwops);
+    iostrm = SDL_IOFromFile(NULL, "sldfkjsldkfj");
+    if (iostrm) {
+        RWOP_ERR_QUIT(iostrm);
     }
-    rwops = SDL_RWFromFile("something", "");
-    if (rwops) {
-        RWOP_ERR_QUIT(rwops);
+    iostrm = SDL_IOFromFile("something", "");
+    if (iostrm) {
+        RWOP_ERR_QUIT(iostrm);
     }
-    rwops = SDL_RWFromFile("something", NULL);
-    if (rwops) {
-        RWOP_ERR_QUIT(rwops);
+    iostrm = SDL_IOFromFile("something", NULL);
+    if (iostrm) {
+        RWOP_ERR_QUIT(iostrm);
     }
     SDL_Log("test1 OK\n");
 
@@ -114,259 +114,259 @@ int main(int argc, char *argv[])
        modes : a, a+, w, w+ checks that it succeeds (file may not exists)
 
      */
-    rwops = SDL_RWFromFile(FBASENAME2, "rb"); /* this file doesn't exist that call must fail */
-    if (rwops) {
-        RWOP_ERR_QUIT(rwops);
+    iostrm = SDL_IOFromFile(FBASENAME2, "rb"); /* this file doesn't exist that call must fail */
+    if (iostrm) {
+        RWOP_ERR_QUIT(iostrm);
     }
-    rwops = SDL_RWFromFile(FBASENAME2, "rb+"); /* this file doesn't exist that call must fail */
-    if (rwops) {
-        RWOP_ERR_QUIT(rwops);
+    iostrm = SDL_IOFromFile(FBASENAME2, "rb+"); /* this file doesn't exist that call must fail */
+    if (iostrm) {
+        RWOP_ERR_QUIT(iostrm);
     }
-    rwops = SDL_RWFromFile(FBASENAME2, "wb");
-    if (!rwops) {
-        RWOP_ERR_QUIT(rwops);
+    iostrm = SDL_IOFromFile(FBASENAME2, "wb");
+    if (!iostrm) {
+        RWOP_ERR_QUIT(iostrm);
     }
-    SDL_RWclose(rwops);
+    SDL_CloseIO(iostrm);
     unlink(FBASENAME2);
-    rwops = SDL_RWFromFile(FBASENAME2, "wb+");
-    if (!rwops) {
-        RWOP_ERR_QUIT(rwops);
+    iostrm = SDL_IOFromFile(FBASENAME2, "wb+");
+    if (!iostrm) {
+        RWOP_ERR_QUIT(iostrm);
     }
-    SDL_RWclose(rwops);
+    SDL_CloseIO(iostrm);
     unlink(FBASENAME2);
-    rwops = SDL_RWFromFile(FBASENAME2, "ab");
-    if (!rwops) {
-        RWOP_ERR_QUIT(rwops);
+    iostrm = SDL_IOFromFile(FBASENAME2, "ab");
+    if (!iostrm) {
+        RWOP_ERR_QUIT(iostrm);
     }
-    SDL_RWclose(rwops);
+    SDL_CloseIO(iostrm);
     unlink(FBASENAME2);
-    rwops = SDL_RWFromFile(FBASENAME2, "ab+");
-    if (!rwops) {
-        RWOP_ERR_QUIT(rwops);
+    iostrm = SDL_IOFromFile(FBASENAME2, "ab+");
+    if (!iostrm) {
+        RWOP_ERR_QUIT(iostrm);
     }
-    SDL_RWclose(rwops);
+    SDL_CloseIO(iostrm);
     unlink(FBASENAME2);
     SDL_Log("test2 OK\n");
 
     /* test 3 : creation, writing , reading, seeking,
                 test : w mode, r mode, w+ mode
      */
-    rwops = SDL_RWFromFile(FBASENAME1, "wb"); /* write only */
-    if (!rwops) {
-        RWOP_ERR_QUIT(rwops);
+    iostrm = SDL_IOFromFile(FBASENAME1, "wb"); /* write only */
+    if (!iostrm) {
+        RWOP_ERR_QUIT(iostrm);
     }
-    if (10 != SDL_RWwrite(rwops, "1234567890", 10)) {
-        RWOP_ERR_QUIT(rwops);
+    if (10 != SDL_WriteIO(iostrm, "1234567890", 10)) {
+        RWOP_ERR_QUIT(iostrm);
     }
-    if (10 != SDL_RWwrite(rwops, "1234567890", 10)) {
-        RWOP_ERR_QUIT(rwops);
+    if (10 != SDL_WriteIO(iostrm, "1234567890", 10)) {
+        RWOP_ERR_QUIT(iostrm);
     }
-    if (7 != SDL_RWwrite(rwops, "1234567", 7)) {
-        RWOP_ERR_QUIT(rwops);
+    if (7 != SDL_WriteIO(iostrm, "1234567", 7)) {
+        RWOP_ERR_QUIT(iostrm);
     }
-    if (0 != SDL_RWseek(rwops, 0L, SDL_RW_SEEK_SET)) {
-        RWOP_ERR_QUIT(rwops);
+    if (0 != SDL_SeekIO(iostrm, 0L, SDL_IO_SEEK_SET)) {
+        RWOP_ERR_QUIT(iostrm);
     }
-    if (0 != SDL_RWread(rwops, test_buf, 1)) {
-        RWOP_ERR_QUIT(rwops); /* we are in write only mode */
+    if (0 != SDL_ReadIO(iostrm, test_buf, 1)) {
+        RWOP_ERR_QUIT(iostrm); /* we are in write only mode */
     }
 
-    SDL_RWclose(rwops);
+    SDL_CloseIO(iostrm);
 
-    rwops = SDL_RWFromFile(FBASENAME1, "rb"); /* read mode, file must exist */
-    if (!rwops) {
-        RWOP_ERR_QUIT(rwops);
+    iostrm = SDL_IOFromFile(FBASENAME1, "rb"); /* read mode, file must exist */
+    if (!iostrm) {
+        RWOP_ERR_QUIT(iostrm);
     }
-    if (0 != SDL_RWseek(rwops, 0L, SDL_RW_SEEK_SET)) {
-        RWOP_ERR_QUIT(rwops);
+    if (0 != SDL_SeekIO(iostrm, 0L, SDL_IO_SEEK_SET)) {
+        RWOP_ERR_QUIT(iostrm);
     }
-    if (20 != SDL_RWseek(rwops, -7, SDL_RW_SEEK_END)) {
-        RWOP_ERR_QUIT(rwops);
+    if (20 != SDL_SeekIO(iostrm, -7, SDL_IO_SEEK_END)) {
+        RWOP_ERR_QUIT(iostrm);
     }
-    if (7 != SDL_RWread(rwops, test_buf, 7)) {
-        RWOP_ERR_QUIT(rwops);
+    if (7 != SDL_ReadIO(iostrm, test_buf, 7)) {
+        RWOP_ERR_QUIT(iostrm);
     }
     if (SDL_memcmp(test_buf, "1234567", 7) != 0) {
-        RWOP_ERR_QUIT(rwops);
+        RWOP_ERR_QUIT(iostrm);
     }
-    if (0 != SDL_RWread(rwops, test_buf, 1)) {
-        RWOP_ERR_QUIT(rwops);
+    if (0 != SDL_ReadIO(iostrm, test_buf, 1)) {
+        RWOP_ERR_QUIT(iostrm);
     }
-    if (0 != SDL_RWread(rwops, test_buf, 1000)) {
-        RWOP_ERR_QUIT(rwops);
+    if (0 != SDL_ReadIO(iostrm, test_buf, 1000)) {
+        RWOP_ERR_QUIT(iostrm);
     }
-    if (0 != SDL_RWseek(rwops, -27, SDL_RW_SEEK_CUR)) {
-        RWOP_ERR_QUIT(rwops);
+    if (0 != SDL_SeekIO(iostrm, -27, SDL_IO_SEEK_CUR)) {
+        RWOP_ERR_QUIT(iostrm);
     }
-    if (27 != SDL_RWread(rwops, test_buf, 30)) {
-        RWOP_ERR_QUIT(rwops);
+    if (27 != SDL_ReadIO(iostrm, test_buf, 30)) {
+        RWOP_ERR_QUIT(iostrm);
     }
     if (SDL_memcmp(test_buf, "12345678901234567890", 20) != 0) {
-        RWOP_ERR_QUIT(rwops);
+        RWOP_ERR_QUIT(iostrm);
     }
-    if (0 != SDL_RWwrite(rwops, test_buf, 1)) {
-        RWOP_ERR_QUIT(rwops); /* readonly mode */
+    if (0 != SDL_WriteIO(iostrm, test_buf, 1)) {
+        RWOP_ERR_QUIT(iostrm); /* readonly mode */
     }
 
-    SDL_RWclose(rwops);
+    SDL_CloseIO(iostrm);
 
     /* test 3: same with w+ mode */
-    rwops = SDL_RWFromFile(FBASENAME1, "wb+"); /* write + read + truncation */
-    if (!rwops) {
-        RWOP_ERR_QUIT(rwops);
+    iostrm = SDL_IOFromFile(FBASENAME1, "wb+"); /* write + read + truncation */
+    if (!iostrm) {
+        RWOP_ERR_QUIT(iostrm);
     }
-    if (10 != SDL_RWwrite(rwops, "1234567890", 10)) {
-        RWOP_ERR_QUIT(rwops);
+    if (10 != SDL_WriteIO(iostrm, "1234567890", 10)) {
+        RWOP_ERR_QUIT(iostrm);
     }
-    if (10 != SDL_RWwrite(rwops, "1234567890", 10)) {
-        RWOP_ERR_QUIT(rwops);
+    if (10 != SDL_WriteIO(iostrm, "1234567890", 10)) {
+        RWOP_ERR_QUIT(iostrm);
     }
-    if (7 != SDL_RWwrite(rwops, "1234567", 7)) {
-        RWOP_ERR_QUIT(rwops);
+    if (7 != SDL_WriteIO(iostrm, "1234567", 7)) {
+        RWOP_ERR_QUIT(iostrm);
     }
-    if (0 != SDL_RWseek(rwops, 0L, SDL_RW_SEEK_SET)) {
-        RWOP_ERR_QUIT(rwops);
+    if (0 != SDL_SeekIO(iostrm, 0L, SDL_IO_SEEK_SET)) {
+        RWOP_ERR_QUIT(iostrm);
     }
-    if (1 != SDL_RWread(rwops, test_buf, 1)) {
-        RWOP_ERR_QUIT(rwops); /* we are in read/write mode */
+    if (1 != SDL_ReadIO(iostrm, test_buf, 1)) {
+        RWOP_ERR_QUIT(iostrm); /* we are in read/write mode */
     }
 
-    if (0 != SDL_RWseek(rwops, 0L, SDL_RW_SEEK_SET)) {
-        RWOP_ERR_QUIT(rwops);
+    if (0 != SDL_SeekIO(iostrm, 0L, SDL_IO_SEEK_SET)) {
+        RWOP_ERR_QUIT(iostrm);
     }
-    if (20 != SDL_RWseek(rwops, -7, SDL_RW_SEEK_END)) {
-        RWOP_ERR_QUIT(rwops);
+    if (20 != SDL_SeekIO(iostrm, -7, SDL_IO_SEEK_END)) {
+        RWOP_ERR_QUIT(iostrm);
     }
-    if (7 != SDL_RWread(rwops, test_buf, 7)) {
-        RWOP_ERR_QUIT(rwops);
+    if (7 != SDL_ReadIO(iostrm, test_buf, 7)) {
+        RWOP_ERR_QUIT(iostrm);
     }
     if (SDL_memcmp(test_buf, "1234567", 7) != 0) {
-        RWOP_ERR_QUIT(rwops);
+        RWOP_ERR_QUIT(iostrm);
     }
-    if (0 != SDL_RWread(rwops, test_buf, 1)) {
-        RWOP_ERR_QUIT(rwops);
+    if (0 != SDL_ReadIO(iostrm, test_buf, 1)) {
+        RWOP_ERR_QUIT(iostrm);
     }
-    if (0 != SDL_RWread(rwops, test_buf, 1000)) {
-        RWOP_ERR_QUIT(rwops);
+    if (0 != SDL_ReadIO(iostrm, test_buf, 1000)) {
+        RWOP_ERR_QUIT(iostrm);
     }
-    if (0 != SDL_RWseek(rwops, -27, SDL_RW_SEEK_CUR)) {
-        RWOP_ERR_QUIT(rwops);
+    if (0 != SDL_SeekIO(iostrm, -27, SDL_IO_SEEK_CUR)) {
+        RWOP_ERR_QUIT(iostrm);
     }
-    if (27 != SDL_RWread(rwops, test_buf, 30)) {
-        RWOP_ERR_QUIT(rwops);
+    if (27 != SDL_ReadIO(iostrm, test_buf, 30)) {
+        RWOP_ERR_QUIT(iostrm);
     }
     if (SDL_memcmp(test_buf, "12345678901234567890", 20) != 0) {
-        RWOP_ERR_QUIT(rwops);
+        RWOP_ERR_QUIT(iostrm);
     }
-    SDL_RWclose(rwops);
+    SDL_CloseIO(iostrm);
     SDL_Log("test3 OK\n");
 
     /* test 4: same in r+ mode */
-    rwops = SDL_RWFromFile(FBASENAME1, "rb+"); /* write + read + file must exists, no truncation */
-    if (!rwops) {
-        RWOP_ERR_QUIT(rwops);
+    iostrm = SDL_IOFromFile(FBASENAME1, "rb+"); /* write + read + file must exists, no truncation */
+    if (!iostrm) {
+        RWOP_ERR_QUIT(iostrm);
     }
-    if (10 != SDL_RWwrite(rwops, "1234567890", 10)) {
-        RWOP_ERR_QUIT(rwops);
+    if (10 != SDL_WriteIO(iostrm, "1234567890", 10)) {
+        RWOP_ERR_QUIT(iostrm);
     }
-    if (10 != SDL_RWwrite(rwops, "1234567890", 10)) {
-        RWOP_ERR_QUIT(rwops);
+    if (10 != SDL_WriteIO(iostrm, "1234567890", 10)) {
+        RWOP_ERR_QUIT(iostrm);
     }
-    if (7 != SDL_RWwrite(rwops, "1234567", 7)) {
-        RWOP_ERR_QUIT(rwops);
+    if (7 != SDL_WriteIO(iostrm, "1234567", 7)) {
+        RWOP_ERR_QUIT(iostrm);
     }
-    if (0 != SDL_RWseek(rwops, 0L, SDL_RW_SEEK_SET)) {
-        RWOP_ERR_QUIT(rwops);
+    if (0 != SDL_SeekIO(iostrm, 0L, SDL_IO_SEEK_SET)) {
+        RWOP_ERR_QUIT(iostrm);
     }
-    if (1 != SDL_RWread(rwops, test_buf, 1)) {
-        RWOP_ERR_QUIT(rwops); /* we are in read/write mode */
+    if (1 != SDL_ReadIO(iostrm, test_buf, 1)) {
+        RWOP_ERR_QUIT(iostrm); /* we are in read/write mode */
     }
 
-    if (0 != SDL_RWseek(rwops, 0L, SDL_RW_SEEK_SET)) {
-        RWOP_ERR_QUIT(rwops);
+    if (0 != SDL_SeekIO(iostrm, 0L, SDL_IO_SEEK_SET)) {
+        RWOP_ERR_QUIT(iostrm);
     }
-    if (20 != SDL_RWseek(rwops, -7, SDL_RW_SEEK_END)) {
-        RWOP_ERR_QUIT(rwops);
+    if (20 != SDL_SeekIO(iostrm, -7, SDL_IO_SEEK_END)) {
+        RWOP_ERR_QUIT(iostrm);
     }
-    if (7 != SDL_RWread(rwops, test_buf, 7)) {
-        RWOP_ERR_QUIT(rwops);
+    if (7 != SDL_ReadIO(iostrm, test_buf, 7)) {
+        RWOP_ERR_QUIT(iostrm);
     }
     if (SDL_memcmp(test_buf, "1234567", 7) != 0) {
-        RWOP_ERR_QUIT(rwops);
+        RWOP_ERR_QUIT(iostrm);
     }
-    if (0 != SDL_RWread(rwops, test_buf, 1)) {
-        RWOP_ERR_QUIT(rwops);
+    if (0 != SDL_ReadIO(iostrm, test_buf, 1)) {
+        RWOP_ERR_QUIT(iostrm);
     }
-    if (0 != SDL_RWread(rwops, test_buf, 1000)) {
-        RWOP_ERR_QUIT(rwops);
+    if (0 != SDL_ReadIO(iostrm, test_buf, 1000)) {
+        RWOP_ERR_QUIT(iostrm);
     }
-    if (0 != SDL_RWseek(rwops, -27, SDL_RW_SEEK_CUR)) {
-        RWOP_ERR_QUIT(rwops);
+    if (0 != SDL_SeekIO(iostrm, -27, SDL_IO_SEEK_CUR)) {
+        RWOP_ERR_QUIT(iostrm);
     }
-    if (27 != SDL_RWread(rwops, test_buf, 30)) {
-        RWOP_ERR_QUIT(rwops);
+    if (27 != SDL_ReadIO(iostrm, test_buf, 30)) {
+        RWOP_ERR_QUIT(iostrm);
     }
     if (SDL_memcmp(test_buf, "12345678901234567890", 20) != 0) {
-        RWOP_ERR_QUIT(rwops);
+        RWOP_ERR_QUIT(iostrm);
     }
-    SDL_RWclose(rwops);
+    SDL_CloseIO(iostrm);
     SDL_Log("test4 OK\n");
 
     /* test5 : append mode */
-    rwops = SDL_RWFromFile(FBASENAME1, "ab+"); /* write + read + append */
-    if (!rwops) {
-        RWOP_ERR_QUIT(rwops);
+    iostrm = SDL_IOFromFile(FBASENAME1, "ab+"); /* write + read + append */
+    if (!iostrm) {
+        RWOP_ERR_QUIT(iostrm);
     }
-    if (10 != SDL_RWwrite(rwops, "1234567890", 10)) {
-        RWOP_ERR_QUIT(rwops);
+    if (10 != SDL_WriteIO(iostrm, "1234567890", 10)) {
+        RWOP_ERR_QUIT(iostrm);
     }
-    if (10 != SDL_RWwrite(rwops, "1234567890", 10)) {
-        RWOP_ERR_QUIT(rwops);
+    if (10 != SDL_WriteIO(iostrm, "1234567890", 10)) {
+        RWOP_ERR_QUIT(iostrm);
     }
-    if (7 != SDL_RWwrite(rwops, "1234567", 7)) {
-        RWOP_ERR_QUIT(rwops);
+    if (7 != SDL_WriteIO(iostrm, "1234567", 7)) {
+        RWOP_ERR_QUIT(iostrm);
     }
-    if (0 != SDL_RWseek(rwops, 0L, SDL_RW_SEEK_SET)) {
-        RWOP_ERR_QUIT(rwops);
+    if (0 != SDL_SeekIO(iostrm, 0L, SDL_IO_SEEK_SET)) {
+        RWOP_ERR_QUIT(iostrm);
     }
 
-    if (1 != SDL_RWread(rwops, test_buf, 1)) {
-        RWOP_ERR_QUIT(rwops);
+    if (1 != SDL_ReadIO(iostrm, test_buf, 1)) {
+        RWOP_ERR_QUIT(iostrm);
     }
-    if (0 != SDL_RWseek(rwops, 0L, SDL_RW_SEEK_SET)) {
-        RWOP_ERR_QUIT(rwops);
+    if (0 != SDL_SeekIO(iostrm, 0L, SDL_IO_SEEK_SET)) {
+        RWOP_ERR_QUIT(iostrm);
     }
 
-    if (20 + 27 != SDL_RWseek(rwops, -7, SDL_RW_SEEK_END)) {
-        RWOP_ERR_QUIT(rwops);
+    if (20 + 27 != SDL_SeekIO(iostrm, -7, SDL_IO_SEEK_END)) {
+        RWOP_ERR_QUIT(iostrm);
     }
-    if (7 != SDL_RWread(rwops, test_buf, 7)) {
-        RWOP_ERR_QUIT(rwops);
+    if (7 != SDL_ReadIO(iostrm, test_buf, 7)) {
+        RWOP_ERR_QUIT(iostrm);
     }
     if (SDL_memcmp(test_buf, "1234567", 7) != 0) {
-        RWOP_ERR_QUIT(rwops);
+        RWOP_ERR_QUIT(iostrm);
     }
-    if (0 != SDL_RWread(rwops, test_buf, 1)) {
-        RWOP_ERR_QUIT(rwops);
+    if (0 != SDL_ReadIO(iostrm, test_buf, 1)) {
+        RWOP_ERR_QUIT(iostrm);
     }
-    if (0 != SDL_RWread(rwops, test_buf, 1000)) {
-        RWOP_ERR_QUIT(rwops);
+    if (0 != SDL_ReadIO(iostrm, test_buf, 1000)) {
+        RWOP_ERR_QUIT(iostrm);
     }
 
-    if (27 != SDL_RWseek(rwops, -27, SDL_RW_SEEK_CUR)) {
-        RWOP_ERR_QUIT(rwops);
+    if (27 != SDL_SeekIO(iostrm, -27, SDL_IO_SEEK_CUR)) {
+        RWOP_ERR_QUIT(iostrm);
     }
 
-    if (0 != SDL_RWseek(rwops, 0L, SDL_RW_SEEK_SET)) {
-        RWOP_ERR_QUIT(rwops);
+    if (0 != SDL_SeekIO(iostrm, 0L, SDL_IO_SEEK_SET)) {
+        RWOP_ERR_QUIT(iostrm);
     }
-    if (30 != SDL_RWread(rwops, test_buf, 30)) {
-        RWOP_ERR_QUIT(rwops);
+    if (30 != SDL_ReadIO(iostrm, test_buf, 30)) {
+        RWOP_ERR_QUIT(iostrm);
     }
     if (SDL_memcmp(test_buf, "123456789012345678901234567123", 30) != 0) {
-        RWOP_ERR_QUIT(rwops);
+        RWOP_ERR_QUIT(iostrm);
     }
-    SDL_RWclose(rwops);
+    SDL_CloseIO(iostrm);
     SDL_Log("test5 OK\n");
     cleanup();
     SDL_Quit();

+ 6 - 6
test/testime.c

@@ -109,7 +109,7 @@ static int unifont_init(const char *fontname)
     Uint32 numGlyphs = 0;
     int lineNumber = 1;
     size_t bytesRead;
-    SDL_RWops *hexFile;
+    SDL_IOStream *hexFile;
     const size_t unifontGlyphSize = UNIFONT_NUM_GLYPHS * sizeof(struct UnifontGlyph);
     const size_t unifontTextureSize = UNIFONT_NUM_TEXTURES * state->num_windows * sizeof(void *);
     char *filename;
@@ -135,7 +135,7 @@ static int unifont_init(const char *fontname)
         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory\n");
         return -1;
     }
-    hexFile = SDL_RWFromFile(filename, "rb");
+    hexFile = SDL_IOFromFile(filename, "rb");
     SDL_free(filename);
     if (!hexFile) {
         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "unifont: Failed to open font file: %s\n", fontname);
@@ -149,7 +149,7 @@ static int unifont_init(const char *fontname)
         Uint8 glyphWidth;
         Uint32 codepoint;
 
-        bytesRead = SDL_RWread(hexFile, hexBuffer, 9);
+        bytesRead = SDL_ReadIO(hexFile, hexBuffer, 9);
         if (numGlyphs > 0 && bytesRead == 0) {
             break; /* EOF */
         }
@@ -185,7 +185,7 @@ static int unifont_init(const char *fontname)
         if (codepointHexSize < 8) {
             SDL_memmove(hexBuffer, hexBuffer + codepointHexSize + 1, bytesOverread);
         }
-        bytesRead = SDL_RWread(hexFile, hexBuffer + bytesOverread, 33 - bytesOverread);
+        bytesRead = SDL_ReadIO(hexFile, hexBuffer + bytesOverread, 33 - bytesOverread);
 
         if (bytesRead < (33 - bytesOverread)) {
             SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "unifont: Unexpected end of hex file.\n");
@@ -195,7 +195,7 @@ static int unifont_init(const char *fontname)
             glyphWidth = 8;
         } else {
             glyphWidth = 16;
-            bytesRead = SDL_RWread(hexFile, hexBuffer + 33, 32);
+            bytesRead = SDL_ReadIO(hexFile, hexBuffer + 33, 32);
             if (bytesRead < 32) {
                 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "unifont: Unexpected end of hex file.\n");
                 return -1;
@@ -223,7 +223,7 @@ static int unifont_init(const char *fontname)
         lineNumber++;
     } while (bytesRead > 0);
 
-    SDL_RWclose(hexFile);
+    SDL_CloseIO(hexFile);
     SDL_Log("unifont: Loaded %" SDL_PRIu32 " glyphs.\n", numGlyphs);
     return 0;
 }

+ 4 - 4
test/testoverlay.c

@@ -318,7 +318,7 @@ static void loop(void)
 
 int main(int argc, char **argv)
 {
-    SDL_RWops *handle;
+    SDL_IOStream *handle;
     int i;
     int j;
     int fps = 12;
@@ -443,16 +443,16 @@ int main(int argc, char **argv)
         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory\n");
         quit(2);
     }
-    handle = SDL_RWFromFile(filename, "rb");
+    handle = SDL_IOFromFile(filename, "rb");
     SDL_free(filename);
     if (!handle) {
         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Can't find the file moose.dat !\n");
         quit(2);
     }
 
-    SDL_RWread(handle, RawMooseData, MOOSEFRAME_SIZE * MOOSEFRAMES_COUNT);
+    SDL_ReadIO(handle, RawMooseData, MOOSEFRAME_SIZE * MOOSEFRAMES_COUNT);
 
-    SDL_RWclose(handle);
+    SDL_CloseIO(handle);
 
     /* Create the window and renderer */
     window_w = MOOSEPIC_W * scale;

+ 6 - 6
test/testresample.c

@@ -30,7 +30,7 @@ int main(int argc, char **argv)
     int bitsize = 0;
     int blockalign = 0;
     int avgbytes = 0;
-    SDL_RWops *io = NULL;
+    SDL_IOStream *io = NULL;
     int dst_len;
     int ret = 0;
     int argpos = 0;
@@ -115,9 +115,9 @@ int main(int argc, char **argv)
     }
 
     /* write out a WAV header... */
-    io = SDL_RWFromFile(file_out, "wb");
+    io = SDL_IOFromFile(file_out, "wb");
     if (!io) {
-        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "fopen('%s') failed: %s\n", file_out, SDL_GetError());
+        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "opening '%s' failed: %s\n", file_out, SDL_GetError());
         ret = 5;
         goto end;
     }
@@ -139,10 +139,10 @@ int main(int argc, char **argv)
     SDL_WriteU16LE(io, (Uint16)bitsize);                        /* significant bits per sample */
     SDL_WriteU32LE(io, 0x61746164);                             /* data */
     SDL_WriteU32LE(io, dst_len);                                /* size */
-    SDL_RWwrite(io, dst_buf, dst_len);
+    SDL_WriteIO(io, dst_buf, dst_len);
 
-    if (SDL_RWclose(io) == -1) {
-        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "fclose('%s') failed: %s\n", file_out, SDL_GetError());
+    if (SDL_CloseIO(io) == -1) {
+        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "closing '%s' failed: %s\n", file_out, SDL_GetError());
         ret = 6;
         goto end;
     }

+ 1 - 1
test/testshape.c

@@ -60,7 +60,7 @@ int main(int argc, char *argv[])
             goto quit;
         }
     } else {
-        shape = SDL_LoadBMP_RW(SDL_RWFromConstMem(glass_bmp, sizeof(glass_bmp)), SDL_TRUE);
+        shape = SDL_LoadBMP_IO(SDL_IOFromConstMem(glass_bmp, sizeof(glass_bmp)), SDL_TRUE);
         if (!shape) {
             SDL_Log("Couldn't load glass.bmp: %s\n", SDL_GetError());
             goto quit;

+ 2 - 2
test/testspriteminimal.c

@@ -39,9 +39,9 @@ static int done;
 static SDL_Texture *CreateTexture(SDL_Renderer *r, unsigned char *data, unsigned int len, int *w, int *h) {
     SDL_Texture *texture = NULL;
     SDL_Surface *surface;
-    SDL_RWops *src = SDL_RWFromConstMem(data, len);
+    SDL_IOStream *src = SDL_IOFromConstMem(data, len);
     if (src) {
-        surface = SDL_LoadBMP_RW(src, SDL_TRUE);
+        surface = SDL_LoadBMP_IO(src, SDL_TRUE);
         if (surface) {
             /* Treat white as transparent */
             SDL_SetSurfaceColorKey(surface, SDL_TRUE, SDL_MapRGB(surface->format, 255, 255, 255));

+ 4 - 4
test/teststreaming.c

@@ -136,7 +136,7 @@ static void loop(void)
 int main(int argc, char **argv)
 {
     SDL_Window *window;
-    SDL_RWops *handle;
+    SDL_IOStream *handle;
     char *filename = NULL;
 
     /* Initialize test framework */
@@ -164,14 +164,14 @@ int main(int argc, char **argv)
         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory\n");
         return -1;
     }
-    handle = SDL_RWFromFile(filename, "rb");
+    handle = SDL_IOFromFile(filename, "rb");
     SDL_free(filename);
     if (!handle) {
         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Can't find the file moose.dat !\n");
         quit(2);
     }
-    SDL_RWread(handle, MooseFrames, MOOSEFRAME_SIZE * MOOSEFRAMES_COUNT);
-    SDL_RWclose(handle);
+    SDL_ReadIO(handle, MooseFrames, MOOSEFRAME_SIZE * MOOSEFRAMES_COUNT);
+    SDL_CloseIO(handle);
 
     /* Create the window and renderer */
     window = SDL_CreateWindow("Happy Moose", MOOSEPIC_W * 4, MOOSEPIC_H * 4, SDL_WINDOW_RESIZABLE);

+ 3 - 3
test/testutils.c

@@ -29,7 +29,7 @@ GetNearbyFilename(const char *file)
     base = SDL_GetBasePath();
 
     if (base) {
-        SDL_RWops *rw;
+        SDL_IOStream *rw;
         size_t len = SDL_strlen(base) + SDL_strlen(file) + 1;
 
         path = SDL_malloc(len);
@@ -42,9 +42,9 @@ GetNearbyFilename(const char *file)
         (void)SDL_snprintf(path, len, "%s%s", base, file);
         SDL_free(base);
 
-        rw = SDL_RWFromFile(path, "rb");
+        rw = SDL_IOFromFile(path, "rb");
         if (rw) {
-            SDL_RWclose(rw);
+            SDL_CloseIO(rw);
             return path;
         }
 

+ 2 - 2
test/testwaylandcustom.c

@@ -36,9 +36,9 @@ static SDL_Texture *CreateTexture(SDL_Renderer *r, unsigned char *data, unsigned
 {
     SDL_Texture *texture = NULL;
     SDL_Surface *surface;
-    SDL_RWops *src = SDL_RWFromConstMem(data, len);
+    SDL_IOStream *src = SDL_IOFromConstMem(data, len);
     if (src) {
-        surface = SDL_LoadBMP_RW(src, SDL_TRUE);
+        surface = SDL_LoadBMP_IO(src, SDL_TRUE);
         if (surface) {
             /* Treat white as transparent */
             SDL_SetSurfaceColorKey(surface, SDL_TRUE, SDL_MapRGB(surface->format, 255, 255, 255));