Fixed a bunch of compiler warnings.
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
22 /* We won't get fseeko64 on QNX if _LARGEFILE64_SOURCE is defined, but the
23 configure script knows the C runtime has it and enables it. */
25 /* Need this so Linux systems define fseek64o, ftell64o and off64_t */
26 #define _LARGEFILE64_SOURCE
29 #include "../SDL_internal.h"
31 #if defined(__WIN32__)
32 #include "../core/windows/SDL_windows.h"
36 /* This file provides a general interface for SDL to read and write
37 data sources. It can easily be extended to files, memory, etc.
40 #include "SDL_endian.h"
41 #include "SDL_rwops.h"
44 #include "cocoa/SDL_rwopsbundlesupport.h"
45 #endif /* __APPLE__ */
48 #include "../core/android/SDL_android.h"
49 #include "SDL_system.h"
53 #include "nacl_io/nacl_io.h"
58 /* Functions to read/write Win32 API file pointers */
60 #ifndef INVALID_SET_FILE_POINTER
61 #define INVALID_SET_FILE_POINTER 0xFFFFFFFF
64 #define READAHEAD_BUFFER_SIZE 1024
67 windows_file_open(SDL_RWops * context, const char *filename, const char *mode)
71 DWORD r_right, w_right;
72 DWORD must_exist, truncate;
76 return -1; /* failed (invalid call) */
78 context->hidden.windowsio.h = INVALID_HANDLE_VALUE; /* mark this as unusable */
79 context->hidden.windowsio.buffer.data = NULL;
80 context->hidden.windowsio.buffer.size = 0;
81 context->hidden.windowsio.buffer.left = 0;
83 /* "r" = reading, file must exist */
84 /* "w" = writing, truncate existing, file may not exist */
85 /* "r+"= reading or writing, file must exist */
86 /* "a" = writing, append file may not exist */
87 /* "a+"= append + read, file may not exist */
88 /* "w+" = read, write, truncate. file may not exist */
90 must_exist = (SDL_strchr(mode, 'r') != NULL) ? OPEN_EXISTING : 0;
91 truncate = (SDL_strchr(mode, 'w') != NULL) ? CREATE_ALWAYS : 0;
92 r_right = (SDL_strchr(mode, '+') != NULL
93 || must_exist) ? GENERIC_READ : 0;
94 a_mode = (SDL_strchr(mode, 'a') != NULL) ? OPEN_ALWAYS : 0;
95 w_right = (a_mode || SDL_strchr(mode, '+')
96 || truncate) ? GENERIC_WRITE : 0;
98 if (!r_right && !w_right) /* inconsistent mode */
99 return -1; /* failed (invalid call) */
101 context->hidden.windowsio.buffer.data =
102 (char *) SDL_malloc(READAHEAD_BUFFER_SIZE);
103 if (!context->hidden.windowsio.buffer.data) {
104 return SDL_OutOfMemory();
106 /* Do not open a dialog box if failure */
108 SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS);
111 LPTSTR tstr = WIN_UTF8ToString(filename);
112 h = CreateFile(tstr, (w_right | r_right),
113 (w_right) ? 0 : FILE_SHARE_READ, NULL,
114 (must_exist | truncate | a_mode),
115 FILE_ATTRIBUTE_NORMAL, NULL);
119 /* restore old behavior */
120 SetErrorMode(old_error_mode);
122 if (h == INVALID_HANDLE_VALUE) {
123 SDL_free(context->hidden.windowsio.buffer.data);
124 context->hidden.windowsio.buffer.data = NULL;
125 SDL_SetError("Couldn't open %s", filename);
126 return -2; /* failed (CreateFile) */
128 context->hidden.windowsio.h = h;
129 context->hidden.windowsio.append = a_mode ? SDL_TRUE : SDL_FALSE;
134 static Sint64 SDLCALL
135 windows_file_size(SDL_RWops * context)
139 if (!context || context->hidden.windowsio.h == INVALID_HANDLE_VALUE) {
140 return SDL_SetError("windows_file_size: invalid context/file not opened");
143 if (!GetFileSizeEx(context->hidden.windowsio.h, &size)) {
144 return WIN_SetError("windows_file_size");
147 return size.QuadPart;
150 static Sint64 SDLCALL
151 windows_file_seek(SDL_RWops * context, Sint64 offset, int whence)
154 LARGE_INTEGER windowsoffset;
156 if (!context || context->hidden.windowsio.h == INVALID_HANDLE_VALUE) {
157 return SDL_SetError("windows_file_seek: invalid context/file not opened");
160 /* FIXME: We may be able to satisfy the seek within buffered data */
161 if (whence == RW_SEEK_CUR && context->hidden.windowsio.buffer.left) {
162 offset -= (long)context->hidden.windowsio.buffer.left;
164 context->hidden.windowsio.buffer.left = 0;
168 windowswhence = FILE_BEGIN;
171 windowswhence = FILE_CURRENT;
174 windowswhence = FILE_END;
177 return SDL_SetError("windows_file_seek: Unknown value for 'whence'");
180 windowsoffset.QuadPart = offset;
181 if (!SetFilePointerEx(context->hidden.windowsio.h, windowsoffset, &windowsoffset, windowswhence)) {
182 return WIN_SetError("windows_file_seek");
184 return windowsoffset.QuadPart;
187 static size_t SDLCALL
188 windows_file_read(SDL_RWops * context, void *ptr, size_t size, size_t maxnum)
191 size_t total_read = 0;
195 total_need = size * maxnum;
197 if (!context || context->hidden.windowsio.h == INVALID_HANDLE_VALUE
201 if (context->hidden.windowsio.buffer.left > 0) {
202 void *data = (char *) context->hidden.windowsio.buffer.data +
203 context->hidden.windowsio.buffer.size -
204 context->hidden.windowsio.buffer.left;
206 SDL_min(total_need, context->hidden.windowsio.buffer.left);
207 SDL_memcpy(ptr, data, read_ahead);
208 context->hidden.windowsio.buffer.left -= read_ahead;
210 if (read_ahead == total_need) {
213 ptr = (char *) ptr + read_ahead;
214 total_need -= read_ahead;
215 total_read += read_ahead;
218 if (total_need < READAHEAD_BUFFER_SIZE) {
220 (context->hidden.windowsio.h, context->hidden.windowsio.buffer.data,
221 READAHEAD_BUFFER_SIZE, &byte_read, NULL)) {
222 SDL_Error(SDL_EFREAD);
225 read_ahead = SDL_min(total_need, (int) byte_read);
226 SDL_memcpy(ptr, context->hidden.windowsio.buffer.data, read_ahead);
227 context->hidden.windowsio.buffer.size = byte_read;
228 context->hidden.windowsio.buffer.left = byte_read - read_ahead;
229 total_read += read_ahead;
232 (context->hidden.windowsio.h, ptr, (DWORD)total_need, &byte_read, NULL)) {
233 SDL_Error(SDL_EFREAD);
236 total_read += byte_read;
238 return (total_read / size);
241 static size_t SDLCALL
242 windows_file_write(SDL_RWops * context, const void *ptr, size_t size,
250 total_bytes = size * num;
252 if (!context || context->hidden.windowsio.h == INVALID_HANDLE_VALUE
253 || total_bytes <= 0 || !size)
256 if (context->hidden.windowsio.buffer.left) {
257 SetFilePointer(context->hidden.windowsio.h,
258 -(LONG)context->hidden.windowsio.buffer.left, NULL,
260 context->hidden.windowsio.buffer.left = 0;
263 /* if in append mode, we must go to the EOF before write */
264 if (context->hidden.windowsio.append) {
265 if (SetFilePointer(context->hidden.windowsio.h, 0L, NULL, FILE_END) ==
266 INVALID_SET_FILE_POINTER) {
267 SDL_Error(SDL_EFWRITE);
273 (context->hidden.windowsio.h, ptr, (DWORD)total_bytes, &byte_written, NULL)) {
274 SDL_Error(SDL_EFWRITE);
278 nwritten = byte_written / size;
283 windows_file_close(SDL_RWops * context)
287 if (context->hidden.windowsio.h != INVALID_HANDLE_VALUE) {
288 CloseHandle(context->hidden.windowsio.h);
289 context->hidden.windowsio.h = INVALID_HANDLE_VALUE; /* to be sure */
291 SDL_free(context->hidden.windowsio.buffer.data);
292 context->hidden.windowsio.buffer.data = NULL;
297 #endif /* __WIN32__ */
302 #define fopen fopen64
305 #define fseek_off_t off64_t
306 #define fseek fseeko64
307 #define ftell ftello64
308 #elif defined(HAVE_FSEEKO)
309 #define fseek_off_t off_t
312 #elif defined(HAVE__FSEEKI64)
313 #define fseek_off_t __int64
314 #define fseek _fseeki64
315 #define ftell _ftelli64
317 #define fseek_off_t long
320 /* Functions to read/write stdio file pointers */
322 static Sint64 SDLCALL
323 stdio_size(SDL_RWops * context)
327 pos = SDL_RWseek(context, 0, RW_SEEK_CUR);
331 size = SDL_RWseek(context, 0, RW_SEEK_END);
333 SDL_RWseek(context, pos, RW_SEEK_SET);
337 static Sint64 SDLCALL
338 stdio_seek(SDL_RWops * context, Sint64 offset, int whence)
340 if (fseek(context->hidden.stdio.fp, (fseek_off_t)offset, whence) == 0) {
341 return ftell(context->hidden.stdio.fp);
343 return SDL_Error(SDL_EFSEEK);
346 static size_t SDLCALL
347 stdio_read(SDL_RWops * context, void *ptr, size_t size, size_t maxnum)
351 nread = fread(ptr, size, maxnum, context->hidden.stdio.fp);
352 if (nread == 0 && ferror(context->hidden.stdio.fp)) {
353 SDL_Error(SDL_EFREAD);
358 static size_t SDLCALL
359 stdio_write(SDL_RWops * context, const void *ptr, size_t size, size_t num)
363 nwrote = fwrite(ptr, size, num, context->hidden.stdio.fp);
364 if (nwrote == 0 && ferror(context->hidden.stdio.fp)) {
365 SDL_Error(SDL_EFWRITE);
371 stdio_close(SDL_RWops * context)
375 if (context->hidden.stdio.autoclose) {
376 /* WARNING: Check the return value here! */
377 if (fclose(context->hidden.stdio.fp) != 0) {
378 status = SDL_Error(SDL_EFWRITE);
385 #endif /* !HAVE_STDIO_H */
387 /* Functions to read/write memory pointers */
389 static Sint64 SDLCALL
390 mem_size(SDL_RWops * context)
392 return (Sint64)(context->hidden.mem.stop - context->hidden.mem.base);
395 static Sint64 SDLCALL
396 mem_seek(SDL_RWops * context, Sint64 offset, int whence)
402 newpos = context->hidden.mem.base + offset;
405 newpos = context->hidden.mem.here + offset;
408 newpos = context->hidden.mem.stop + offset;
411 return SDL_SetError("Unknown value for 'whence'");
413 if (newpos < context->hidden.mem.base) {
414 newpos = context->hidden.mem.base;
416 if (newpos > context->hidden.mem.stop) {
417 newpos = context->hidden.mem.stop;
419 context->hidden.mem.here = newpos;
420 return (Sint64)(context->hidden.mem.here - context->hidden.mem.base);
423 static size_t SDLCALL
424 mem_read(SDL_RWops * context, void *ptr, size_t size, size_t maxnum)
427 size_t mem_available;
429 total_bytes = (maxnum * size);
430 if ((maxnum <= 0) || (size <= 0)
431 || ((total_bytes / maxnum) != (size_t) size)) {
435 mem_available = (context->hidden.mem.stop - context->hidden.mem.here);
436 if (total_bytes > mem_available) {
437 total_bytes = mem_available;
440 SDL_memcpy(ptr, context->hidden.mem.here, total_bytes);
441 context->hidden.mem.here += total_bytes;
443 return (total_bytes / size);
446 static size_t SDLCALL
447 mem_write(SDL_RWops * context, const void *ptr, size_t size, size_t num)
449 if ((context->hidden.mem.here + (num * size)) > context->hidden.mem.stop) {
450 num = (context->hidden.mem.stop - context->hidden.mem.here) / size;
452 SDL_memcpy(context->hidden.mem.here, ptr, num * size);
453 context->hidden.mem.here += num * size;
457 static size_t SDLCALL
458 mem_writeconst(SDL_RWops * context, const void *ptr, size_t size, size_t num)
460 SDL_SetError("Can't write to read-only memory");
465 mem_close(SDL_RWops * context)
474 /* Functions to create SDL_RWops structures from various data sources */
477 SDL_RWFromFile(const char *file, const char *mode)
479 SDL_RWops *rwops = NULL;
480 if (!file || !*file || !mode || !*mode) {
481 SDL_SetError("SDL_RWFromFile(): No file or no mode specified");
484 #if defined(__ANDROID__)
486 /* Try to open the file on the filesystem first */
488 FILE *fp = fopen(file, mode);
490 return SDL_RWFromFP(fp, 1);
493 /* Try opening it from internal storage if it's a relative path */
497 path = SDL_stack_alloc(char, PATH_MAX);
499 SDL_snprintf(path, PATH_MAX, "%s/%s",
500 SDL_AndroidGetInternalStoragePath(), file);
501 fp = fopen(path, mode);
502 SDL_stack_free(path);
504 return SDL_RWFromFP(fp, 1);
508 #endif /* HAVE_STDIO_H */
510 /* Try to open the file from the asset system */
511 rwops = SDL_AllocRW();
513 return NULL; /* SDL_SetError already setup by SDL_AllocRW() */
514 if (Android_JNI_FileOpen(rwops, file, mode) < 0) {
518 rwops->size = Android_JNI_FileSize;
519 rwops->seek = Android_JNI_FileSeek;
520 rwops->read = Android_JNI_FileRead;
521 rwops->write = Android_JNI_FileWrite;
522 rwops->close = Android_JNI_FileClose;
523 rwops->type = SDL_RWOPS_JNIFILE;
525 #elif defined(__WIN32__)
526 rwops = SDL_AllocRW();
528 return NULL; /* SDL_SetError already setup by SDL_AllocRW() */
529 if (windows_file_open(rwops, file, mode) < 0) {
533 rwops->size = windows_file_size;
534 rwops->seek = windows_file_seek;
535 rwops->read = windows_file_read;
536 rwops->write = windows_file_write;
537 rwops->close = windows_file_close;
538 rwops->type = SDL_RWOPS_WINFILE;
543 FILE *fp = SDL_OpenFPFromBundleOrFallback(file, mode);
546 fopen_s(&fp, file, mode);
548 FILE *fp = fopen(file, mode);
551 SDL_SetError("Couldn't open %s", file);
553 rwops = SDL_RWFromFP(fp, 1);
557 SDL_SetError("SDL not compiled with stdio support");
558 #endif /* !HAVE_STDIO_H */
565 SDL_RWFromFP(FILE * fp, SDL_bool autoclose)
567 SDL_RWops *rwops = NULL;
569 rwops = SDL_AllocRW();
571 rwops->size = stdio_size;
572 rwops->seek = stdio_seek;
573 rwops->read = stdio_read;
574 rwops->write = stdio_write;
575 rwops->close = stdio_close;
576 rwops->hidden.stdio.fp = fp;
577 rwops->hidden.stdio.autoclose = autoclose;
578 rwops->type = SDL_RWOPS_STDFILE;
584 SDL_RWFromFP(void * fp, SDL_bool autoclose)
586 SDL_SetError("SDL not compiled with stdio support");
589 #endif /* HAVE_STDIO_H */
592 SDL_RWFromMem(void *mem, int size)
594 SDL_RWops *rwops = NULL;
596 SDL_InvalidParamError("mem");
600 SDL_InvalidParamError("size");
604 rwops = SDL_AllocRW();
606 rwops->size = mem_size;
607 rwops->seek = mem_seek;
608 rwops->read = mem_read;
609 rwops->write = mem_write;
610 rwops->close = mem_close;
611 rwops->hidden.mem.base = (Uint8 *) mem;
612 rwops->hidden.mem.here = rwops->hidden.mem.base;
613 rwops->hidden.mem.stop = rwops->hidden.mem.base + size;
614 rwops->type = SDL_RWOPS_MEMORY;
620 SDL_RWFromConstMem(const void *mem, int size)
622 SDL_RWops *rwops = NULL;
624 SDL_InvalidParamError("mem");
628 SDL_InvalidParamError("size");
632 rwops = SDL_AllocRW();
634 rwops->size = mem_size;
635 rwops->seek = mem_seek;
636 rwops->read = mem_read;
637 rwops->write = mem_writeconst;
638 rwops->close = mem_close;
639 rwops->hidden.mem.base = (Uint8 *) mem;
640 rwops->hidden.mem.here = rwops->hidden.mem.base;
641 rwops->hidden.mem.stop = rwops->hidden.mem.base + size;
642 rwops->type = SDL_RWOPS_MEMORY_RO;
652 area = (SDL_RWops *) SDL_malloc(sizeof *area);
656 area->type = SDL_RWOPS_UNKNOWN;
662 SDL_FreeRW(SDL_RWops * area)
667 /* Load all the data from an SDL data stream */
669 SDL_LoadFile_RW(SDL_RWops * src, size_t *datasize, int freesrc)
671 const int FILE_CHUNK_SIZE = 1024;
673 size_t size_read, size_total;
674 void *data = NULL, *newdata;
677 SDL_InvalidParamError("src");
681 size = SDL_RWsize(src);
683 size = FILE_CHUNK_SIZE;
685 data = SDL_malloc((size_t)(size + 1));
689 if ((((Sint64)size_total) + FILE_CHUNK_SIZE) > size) {
690 size = (size_total + FILE_CHUNK_SIZE);
691 newdata = SDL_realloc(data, (size_t)(size + 1));
701 size_read = SDL_RWread(src, (char *)data+size_total, 1, (size_t)(size-size_total));
702 if (size_read == 0) {
705 size_total += size_read;
709 *datasize = size_total;
711 ((char *)data)[size_total] = '\0';
714 if (freesrc && src) {
720 /* Functions for dynamically reading and writing endian-specific values */
723 SDL_ReadU8(SDL_RWops * src)
727 SDL_RWread(src, &value, sizeof (value), 1);
732 SDL_ReadLE16(SDL_RWops * src)
736 SDL_RWread(src, &value, sizeof (value), 1);
737 return SDL_SwapLE16(value);
741 SDL_ReadBE16(SDL_RWops * src)
745 SDL_RWread(src, &value, sizeof (value), 1);
746 return SDL_SwapBE16(value);
750 SDL_ReadLE32(SDL_RWops * src)
754 SDL_RWread(src, &value, sizeof (value), 1);
755 return SDL_SwapLE32(value);
759 SDL_ReadBE32(SDL_RWops * src)
763 SDL_RWread(src, &value, sizeof (value), 1);
764 return SDL_SwapBE32(value);
768 SDL_ReadLE64(SDL_RWops * src)
772 SDL_RWread(src, &value, sizeof (value), 1);
773 return SDL_SwapLE64(value);
777 SDL_ReadBE64(SDL_RWops * src)
781 SDL_RWread(src, &value, sizeof (value), 1);
782 return SDL_SwapBE64(value);
786 SDL_WriteU8(SDL_RWops * dst, Uint8 value)
788 return SDL_RWwrite(dst, &value, sizeof (value), 1);
792 SDL_WriteLE16(SDL_RWops * dst, Uint16 value)
794 const Uint16 swapped = SDL_SwapLE16(value);
795 return SDL_RWwrite(dst, &swapped, sizeof (swapped), 1);
799 SDL_WriteBE16(SDL_RWops * dst, Uint16 value)
801 const Uint16 swapped = SDL_SwapBE16(value);
802 return SDL_RWwrite(dst, &swapped, sizeof (swapped), 1);
806 SDL_WriteLE32(SDL_RWops * dst, Uint32 value)
808 const Uint32 swapped = SDL_SwapLE32(value);
809 return SDL_RWwrite(dst, &swapped, sizeof (swapped), 1);
813 SDL_WriteBE32(SDL_RWops * dst, Uint32 value)
815 const Uint32 swapped = SDL_SwapBE32(value);
816 return SDL_RWwrite(dst, &swapped, sizeof (swapped), 1);
820 SDL_WriteLE64(SDL_RWops * dst, Uint64 value)
822 const Uint64 swapped = SDL_SwapLE64(value);
823 return SDL_RWwrite(dst, &swapped, sizeof (swapped), 1);
827 SDL_WriteBE64(SDL_RWops * dst, Uint64 value)
829 const Uint64 swapped = SDL_SwapBE64(value);
830 return SDL_RWwrite(dst, &swapped, sizeof (swapped), 1);
833 /* vi: set ts=4 sw=4 expandtab: */