mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-04-25 08:44:13 +00:00
rwops: Renamed SDL_RWops to SDL_IOStream, and other related symbols.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -1152,80 +1153,79 @@ 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_RWops is now an opaque structure. The existing APIs to create a RWops (SDL_RWFromFile, etc) still function as expected, but to make a custom RWops with app-provided function pointers, call SDL_OpenRW and provide the function pointers through there. To call into a RWops's functionality, use the standard APIs (SDL_ReadRW, etc) instead of calling into function pointers directly.
|
||||
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 concealed.
|
||||
|
||||
The RWops function pointers are now in a separate structure called SDL_RWopsInteface, which is provided to SDL_OpenRW. All the functions now take a `void *` userdata argument for their first parameter instead of an SDL_RWops, since that's now an opaque structure.
|
||||
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.
|
||||
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:
|
||||
|
||||
```c
|
||||
size_t SDL_RWread(SDL_RWops *context, void *ptr, size_t size, size_t maxnum);
|
||||
size_t SDL_RWwrite(SDL_RWops *context, const void *ptr, size_t size, size_t maxnum);
|
||||
size_t SDL_RWread(SDL_IOStream *context, void *ptr, size_t size, size_t maxnum);
|
||||
size_t SDL_RWwrite(SDL_IOStream *context, const void *ptr, size_t size, size_t maxnum);
|
||||
```
|
||||
|
||||
But now they look more like POSIX:
|
||||
|
||||
```c
|
||||
size_t SDL_ReadRW(void *userdata, void *ptr, size_t size);
|
||||
size_t SDL_WriteRW(void *userdata, 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)
|
||||
size_t custom_read(void *ptr, size_t size, size_t nitems, SDL_IOStream *stream)
|
||||
{
|
||||
return SDL_RWread(stream, ptr, size, nitems);
|
||||
}
|
||||
```
|
||||
should be changed to:
|
||||
```c
|
||||
size_t custom_read(void *ptr, size_t size, size_t nitems, SDL_RWops *stream)
|
||||
size_t custom_read(void *ptr, size_t size, size_t nitems, SDL_IOStream *stream, SDL_IOStatus *status)
|
||||
{
|
||||
if (size > 0 && nitems > 0) {
|
||||
return SDL_ReadRW(stream, ptr, size * nitems) / size;
|
||||
return SDL_ReadIO(stream, ptr, size * nitems) / size;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
SDL_RWops::type was removed and has no replacement; it wasn't meaningful for app-provided implementations at all, and wasn't much use for SDL's internal implementations, either.
|
||||
SDL_IOStream::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_RWopsInterface::close implementations should clean up their own userdata, but not call SDL_CloseRW on themselves; now the contract is always that SDL_CloseRW is called, which calls `->close` and then frees the opaque object.
|
||||
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.
|
||||
|
||||
SDL_AllocRW(), SDL_FreeRW(), SDL_CloseRW() 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_OpenRW() and SDL_CloseRW().
|
||||
|
||||
|
||||
You can implement this in your own code easily:
|
||||
```c
|
||||
#include <stdio.h>
|
||||
|
||||
typedef struct RWopsStdioFPData
|
||||
typedef struct IOStreamStdioFPData
|
||||
{
|
||||
FILE *fp;
|
||||
SDL_bool autoclose;
|
||||
} RWopsStdioFPData;
|
||||
} IOStreamStdioFPData;
|
||||
|
||||
static Sint64 SDLCALL stdio_seek(void *userdata, Sint64 offset, int whence)
|
||||
{
|
||||
FILE *fp = ((RWopsStdioFPData *) userdata)->fp;
|
||||
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:
|
||||
@@ -1242,9 +1242,9 @@ static Sint64 SDLCALL stdio_seek(void *userdata, Sint64 offset, int whence)
|
||||
return SDL_Error(SDL_EFSEEK);
|
||||
}
|
||||
|
||||
static size_t SDLCALL stdio_read(void *userdata, void *ptr, size_t size)
|
||||
static size_t SDLCALL stdio_read(void *userdata, void *ptr, size_t size, SDL_IOStatus *status)
|
||||
{
|
||||
FILE *fp = ((RWopsStdioFPData *) userdata)->fp;
|
||||
FILE *fp = ((IOStreamStdioFPData *) userdata)->fp;
|
||||
const size_t bytes = fread(ptr, 1, size, fp);
|
||||
if (bytes == 0 && ferror(fp)) {
|
||||
SDL_Error(SDL_EFREAD);
|
||||
@@ -1252,9 +1252,9 @@ static size_t SDLCALL stdio_read(void *userdata, void *ptr, size_t size)
|
||||
return bytes;
|
||||
}
|
||||
|
||||
static size_t SDLCALL stdio_write(void *userdata, const void *ptr, size_t size)
|
||||
static size_t SDLCALL stdio_write(void *userdata, const void *ptr, size_t size, SDL_IOStatus *status)
|
||||
{
|
||||
FILE *fp = ((RWopsStdioFPData *) userdata)->fp;
|
||||
FILE *fp = ((IOStreamStdioFPData *) userdata)->fp;
|
||||
const size_t bytes = fwrite(ptr, 1, size, fp);
|
||||
if (bytes == 0 && ferror(fp)) {
|
||||
SDL_Error(SDL_EFWRITE);
|
||||
@@ -1264,7 +1264,7 @@ static size_t SDLCALL stdio_write(void *userdata, const void *ptr, size_t size)
|
||||
|
||||
static int SDLCALL stdio_close(void *userdata)
|
||||
{
|
||||
RWopsStdioData *rwopsdata = (RWopsStdioData *) userdata;
|
||||
IOStreamStdioData *rwopsdata = (IOStreamStdioData *) userdata;
|
||||
int status = 0;
|
||||
if (rwopsdata->autoclose) {
|
||||
if (fclose(rwopsdata->fp) != 0) {
|
||||
@@ -1274,19 +1274,19 @@ static int SDLCALL stdio_close(void *userdata)
|
||||
return status;
|
||||
}
|
||||
|
||||
SDL_RWops *SDL_RWFromFP(FILE *fp, SDL_bool autoclose)
|
||||
SDL_IOStream *SDL_RWFromFP(FILE *fp, SDL_bool autoclose)
|
||||
{
|
||||
SDL_RWopsInterface iface;
|
||||
RWopsStdioFPData *rwopsdata;
|
||||
SDL_RWops *rwops;
|
||||
SDL_IOStreamInterface iface;
|
||||
IOStreamStdioFPData *rwopsdata;
|
||||
SDL_IOStream *rwops;
|
||||
|
||||
rwopsdata = (RWopsStdioFPData *) SDL_malloc(sizeof (*rwopsdata));
|
||||
rwopsdata = (IOStreamStdioFPData *) SDL_malloc(sizeof (*rwopsdata));
|
||||
if (!rwopsdata) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SDL_zero(iface);
|
||||
/* There's no stdio_size because SDL_SizeRW emulates it the same way we'd do it for stdio anyhow. */
|
||||
/* 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;
|
||||
@@ -1295,7 +1295,7 @@ SDL_RWops *SDL_RWFromFP(FILE *fp, SDL_bool autoclose)
|
||||
rwopsdata->fp = fp;
|
||||
rwopsdata->autoclose = autoclose;
|
||||
|
||||
rwops = SDL_OpenRW(&iface, rwopsdata);
|
||||
rwops = SDL_OpenIO(&iface, rwopsdata);
|
||||
if (!rwops) {
|
||||
iface.close(rwopsdata);
|
||||
}
|
||||
@@ -1303,15 +1303,22 @@ SDL_RWops *SDL_RWFromFP(FILE *fp, SDL_bool autoclose)
|
||||
}
|
||||
```
|
||||
|
||||
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_RWclose() => SDL_CloseRW()
|
||||
* SDL_RWread() => SDL_ReadRW()
|
||||
* SDL_RWseek() => SDL_SeekRW()
|
||||
* SDL_RWsize() => SDL_SizeRW()
|
||||
* SDL_RWtell() => SDL_TellRW()
|
||||
* SDL_RWwrite() => SDL_WriteRW()
|
||||
* SDL_CloseRW() => SDL_CloseIO()
|
||||
* 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()
|
||||
@@ -1325,6 +1332,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.
|
||||
@@ -1448,8 +1459,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()
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user