rwops: Reworked RWops for SDL3.

- SDL_RWops is now an opaque struct.
- SDL_AllocRW is gone. If an app is creating a custom RWops, they pass the
  function pointers to SDL_CreateRW(), which are stored internally.
- SDL_RWclose is gone, there is only SDL_DestroyRW(), which calls the
  implementation's `->close` method before freeing other things.
- There is only one path to create and use RWops now, so we don't have to
  worry about whether `->close` will call SDL_DestroyRW, or if this will
  risk any Properties not being released, etc.
- SDL_RWFrom* still works as expected, for getting a RWops without having
  to supply your own implementation. Objects from these functions are also
  destroyed with SDL_DestroyRW.
- Lots of other cleanup and SDL3ization of the library code.
This commit is contained in:
Ryan C. Gordon
2024-03-12 01:14:38 -04:00
parent 495e432fb9
commit 525919b315
22 changed files with 424 additions and 470 deletions

View File

@@ -269,15 +269,12 @@ static int rwops_testMem(void *arg)
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");
result = SDL_DestroyRW(rw);
SDLTest_AssertPass("Call to SDL_DestroyRW() succeeded");
SDLTest_AssertCheck(result == 0, "Verify result value is 0; got: %d", result);
return TEST_COMPLETED;
@@ -304,15 +301,12 @@ static int rwops_testConstMem(void *arg)
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");
result = SDL_DestroyRW(rw);
SDLTest_AssertPass("Call to SDL_DestroyRW() succeeded");
SDLTest_AssertCheck(result == 0, "Verify result value is 0; got: %d", result);
return TEST_COMPLETED;
@@ -339,27 +333,12 @@ static int rwops_testFileRead(void *arg)
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");
result = SDL_DestroyRW(rw);
SDLTest_AssertPass("Call to SDL_DestroyRW() succeeded");
SDLTest_AssertCheck(result == 0, "Verify result value is 0; got: %d", result);
return TEST_COMPLETED;
@@ -386,27 +365,12 @@ static int rwops_testFileWrite(void *arg)
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");
result = SDL_DestroyRW(rw);
SDLTest_AssertPass("Call to SDL_DestroyRW() succeeded");
SDLTest_AssertCheck(result == 0, "Verify result value is 0; got: %d", result);
return TEST_COMPLETED;
@@ -421,18 +385,17 @@ static int rwops_testFileWrite(void *arg)
static int rwops_testAllocFree(void *arg)
{
/* Allocate context */
SDL_RWops *rw = SDL_CreateRW();
SDL_RWopsInterface iface;
SDL_RWops *rw;
SDL_zero(iface);
rw = SDL_CreateRW(&iface, NULL);
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");
@@ -472,8 +435,8 @@ static int rwops_testCompareRWFromMemWithRWFromFile(void *arg)
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)");
result = SDL_DestroyRW(rwops_mem);
SDLTest_AssertPass("Call to SDL_DestroyRW(mem)");
SDLTest_AssertCheck(result == 0, "Verify result value is 0; got: %d", result);
/* Read/see from file */
@@ -483,8 +446,8 @@ static int rwops_testCompareRWFromMemWithRWFromFile(void *arg)
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)");
result = SDL_DestroyRW(rwops_file);
SDLTest_AssertPass("Call to SDL_DestroyRW(file)");
SDLTest_AssertCheck(result == 0, "Verify result value is 0; got: %d", result);
/* Compare */
@@ -627,8 +590,8 @@ static int rwops_testFileWriteReadEndian(void *arg)
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");
cresult = SDL_DestroyRW(rw);
SDLTest_AssertPass("Call to SDL_DestroyRW() succeeded");
SDLTest_AssertCheck(cresult == 0, "Verify result value is 0; got: %d", cresult);
}

View File

