Fixed implicit function declaration for SDL_AndroidGetInternalStoragePath().
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2013 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.
21 /* Need this so Linux systems define fseek64o, ftell64o and off64_t */
22 #define _LARGEFILE64_SOURCE
23 #include "SDL_config.h"
25 /* This file provides a general interface for SDL to read and write
26 data sources. It can easily be extended to files, memory, etc.
29 #include "SDL_endian.h"
30 #include "SDL_rwops.h"
33 #include "cocoa/SDL_rwopsbundlesupport.h"
34 #endif /* __APPLE__ */
37 #include "../core/android/SDL_android.h"
38 #include "SDL_system.h"
43 /* Functions to read/write Win32 API file pointers */
45 #include "../core/windows/SDL_windows.h"
47 #ifndef INVALID_SET_FILE_POINTER
48 #define INVALID_SET_FILE_POINTER 0xFFFFFFFF
51 #define READAHEAD_BUFFER_SIZE 1024
54 windows_file_open(SDL_RWops * context, const char *filename, const char *mode)
58 DWORD r_right, w_right;
59 DWORD must_exist, truncate;
63 return -1; /* failed (invalid call) */
65 context->hidden.windowsio.h = INVALID_HANDLE_VALUE; /* mark this as unusable */
66 context->hidden.windowsio.buffer.data = NULL;
67 context->hidden.windowsio.buffer.size = 0;
68 context->hidden.windowsio.buffer.left = 0;
70 /* "r" = reading, file must exist */
71 /* "w" = writing, truncate existing, file may not exist */
72 /* "r+"= reading or writing, file must exist */
73 /* "a" = writing, append file may not exist */
74 /* "a+"= append + read, file may not exist */
75 /* "w+" = read, write, truncate. file may not exist */
77 must_exist = (SDL_strchr(mode, 'r') != NULL) ? OPEN_EXISTING : 0;
78 truncate = (SDL_strchr(mode, 'w') != NULL) ? CREATE_ALWAYS : 0;
79 r_right = (SDL_strchr(mode, '+') != NULL
80 || must_exist) ? GENERIC_READ : 0;
81 a_mode = (SDL_strchr(mode, 'a') != NULL) ? OPEN_ALWAYS : 0;
82 w_right = (a_mode || SDL_strchr(mode, '+')
83 || truncate) ? GENERIC_WRITE : 0;
85 if (!r_right && !w_right) /* inconsistent mode */
86 return -1; /* failed (invalid call) */
88 context->hidden.windowsio.buffer.data =
89 (char *) SDL_malloc(READAHEAD_BUFFER_SIZE);
90 if (!context->hidden.windowsio.buffer.data) {
91 return SDL_OutOfMemory();
93 /* Do not open a dialog box if failure */
95 SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS);
98 LPTSTR tstr = WIN_UTF8ToString(filename);
99 h = CreateFile(tstr, (w_right | r_right),
100 (w_right) ? 0 : FILE_SHARE_READ, NULL,
101 (must_exist | truncate | a_mode),
102 FILE_ATTRIBUTE_NORMAL, NULL);
106 /* restore old behavior */
107 SetErrorMode(old_error_mode);
109 if (h == INVALID_HANDLE_VALUE) {
110 SDL_free(context->hidden.windowsio.buffer.data);
111 context->hidden.windowsio.buffer.data = NULL;
112 SDL_SetError("Couldn't open %s", filename);
113 return -2; /* failed (CreateFile) */
115 context->hidden.windowsio.h = h;
116 context->hidden.windowsio.append = a_mode ? SDL_TRUE : SDL_FALSE;
121 static Sint64 SDLCALL
122 windows_file_size(SDL_RWops * context)
126 if (!context || context->hidden.windowsio.h == INVALID_HANDLE_VALUE) {
127 return SDL_SetError("windows_file_size: invalid context/file not opened");
130 if (!GetFileSizeEx(context->hidden.windowsio.h, &size)) {
131 return WIN_SetError("windows_file_size");
134 return size.QuadPart;
137 static Sint64 SDLCALL
138 windows_file_seek(SDL_RWops * context, Sint64 offset, int whence)
141 LARGE_INTEGER windowsoffset;
143 if (!context || context->hidden.windowsio.h == INVALID_HANDLE_VALUE) {
144 return SDL_SetError("windows_file_seek: invalid context/file not opened");
147 /* FIXME: We may be able to satisfy the seek within buffered data */
148 if (whence == RW_SEEK_CUR && context->hidden.windowsio.buffer.left) {
149 offset -= (long)context->hidden.windowsio.buffer.left;
151 context->hidden.windowsio.buffer.left = 0;
155 windowswhence = FILE_BEGIN;
158 windowswhence = FILE_CURRENT;
161 windowswhence = FILE_END;
164 return SDL_SetError("windows_file_seek: Unknown value for 'whence'");
167 windowsoffset.QuadPart = offset;
168 if (!SetFilePointerEx(context->hidden.windowsio.h, windowsoffset, &windowsoffset, windowswhence)) {
169 return WIN_SetError("windows_file_seek");
171 return windowsoffset.QuadPart;
174 static size_t SDLCALL
175 windows_file_read(SDL_RWops * context, void *ptr, size_t size, size_t maxnum)
178 size_t total_read = 0;
182 total_need = size * maxnum;
184 if (!context || context->hidden.windowsio.h == INVALID_HANDLE_VALUE
188 if (context->hidden.windowsio.buffer.left > 0) {
189 void *data = (char *) context->hidden.windowsio.buffer.data +
190 context->hidden.windowsio.buffer.size -
191 context->hidden.windowsio.buffer.left;
193 SDL_min(total_need, context->hidden.windowsio.buffer.left);
194 SDL_memcpy(ptr, data, read_ahead);
195 context->hidden.windowsio.buffer.left -= read_ahead;
197 if (read_ahead == total_need) {
200 ptr = (char *) ptr + read_ahead;
201 total_need -= read_ahead;
202 total_read += read_ahead;
205 if (total_need < READAHEAD_BUFFER_SIZE) {
207 (context->hidden.windowsio.h, context->hidden.windowsio.buffer.data,
208 READAHEAD_BUFFER_SIZE, &byte_read, NULL)) {
209 SDL_Error(SDL_EFREAD);
212 read_ahead = SDL_min(total_need, (int) byte_read);
213 SDL_memcpy(ptr, context->hidden.windowsio.buffer.data, read_ahead);
214 context->hidden.windowsio.buffer.size = byte_read;
215 context->hidden.windowsio.buffer.left = byte_read - read_ahead;
216 total_read += read_ahead;
219 (context->hidden.windowsio.h, ptr, (DWORD)total_need, &byte_read, NULL)) {
220 SDL_Error(SDL_EFREAD);
223 total_read += byte_read;
225 return (total_read / size);
228 static size_t SDLCALL
229 windows_file_write(SDL_RWops * context, const void *ptr, size_t size,
237 total_bytes = size * num;
239 if (!context || context->hidden.windowsio.h == INVALID_HANDLE_VALUE
240 || total_bytes <= 0 || !size)
243 if (context->hidden.windowsio.buffer.left) {
244 SetFilePointer(context->hidden.windowsio.h,
245 -(LONG)context->hidden.windowsio.buffer.left, NULL,
247 context->hidden.windowsio.buffer.left = 0;
250 /* if in append mode, we must go to the EOF before write */
251 if (context->hidden.windowsio.append) {
252 if (SetFilePointer(context->hidden.windowsio.h, 0L, NULL, FILE_END) ==
253 INVALID_SET_FILE_POINTER) {
254 SDL_Error(SDL_EFWRITE);
260 (context->hidden.windowsio.h, ptr, (DWORD)total_bytes, &byte_written, NULL)) {
261 SDL_Error(SDL_EFWRITE);
265 nwritten = byte_written / size;
270 windows_file_close(SDL_RWops * context)
274 if (context->hidden.windowsio.h != INVALID_HANDLE_VALUE) {
275 CloseHandle(context->hidden.windowsio.h);
276 context->hidden.windowsio.h = INVALID_HANDLE_VALUE; /* to be sure */
278 if (context->hidden.windowsio.buffer.data) {
279 SDL_free(context->hidden.windowsio.buffer.data);
280 context->hidden.windowsio.buffer.data = NULL;
286 #endif /* __WIN32__ */
290 /* Functions to read/write stdio file pointers */
292 static Sint64 SDLCALL
293 stdio_size(SDL_RWops * context)
297 pos = SDL_RWseek(context, 0, RW_SEEK_CUR);
301 size = SDL_RWseek(context, 0, RW_SEEK_END);
303 SDL_RWseek(context, pos, RW_SEEK_SET);
307 static Sint64 SDLCALL
308 stdio_seek(SDL_RWops * context, Sint64 offset, int whence)
311 if (fseeko64(context->hidden.stdio.fp, (off64_t)offset, whence) == 0) {
312 return ftello64(context->hidden.stdio.fp);
314 #elif defined(HAVE_FSEEKO)
315 if (fseeko(context->hidden.stdio.fp, (off_t)offset, whence) == 0) {
316 return ftello(context->hidden.stdio.fp);
319 if (fseek(context->hidden.stdio.fp, offset, whence) == 0) {
320 return (ftell(context->hidden.stdio.fp));
323 return SDL_Error(SDL_EFSEEK);
326 static size_t SDLCALL
327 stdio_read(SDL_RWops * context, void *ptr, size_t size, size_t maxnum)
331 nread = fread(ptr, size, maxnum, context->hidden.stdio.fp);
332 if (nread == 0 && ferror(context->hidden.stdio.fp)) {
333 SDL_Error(SDL_EFREAD);
338 static size_t SDLCALL
339 stdio_write(SDL_RWops * context, const void *ptr, size_t size, size_t num)
343 nwrote = fwrite(ptr, size, num, context->hidden.stdio.fp);
344 if (nwrote == 0 && ferror(context->hidden.stdio.fp)) {
345 SDL_Error(SDL_EFWRITE);
351 stdio_close(SDL_RWops * context)
355 if (context->hidden.stdio.autoclose) {
356 /* WARNING: Check the return value here! */
357 if (fclose(context->hidden.stdio.fp) != 0) {
358 status = SDL_Error(SDL_EFWRITE);
365 #endif /* !HAVE_STDIO_H */
367 /* Functions to read/write memory pointers */
369 static Sint64 SDLCALL
370 mem_size(SDL_RWops * context)
372 return (Sint64)(context->hidden.mem.stop - context->hidden.mem.base);
375 static Sint64 SDLCALL
376 mem_seek(SDL_RWops * context, Sint64 offset, int whence)
382 newpos = context->hidden.mem.base + offset;
385 newpos = context->hidden.mem.here + offset;
388 newpos = context->hidden.mem.stop + offset;
391 return SDL_SetError("Unknown value for 'whence'");
393 if (newpos < context->hidden.mem.base) {
394 newpos = context->hidden.mem.base;
396 if (newpos > context->hidden.mem.stop) {
397 newpos = context->hidden.mem.stop;
399 context->hidden.mem.here = newpos;
400 return (Sint64)(context->hidden.mem.here - context->hidden.mem.base);
403 static size_t SDLCALL
404 mem_read(SDL_RWops * context, void *ptr, size_t size, size_t maxnum)
407 size_t mem_available;
409 total_bytes = (maxnum * size);
410 if ((maxnum <= 0) || (size <= 0)
411 || ((total_bytes / maxnum) != (size_t) size)) {
415 mem_available = (context->hidden.mem.stop - context->hidden.mem.here);
416 if (total_bytes > mem_available) {
417 total_bytes = mem_available;
420 SDL_memcpy(ptr, context->hidden.mem.here, total_bytes);
421 context->hidden.mem.here += total_bytes;
423 return (total_bytes / size);
426 static size_t SDLCALL
427 mem_write(SDL_RWops * context, const void *ptr, size_t size, size_t num)
429 if ((context->hidden.mem.here + (num * size)) > context->hidden.mem.stop) {
430 num = (context->hidden.mem.stop - context->hidden.mem.here) / size;
432 SDL_memcpy(context->hidden.mem.here, ptr, num * size);
433 context->hidden.mem.here += num * size;
437 static size_t SDLCALL
438 mem_writeconst(SDL_RWops * context, const void *ptr, size_t size, size_t num)
440 SDL_SetError("Can't write to read-only memory");
445 mem_close(SDL_RWops * context)
454 /* Functions to create SDL_RWops structures from various data sources */
457 SDL_RWFromFile(const char *file, const char *mode)
459 SDL_RWops *rwops = NULL;
460 if (!file || !*file || !mode || !*mode) {
461 SDL_SetError("SDL_RWFromFile(): No file or no mode specified");
466 /* Try to open the file on the filesystem first */
468 FILE *fp = fopen(file, mode);
470 return SDL_RWFromFP(fp, 1);
473 /* Try opening it from internal storage if it's a relative path */
477 path = SDL_stack_alloc(char, PATH_MAX);
479 SDL_snprintf(path, PATH_MAX, "%s/%s",
480 SDL_AndroidGetInternalStoragePath(), file);
481 fp = fopen(path, mode);
482 SDL_stack_free(path);
484 return SDL_RWFromFP(fp, 1);
488 #endif /* HAVE_STDIO_H */
490 /* Try to open the file from the asset system */
491 rwops = SDL_AllocRW();
493 return NULL; /* SDL_SetError already setup by SDL_AllocRW() */
494 if (Android_JNI_FileOpen(rwops, file, mode) < 0) {
498 rwops->size = Android_JNI_FileSize;
499 rwops->seek = Android_JNI_FileSeek;
500 rwops->read = Android_JNI_FileRead;
501 rwops->write = Android_JNI_FileWrite;
502 rwops->close = Android_JNI_FileClose;
503 rwops->type = SDL_RWOPS_JNIFILE;
505 #elif defined(__WIN32__)
506 rwops = SDL_AllocRW();
508 return NULL; /* SDL_SetError already setup by SDL_AllocRW() */
509 if (windows_file_open(rwops, file, mode) < 0) {
513 rwops->size = windows_file_size;
514 rwops->seek = windows_file_seek;
515 rwops->read = windows_file_read;
516 rwops->write = windows_file_write;
517 rwops->close = windows_file_close;
518 rwops->type = SDL_RWOPS_WINFILE;
523 FILE *fp = SDL_OpenFPFromBundleOrFallback(file, mode);
525 FILE *fp = fopen(file, mode);
528 SDL_SetError("Couldn't open %s", file);
530 rwops = SDL_RWFromFP(fp, 1);
534 SDL_SetError("SDL not compiled with stdio support");
535 #endif /* !HAVE_STDIO_H */
542 SDL_RWFromFP(FILE * fp, SDL_bool autoclose)
544 SDL_RWops *rwops = NULL;
546 rwops = SDL_AllocRW();
548 rwops->size = stdio_size;
549 rwops->seek = stdio_seek;
550 rwops->read = stdio_read;
551 rwops->write = stdio_write;
552 rwops->close = stdio_close;
553 rwops->hidden.stdio.fp = fp;
554 rwops->hidden.stdio.autoclose = autoclose;
555 rwops->type = SDL_RWOPS_STDFILE;
561 SDL_RWFromFP(void * fp, SDL_bool autoclose)
563 SDL_SetError("SDL not compiled with stdio support");
566 #endif /* HAVE_STDIO_H */
569 SDL_RWFromMem(void *mem, int size)
571 SDL_RWops *rwops = NULL;
573 SDL_InvalidParamError("mem");
577 SDL_InvalidParamError("size");
581 rwops = SDL_AllocRW();
583 rwops->size = mem_size;
584 rwops->seek = mem_seek;
585 rwops->read = mem_read;
586 rwops->write = mem_write;
587 rwops->close = mem_close;
588 rwops->hidden.mem.base = (Uint8 *) mem;
589 rwops->hidden.mem.here = rwops->hidden.mem.base;
590 rwops->hidden.mem.stop = rwops->hidden.mem.base + size;
591 rwops->type = SDL_RWOPS_MEMORY;
597 SDL_RWFromConstMem(const void *mem, int size)
599 SDL_RWops *rwops = NULL;
601 SDL_InvalidParamError("mem");
605 SDL_InvalidParamError("size");
609 rwops = SDL_AllocRW();
611 rwops->size = mem_size;
612 rwops->seek = mem_seek;
613 rwops->read = mem_read;
614 rwops->write = mem_writeconst;
615 rwops->close = mem_close;
616 rwops->hidden.mem.base = (Uint8 *) mem;
617 rwops->hidden.mem.here = rwops->hidden.mem.base;
618 rwops->hidden.mem.stop = rwops->hidden.mem.base + size;
619 rwops->type = SDL_RWOPS_MEMORY_RO;
629 area = (SDL_RWops *) SDL_malloc(sizeof *area);
633 area->type = SDL_RWOPS_UNKNOWN;
639 SDL_FreeRW(SDL_RWops * area)
644 /* Functions for dynamically reading and writing endian-specific values */
647 SDL_ReadU8(SDL_RWops * src)
651 SDL_RWread(src, &value, (sizeof value), 1);
656 SDL_ReadLE16(SDL_RWops * src)
660 SDL_RWread(src, &value, (sizeof value), 1);
661 return (SDL_SwapLE16(value));
665 SDL_ReadBE16(SDL_RWops * src)
669 SDL_RWread(src, &value, (sizeof value), 1);
670 return (SDL_SwapBE16(value));
674 SDL_ReadLE32(SDL_RWops * src)
678 SDL_RWread(src, &value, (sizeof value), 1);
679 return (SDL_SwapLE32(value));
683 SDL_ReadBE32(SDL_RWops * src)
687 SDL_RWread(src, &value, (sizeof value), 1);
688 return (SDL_SwapBE32(value));
692 SDL_ReadLE64(SDL_RWops * src)
696 SDL_RWread(src, &value, (sizeof value), 1);
697 return (SDL_SwapLE64(value));
701 SDL_ReadBE64(SDL_RWops * src)
705 SDL_RWread(src, &value, (sizeof value), 1);
706 return (SDL_SwapBE64(value));
710 SDL_WriteU8(SDL_RWops * dst, Uint8 value)
712 return (SDL_RWwrite(dst, &value, (sizeof value), 1));
716 SDL_WriteLE16(SDL_RWops * dst, Uint16 value)
718 value = SDL_SwapLE16(value);
719 return (SDL_RWwrite(dst, &value, (sizeof value), 1));
723 SDL_WriteBE16(SDL_RWops * dst, Uint16 value)
725 value = SDL_SwapBE16(value);
726 return (SDL_RWwrite(dst, &value, (sizeof value), 1));
730 SDL_WriteLE32(SDL_RWops * dst, Uint32 value)
732 value = SDL_SwapLE32(value);
733 return (SDL_RWwrite(dst, &value, (sizeof value), 1));
737 SDL_WriteBE32(SDL_RWops * dst, Uint32 value)
739 value = SDL_SwapBE32(value);
740 return (SDL_RWwrite(dst, &value, (sizeof value), 1));
744 SDL_WriteLE64(SDL_RWops * dst, Uint64 value)
746 value = SDL_SwapLE64(value);
747 return (SDL_RWwrite(dst, &value, (sizeof value), 1));
751 SDL_WriteBE64(SDL_RWops * dst, Uint64 value)
753 value = SDL_SwapBE64(value);
754 return (SDL_RWwrite(dst, &value, (sizeof value), 1));
757 /* vi: set ts=4 sw=4 expandtab: */