SDL_rwops.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827
  1. /*
  2. Simple DirectMedia Layer
  3. Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
  4. This software is provided 'as-is', without any express or implied
  5. warranty. In no event will the authors be held liable for any damages
  6. arising from the use of this software.
  7. Permission is granted to anyone to use this software for any purpose,
  8. including commercial applications, and to alter it and redistribute it
  9. freely, subject to the following restrictions:
  10. 1. The origin of this software must not be misrepresented; you must not
  11. claim that you wrote the original software. If you use this software
  12. in a product, an acknowledgment in the product documentation would be
  13. appreciated but is not required.
  14. 2. Altered source versions must be plainly marked as such, and must not be
  15. misrepresented as being the original software.
  16. 3. This notice may not be removed or altered from any source distribution.
  17. */
  18. /* Need this so Linux systems define fseek64o, ftell64o and off64_t */
  19. #define _LARGEFILE64_SOURCE
  20. #include "../SDL_internal.h"
  21. #if defined(__WIN32__)
  22. #include "../core/windows/SDL_windows.h"
  23. #endif
  24. /* This file provides a general interface for SDL to read and write
  25. data sources. It can easily be extended to files, memory, etc.
  26. */
  27. #include "SDL_endian.h"
  28. #include "SDL_rwops.h"
  29. #ifdef __APPLE__
  30. #include "cocoa/SDL_rwopsbundlesupport.h"
  31. #endif /* __APPLE__ */
  32. #ifdef __ANDROID__
  33. #include "../core/android/SDL_android.h"
  34. #include "SDL_system.h"
  35. #endif
  36. #if __NACL__
  37. #include "nacl_io/nacl_io.h"
  38. #endif
  39. #ifdef __WIN32__
  40. /* Functions to read/write Win32 API file pointers */
  41. #ifndef INVALID_SET_FILE_POINTER
  42. #define INVALID_SET_FILE_POINTER 0xFFFFFFFF
  43. #endif
  44. #define READAHEAD_BUFFER_SIZE 1024
  45. static int SDLCALL
  46. windows_file_open(SDL_RWops * context, const char *filename, const char *mode)
  47. {
  48. UINT old_error_mode;
  49. HANDLE h;
  50. DWORD r_right, w_right;
  51. DWORD must_exist, truncate;
  52. int a_mode;
  53. if (!context)
  54. return -1; /* failed (invalid call) */
  55. context->hidden.windowsio.h = INVALID_HANDLE_VALUE; /* mark this as unusable */
  56. context->hidden.windowsio.buffer.data = NULL;
  57. context->hidden.windowsio.buffer.size = 0;
  58. context->hidden.windowsio.buffer.left = 0;
  59. /* "r" = reading, file must exist */
  60. /* "w" = writing, truncate existing, file may not exist */
  61. /* "r+"= reading or writing, file must exist */
  62. /* "a" = writing, append file may not exist */
  63. /* "a+"= append + read, file may not exist */
  64. /* "w+" = read, write, truncate. file may not exist */
  65. must_exist = (SDL_strchr(mode, 'r') != NULL) ? OPEN_EXISTING : 0;
  66. truncate = (SDL_strchr(mode, 'w') != NULL) ? CREATE_ALWAYS : 0;
  67. r_right = (SDL_strchr(mode, '+') != NULL
  68. || must_exist) ? GENERIC_READ : 0;
  69. a_mode = (SDL_strchr(mode, 'a') != NULL) ? OPEN_ALWAYS : 0;
  70. w_right = (a_mode || SDL_strchr(mode, '+')
  71. || truncate) ? GENERIC_WRITE : 0;
  72. if (!r_right && !w_right) /* inconsistent mode */
  73. return -1; /* failed (invalid call) */
  74. context->hidden.windowsio.buffer.data =
  75. (char *) SDL_malloc(READAHEAD_BUFFER_SIZE);
  76. if (!context->hidden.windowsio.buffer.data) {
  77. return SDL_OutOfMemory();
  78. }
  79. /* Do not open a dialog box if failure */
  80. old_error_mode =
  81. SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS);
  82. {
  83. LPTSTR tstr = WIN_UTF8ToString(filename);
  84. h = CreateFile(tstr, (w_right | r_right),
  85. (w_right) ? 0 : FILE_SHARE_READ, NULL,
  86. (must_exist | truncate | a_mode),
  87. FILE_ATTRIBUTE_NORMAL, NULL);
  88. SDL_free(tstr);
  89. }
  90. /* restore old behavior */
  91. SetErrorMode(old_error_mode);
  92. if (h == INVALID_HANDLE_VALUE) {
  93. SDL_free(context->hidden.windowsio.buffer.data);
  94. context->hidden.windowsio.buffer.data = NULL;
  95. SDL_SetError("Couldn't open %s", filename);
  96. return -2; /* failed (CreateFile) */
  97. }
  98. context->hidden.windowsio.h = h;
  99. context->hidden.windowsio.append = a_mode ? SDL_TRUE : SDL_FALSE;
  100. return 0; /* ok */
  101. }
  102. static Sint64 SDLCALL
  103. windows_file_size(SDL_RWops * context)
  104. {
  105. LARGE_INTEGER size;
  106. if (!context || context->hidden.windowsio.h == INVALID_HANDLE_VALUE) {
  107. return SDL_SetError("windows_file_size: invalid context/file not opened");
  108. }
  109. if (!GetFileSizeEx(context->hidden.windowsio.h, &size)) {
  110. return WIN_SetError("windows_file_size");
  111. }
  112. return size.QuadPart;
  113. }
  114. static Sint64 SDLCALL
  115. windows_file_seek(SDL_RWops * context, Sint64 offset, int whence)
  116. {
  117. DWORD windowswhence;
  118. LARGE_INTEGER windowsoffset;
  119. if (!context || context->hidden.windowsio.h == INVALID_HANDLE_VALUE) {
  120. return SDL_SetError("windows_file_seek: invalid context/file not opened");
  121. }
  122. /* FIXME: We may be able to satisfy the seek within buffered data */
  123. if (whence == RW_SEEK_CUR && context->hidden.windowsio.buffer.left) {
  124. offset -= (long)context->hidden.windowsio.buffer.left;
  125. }
  126. context->hidden.windowsio.buffer.left = 0;
  127. switch (whence) {
  128. case RW_SEEK_SET:
  129. windowswhence = FILE_BEGIN;
  130. break;
  131. case RW_SEEK_CUR:
  132. windowswhence = FILE_CURRENT;
  133. break;
  134. case RW_SEEK_END:
  135. windowswhence = FILE_END;
  136. break;
  137. default:
  138. return SDL_SetError("windows_file_seek: Unknown value for 'whence'");
  139. }
  140. windowsoffset.QuadPart = offset;
  141. if (!SetFilePointerEx(context->hidden.windowsio.h, windowsoffset, &windowsoffset, windowswhence)) {
  142. return WIN_SetError("windows_file_seek");
  143. }
  144. return windowsoffset.QuadPart;
  145. }
  146. static size_t SDLCALL
  147. windows_file_read(SDL_RWops * context, void *ptr, size_t size, size_t maxnum)
  148. {
  149. size_t total_need;
  150. size_t total_read = 0;
  151. size_t read_ahead;
  152. DWORD byte_read;
  153. total_need = size * maxnum;
  154. if (!context || context->hidden.windowsio.h == INVALID_HANDLE_VALUE
  155. || !total_need)
  156. return 0;
  157. if (context->hidden.windowsio.buffer.left > 0) {
  158. void *data = (char *) context->hidden.windowsio.buffer.data +
  159. context->hidden.windowsio.buffer.size -
  160. context->hidden.windowsio.buffer.left;
  161. read_ahead =
  162. SDL_min(total_need, context->hidden.windowsio.buffer.left);
  163. SDL_memcpy(ptr, data, read_ahead);
  164. context->hidden.windowsio.buffer.left -= read_ahead;
  165. if (read_ahead == total_need) {
  166. return maxnum;
  167. }
  168. ptr = (char *) ptr + read_ahead;
  169. total_need -= read_ahead;
  170. total_read += read_ahead;
  171. }
  172. if (total_need < READAHEAD_BUFFER_SIZE) {
  173. if (!ReadFile
  174. (context->hidden.windowsio.h, context->hidden.windowsio.buffer.data,
  175. READAHEAD_BUFFER_SIZE, &byte_read, NULL)) {
  176. SDL_Error(SDL_EFREAD);
  177. return 0;
  178. }
  179. read_ahead = SDL_min(total_need, (int) byte_read);
  180. SDL_memcpy(ptr, context->hidden.windowsio.buffer.data, read_ahead);
  181. context->hidden.windowsio.buffer.size = byte_read;
  182. context->hidden.windowsio.buffer.left = byte_read - read_ahead;
  183. total_read += read_ahead;
  184. } else {
  185. if (!ReadFile
  186. (context->hidden.windowsio.h, ptr, (DWORD)total_need, &byte_read, NULL)) {
  187. SDL_Error(SDL_EFREAD);
  188. return 0;
  189. }
  190. total_read += byte_read;
  191. }
  192. return (total_read / size);
  193. }
  194. static size_t SDLCALL
  195. windows_file_write(SDL_RWops * context, const void *ptr, size_t size,
  196. size_t num)
  197. {
  198. size_t total_bytes;
  199. DWORD byte_written;
  200. size_t nwritten;
  201. total_bytes = size * num;
  202. if (!context || context->hidden.windowsio.h == INVALID_HANDLE_VALUE
  203. || total_bytes <= 0 || !size)
  204. return 0;
  205. if (context->hidden.windowsio.buffer.left) {
  206. SetFilePointer(context->hidden.windowsio.h,
  207. -(LONG)context->hidden.windowsio.buffer.left, NULL,
  208. FILE_CURRENT);
  209. context->hidden.windowsio.buffer.left = 0;
  210. }
  211. /* if in append mode, we must go to the EOF before write */
  212. if (context->hidden.windowsio.append) {
  213. if (SetFilePointer(context->hidden.windowsio.h, 0L, NULL, FILE_END) ==
  214. INVALID_SET_FILE_POINTER) {
  215. SDL_Error(SDL_EFWRITE);
  216. return 0;
  217. }
  218. }
  219. if (!WriteFile
  220. (context->hidden.windowsio.h, ptr, (DWORD)total_bytes, &byte_written, NULL)) {
  221. SDL_Error(SDL_EFWRITE);
  222. return 0;
  223. }
  224. nwritten = byte_written / size;
  225. return nwritten;
  226. }
  227. static int SDLCALL
  228. windows_file_close(SDL_RWops * context)
  229. {
  230. if (context) {
  231. if (context->hidden.windowsio.h != INVALID_HANDLE_VALUE) {
  232. CloseHandle(context->hidden.windowsio.h);
  233. context->hidden.windowsio.h = INVALID_HANDLE_VALUE; /* to be sure */
  234. }
  235. SDL_free(context->hidden.windowsio.buffer.data);
  236. context->hidden.windowsio.buffer.data = NULL;
  237. SDL_FreeRW(context);
  238. }
  239. return 0;
  240. }
  241. #endif /* __WIN32__ */
  242. #ifdef HAVE_STDIO_H
  243. #ifdef HAVE_FOPEN64
  244. #define fopen fopen64
  245. #endif
  246. #ifdef HAVE_FSEEKO64
  247. #define fseek_off_t off64_t
  248. #define fseek fseeko64
  249. #define ftell ftello64
  250. #elif defined(HAVE_FSEEKO)
  251. #define fseek_off_t off_t
  252. #define fseek fseeko
  253. #define ftell ftello
  254. #elif defined(HAVE__FSEEKI64)
  255. #define fseek_off_t __int64
  256. #define fseek _fseeki64
  257. #define ftell _ftelli64
  258. #else
  259. #define fseek_off_t long
  260. #endif
  261. /* Functions to read/write stdio file pointers */
  262. static Sint64 SDLCALL
  263. stdio_size(SDL_RWops * context)
  264. {
  265. Sint64 pos, size;
  266. pos = SDL_RWseek(context, 0, RW_SEEK_CUR);
  267. if (pos < 0) {
  268. return -1;
  269. }
  270. size = SDL_RWseek(context, 0, RW_SEEK_END);
  271. SDL_RWseek(context, pos, RW_SEEK_SET);
  272. return size;
  273. }
  274. static Sint64 SDLCALL
  275. stdio_seek(SDL_RWops * context, Sint64 offset, int whence)
  276. {
  277. if (fseek(context->hidden.stdio.fp, (fseek_off_t)offset, whence) == 0) {
  278. return ftell(context->hidden.stdio.fp);
  279. }
  280. return SDL_Error(SDL_EFSEEK);
  281. }
  282. static size_t SDLCALL
  283. stdio_read(SDL_RWops * context, void *ptr, size_t size, size_t maxnum)
  284. {
  285. size_t nread;
  286. nread = fread(ptr, size, maxnum, context->hidden.stdio.fp);
  287. if (nread == 0 && ferror(context->hidden.stdio.fp)) {
  288. SDL_Error(SDL_EFREAD);
  289. }
  290. return nread;
  291. }
  292. static size_t SDLCALL
  293. stdio_write(SDL_RWops * context, const void *ptr, size_t size, size_t num)
  294. {
  295. size_t nwrote;
  296. nwrote = fwrite(ptr, size, num, context->hidden.stdio.fp);
  297. if (nwrote == 0 && ferror(context->hidden.stdio.fp)) {
  298. SDL_Error(SDL_EFWRITE);
  299. }
  300. return nwrote;
  301. }
  302. static int SDLCALL
  303. stdio_close(SDL_RWops * context)
  304. {
  305. int status = 0;
  306. if (context) {
  307. if (context->hidden.stdio.autoclose) {
  308. /* WARNING: Check the return value here! */
  309. if (fclose(context->hidden.stdio.fp) != 0) {
  310. status = SDL_Error(SDL_EFWRITE);
  311. }
  312. }
  313. SDL_FreeRW(context);
  314. }
  315. return status;
  316. }
  317. #endif /* !HAVE_STDIO_H */
  318. /* Functions to read/write memory pointers */
  319. static Sint64 SDLCALL
  320. mem_size(SDL_RWops * context)
  321. {
  322. return (Sint64)(context->hidden.mem.stop - context->hidden.mem.base);
  323. }
  324. static Sint64 SDLCALL
  325. mem_seek(SDL_RWops * context, Sint64 offset, int whence)
  326. {
  327. Uint8 *newpos;
  328. switch (whence) {
  329. case RW_SEEK_SET:
  330. newpos = context->hidden.mem.base + offset;
  331. break;
  332. case RW_SEEK_CUR:
  333. newpos = context->hidden.mem.here + offset;
  334. break;
  335. case RW_SEEK_END:
  336. newpos = context->hidden.mem.stop + offset;
  337. break;
  338. default:
  339. return SDL_SetError("Unknown value for 'whence'");
  340. }
  341. if (newpos < context->hidden.mem.base) {
  342. newpos = context->hidden.mem.base;
  343. }
  344. if (newpos > context->hidden.mem.stop) {
  345. newpos = context->hidden.mem.stop;
  346. }
  347. context->hidden.mem.here = newpos;
  348. return (Sint64)(context->hidden.mem.here - context->hidden.mem.base);
  349. }
  350. static size_t SDLCALL
  351. mem_read(SDL_RWops * context, void *ptr, size_t size, size_t maxnum)
  352. {
  353. size_t total_bytes;
  354. size_t mem_available;
  355. total_bytes = (maxnum * size);
  356. if ((maxnum <= 0) || (size <= 0)
  357. || ((total_bytes / maxnum) != (size_t) size)) {
  358. return 0;
  359. }
  360. mem_available = (context->hidden.mem.stop - context->hidden.mem.here);
  361. if (total_bytes > mem_available) {
  362. total_bytes = mem_available;
  363. }
  364. SDL_memcpy(ptr, context->hidden.mem.here, total_bytes);
  365. context->hidden.mem.here += total_bytes;
  366. return (total_bytes / size);
  367. }
  368. static size_t SDLCALL
  369. mem_write(SDL_RWops * context, const void *ptr, size_t size, size_t num)
  370. {
  371. if ((context->hidden.mem.here + (num * size)) > context->hidden.mem.stop) {
  372. num = (context->hidden.mem.stop - context->hidden.mem.here) / size;
  373. }
  374. SDL_memcpy(context->hidden.mem.here, ptr, num * size);
  375. context->hidden.mem.here += num * size;
  376. return num;
  377. }
  378. static size_t SDLCALL
  379. mem_writeconst(SDL_RWops * context, const void *ptr, size_t size, size_t num)
  380. {
  381. SDL_SetError("Can't write to read-only memory");
  382. return 0;
  383. }
  384. static int SDLCALL
  385. mem_close(SDL_RWops * context)
  386. {
  387. if (context) {
  388. SDL_FreeRW(context);
  389. }
  390. return 0;
  391. }
  392. /* Functions to create SDL_RWops structures from various data sources */
  393. SDL_RWops *
  394. SDL_RWFromFile(const char *file, const char *mode)
  395. {
  396. SDL_RWops *rwops = NULL;
  397. if (!file || !*file || !mode || !*mode) {
  398. SDL_SetError("SDL_RWFromFile(): No file or no mode specified");
  399. return NULL;
  400. }
  401. #if defined(__ANDROID__)
  402. #ifdef HAVE_STDIO_H
  403. /* Try to open the file on the filesystem first */
  404. if (*file == '/') {
  405. FILE *fp = fopen(file, mode);
  406. if (fp) {
  407. return SDL_RWFromFP(fp, 1);
  408. }
  409. } else {
  410. /* Try opening it from internal storage if it's a relative path */
  411. char *path;
  412. FILE *fp;
  413. path = SDL_stack_alloc(char, PATH_MAX);
  414. if (path) {
  415. SDL_snprintf(path, PATH_MAX, "%s/%s",
  416. SDL_AndroidGetInternalStoragePath(), file);
  417. fp = fopen(path, mode);
  418. SDL_stack_free(path);
  419. if (fp) {
  420. return SDL_RWFromFP(fp, 1);
  421. }
  422. }
  423. }
  424. #endif /* HAVE_STDIO_H */
  425. /* Try to open the file from the asset system */
  426. rwops = SDL_AllocRW();
  427. if (!rwops)
  428. return NULL; /* SDL_SetError already setup by SDL_AllocRW() */
  429. if (Android_JNI_FileOpen(rwops, file, mode) < 0) {
  430. SDL_FreeRW(rwops);
  431. return NULL;
  432. }
  433. rwops->size = Android_JNI_FileSize;
  434. rwops->seek = Android_JNI_FileSeek;
  435. rwops->read = Android_JNI_FileRead;
  436. rwops->write = Android_JNI_FileWrite;
  437. rwops->close = Android_JNI_FileClose;
  438. rwops->type = SDL_RWOPS_JNIFILE;
  439. #elif defined(__WIN32__)
  440. rwops = SDL_AllocRW();
  441. if (!rwops)
  442. return NULL; /* SDL_SetError already setup by SDL_AllocRW() */
  443. if (windows_file_open(rwops, file, mode) < 0) {
  444. SDL_FreeRW(rwops);
  445. return NULL;
  446. }
  447. rwops->size = windows_file_size;
  448. rwops->seek = windows_file_seek;
  449. rwops->read = windows_file_read;
  450. rwops->write = windows_file_write;
  451. rwops->close = windows_file_close;
  452. rwops->type = SDL_RWOPS_WINFILE;
  453. #elif HAVE_STDIO_H
  454. {
  455. #ifdef __APPLE__
  456. FILE *fp = SDL_OpenFPFromBundleOrFallback(file, mode);
  457. #elif __WINRT__
  458. FILE *fp = NULL;
  459. fopen_s(&fp, file, mode);
  460. #else
  461. FILE *fp = fopen(file, mode);
  462. #endif
  463. if (fp == NULL) {
  464. SDL_SetError("Couldn't open %s", file);
  465. } else {
  466. rwops = SDL_RWFromFP(fp, 1);
  467. }
  468. }
  469. #else
  470. SDL_SetError("SDL not compiled with stdio support");
  471. #endif /* !HAVE_STDIO_H */
  472. return rwops;
  473. }
  474. #ifdef HAVE_STDIO_H
  475. SDL_RWops *
  476. SDL_RWFromFP(FILE * fp, SDL_bool autoclose)
  477. {
  478. SDL_RWops *rwops = NULL;
  479. rwops = SDL_AllocRW();
  480. if (rwops != NULL) {
  481. rwops->size = stdio_size;
  482. rwops->seek = stdio_seek;
  483. rwops->read = stdio_read;
  484. rwops->write = stdio_write;
  485. rwops->close = stdio_close;
  486. rwops->hidden.stdio.fp = fp;
  487. rwops->hidden.stdio.autoclose = autoclose;
  488. rwops->type = SDL_RWOPS_STDFILE;
  489. }
  490. return rwops;
  491. }
  492. #else
  493. SDL_RWops *
  494. SDL_RWFromFP(void * fp, SDL_bool autoclose)
  495. {
  496. SDL_SetError("SDL not compiled with stdio support");
  497. return NULL;
  498. }
  499. #endif /* HAVE_STDIO_H */
  500. SDL_RWops *
  501. SDL_RWFromMem(void *mem, int size)
  502. {
  503. SDL_RWops *rwops = NULL;
  504. if (!mem) {
  505. SDL_InvalidParamError("mem");
  506. return rwops;
  507. }
  508. if (!size) {
  509. SDL_InvalidParamError("size");
  510. return rwops;
  511. }
  512. rwops = SDL_AllocRW();
  513. if (rwops != NULL) {
  514. rwops->size = mem_size;
  515. rwops->seek = mem_seek;
  516. rwops->read = mem_read;
  517. rwops->write = mem_write;
  518. rwops->close = mem_close;
  519. rwops->hidden.mem.base = (Uint8 *) mem;
  520. rwops->hidden.mem.here = rwops->hidden.mem.base;
  521. rwops->hidden.mem.stop = rwops->hidden.mem.base + size;
  522. rwops->type = SDL_RWOPS_MEMORY;
  523. }
  524. return rwops;
  525. }
  526. SDL_RWops *
  527. SDL_RWFromConstMem(const void *mem, int size)
  528. {
  529. SDL_RWops *rwops = NULL;
  530. if (!mem) {
  531. SDL_InvalidParamError("mem");
  532. return rwops;
  533. }
  534. if (!size) {
  535. SDL_InvalidParamError("size");
  536. return rwops;
  537. }
  538. rwops = SDL_AllocRW();
  539. if (rwops != NULL) {
  540. rwops->size = mem_size;
  541. rwops->seek = mem_seek;
  542. rwops->read = mem_read;
  543. rwops->write = mem_writeconst;
  544. rwops->close = mem_close;
  545. rwops->hidden.mem.base = (Uint8 *) mem;
  546. rwops->hidden.mem.here = rwops->hidden.mem.base;
  547. rwops->hidden.mem.stop = rwops->hidden.mem.base + size;
  548. rwops->type = SDL_RWOPS_MEMORY_RO;
  549. }
  550. return rwops;
  551. }
  552. SDL_RWops *
  553. SDL_AllocRW(void)
  554. {
  555. SDL_RWops *area;
  556. area = (SDL_RWops *) SDL_malloc(sizeof *area);
  557. if (area == NULL) {
  558. SDL_OutOfMemory();
  559. } else {
  560. area->type = SDL_RWOPS_UNKNOWN;
  561. }
  562. return area;
  563. }
  564. void
  565. SDL_FreeRW(SDL_RWops * area)
  566. {
  567. SDL_free(area);
  568. }
  569. /* Load all the data from an SDL data stream */
  570. void *
  571. SDL_LoadFile_RW(SDL_RWops * src, size_t *datasize, int freesrc)
  572. {
  573. const int FILE_CHUNK_SIZE = 1024;
  574. Sint64 size;
  575. size_t size_read, size_total;
  576. void *data = NULL, *newdata;
  577. if (!src) {
  578. SDL_InvalidParamError("src");
  579. return NULL;
  580. }
  581. size = SDL_RWsize(src);
  582. if (size < 0) {
  583. size = FILE_CHUNK_SIZE;
  584. }
  585. data = SDL_malloc((size_t)(size + 1));
  586. size_total = 0;
  587. for (;;) {
  588. if ((size_total + FILE_CHUNK_SIZE) > size) {
  589. size = (size_total + FILE_CHUNK_SIZE);
  590. newdata = SDL_realloc(data, (size_t)(size + 1));
  591. if (!newdata) {
  592. SDL_free(data);
  593. data = NULL;
  594. SDL_OutOfMemory();
  595. goto done;
  596. }
  597. data = newdata;
  598. }
  599. size_read = SDL_RWread(src, (char *)data+size_total, 1, (size_t)(size-size_total));
  600. if (size_read == 0) {
  601. break;
  602. }
  603. size_total += size_read;
  604. }
  605. if (datasize) {
  606. *datasize = size_total;
  607. }
  608. ((char *)data)[size_total] = '\0';
  609. done:
  610. if (freesrc && src) {
  611. SDL_RWclose(src);
  612. }
  613. return data;
  614. }
  615. /* Functions for dynamically reading and writing endian-specific values */
  616. Uint8
  617. SDL_ReadU8(SDL_RWops * src)
  618. {
  619. Uint8 value = 0;
  620. SDL_RWread(src, &value, sizeof (value), 1);
  621. return value;
  622. }
  623. Uint16
  624. SDL_ReadLE16(SDL_RWops * src)
  625. {
  626. Uint16 value = 0;
  627. SDL_RWread(src, &value, sizeof (value), 1);
  628. return SDL_SwapLE16(value);
  629. }
  630. Uint16
  631. SDL_ReadBE16(SDL_RWops * src)
  632. {
  633. Uint16 value = 0;
  634. SDL_RWread(src, &value, sizeof (value), 1);
  635. return SDL_SwapBE16(value);
  636. }
  637. Uint32
  638. SDL_ReadLE32(SDL_RWops * src)
  639. {
  640. Uint32 value = 0;
  641. SDL_RWread(src, &value, sizeof (value), 1);
  642. return SDL_SwapLE32(value);
  643. }
  644. Uint32
  645. SDL_ReadBE32(SDL_RWops * src)
  646. {
  647. Uint32 value = 0;
  648. SDL_RWread(src, &value, sizeof (value), 1);
  649. return SDL_SwapBE32(value);
  650. }
  651. Uint64
  652. SDL_ReadLE64(SDL_RWops * src)
  653. {
  654. Uint64 value = 0;
  655. SDL_RWread(src, &value, sizeof (value), 1);
  656. return SDL_SwapLE64(value);
  657. }
  658. Uint64
  659. SDL_ReadBE64(SDL_RWops * src)
  660. {
  661. Uint64 value = 0;
  662. SDL_RWread(src, &value, sizeof (value), 1);
  663. return SDL_SwapBE64(value);
  664. }
  665. size_t
  666. SDL_WriteU8(SDL_RWops * dst, Uint8 value)
  667. {
  668. return SDL_RWwrite(dst, &value, sizeof (value), 1);
  669. }
  670. size_t
  671. SDL_WriteLE16(SDL_RWops * dst, Uint16 value)
  672. {
  673. const Uint16 swapped = SDL_SwapLE16(value);
  674. return SDL_RWwrite(dst, &swapped, sizeof (swapped), 1);
  675. }
  676. size_t
  677. SDL_WriteBE16(SDL_RWops * dst, Uint16 value)
  678. {
  679. const Uint16 swapped = SDL_SwapBE16(value);
  680. return SDL_RWwrite(dst, &swapped, sizeof (swapped), 1);
  681. }
  682. size_t
  683. SDL_WriteLE32(SDL_RWops * dst, Uint32 value)
  684. {
  685. const Uint32 swapped = SDL_SwapLE32(value);
  686. return SDL_RWwrite(dst, &swapped, sizeof (swapped), 1);
  687. }
  688. size_t
  689. SDL_WriteBE32(SDL_RWops * dst, Uint32 value)
  690. {
  691. const Uint32 swapped = SDL_SwapBE32(value);
  692. return SDL_RWwrite(dst, &swapped, sizeof (swapped), 1);
  693. }
  694. size_t
  695. SDL_WriteLE64(SDL_RWops * dst, Uint64 value)
  696. {
  697. const Uint64 swapped = SDL_SwapLE64(value);
  698. return SDL_RWwrite(dst, &swapped, sizeof (swapped), 1);
  699. }
  700. size_t
  701. SDL_WriteBE64(SDL_RWops * dst, Uint64 value)
  702. {
  703. const Uint64 swapped = SDL_SwapBE64(value);
  704. return SDL_RWwrite(dst, &swapped, sizeof (swapped), 1);
  705. }
  706. /* vi: set ts=4 sw=4 expandtab: */