@@ -55,7 +55,7 @@ rwops_error_quit(unsigned line, SDL_RWops *rwops)
{
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "testfile.c(%d): failed\n", line);
if (rwops) {
SDL_RWclose(rwops); /* This calls SDL_DestroyRW(rwops); */
SDL_DestroyRW(rwops);
}
cleanup();
SDLTest_CommonDestroyState(state);
@@ -126,25 +126,25 @@ int main(int argc, char *argv[])
if (!rwops) {
RWOP_ERR_QUIT(rwops);
}
SDL_RWclose(rwops);
SDL_DestroyRW(rwops);
unlink(FBASENAME2);
rwops = SDL_RWFromFile(FBASENAME2, "wb+");
if (!rwops) {
RWOP_ERR_QUIT(rwops);
}
SDL_RWclose(rwops);
SDL_DestroyRW(rwops);
unlink(FBASENAME2);
rwops = SDL_RWFromFile(FBASENAME2, "ab");
if (!rwops) {
RWOP_ERR_QUIT(rwops);
}
SDL_RWclose(rwops);
SDL_DestroyRW(rwops);
unlink(FBASENAME2);
rwops = SDL_RWFromFile(FBASENAME2, "ab+");
if (!rwops) {
RWOP_ERR_QUIT(rwops);
}
SDL_RWclose(rwops);
SDL_DestroyRW(rwops);
unlink(FBASENAME2);
SDL_Log("test2 OK\n");
@@ -171,7 +171,7 @@ int main(int argc, char *argv[])
RWOP_ERR_QUIT(rwops); /* we are in write only mode */
}
SDL_RWclose(rwops);
SDL_DestroyRW(rwops);
rwops = SDL_RWFromFile(FBASENAME1, "rb"); /* read mode, file must exist */
if (!rwops) {
@@ -208,7 +208,7 @@ int main(int argc, char *argv[])
RWOP_ERR_QUIT(rwops); /* readonly mode */
}
SDL_RWclose(rwops);
SDL_DestroyRW(rwops);
/* test 3: same with w+ mode */
rwops = SDL_RWFromFile(FBASENAME1, "wb+"); /* write + read + truncation */
@@ -258,7 +258,7 @@ int main(int argc, char *argv[])
if (SDL_memcmp(test_buf, "12345678901234567890", 20) != 0) {
RWOP_ERR_QUIT(rwops);
}
SDL_RWclose(rwops);
SDL_DestroyRW(rwops);
SDL_Log("test3 OK\n");
/* test 4: same in r+ mode */
@@ -309,7 +309,7 @@ int main(int argc, char *argv[])
if (SDL_memcmp(test_buf, "12345678901234567890", 20) != 0) {
RWOP_ERR_QUIT(rwops);
}
SDL_RWclose(rwops);
SDL_DestroyRW(rwops);
SDL_Log("test4 OK\n");
/* test5 : append mode */
@@ -366,7 +366,7 @@ int main(int argc, char *argv[])
if (SDL_memcmp(test_buf, "123456789012345678901234567123", 30) != 0) {
RWOP_ERR_QUIT(rwops);
}
SDL_RWclose(rwops);
SDL_DestroyRW(rwops);
SDL_Log("test5 OK\n");
cleanup();
SDL_Quit();

View File

@@ -223,7 +223,7 @@ static int unifont_init(const char *fontname)
lineNumber++;
} while (bytesRead > 0);
SDL_RWclose(hexFile);
SDL_DestroyRW(hexFile);
SDL_Log("unifont: Loaded %" SDL_PRIu32 " glyphs.\n", numGlyphs);
return 0;
}

View File

@@ -452,7 +452,7 @@ int main(int argc, char **argv)
SDL_RWread(handle, RawMooseData, MOOSEFRAME_SIZE * MOOSEFRAMES_COUNT);
SDL_RWclose(handle);
SDL_DestroyRW(handle);
/* Create the window and renderer */
window_w = MOOSEPIC_W * scale;

View File

@@ -141,7 +141,7 @@ int main(int argc, char **argv)
SDL_WriteU32LE(io, dst_len); /* size */
SDL_RWwrite(io, dst_buf, dst_len);
if (SDL_RWclose(io) == -1) {
if (SDL_DestroyRW(io) == -1) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "fclose('%s') failed: %s\n", file_out, SDL_GetError());
ret = 6;
goto end;

View File

@@ -171,7 +171,7 @@ int main(int argc, char **argv)
quit(2);
}
SDL_RWread(handle, MooseFrames, MOOSEFRAME_SIZE * MOOSEFRAMES_COUNT);
SDL_RWclose(handle);
SDL_DestroyRW(handle);
/* Create the window and renderer */
window = SDL_CreateWindow("Happy Moose", MOOSEPIC_W * 4, MOOSEPIC_H * 4, SDL_WINDOW_RESIZABLE);

View File

@@ -44,7 +44,7 @@ GetNearbyFilename(const char *file)
rw = SDL_RWFromFile(path, "rb");
if (rw) {
SDL_RWclose(rw);
SDL_DestroyRW(rw);
return path;
}