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