SDL  2.0
SDL_rwops.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
4 
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.
8 
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:
12 
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.
20 */
21 
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. */
24 #ifndef __QNXNTO__
25 /* Need this so Linux systems define fseek64o, ftell64o and off64_t */
26 #define _LARGEFILE64_SOURCE
27 #endif
28 
29 #include "../SDL_internal.h"
30 
31 #if defined(__WIN32__)
32 #include "../core/windows/SDL_windows.h"
33 #endif
34 
35 #ifdef HAVE_STDIO_H
36 #include <stdio.h>
37 #endif
38 
39 #ifdef HAVE_LIMITS_H
40 #include <limits.h>
41 #endif
42 
43 /* This file provides a general interface for SDL to read and write
44  data sources. It can easily be extended to files, memory, etc.
45 */
46 
47 #include "SDL_endian.h"
48 #include "SDL_rwops.h"
49 
50 #ifdef __APPLE__
52 #endif /* __APPLE__ */
53 
54 #ifdef __ANDROID__
55 #include "../core/android/SDL_android.h"
56 #include "SDL_system.h"
57 #endif
58 
59 #if __NACL__
60 #include "nacl_io/nacl_io.h"
61 #endif
62 
63 #ifdef __WIN32__
64 
65 /* Functions to read/write Win32 API file pointers */
66 
67 #ifndef INVALID_SET_FILE_POINTER
68 #define INVALID_SET_FILE_POINTER 0xFFFFFFFF
69 #endif
70 
71 #define READAHEAD_BUFFER_SIZE 1024
72 
73 static int SDLCALL
74 windows_file_open(SDL_RWops * context, const char *filename, const char *mode)
75 {
76  UINT old_error_mode;
77  HANDLE h;
78  DWORD r_right, w_right;
79  DWORD must_exist, truncate;
80  int a_mode;
81 
82  if (!context)
83  return -1; /* failed (invalid call) */
84 
85  context->hidden.windowsio.h = INVALID_HANDLE_VALUE; /* mark this as unusable */
86  context->hidden.windowsio.buffer.data = NULL;
87  context->hidden.windowsio.buffer.size = 0;
88  context->hidden.windowsio.buffer.left = 0;
89 
90  /* "r" = reading, file must exist */
91  /* "w" = writing, truncate existing, file may not exist */
92  /* "r+"= reading or writing, file must exist */
93  /* "a" = writing, append file may not exist */
94  /* "a+"= append + read, file may not exist */
95  /* "w+" = read, write, truncate. file may not exist */
96 
97  must_exist = (SDL_strchr(mode, 'r') != NULL) ? OPEN_EXISTING : 0;
98  truncate = (SDL_strchr(mode, 'w') != NULL) ? CREATE_ALWAYS : 0;
99  r_right = (SDL_strchr(mode, '+') != NULL
100  || must_exist) ? GENERIC_READ : 0;
101  a_mode = (SDL_strchr(mode, 'a') != NULL) ? OPEN_ALWAYS : 0;
102  w_right = (a_mode || SDL_strchr(mode, '+')
103  || truncate) ? GENERIC_WRITE : 0;
104 
105  if (!r_right && !w_right) /* inconsistent mode */
106  return -1; /* failed (invalid call) */
107 
108  context->hidden.windowsio.buffer.data =
109  (char *) SDL_malloc(READAHEAD_BUFFER_SIZE);
110  if (!context->hidden.windowsio.buffer.data) {
111  return SDL_OutOfMemory();
112  }
113  /* Do not open a dialog box if failure */
114  old_error_mode =
115  SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS);
116 
117  {
118  LPTSTR tstr = WIN_UTF8ToString(filename);
119  h = CreateFile(tstr, (w_right | r_right),
120  (w_right) ? 0 : FILE_SHARE_READ, NULL,
121  (must_exist | truncate | a_mode),
122  FILE_ATTRIBUTE_NORMAL, NULL);
123  SDL_free(tstr);
124  }
125 
126  /* restore old behavior */
127  SetErrorMode(old_error_mode);
128 
129  if (h == INVALID_HANDLE_VALUE) {
130  SDL_free(context->hidden.windowsio.buffer.data);
131  context->hidden.windowsio.buffer.data = NULL;
132  SDL_SetError("Couldn't open %s", filename);
133  return -2; /* failed (CreateFile) */
134  }
135  context->hidden.windowsio.h = h;
136  context->hidden.windowsio.append = a_mode ? SDL_TRUE : SDL_FALSE;
137 
138  return 0; /* ok */
139 }
140 
141 static Sint64 SDLCALL
142 windows_file_size(SDL_RWops * context)
143 {
144  LARGE_INTEGER size;
145 
146  if (!context || context->hidden.windowsio.h == INVALID_HANDLE_VALUE) {
147  return SDL_SetError("windows_file_size: invalid context/file not opened");
148  }
149 
150  if (!GetFileSizeEx(context->hidden.windowsio.h, &size)) {
151  return WIN_SetError("windows_file_size");
152  }
153 
154  return size.QuadPart;
155 }
156 
157 static Sint64 SDLCALL
158 windows_file_seek(SDL_RWops * context, Sint64 offset, int whence)
159 {
160  DWORD windowswhence;
161  LARGE_INTEGER windowsoffset;
162 
163  if (!context || context->hidden.windowsio.h == INVALID_HANDLE_VALUE) {
164  return SDL_SetError("windows_file_seek: invalid context/file not opened");
165  }
166 
167  /* FIXME: We may be able to satisfy the seek within buffered data */
168  if (whence == RW_SEEK_CUR && context->hidden.windowsio.buffer.left) {
169  offset -= (long)context->hidden.windowsio.buffer.left;
170  }
171  context->hidden.windowsio.buffer.left = 0;
172 
173  switch (whence) {
174  case RW_SEEK_SET:
175  windowswhence = FILE_BEGIN;
176  break;
177  case RW_SEEK_CUR:
178  windowswhence = FILE_CURRENT;
179  break;
180  case RW_SEEK_END:
181  windowswhence = FILE_END;
182  break;
183  default:
184  return SDL_SetError("windows_file_seek: Unknown value for 'whence'");
185  }
186 
187  windowsoffset.QuadPart = offset;
188  if (!SetFilePointerEx(context->hidden.windowsio.h, windowsoffset, &windowsoffset, windowswhence)) {
189  return WIN_SetError("windows_file_seek");
190  }
191  return windowsoffset.QuadPart;
192 }
193 
194 static size_t SDLCALL
195 windows_file_read(SDL_RWops * context, void *ptr, size_t size, size_t maxnum)
196 {
197  size_t total_need;
198  size_t total_read = 0;
199  size_t read_ahead;
200  DWORD byte_read;
201 
202  total_need = size * maxnum;
203 
204  if (!context || context->hidden.windowsio.h == INVALID_HANDLE_VALUE
205  || !total_need)
206  return 0;
207 
208  if (context->hidden.windowsio.buffer.left > 0) {
209  void *data = (char *) context->hidden.windowsio.buffer.data +
210  context->hidden.windowsio.buffer.size -
211  context->hidden.windowsio.buffer.left;
212  read_ahead =
213  SDL_min(total_need, context->hidden.windowsio.buffer.left);
214  SDL_memcpy(ptr, data, read_ahead);
215  context->hidden.windowsio.buffer.left -= read_ahead;
216 
217  if (read_ahead == total_need) {
218  return maxnum;
219  }
220  ptr = (char *) ptr + read_ahead;
221  total_need -= read_ahead;
222  total_read += read_ahead;
223  }
224 
225  if (total_need < READAHEAD_BUFFER_SIZE) {
226  if (!ReadFile
227  (context->hidden.windowsio.h, context->hidden.windowsio.buffer.data,
228  READAHEAD_BUFFER_SIZE, &byte_read, NULL)) {
230  return 0;
231  }
232  read_ahead = SDL_min(total_need, (int) byte_read);
233  SDL_memcpy(ptr, context->hidden.windowsio.buffer.data, read_ahead);
234  context->hidden.windowsio.buffer.size = byte_read;
235  context->hidden.windowsio.buffer.left = byte_read - read_ahead;
236  total_read += read_ahead;
237  } else {
238  if (!ReadFile
239  (context->hidden.windowsio.h, ptr, (DWORD)total_need, &byte_read, NULL)) {
241  return 0;
242  }
243  total_read += byte_read;
244  }
245  return (total_read / size);
246 }
247 
248 static size_t SDLCALL
249 windows_file_write(SDL_RWops * context, const void *ptr, size_t size,
250  size_t num)
251 {
252 
253  size_t total_bytes;
254  DWORD byte_written;
255  size_t nwritten;
256 
257  total_bytes = size * num;
258 
259  if (!context || context->hidden.windowsio.h == INVALID_HANDLE_VALUE
260  || total_bytes <= 0 || !size)
261  return 0;
262 
263  if (context->hidden.windowsio.buffer.left) {
264  SetFilePointer(context->hidden.windowsio.h,
265  -(LONG)context->hidden.windowsio.buffer.left, NULL,
266  FILE_CURRENT);
267  context->hidden.windowsio.buffer.left = 0;
268  }
269 
270  /* if in append mode, we must go to the EOF before write */
271  if (context->hidden.windowsio.append) {
272  if (SetFilePointer(context->hidden.windowsio.h, 0L, NULL, FILE_END) ==
273  INVALID_SET_FILE_POINTER) {
275  return 0;
276  }
277  }
278 
279  if (!WriteFile
280  (context->hidden.windowsio.h, ptr, (DWORD)total_bytes, &byte_written, NULL)) {
282  return 0;
283  }
284 
285  nwritten = byte_written / size;
286  return nwritten;
287 }
288 
289 static int SDLCALL
290 windows_file_close(SDL_RWops * context)
291 {
292 
293  if (context) {
294  if (context->hidden.windowsio.h != INVALID_HANDLE_VALUE) {
295  CloseHandle(context->hidden.windowsio.h);
296  context->hidden.windowsio.h = INVALID_HANDLE_VALUE; /* to be sure */
297  }
298  SDL_free(context->hidden.windowsio.buffer.data);
299  context->hidden.windowsio.buffer.data = NULL;
300  SDL_FreeRW(context);
301  }
302  return 0;
303 }
304 #endif /* __WIN32__ */
305 
306 #ifdef HAVE_STDIO_H
307 
308 #ifdef HAVE_FOPEN64
309 #define fopen fopen64
310 #endif
311 #ifdef HAVE_FSEEKO64
312 #define fseek_off_t off64_t
313 #define fseek fseeko64
314 #define ftell ftello64
315 #elif defined(HAVE_FSEEKO)
316 #if defined(OFF_MIN) && defined(OFF_MAX)
317 #define FSEEK_OFF_MIN OFF_MIN
318 #define FSEEK_OFF_MAX OFF_MAX
319 #elif defined(HAVE_LIMITS_H)
320 /* POSIX doesn't specify the minimum and maximum macros for off_t so
321  * we have to improvise and dance around implementation-defined
322  * behavior. This may fail if the off_t type has padding bits or
323  * is not a two's-complement representation. The compilers will detect
324  * and eliminate the dead code if off_t has 64 bits.
325  */
326 #define FSEEK_OFF_MAX (((((off_t)1 << (sizeof(off_t) * CHAR_BIT - 2)) - 1) << 1) + 1)
327 #define FSEEK_OFF_MIN (-(FSEEK_OFF_MAX) - 1)
328 #endif
329 #define fseek_off_t off_t
330 #define fseek fseeko
331 #define ftell ftello
332 #elif defined(HAVE__FSEEKI64)
333 #define fseek_off_t __int64
334 #define fseek _fseeki64
335 #define ftell _ftelli64
336 #else
337 #ifdef HAVE_LIMITS_H
338 #define FSEEK_OFF_MIN LONG_MIN
339 #define FSEEK_OFF_MAX LONG_MAX
340 #endif
341 #define fseek_off_t long
342 #endif
343 
344 /* Functions to read/write stdio file pointers */
345 
346 static Sint64 SDLCALL
347 stdio_size(SDL_RWops * context)
348 {
349  Sint64 pos, size;
350 
351  pos = SDL_RWseek(context, 0, RW_SEEK_CUR);
352  if (pos < 0) {
353  return -1;
354  }
355  size = SDL_RWseek(context, 0, RW_SEEK_END);
356 
357  SDL_RWseek(context, pos, RW_SEEK_SET);
358  return size;
359 }
360 
361 static Sint64 SDLCALL
362 stdio_seek(SDL_RWops * context, Sint64 offset, int whence)
363 {
364 #if defined(FSEEK_OFF_MIN) && defined(FSEEK_OFF_MAX)
365  if (offset < (Sint64)(FSEEK_OFF_MIN) || offset > (Sint64)(FSEEK_OFF_MAX)) {
366  return SDL_SetError("Seek offset out of range");
367  }
368 #endif
369 
370  if (fseek(context->hidden.stdio.fp, (fseek_off_t)offset, whence) == 0) {
371  Sint64 pos = ftell(context->hidden.stdio.fp);
372  if (pos < 0) {
373  return SDL_SetError("Couldn't get stream offset");
374  }
375  return pos;
376  }
377  return SDL_Error(SDL_EFSEEK);
378 }
379 
380 static size_t SDLCALL
381 stdio_read(SDL_RWops * context, void *ptr, size_t size, size_t maxnum)
382 {
383  size_t nread;
384 
385  nread = fread(ptr, size, maxnum, context->hidden.stdio.fp);
386  if (nread == 0 && ferror(context->hidden.stdio.fp)) {
388  }
389  return nread;
390 }
391 
392 static size_t SDLCALL
393 stdio_write(SDL_RWops * context, const void *ptr, size_t size, size_t num)
394 {
395  size_t nwrote;
396 
397  nwrote = fwrite(ptr, size, num, context->hidden.stdio.fp);
398  if (nwrote == 0 && ferror(context->hidden.stdio.fp)) {
400  }
401  return nwrote;
402 }
403 
404 static int SDLCALL
405 stdio_close(SDL_RWops * context)
406 {
407  int status = 0;
408  if (context) {
409  if (context->hidden.stdio.autoclose) {
410  /* WARNING: Check the return value here! */
411  if (fclose(context->hidden.stdio.fp) != 0) {
412  status = SDL_Error(SDL_EFWRITE);
413  }
414  }
415  SDL_FreeRW(context);
416  }
417  return status;
418 }
419 #endif /* !HAVE_STDIO_H */
420 
421 /* Functions to read/write memory pointers */
422 
423 static Sint64 SDLCALL
424 mem_size(SDL_RWops * context)
425 {
426  return (Sint64)(context->hidden.mem.stop - context->hidden.mem.base);
427 }
428 
429 static Sint64 SDLCALL
430 mem_seek(SDL_RWops * context, Sint64 offset, int whence)
431 {
432  Uint8 *newpos;
433 
434  switch (whence) {
435  case RW_SEEK_SET:
436  newpos = context->hidden.mem.base + offset;
437  break;
438  case RW_SEEK_CUR:
439  newpos = context->hidden.mem.here + offset;
440  break;
441  case RW_SEEK_END:
442  newpos = context->hidden.mem.stop + offset;
443  break;
444  default:
445  return SDL_SetError("Unknown value for 'whence'");
446  }
447  if (newpos < context->hidden.mem.base) {
448  newpos = context->hidden.mem.base;
449  }
450  if (newpos > context->hidden.mem.stop) {
451  newpos = context->hidden.mem.stop;
452  }
453  context->hidden.mem.here = newpos;
454  return (Sint64)(context->hidden.mem.here - context->hidden.mem.base);
455 }
456 
457 static size_t SDLCALL
458 mem_read(SDL_RWops * context, void *ptr, size_t size, size_t maxnum)
459 {
460  size_t total_bytes;
461  size_t mem_available;
462 
463  total_bytes = (maxnum * size);
464  if ((maxnum <= 0) || (size <= 0)
465  || ((total_bytes / maxnum) != (size_t) size)) {
466  return 0;
467  }
468 
469  mem_available = (context->hidden.mem.stop - context->hidden.mem.here);
470  if (total_bytes > mem_available) {
471  total_bytes = mem_available;
472  }
473 
474  SDL_memcpy(ptr, context->hidden.mem.here, total_bytes);
475  context->hidden.mem.here += total_bytes;
476 
477  return (total_bytes / size);
478 }
479 
480 static size_t SDLCALL
481 mem_write(SDL_RWops * context, const void *ptr, size_t size, size_t num)
482 {
483  if ((context->hidden.mem.here + (num * size)) > context->hidden.mem.stop) {
484  num = (context->hidden.mem.stop - context->hidden.mem.here) / size;
485  }
486  SDL_memcpy(context->hidden.mem.here, ptr, num * size);
487  context->hidden.mem.here += num * size;
488  return num;
489 }
490 
491 static size_t SDLCALL
492 mem_writeconst(SDL_RWops * context, const void *ptr, size_t size, size_t num)
493 {
494  SDL_SetError("Can't write to read-only memory");
495  return 0;
496 }
497 
498 static int SDLCALL
500 {
501  if (context) {
502  SDL_FreeRW(context);
503  }
504  return 0;
505 }
506 
507 
508 /* Functions to create SDL_RWops structures from various data sources */
509 
510 SDL_RWops *
511 SDL_RWFromFile(const char *file, const char *mode)
512 {
513  SDL_RWops *rwops = NULL;
514  if (!file || !*file || !mode || !*mode) {
515  SDL_SetError("SDL_RWFromFile(): No file or no mode specified");
516  return NULL;
517  }
518 #if defined(__ANDROID__)
519 #ifdef HAVE_STDIO_H
520  /* Try to open the file on the filesystem first */
521  if (*file == '/') {
522  FILE *fp = fopen(file, mode);
523  if (fp) {
524  return SDL_RWFromFP(fp, 1);
525  }
526  } else {
527  /* Try opening it from internal storage if it's a relative path */
528  char *path;
529  FILE *fp;
530 
531  path = SDL_stack_alloc(char, PATH_MAX);
532  if (path) {
533  SDL_snprintf(path, PATH_MAX, "%s/%s",
535  fp = fopen(path, mode);
536  SDL_stack_free(path);
537  if (fp) {
538  return SDL_RWFromFP(fp, 1);
539  }
540  }
541  }
542 #endif /* HAVE_STDIO_H */
543 
544  /* Try to open the file from the asset system */
545  rwops = SDL_AllocRW();
546  if (!rwops)
547  return NULL; /* SDL_SetError already setup by SDL_AllocRW() */
548  if (Android_JNI_FileOpen(rwops, file, mode) < 0) {
549  SDL_FreeRW(rwops);
550  return NULL;
551  }
552  rwops->size = Android_JNI_FileSize;
553  rwops->seek = Android_JNI_FileSeek;
554  rwops->read = Android_JNI_FileRead;
555  rwops->write = Android_JNI_FileWrite;
556  rwops->close = Android_JNI_FileClose;
557  rwops->type = SDL_RWOPS_JNIFILE;
558 
559 #elif defined(__WIN32__)
560  rwops = SDL_AllocRW();
561  if (!rwops)
562  return NULL; /* SDL_SetError already setup by SDL_AllocRW() */
563  if (windows_file_open(rwops, file, mode) < 0) {
564  SDL_FreeRW(rwops);
565  return NULL;
566  }
567  rwops->size = windows_file_size;
568  rwops->seek = windows_file_seek;
569  rwops->read = windows_file_read;
570  rwops->write = windows_file_write;
571  rwops->close = windows_file_close;
572  rwops->type = SDL_RWOPS_WINFILE;
573 
574 #elif HAVE_STDIO_H
575  {
576  #ifdef __APPLE__
577  FILE *fp = SDL_OpenFPFromBundleOrFallback(file, mode);
578  #elif __WINRT__
579  FILE *fp = NULL;
580  fopen_s(&fp, file, mode);
581  #else
582  FILE *fp = fopen(file, mode);
583  #endif
584  if (fp == NULL) {
585  SDL_SetError("Couldn't open %s", file);
586  } else {
587  rwops = SDL_RWFromFP(fp, 1);
588  }
589  }
590 #else
591  SDL_SetError("SDL not compiled with stdio support");
592 #endif /* !HAVE_STDIO_H */
593 
594  return rwops;
595 }
596 
597 #ifdef HAVE_STDIO_H
598 SDL_RWops *
599 SDL_RWFromFP(FILE * fp, SDL_bool autoclose)
600 {
601  SDL_RWops *rwops = NULL;
602 
603  rwops = SDL_AllocRW();
604  if (rwops != NULL) {
605  rwops->size = stdio_size;
606  rwops->seek = stdio_seek;
607  rwops->read = stdio_read;
608  rwops->write = stdio_write;
609  rwops->close = stdio_close;
610  rwops->hidden.stdio.fp = fp;
611  rwops->hidden.stdio.autoclose = autoclose;
612  rwops->type = SDL_RWOPS_STDFILE;
613  }
614  return rwops;
615 }
616 #else
617 SDL_RWops *
618 SDL_RWFromFP(void * fp, SDL_bool autoclose)
619 {
620  SDL_SetError("SDL not compiled with stdio support");
621  return NULL;
622 }
623 #endif /* HAVE_STDIO_H */
624 
625 SDL_RWops *
626 SDL_RWFromMem(void *mem, int size)
627 {
628  SDL_RWops *rwops = NULL;
629  if (!mem) {
630  SDL_InvalidParamError("mem");
631  return rwops;
632  }
633  if (!size) {
634  SDL_InvalidParamError("size");
635  return rwops;
636  }
637 
638  rwops = SDL_AllocRW();
639  if (rwops != NULL) {
640  rwops->size = mem_size;
641  rwops->seek = mem_seek;
642  rwops->read = mem_read;
643  rwops->write = mem_write;
644  rwops->close = mem_close;
645  rwops->hidden.mem.base = (Uint8 *) mem;
646  rwops->hidden.mem.here = rwops->hidden.mem.base;
647  rwops->hidden.mem.stop = rwops->hidden.mem.base + size;
648  rwops->type = SDL_RWOPS_MEMORY;
649  }
650  return rwops;
651 }
652 
653 SDL_RWops *
654 SDL_RWFromConstMem(const void *mem, int size)
655 {
656  SDL_RWops *rwops = NULL;
657  if (!mem) {
658  SDL_InvalidParamError("mem");
659  return rwops;
660  }
661  if (!size) {
662  SDL_InvalidParamError("size");
663  return rwops;
664  }
665 
666  rwops = SDL_AllocRW();
667  if (rwops != NULL) {
668  rwops->size = mem_size;
669  rwops->seek = mem_seek;
670  rwops->read = mem_read;
671  rwops->write = mem_writeconst;
672  rwops->close = mem_close;
673  rwops->hidden.mem.base = (Uint8 *) mem;
674  rwops->hidden.mem.here = rwops->hidden.mem.base;
675  rwops->hidden.mem.stop = rwops->hidden.mem.base + size;
676  rwops->type = SDL_RWOPS_MEMORY_RO;
677  }
678  return rwops;
679 }
680 
681 SDL_RWops *
683 {
684  SDL_RWops *area;
685 
686  area = (SDL_RWops *) SDL_malloc(sizeof *area);
687  if (area == NULL) {
688  SDL_OutOfMemory();
689  } else {
690  area->type = SDL_RWOPS_UNKNOWN;
691  }
692  return area;
693 }
694 
695 void
697 {
698  SDL_free(area);
699 }
700 
701 /* Load all the data from an SDL data stream */
702 void *
703 SDL_LoadFile_RW(SDL_RWops * src, size_t *datasize, int freesrc)
704 {
705  const int FILE_CHUNK_SIZE = 1024;
706  Sint64 size;
707  size_t size_read, size_total;
708  void *data = NULL, *newdata;
709 
710  if (!src) {
711  SDL_InvalidParamError("src");
712  return NULL;
713  }
714 
715  size = SDL_RWsize(src);
716  if (size < 0) {
717  size = FILE_CHUNK_SIZE;
718  }
719  data = SDL_malloc((size_t)(size + 1));
720 
721  size_total = 0;
722  for (;;) {
723  if ((((Sint64)size_total) + FILE_CHUNK_SIZE) > size) {
724  size = (size_total + FILE_CHUNK_SIZE);
725  newdata = SDL_realloc(data, (size_t)(size + 1));
726  if (!newdata) {
727  SDL_free(data);
728  data = NULL;
729  SDL_OutOfMemory();
730  goto done;
731  }
732  data = newdata;
733  }
734 
735  size_read = SDL_RWread(src, (char *)data+size_total, 1, (size_t)(size-size_total));
736  if (size_read == 0) {
737  break;
738  }
739  size_total += size_read;
740  }
741 
742  if (datasize) {
743  *datasize = size_total;
744  }
745  ((char *)data)[size_total] = '\0';
746 
747 done:
748  if (freesrc && src) {
749  SDL_RWclose(src);
750  }
751  return data;
752 }
753 
754 /* Functions for dynamically reading and writing endian-specific values */
755 
756 Uint8
758 {
759  Uint8 value = 0;
760 
761  SDL_RWread(src, &value, sizeof (value), 1);
762  return value;
763 }
764 
765 Uint16
767 {
768  Uint16 value = 0;
769 
770  SDL_RWread(src, &value, sizeof (value), 1);
771  return SDL_SwapLE16(value);
772 }
773 
774 Uint16
776 {
777  Uint16 value = 0;
778 
779  SDL_RWread(src, &value, sizeof (value), 1);
780  return SDL_SwapBE16(value);
781 }
782 
783 Uint32
785 {
786  Uint32 value = 0;
787 
788  SDL_RWread(src, &value, sizeof (value), 1);
789  return SDL_SwapLE32(value);
790 }
791 
792 Uint32
794 {
795  Uint32 value = 0;
796 
797  SDL_RWread(src, &value, sizeof (value), 1);
798  return SDL_SwapBE32(value);
799 }
800 
801 Uint64
803 {
804  Uint64 value = 0;
805 
806  SDL_RWread(src, &value, sizeof (value), 1);
807  return SDL_SwapLE64(value);
808 }
809 
810 Uint64
812 {
813  Uint64 value = 0;
814 
815  SDL_RWread(src, &value, sizeof (value), 1);
816  return SDL_SwapBE64(value);
817 }
818 
819 size_t
821 {
822  return SDL_RWwrite(dst, &value, sizeof (value), 1);
823 }
824 
825 size_t
827 {
828  const Uint16 swapped = SDL_SwapLE16(value);
829  return SDL_RWwrite(dst, &swapped, sizeof (swapped), 1);
830 }
831 
832 size_t
834 {
835  const Uint16 swapped = SDL_SwapBE16(value);
836  return SDL_RWwrite(dst, &swapped, sizeof (swapped), 1);
837 }
838 
839 size_t
841 {
842  const Uint32 swapped = SDL_SwapLE32(value);
843  return SDL_RWwrite(dst, &swapped, sizeof (swapped), 1);
844 }
845 
846 size_t
848 {
849  const Uint32 swapped = SDL_SwapBE32(value);
850  return SDL_RWwrite(dst, &swapped, sizeof (swapped), 1);
851 }
852 
853 size_t
855 {
856  const Uint64 swapped = SDL_SwapLE64(value);
857  return SDL_RWwrite(dst, &swapped, sizeof (swapped), 1);
858 }
859 
860 size_t
862 {
863  const Uint64 swapped = SDL_SwapBE64(value);
864  return SDL_RWwrite(dst, &swapped, sizeof (swapped), 1);
865 }
866 
867 /* vi: set ts=4 sw=4 expandtab: */
#define SDL_SwapBE64(X)
Definition: SDL_endian.h:238
int Android_JNI_FileClose(SDL_RWops *ctx)
#define WIN_UTF8ToString(S)
Definition: SDL_windows.h:47
#define SDL_min(x, y)
Definition: SDL_stdinc.h:406
GLuint num
Uint32 SDL_ReadBE32(SDL_RWops *src)
Definition: SDL_rwops.c:793
void SDL_FreeRW(SDL_RWops *area)
Definition: SDL_rwops.c:696
GLenum GLenum dst
#define SDL_RWsize(ctx)
Definition: SDL_rwops.h:184
#define SDL_RWwrite(ctx, ptr, size, n)
Definition: SDL_rwops.h:188
GLfloat GLfloat GLfloat GLfloat h
#define SDL_RWOPS_WINFILE
Definition: SDL_rwops.h:43
SDL_RWops * SDL_RWFromConstMem(const void *mem, int size)
Definition: SDL_rwops.c:654
static screen_context_t context
Definition: video.c:25
#define SDL_RWread(ctx, ptr, size, n)
Definition: SDL_rwops.h:187
size_t(* write)(struct SDL_RWops *context, const void *ptr, size_t size, size_t num)
Definition: SDL_rwops.h:83
#define SDL_RWOPS_UNKNOWN
Definition: SDL_rwops.h:42
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
GLintptr offset
#define RW_SEEK_END
Definition: SDL_rwops.h:176
uint32_t Uint32
Definition: SDL_stdinc.h:181
#define SDL_InvalidParamError(param)
Definition: SDL_error.h:54
#define SDL_realloc
GLenum src
static size_t mem_writeconst(SDL_RWops *context, const void *ptr, size_t size, size_t num)
Definition: SDL_rwops.c:492
size_t SDL_WriteLE32(SDL_RWops *dst, Uint32 value)
Definition: SDL_rwops.c:840
#define SDL_Error
static Sint64 mem_size(SDL_RWops *context)
Definition: SDL_rwops.c:424
uint64_t Uint64
Definition: SDL_stdinc.h:194
int Android_JNI_FileOpen(SDL_RWops *ctx, const char *fileName, const char *mode)
Uint32 type
Definition: SDL_rwops.h:93
struct SDL_RWops::@10::@11 windowsio
#define SDL_SwapBE32(X)
Definition: SDL_endian.h:237
struct SDL_RWops::@10::@13 mem
#define SDL_SwapLE64(X)
Definition: SDL_endian.h:234
#define SDL_SwapBE16(X)
Definition: SDL_endian.h:236
Uint64 SDL_ReadLE64(SDL_RWops *src)
Definition: SDL_rwops.c:802
struct SDL_RWops::@10::@12 stdio
#define SDL_strchr
Sint64(* seek)(struct SDL_RWops *context, Sint64 offset, int whence)
Definition: SDL_rwops.h:65
#define SDL_RWseek(ctx, offset, whence)
Definition: SDL_rwops.h:185
static size_t mem_write(SDL_RWops *context, const void *ptr, size_t size, size_t num)
Definition: SDL_rwops.c:481
Uint16 SDL_ReadBE16(SDL_RWops *src)
Definition: SDL_rwops.c:775
SDL_RWops * SDL_AllocRW(void)
Definition: SDL_rwops.c:682
size_t SDL_WriteBE16(SDL_RWops *dst, Uint16 value)
Definition: SDL_rwops.c:833
void * SDL_LoadFile_RW(SDL_RWops *src, size_t *datasize, int freesrc)
Definition: SDL_rwops.c:703
unsigned int size_t
size_t SDL_WriteBE64(SDL_RWops *dst, Uint64 value)
Definition: SDL_rwops.c:861
#define SDL_memcpy
SDL_RWops * SDL_RWFromFile(const char *file, const char *mode)
Definition: SDL_rwops.c:511
static int mem_close(SDL_RWops *context)
Definition: SDL_rwops.c:499
uint8_t Uint8
Definition: SDL_stdinc.h:157
#define SDL_free
#define SDL_stack_alloc(type, count)
Definition: SDL_stdinc.h:354
#define SDL_SwapLE32(X)
Definition: SDL_endian.h:233
int done
Definition: checkkeys.c:28
int(* close)(struct SDL_RWops *context)
Definition: SDL_rwops.h:91
SDL_RWops * SDL_RWFromFP(void *fp, SDL_bool autoclose)
Definition: SDL_rwops.c:618
size_t Android_JNI_FileWrite(SDL_RWops *ctx, const void *buffer, size_t size, size_t num)
size_t SDL_WriteBE32(SDL_RWops *dst, Uint32 value)
Definition: SDL_rwops.c:847
GLenum mode
GLsizei const GLfloat * value
static Sint64 mem_seek(SDL_RWops *context, Sint64 offset, int whence)
Definition: SDL_rwops.c:430
Uint32 SDL_ReadLE32(SDL_RWops *src)
Definition: SDL_rwops.c:784
size_t SDL_WriteLE64(SDL_RWops *dst, Uint64 value)
Definition: SDL_rwops.c:854
GLsizeiptr size
Sint64(* size)(struct SDL_RWops *context)
Definition: SDL_rwops.h:57
#define NULL
Definition: begin_code.h:164
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_bool
Definition: SDL_stdinc.h:139
SDL_RWops * SDL_RWFromMem(void *mem, int size)
Definition: SDL_rwops.c:626
#define SDL_RWclose(ctx)
Definition: SDL_rwops.h:189
int WIN_SetError(const char *prefix)
#define SDL_RWOPS_MEMORY
Definition: SDL_rwops.h:46
#define SDL_SetError
union SDL_RWops::@10 hidden
#define SDL_RWOPS_STDFILE
Definition: SDL_rwops.h:44
size_t Android_JNI_FileRead(SDL_RWops *ctx, void *buffer, size_t size, size_t maxnum)
#define SDL_RWOPS_MEMORY_RO
Definition: SDL_rwops.h:47
size_t SDL_WriteU8(SDL_RWops *dst, Uint8 value)
Definition: SDL_rwops.c:820
size_t(* read)(struct SDL_RWops *context, void *ptr, size_t size, size_t maxnum)
Definition: SDL_rwops.h:74
#define RW_SEEK_SET
Definition: SDL_rwops.h:174
uint16_t Uint16
Definition: SDL_stdinc.h:169
#define SDL_snprintf
Uint8 SDL_ReadU8(SDL_RWops *src)
Definition: SDL_rwops.c:757
#define SDL_malloc
GLsizei const GLchar *const * path
Uint64 SDL_ReadBE64(SDL_RWops *src)
Definition: SDL_rwops.c:811
#define RW_SEEK_CUR
Definition: SDL_rwops.h:175
int64_t Sint64
Definition: SDL_stdinc.h:188
#define SDL_stack_free(data)
Definition: SDL_stdinc.h:355
size_t SDL_WriteLE16(SDL_RWops *dst, Uint16 value)
Definition: SDL_rwops.c:826
#define SDL_SwapLE16(X)
Definition: SDL_endian.h:232
static size_t mem_read(SDL_RWops *context, void *ptr, size_t size, size_t maxnum)
Definition: SDL_rwops.c:458
#define SDLCALL
Definition: SDL_internal.h:45
#define SDL_AndroidGetInternalStoragePath
Sint64 Android_JNI_FileSeek(SDL_RWops *ctx, Sint64 offset, int whence)
Uint16 SDL_ReadLE16(SDL_RWops *src)
Definition: SDL_rwops.c:766
Sint64 Android_JNI_FileSize(SDL_RWops *ctx)
#define SDL_RWOPS_JNIFILE
Definition: SDL_rwops.h:45