mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-03-20 15:51:07 +01:00
iostream: Properly support the "x" mode for SDL_IOFromFile()
The "x" mode for `fopen()` (open file only if it doesn't exist) used to be a glibc-exclusive extension, but was later standardized in C11, and is now also implemented as part of every other widely-used libc: * musl: https://git.musl-libc.org/cgit/musl/tree/src/stdio/__fmodeflags.c?id=0ccaf0572e9cccda2cced0f7ee659af4c1c6679a * Android Bionic / OpenBSD:731631f300/libc/upstream-openbsd/lib/libc/stdio/flags.c (86)* Apple / FreeBSD:63976b830a/stdio/FreeBSD/flags.c (L91-L92)As a result, "x" has already been working on all our automatically tested platforms that implement `SDL_IOFromFile()` via `fopen()`. So all we'd be missing for proper support is a Windows implementation using `CREATE_NEW`, and the documentation that this mode exists and is intended to work.
This commit is contained in:
@@ -203,6 +203,8 @@ typedef struct SDL_IOStream SDL_IOStream;
|
|||||||
* - "w": Create an empty file for writing. If a file with the same name
|
* - "w": Create an empty file for writing. If a file with the same name
|
||||||
* already exists its content is erased and the file is treated as a new
|
* already exists its content is erased and the file is treated as a new
|
||||||
* empty file.
|
* empty file.
|
||||||
|
* - "wx": Create an empty file for writing. If a file with the same name
|
||||||
|
* already exists, the call fails.
|
||||||
* - "a": Append to a file. Writing operations append data at the end of the
|
* - "a": Append to a file. Writing operations append data at the end of the
|
||||||
* file. The file is created if it does not exist.
|
* file. The file is created if it does not exist.
|
||||||
* - "r+": Open a file for update both reading and writing. The file must
|
* - "r+": Open a file for update both reading and writing. The file must
|
||||||
@@ -210,6 +212,8 @@ typedef struct SDL_IOStream SDL_IOStream;
|
|||||||
* - "w+": Create an empty file for both reading and writing. If a file with
|
* - "w+": Create an empty file for both reading and writing. If a file with
|
||||||
* the same name already exists its content is erased and the file is
|
* the same name already exists its content is erased and the file is
|
||||||
* treated as a new empty file.
|
* treated as a new empty file.
|
||||||
|
* - "w+x": Create an empty file for both reading and writing. If a file with
|
||||||
|
* the same name already exists, the call fails.
|
||||||
* - "a+": Open a file for reading and appending. All writing operations are
|
* - "a+": Open a file for reading and appending. All writing operations are
|
||||||
* performed at the end of the file, protecting the previous content to be
|
* performed at the end of the file, protecting the previous content to be
|
||||||
* overwritten. You can reposition (fseek, rewind) the internal pointer to
|
* overwritten. You can reposition (fseek, rewind) the internal pointer to
|
||||||
|
|||||||
@@ -94,10 +94,12 @@ static HANDLE SDLCALL windows_file_open(const char *filename, const char *mode)
|
|||||||
|
|
||||||
// "r" = reading, file must exist
|
// "r" = reading, file must exist
|
||||||
// "w" = writing, truncate existing, file may not exist
|
// "w" = writing, truncate existing, file may not exist
|
||||||
|
// "wx"= writing, file must not exist
|
||||||
// "r+"= reading or writing, file must exist
|
// "r+"= reading or writing, file must exist
|
||||||
// "a" = writing, append file may not exist
|
// "a" = writing, append file may not exist
|
||||||
// "a+"= append + read, file may not exist
|
// "a+"= append + read, file may not exist
|
||||||
// "w+" = read, write, truncate. file may not exist
|
// "w+" = read, write, truncate. file may not exist
|
||||||
|
// "w+x"= read, write, file must not exist
|
||||||
|
|
||||||
must_exist = (SDL_strchr(mode, 'r') != NULL) ? OPEN_EXISTING : 0;
|
must_exist = (SDL_strchr(mode, 'r') != NULL) ? OPEN_EXISTING : 0;
|
||||||
truncate = (SDL_strchr(mode, 'w') != NULL) ? CREATE_ALWAYS : 0;
|
truncate = (SDL_strchr(mode, 'w') != NULL) ? CREATE_ALWAYS : 0;
|
||||||
@@ -105,6 +107,10 @@ static HANDLE SDLCALL windows_file_open(const char *filename, const char *mode)
|
|||||||
a_mode = (SDL_strchr(mode, 'a') != NULL) ? OPEN_ALWAYS : 0;
|
a_mode = (SDL_strchr(mode, 'a') != NULL) ? OPEN_ALWAYS : 0;
|
||||||
w_right = (a_mode || SDL_strchr(mode, '+') || truncate) ? GENERIC_WRITE : 0;
|
w_right = (a_mode || SDL_strchr(mode, '+') || truncate) ? GENERIC_WRITE : 0;
|
||||||
|
|
||||||
|
if (truncate && (SDL_strchr(mode, 'x') != NULL)) {
|
||||||
|
truncate = CREATE_NEW;
|
||||||
|
}
|
||||||
|
|
||||||
if (!r_right && !w_right) {
|
if (!r_right && !w_right) {
|
||||||
return INVALID_HANDLE_VALUE; // inconsistent mode
|
return INVALID_HANDLE_VALUE; // inconsistent mode
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -615,9 +615,9 @@ static int SDLCALL iostrm_testFileWrite(void *arg)
|
|||||||
int result;
|
int result;
|
||||||
|
|
||||||
/* Write test. */
|
/* Write test. */
|
||||||
rw = SDL_IOFromFile(IOStreamWriteTestFilename, "w+");
|
rw = SDL_IOFromFile(IOStreamWriteTestFilename, "w+x");
|
||||||
SDLTest_AssertPass("Call to SDL_IOFromFile(..,\"w+\") succeeded");
|
SDLTest_AssertPass("Call to SDL_IOFromFile(..,\"w+x\") succeeded");
|
||||||
SDLTest_AssertCheck(rw != NULL, "Verify opening file with SDL_IOFromFile in write mode does not return NULL");
|
SDLTest_AssertCheck(rw != NULL, "Verify opening file with SDL_IOFromFile in exclusive write mode does not return NULL");
|
||||||
|
|
||||||
/* Bail out if NULL */
|
/* Bail out if NULL */
|
||||||
if (rw == NULL) {
|
if (rw == NULL) {
|
||||||
@@ -632,6 +632,11 @@ static int SDLCALL iostrm_testFileWrite(void *arg)
|
|||||||
SDLTest_AssertPass("Call to SDL_CloseIO() succeeded");
|
SDLTest_AssertPass("Call to SDL_CloseIO() succeeded");
|
||||||
SDLTest_AssertCheck(result == true, "Verify result value is true; got: %d", result);
|
SDLTest_AssertCheck(result == true, "Verify result value is true; got: %d", result);
|
||||||
|
|
||||||
|
/* Exclusively opening an existing file should fail. */
|
||||||
|
rw = SDL_IOFromFile(IOStreamWriteTestFilename, "wx");
|
||||||
|
SDLTest_AssertPass("Call to SDL_IOFromFile(..,\"wx\") succeeded");
|
||||||
|
SDLTest_AssertCheck(rw == NULL, "Verify opening existing file with SDL_IOFromFile in exclusive write mode returns NULL");
|
||||||
|
|
||||||
return TEST_COMPLETED;
|
return TEST_COMPLETED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user