Atlas - SDL_rwops.c

Home / ext / SDL2 / src / file Lines: 1 | Size: 23135 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)]
[FILE BEGIN]
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2018 Sam Lantinga <[email protected]> 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__ 51#include "cocoa/SDL_rwopsbundlesupport.h" 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 73static int SDLCALL 74windows_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 141static Sint64 SDLCALL 142windows_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 157static Sint64 SDLCALL 158windows_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 194static size_t SDLCALL 195windows_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)) { 229 SDL_Error(SDL_EFREAD); 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)) { 240 SDL_Error(SDL_EFREAD); 241 return 0; 242 } 243 total_read += byte_read; 244 } 245 return (total_read / size); 246} 247 248static size_t SDLCALL 249windows_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) { 274 SDL_Error(SDL_EFWRITE); 275 return 0; 276 } 277 } 278 279 if (!WriteFile 280 (context->hidden.windowsio.h, ptr, (DWORD)total_bytes, &byte_written, NULL)) { 281 SDL_Error(SDL_EFWRITE); 282 return 0; 283 } 284 285 nwritten = byte_written / size; 286 return nwritten; 287} 288 289static int SDLCALL 290windows_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 346static Sint64 SDLCALL 347stdio_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 361static Sint64 SDLCALL 362stdio_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 380static size_t SDLCALL 381stdio_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)) { 387 SDL_Error(SDL_EFREAD); 388 } 389 return nread; 390} 391 392static size_t SDLCALL 393stdio_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)) { 399 SDL_Error(SDL_EFWRITE); 400 } 401 return nwrote; 402} 403 404static int SDLCALL 405stdio_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 423static Sint64 SDLCALL 424mem_size(SDL_RWops * context) 425{ 426 return (Sint64)(context->hidden.mem.stop - context->hidden.mem.base); 427} 428 429static Sint64 SDLCALL 430mem_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 457static size_t SDLCALL 458mem_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 480static size_t SDLCALL 481mem_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 491static size_t SDLCALL 492mem_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 498static int SDLCALL 499mem_close(SDL_RWops * context) 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 510SDL_RWops * 511SDL_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", 534 SDL_AndroidGetInternalStoragePath(), file); 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 598SDL_RWops * 599SDL_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 617SDL_RWops * 618SDL_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 625SDL_RWops * 626SDL_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 653SDL_RWops * 654SDL_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 681SDL_RWops * 682SDL_AllocRW(void) 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 695void 696SDL_FreeRW(SDL_RWops * area) 697{ 698 SDL_free(area); 699} 700 701/* Load all the data from an SDL data stream */ 702void * 703SDL_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 747done: 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 756Uint8 757SDL_ReadU8(SDL_RWops * src) 758{ 759 Uint8 value = 0; 760 761 SDL_RWread(src, &value, sizeof (value), 1); 762 return value; 763} 764 765Uint16 766SDL_ReadLE16(SDL_RWops * src) 767{ 768 Uint16 value = 0; 769 770 SDL_RWread(src, &value, sizeof (value), 1); 771 return SDL_SwapLE16(value); 772} 773 774Uint16 775SDL_ReadBE16(SDL_RWops * src) 776{ 777 Uint16 value = 0; 778 779 SDL_RWread(src, &value, sizeof (value), 1); 780 return SDL_SwapBE16(value); 781} 782 783Uint32 784SDL_ReadLE32(SDL_RWops * src) 785{ 786 Uint32 value = 0; 787 788 SDL_RWread(src, &value, sizeof (value), 1); 789 return SDL_SwapLE32(value); 790} 791 792Uint32 793SDL_ReadBE32(SDL_RWops * src) 794{ 795 Uint32 value = 0; 796 797 SDL_RWread(src, &value, sizeof (value), 1); 798 return SDL_SwapBE32(value); 799} 800 801Uint64 802SDL_ReadLE64(SDL_RWops * src) 803{ 804 Uint64 value = 0; 805 806 SDL_RWread(src, &value, sizeof (value), 1); 807 return SDL_SwapLE64(value); 808} 809 810Uint64 811SDL_ReadBE64(SDL_RWops * src) 812{ 813 Uint64 value = 0; 814 815 SDL_RWread(src, &value, sizeof (value), 1); 816 return SDL_SwapBE64(value); 817} 818 819size_t 820SDL_WriteU8(SDL_RWops * dst, Uint8 value) 821{ 822 return SDL_RWwrite(dst, &value, sizeof (value), 1); 823} 824 825size_t 826SDL_WriteLE16(SDL_RWops * dst, Uint16 value) 827{ 828 const Uint16 swapped = SDL_SwapLE16(value); 829 return SDL_RWwrite(dst, &swapped, sizeof (swapped), 1); 830} 831 832size_t 833SDL_WriteBE16(SDL_RWops * dst, Uint16 value) 834{ 835 const Uint16 swapped = SDL_SwapBE16(value); 836 return SDL_RWwrite(dst, &swapped, sizeof (swapped), 1); 837} 838 839size_t 840SDL_WriteLE32(SDL_RWops * dst, Uint32 value) 841{ 842 const Uint32 swapped = SDL_SwapLE32(value); 843 return SDL_RWwrite(dst, &swapped, sizeof (swapped), 1); 844} 845 846size_t 847SDL_WriteBE32(SDL_RWops * dst, Uint32 value) 848{ 849 const Uint32 swapped = SDL_SwapBE32(value); 850 return SDL_RWwrite(dst, &swapped, sizeof (swapped), 1); 851} 852 853size_t 854SDL_WriteLE64(SDL_RWops * dst, Uint64 value) 855{ 856 const Uint64 swapped = SDL_SwapLE64(value); 857 return SDL_RWwrite(dst, &swapped, sizeof (swapped), 1); 858} 859 860size_t 861SDL_WriteBE64(SDL_RWops * dst, Uint64 value) 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: */ 868
[FILE END]
(C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.