SDL  2.0
SDL_rwops.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2019 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;
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  }
356 
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  }
416  }
417  return status;
418 }
419 #endif /* !HAVE_STDIO_H */
420 
421 /* Functions to read/write memory pointers */
422 
423 static Sint64 SDLCALL
425 {
426  return (Sint64)(context->hidden.mem.stop - context->hidden.mem.base);
427 }
428 
429 static Sint64 SDLCALL
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) {
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  /* !!! FIXME: why not just "char path[PATH_MAX];" ? */
532  path = SDL_stack_alloc(char, PATH_MAX);
533  if (path) {
534  SDL_snprintf(path, PATH_MAX, "%s/%s",
536  fp = fopen(path, mode);
538  if (fp) {
539  return SDL_RWFromFP(fp, 1);
540  }
541  }
542  }
543 #endif /* HAVE_STDIO_H */
544 
545  /* Try to open the file from the asset system */
546  rwops = SDL_AllocRW();
547  if (!rwops)
548  return NULL; /* SDL_SetError already setup by SDL_AllocRW() */
549  if (Android_JNI_FileOpen(rwops, file, mode) < 0) {
550  SDL_FreeRW(rwops);
551  return NULL;
552  }
553  rwops->size = Android_JNI_FileSize;
554  rwops->seek = Android_JNI_FileSeek;
555  rwops->read = Android_JNI_FileRead;
556  rwops->write = Android_JNI_FileWrite;
557  rwops->close = Android_JNI_FileClose;
558  rwops->type = SDL_RWOPS_JNIFILE;
559 
560 #elif defined(__WIN32__)
561  rwops = SDL_AllocRW();
562  if (!rwops)
563  return NULL; /* SDL_SetError already setup by SDL_AllocRW() */
564  if (windows_file_open(rwops, file, mode) < 0) {
565  SDL_FreeRW(rwops);
566  return NULL;
567  }
568  rwops->size = windows_file_size;
569  rwops->seek = windows_file_seek;
570  rwops->read = windows_file_read;
571  rwops->write = windows_file_write;
572  rwops->close = windows_file_close;
573  rwops->type = SDL_RWOPS_WINFILE;
574 
575 #elif HAVE_STDIO_H
576  {
577  #ifdef __APPLE__
578  FILE *fp = SDL_OpenFPFromBundleOrFallback(file, mode);
579  #elif __WINRT__
580  FILE *fp = NULL;
581  fopen_s(&fp, file, mode);
582  #else
583  FILE *fp = fopen(file, mode);
584  #endif
585  if (fp == NULL) {
586  SDL_SetError("Couldn't open %s", file);
587  } else {
588  rwops = SDL_RWFromFP(fp, 1);
589  }
590  }
591 #else
592  SDL_SetError("SDL not compiled with stdio support");
593 #endif /* !HAVE_STDIO_H */
594 
595  return rwops;
596 }
597 
598 #ifdef HAVE_STDIO_H
599 SDL_RWops *
600 SDL_RWFromFP(FILE * fp, SDL_bool autoclose)
601 {
602  SDL_RWops *rwops = NULL;
603 
604  rwops = SDL_AllocRW();
605  if (rwops != NULL) {
606  rwops->size = stdio_size;
607  rwops->seek = stdio_seek;
608  rwops->read = stdio_read;
609  rwops->write = stdio_write;
610  rwops->close = stdio_close;
611  rwops->hidden.stdio.fp = fp;
612  rwops->hidden.stdio.autoclose = autoclose;
613  rwops->type = SDL_RWOPS_STDFILE;
614  }
615  return rwops;
616 }
617 #else
618 SDL_RWops *
619 SDL_RWFromFP(void * fp, SDL_bool autoclose)
620 {
621  SDL_SetError("SDL not compiled with stdio support");
622  return NULL;
623 }
624 #endif /* HAVE_STDIO_H */
625 
626 SDL_RWops *
627 SDL_RWFromMem(void *mem, int size)
628 {
629  SDL_RWops *rwops = NULL;
630  if (!mem) {
631  SDL_InvalidParamError("mem");
632  return rwops;
633  }
634  if (!size) {
635  SDL_InvalidParamError("size");
636  return rwops;
637  }
638 
639  rwops = SDL_AllocRW();
640  if (rwops != NULL) {
641  rwops->size = mem_size;
642  rwops->seek = mem_seek;
643  rwops->read = mem_read;
644  rwops->write = mem_write;
645  rwops->close = mem_close;
646  rwops->hidden.mem.base = (Uint8 *) mem;
647  rwops->hidden.mem.here = rwops->hidden.mem.base;
648  rwops->hidden.mem.stop = rwops->hidden.mem.base + size;
649  rwops->type = SDL_RWOPS_MEMORY;
650  }
651  return rwops;
652 }
653 
654 SDL_RWops *
655 SDL_RWFromConstMem(const void *mem, int size)
656 {
657  SDL_RWops *rwops = NULL;
658  if (!mem) {
659  SDL_InvalidParamError("mem");
660  return rwops;
661  }
662  if (!size) {
663  SDL_InvalidParamError("size");
664  return rwops;
665  }
666 
667  rwops = SDL_AllocRW();
668  if (rwops != NULL) {
669  rwops->size = mem_size;
670  rwops->seek = mem_seek;
671  rwops->read = mem_read;
672  rwops->write = mem_writeconst;
673  rwops->close = mem_close;
674  rwops->hidden.mem.base = (Uint8 *) mem;
675  rwops->hidden.mem.here = rwops->hidden.mem.base;
676  rwops->hidden.mem.stop = rwops->hidden.mem.base + size;
677  rwops->type = SDL_RWOPS_MEMORY_RO;
678  }
679  return rwops;
680 }
681 
682 SDL_RWops *
684 {
685  SDL_RWops *area;
686 
687  area = (SDL_RWops *) SDL_malloc(sizeof *area);
688  if (area == NULL) {
689  SDL_OutOfMemory();
690  } else {
691  area->type = SDL_RWOPS_UNKNOWN;
692  }
693  return area;
694 }
695 
696 void
698 {
699  SDL_free(area);
700 }
701 
702 /* Load all the data from an SDL data stream */
703 void *
704 SDL_LoadFile_RW(SDL_RWops * src, size_t *datasize, int freesrc)
705 {
706  const int FILE_CHUNK_SIZE = 1024;
707  Sint64 size;
708  size_t size_read, size_total;
709  void *data = NULL, *newdata;
710 
711  if (!src) {
712  SDL_InvalidParamError("src");
713  return NULL;
714  }
715 
716  size = SDL_RWsize(src);
717  if (size < 0) {
718  size = FILE_CHUNK_SIZE;
719  }
720  data = SDL_malloc((size_t)(size + 1));
721 
722  size_total = 0;
723  for (;;) {
724  if ((((Sint64)size_total) + FILE_CHUNK_SIZE) > size) {
725  size = (size_total + FILE_CHUNK_SIZE);
726  newdata = SDL_realloc(data, (size_t)(size + 1));
727  if (!newdata) {
728  SDL_free(data);
729  data = NULL;
730  SDL_OutOfMemory();
731  goto done;
732  }
733  data = newdata;
734  }
735 
736  size_read = SDL_RWread(src, (char *)data+size_total, 1, (size_t)(size-size_total));
737  if (size_read == 0) {
738  break;
739  }
740  size_total += size_read;
741  }
742 
743  if (datasize) {
744  *datasize = size_total;
745  }
746  ((char *)data)[size_total] = '\0';
747 
748 done:
749  if (freesrc && src) {
750  SDL_RWclose(src);
751  }
752  return data;
753 }
754 
755 void *
756 SDL_LoadFile(const char *file, size_t *datasize)
757 {
758  return SDL_LoadFile_RW(SDL_RWFromFile(file, "rb"), datasize, 1);
759 }
760 
761 Sint64
763 {
764  return context->size(context);
765 }
766 
767 Sint64
769 {
770  return context->seek(context, offset, whence);
771 }
772 
773 Sint64
775 {
776  return context->seek(context, 0, RW_SEEK_CUR);
777 }
778 
779 size_t
780 SDL_RWread(SDL_RWops *context, void *ptr, size_t size, size_t maxnum)
781 {
782  return context->read(context, ptr, size, maxnum);
783 }
784 
785 size_t
786 SDL_RWwrite(SDL_RWops *context, const void *ptr, size_t size, size_t num)
787 {
788  return context->write(context, ptr, size, num);
789 }
790 
791 int
793 {
794  return context->close(context);
795 }
796 
797 /* Functions for dynamically reading and writing endian-specific values */
798 
799 Uint8
801 {
802  Uint8 value = 0;
803 
804  SDL_RWread(src, &value, sizeof (value), 1);
805  return value;
806 }
807 
808 Uint16
810 {
811  Uint16 value = 0;
812 
813  SDL_RWread(src, &value, sizeof (value), 1);
814  return SDL_SwapLE16(value);
815 }
816 
817 Uint16
819 {
820  Uint16 value = 0;
821 
822  SDL_RWread(src, &value, sizeof (value), 1);
823  return SDL_SwapBE16(value);
824 }
825 
826 Uint32
828 {
829  Uint32 value = 0;
830 
831  SDL_RWread(src, &value, sizeof (value), 1);
832  return SDL_SwapLE32(value);
833 }
834 
835 Uint32
837 {
838  Uint32 value = 0;
839 
840  SDL_RWread(src, &value, sizeof (value), 1);
841  return SDL_SwapBE32(value);
842 }
843 
844 Uint64
846 {
847  Uint64 value = 0;
848 
849  SDL_RWread(src, &value, sizeof (value), 1);
850  return SDL_SwapLE64(value);
851 }
852 
853 Uint64
855 {
856  Uint64 value = 0;
857 
858  SDL_RWread(src, &value, sizeof (value), 1);
859  return SDL_SwapBE64(value);
860 }
861 
862 size_t
864 {
865  return SDL_RWwrite(dst, &value, sizeof (value), 1);
866 }
867 
868 size_t
870 {
871  const Uint16 swapped = SDL_SwapLE16(value);
872  return SDL_RWwrite(dst, &swapped, sizeof (swapped), 1);
873 }
874 
875 size_t
877 {
878  const Uint16 swapped = SDL_SwapBE16(value);
879  return SDL_RWwrite(dst, &swapped, sizeof (swapped), 1);
880 }
881 
882 size_t
884 {
885  const Uint32 swapped = SDL_SwapLE32(value);
886  return SDL_RWwrite(dst, &swapped, sizeof (swapped), 1);
887 }
888 
889 size_t
891 {
892  const Uint32 swapped = SDL_SwapBE32(value);
893  return SDL_RWwrite(dst, &swapped, sizeof (swapped), 1);
894 }
895 
896 size_t
898 {
899  const Uint64 swapped = SDL_SwapLE64(value);
900  return SDL_RWwrite(dst, &swapped, sizeof (swapped), 1);
901 }
902 
903 size_t
905 {
906  const Uint64 swapped = SDL_SwapBE64(value);
907  return SDL_RWwrite(dst, &swapped, sizeof (swapped), 1);
908 }
909 
910 /* vi: set ts=4 sw=4 expandtab: */
sort_controllers.filename
string filename
Definition: sort_controllers.py:8
SDL_FreeRW
void SDL_FreeRW(SDL_RWops *area)
Definition: SDL_rwops.c:697
SDL_RWOPS_JNIFILE
#define SDL_RWOPS_JNIFILE
Definition: SDL_rwops.h:45
offset
GLintptr offset
Definition: SDL_opengl_glext.h:538
WIN_UTF8ToString
#define WIN_UTF8ToString(S)
Definition: SDL_windows.h:47
SDL_RWclose
int SDL_RWclose(SDL_RWops *context)
Definition: SDL_rwops.c:792
SDL_ReadBE32
Uint32 SDL_ReadBE32(SDL_RWops *src)
Definition: SDL_rwops.c:836
NULL
#define NULL
Definition: begin_code.h:167
SDL_SwapBE16
#define SDL_SwapBE16(X)
Definition: SDL_endian.h:236
SDL_RWtell
Sint64 SDL_RWtell(SDL_RWops *context)
Definition: SDL_rwops.c:774
mode
GLenum mode
Definition: SDL_opengl_glext.h:1122
SDL_RWOPS_WINFILE
#define SDL_RWOPS_WINFILE
Definition: SDL_rwops.h:43
Android_JNI_FileSeek
Sint64 Android_JNI_FileSeek(SDL_RWops *ctx, Sint64 offset, int whence)
RW_SEEK_END
#define RW_SEEK_END
Definition: SDL_rwops.h:176
SDLCALL
#define SDLCALL
Definition: SDL_internal.h:49
SDL_RWseek
Sint64 SDL_RWseek(SDL_RWops *context, Sint64 offset, int whence)
Definition: SDL_rwops.c:768
SDL_LoadFile
void * SDL_LoadFile(const char *file, size_t *datasize)
Definition: SDL_rwops.c:756
SDL_realloc
#define SDL_realloc
Definition: SDL_dynapi_overrides.h:376
SDL_InvalidParamError
#define SDL_InvalidParamError(param)
Definition: SDL_error.h:54
mem_writeconst
static size_t mem_writeconst(SDL_RWops *context, const void *ptr, size_t size, size_t num)
Definition: SDL_rwops.c:492
num
GLuint num
Definition: SDL_opengl_glext.h:4956
SDL_endian.h
SDL_RWFromConstMem
SDL_RWops * SDL_RWFromConstMem(const void *mem, int size)
Definition: SDL_rwops.c:655
path
GLsizei const GLchar *const * path
Definition: SDL_opengl_glext.h:3730
mem_size
static Sint64 mem_size(SDL_RWops *context)
Definition: SDL_rwops.c:424
SDL_ReadLE64
Uint64 SDL_ReadLE64(SDL_RWops *src)
Definition: SDL_rwops.c:845
SDL_WriteLE32
size_t SDL_WriteLE32(SDL_RWops *dst, Uint32 value)
Definition: SDL_rwops.c:883
SDL_RWOPS_UNKNOWN
#define SDL_RWOPS_UNKNOWN
Definition: SDL_rwops.h:42
h
GLfloat GLfloat GLfloat GLfloat h
Definition: SDL_opengl_glext.h:1946
SDL_SwapLE16
#define SDL_SwapLE16(X)
Definition: SDL_endian.h:232
SDL_AllocRW
SDL_RWops * SDL_AllocRW(void)
Definition: SDL_rwops.c:683
data
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1973
SDL_stack_alloc
#define SDL_stack_alloc(type, count)
Definition: SDL_stdinc.h:354
SDL_LoadFile_RW
void * SDL_LoadFile_RW(SDL_RWops *src, size_t *datasize, int freesrc)
Definition: SDL_rwops.c:704
dst
GLenum GLenum dst
Definition: SDL_opengl_glext.h:1737
SDL_RWsize
Sint64 SDL_RWsize(SDL_RWops *context)
Definition: SDL_rwops.c:762
SDL_Error
#define SDL_Error
Definition: SDL_dynapi_overrides.h:115
SDL_RWops::seek
Sint64(* seek)(struct SDL_RWops *context, Sint64 offset, int whence)
Definition: SDL_rwops.h:65
SDL_memcpy
#define SDL_memcpy
Definition: SDL_dynapi_overrides.h:387
Uint8
uint8_t Uint8
Definition: SDL_stdinc.h:179
SDL_RWFromFile
SDL_RWops * SDL_RWFromFile(const char *file, const char *mode)
Definition: SDL_rwops.c:511
done
int done
Definition: checkkeys.c:28
SDL_ReadBE16
Uint16 SDL_ReadBE16(SDL_RWops *src)
Definition: SDL_rwops.c:818
context
static screen_context_t context
Definition: video.c:25
SDL_strchr
#define SDL_strchr
Definition: SDL_dynapi_overrides.h:401
mem_write
static size_t mem_write(SDL_RWops *context, const void *ptr, size_t size, size_t num)
Definition: SDL_rwops.c:481
SDL_RWFromFP
SDL_RWops * SDL_RWFromFP(void *fp, SDL_bool autoclose)
Definition: SDL_rwops.c:619
SDL_free
#define SDL_free
Definition: SDL_dynapi_overrides.h:377
SDL_WriteBE16
size_t SDL_WriteBE16(SDL_RWops *dst, Uint16 value)
Definition: SDL_rwops.c:876
SDL_RWops::type
Uint32 type
Definition: SDL_rwops.h:93
SDL_WriteBE32
size_t SDL_WriteBE32(SDL_RWops *dst, Uint32 value)
Definition: SDL_rwops.c:890
SDL_FALSE
Definition: SDL_stdinc.h:163
Android_JNI_FileRead
size_t Android_JNI_FileRead(SDL_RWops *ctx, void *buffer, size_t size, size_t maxnum)
SDL_WriteBE64
size_t SDL_WriteBE64(SDL_RWops *dst, Uint64 value)
Definition: SDL_rwops.c:904
mem_close
static int mem_close(SDL_RWops *context)
Definition: SDL_rwops.c:499
SDL_ReadLE32
Uint32 SDL_ReadLE32(SDL_RWops *src)
Definition: SDL_rwops.c:827
SDL_WriteLE64
size_t SDL_WriteLE64(SDL_RWops *dst, Uint64 value)
Definition: SDL_rwops.c:897
SDL_min
#define SDL_min(x, y)
Definition: SDL_stdinc.h:406
Android_JNI_FileSize
Sint64 Android_JNI_FileSize(SDL_RWops *ctx)
Android_JNI_FileOpen
int Android_JNI_FileOpen(SDL_RWops *ctx, const char *fileName, const char *mode)
mem_seek
static Sint64 mem_seek(SDL_RWops *context, Sint64 offset, int whence)
Definition: SDL_rwops.c:430
Android_JNI_FileClose
int Android_JNI_FileClose(SDL_RWops *ctx)
SDL_RWops::hidden
union SDL_RWops::@9 hidden
SDL_OutOfMemory
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
size
GLsizeiptr size
Definition: SDL_opengl_glext.h:537
SDL_RWOPS_MEMORY
#define SDL_RWOPS_MEMORY
Definition: SDL_rwops.h:46
SDL_bool
SDL_bool
Definition: SDL_stdinc.h:161
SDL_RWOPS_MEMORY_RO
#define SDL_RWOPS_MEMORY_RO
Definition: SDL_rwops.h:47
SDL_RWwrite
size_t SDL_RWwrite(SDL_RWops *context, const void *ptr, size_t size, size_t num)
Definition: SDL_rwops.c:786
SDL_RWops::close
int(* close)(struct SDL_RWops *context)
Definition: SDL_rwops.h:91
src
GLenum src
Definition: SDL_opengl_glext.h:1737
SDL_SwapBE64
#define SDL_SwapBE64(X)
Definition: SDL_endian.h:238
SDL_stack_free
#define SDL_stack_free(data)
Definition: SDL_stdinc.h:355
SDL_RWops::mem
struct SDL_RWops::@9::@12 mem
RW_SEEK_SET
#define RW_SEEK_SET
Definition: SDL_rwops.h:174
value
GLsizei const GLfloat * value
Definition: SDL_opengl_glext.h:698
SDL_RWFromMem
SDL_RWops * SDL_RWFromMem(void *mem, int size)
Definition: SDL_rwops.c:627
SDL_SetError
#define SDL_SetError
Definition: SDL_dynapi_overrides.h:30
WIN_SetError
int WIN_SetError(const char *prefix)
SDL_snprintf
#define SDL_snprintf
Definition: SDL_dynapi_overrides.h:40
Uint64
uint64_t Uint64
Definition: SDL_stdinc.h:216
SDL_RWread
size_t SDL_RWread(SDL_RWops *context, void *ptr, size_t size, size_t maxnum)
Definition: SDL_rwops.c:780
SDL_TRUE
Definition: SDL_stdinc.h:164
SDL_ReadU8
Uint8 SDL_ReadU8(SDL_RWops *src)
Definition: SDL_rwops.c:800
SDL_system.h
SDL_RWOPS_STDFILE
#define SDL_RWOPS_STDFILE
Definition: SDL_rwops.h:44
Android_JNI_FileWrite
size_t Android_JNI_FileWrite(SDL_RWops *ctx, const void *buffer, size_t size, size_t num)
SDL_RWops::stdio
struct SDL_RWops::@9::@11 stdio
RW_SEEK_CUR
#define RW_SEEK_CUR
Definition: SDL_rwops.h:175
SDL_WriteU8
size_t SDL_WriteU8(SDL_RWops *dst, Uint8 value)
Definition: SDL_rwops.c:863
Uint32
uint32_t Uint32
Definition: SDL_stdinc.h:203
SDL_RWops::size
Sint64(* size)(struct SDL_RWops *context)
Definition: SDL_rwops.h:57
SDL_RWops::read
size_t(* read)(struct SDL_RWops *context, void *ptr, size_t size, size_t maxnum)
Definition: SDL_rwops.h:74
SDL_SwapBE32
#define SDL_SwapBE32(X)
Definition: SDL_endian.h:237
SDL_EFSEEK
Definition: SDL_error.h:60
SDL_malloc
#define SDL_malloc
Definition: SDL_dynapi_overrides.h:374
SDL_RWops
Definition: SDL_rwops.h:52
SDL_ReadBE64
Uint64 SDL_ReadBE64(SDL_RWops *src)
Definition: SDL_rwops.c:854
SDL_ReadLE16
Uint16 SDL_ReadLE16(SDL_RWops *src)
Definition: SDL_rwops.c:809
size_t
unsigned int size_t
Definition: SDL_config_windows.h:68
SDL_SwapLE64
#define SDL_SwapLE64(X)
Definition: SDL_endian.h:234
SDL_WriteLE16
size_t SDL_WriteLE16(SDL_RWops *dst, Uint16 value)
Definition: SDL_rwops.c:869
SDL_SwapLE32
#define SDL_SwapLE32(X)
Definition: SDL_endian.h:233
Sint64
int64_t Sint64
Definition: SDL_stdinc.h:210
SDL_RWops::write
size_t(* write)(struct SDL_RWops *context, const void *ptr, size_t size, size_t num)
Definition: SDL_rwops.h:83
mem_read
static size_t mem_read(SDL_RWops *context, void *ptr, size_t size, size_t maxnum)
Definition: SDL_rwops.c:458
SDL_EFWRITE
Definition: SDL_error.h:59
SDL_EFREAD
Definition: SDL_error.h:58
SDL_rwopsbundlesupport.h
SDL_AndroidGetInternalStoragePath
#define SDL_AndroidGetInternalStoragePath
Definition: SDL_dynapi_overrides.h:51
Uint16
uint16_t Uint16
Definition: SDL_stdinc.h:191
SDL_rwops.h