e14743d1 |
1 | /* |
2 | SDL - Simple DirectMedia Layer |
3 | Copyright (C) 1997-2009 Sam Lantinga |
4 | |
5 | This library is free software; you can redistribute it and/or |
6 | modify it under the terms of the GNU Lesser General Public |
7 | License as published by the Free Software Foundation; either |
8 | version 2.1 of the License, or (at your option) any later version. |
9 | |
10 | This library is distributed in the hope that it will be useful, |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | Lesser General Public License for more details. |
14 | |
15 | You should have received a copy of the GNU Lesser General Public |
16 | License along with this library; if not, write to the Free Software |
17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
18 | |
19 | Sam Lantinga |
20 | slouken@libsdl.org |
21 | */ |
22 | #include "SDL_config.h" |
23 | |
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 | |
28 | #include "SDL_endian.h" |
29 | #include "SDL_rwops.h" |
30 | |
31 | |
32 | #if defined(__WIN32__) && !defined(__SYMBIAN32__) |
33 | |
34 | /* Functions to read/write Win32 API file pointers */ |
35 | /* Will not use it on WinCE because stdio is buffered, it means |
36 | faster, and all stdio functions anyway are embedded in coredll.dll - |
37 | the main wince dll*/ |
38 | |
39 | #define WINDOWS_LEAN_AND_MEAN |
40 | #include <windows.h> |
41 | |
42 | #ifndef INVALID_SET_FILE_POINTER |
43 | #define INVALID_SET_FILE_POINTER 0xFFFFFFFF |
44 | #endif |
45 | |
46 | #define READAHEAD_BUFFER_SIZE 1024 |
47 | |
48 | static int SDLCALL win32_file_open(SDL_RWops *context, const char *filename, const char *mode) |
49 | { |
50 | #ifndef _WIN32_WCE |
51 | UINT old_error_mode; |
52 | #endif |
53 | HANDLE h; |
54 | DWORD r_right, w_right; |
55 | DWORD must_exist, truncate; |
56 | int a_mode; |
57 | |
58 | if (!context) |
59 | return -1; /* failed (invalid call) */ |
60 | |
61 | context->hidden.win32io.h = INVALID_HANDLE_VALUE; /* mark this as unusable */ |
62 | context->hidden.win32io.buffer.data = NULL; |
63 | context->hidden.win32io.buffer.size = 0; |
64 | context->hidden.win32io.buffer.left = 0; |
65 | |
66 | /* "r" = reading, file must exist */ |
67 | /* "w" = writing, truncate existing, file may not exist */ |
68 | /* "r+"= reading or writing, file must exist */ |
69 | /* "a" = writing, append file may not exist */ |
70 | /* "a+"= append + read, file may not exist */ |
71 | /* "w+" = read, write, truncate. file may not exist */ |
72 | |
73 | must_exist = ( SDL_strchr(mode,'r') != NULL ) ? OPEN_EXISTING : 0; |
74 | truncate = ( SDL_strchr(mode,'w') != NULL ) ? CREATE_ALWAYS : 0; |
75 | r_right = ( SDL_strchr(mode,'+') != NULL || must_exist ) ? GENERIC_READ : 0; |
76 | a_mode = ( SDL_strchr(mode,'a') != NULL ) ? OPEN_ALWAYS : 0; |
77 | w_right = ( a_mode || SDL_strchr(mode,'+') || truncate ) ? GENERIC_WRITE : 0; |
78 | |
79 | if (!r_right && !w_right) /* inconsistent mode */ |
80 | return -1; /* failed (invalid call) */ |
81 | |
82 | context->hidden.win32io.buffer.data = (char *)SDL_malloc(READAHEAD_BUFFER_SIZE); |
83 | if (!context->hidden.win32io.buffer.data) { |
84 | SDL_OutOfMemory(); |
85 | return -1; |
86 | } |
87 | |
88 | #ifdef _WIN32_WCE |
89 | { |
90 | size_t size = SDL_strlen(filename)+1; |
91 | wchar_t *filenameW = SDL_stack_alloc(wchar_t, size); |
92 | |
93 | if ( MultiByteToWideChar(CP_UTF8, 0, filename, -1, filenameW, size) == 0 ) { |
94 | SDL_stack_free(filenameW); |
95 | SDL_free(context->hidden.win32io.buffer.data); |
96 | context->hidden.win32io.buffer.data = NULL; |
97 | SDL_SetError("Unable to convert filename to Unicode"); |
98 | return -1; |
99 | } |
100 | h = CreateFile(filenameW, (w_right|r_right), (w_right)? 0 : FILE_SHARE_READ, |
101 | NULL, (must_exist|truncate|a_mode), FILE_ATTRIBUTE_NORMAL,NULL); |
102 | SDL_stack_free(filenameW); |
103 | } |
104 | #else |
105 | { |
106 | |
107 | /* handle Unicode filenames. We do some tapdancing here to make sure this |
108 | works on Win9x, which doesn't support anything but 1-byte codepages. */ |
109 | const size_t size = SDL_strlen(filename)+1; |
110 | static int unicode_support = -1; |
111 | |
112 | if (unicode_support == -1) { |
113 | OSVERSIONINFO osVerInfo; /* Information about the OS */ |
114 | osVerInfo.dwOSVersionInfoSize = sizeof(osVerInfo); |
115 | if (!GetVersionEx(&osVerInfo)) { |
116 | unicode_support = 0; |
117 | } else if (osVerInfo.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS) { |
118 | unicode_support = 1; /* Not Win95/98/ME. */ |
119 | } else { |
120 | unicode_support = 0; |
121 | } |
122 | } |
123 | |
124 | if (unicode_support) { /* everything but Win95/98/ME. */ |
125 | wchar_t *filenameW = SDL_stack_alloc(wchar_t, size); |
126 | if ( MultiByteToWideChar(CP_UTF8, 0, filename, -1, filenameW, size) == 0 ) { |
127 | SDL_stack_free(filenameW); |
128 | SDL_free(context->hidden.win32io.buffer.data); |
129 | context->hidden.win32io.buffer.data = NULL; |
130 | SDL_SetError("Unable to convert filename to Unicode"); |
131 | return -1; |
132 | } |
133 | |
134 | /* Do not open a dialog box if failure */ |
135 | old_error_mode = SetErrorMode(SEM_NOOPENFILEERRORBOX|SEM_FAILCRITICALERRORS); |
136 | h = CreateFileW(filenameW, (w_right|r_right), (w_right)? 0 : FILE_SHARE_READ, |
137 | NULL, (must_exist|truncate|a_mode), FILE_ATTRIBUTE_NORMAL,NULL); |
138 | /* restore old behaviour */ |
139 | SetErrorMode(old_error_mode); |
140 | |
141 | SDL_stack_free(filenameW); |
142 | } else { |
143 | /* CP_UTF8 might not be supported (Win95), so use SDL_iconv to get wchars. */ |
144 | /* Use UCS2: no UTF-16 support here. Try again in SDL 1.3. :) */ |
145 | char *utf16 = SDL_iconv_string("UCS2", "UTF8", filename, SDL_strlen(filename) + 1); |
146 | char *filenameA = SDL_stack_alloc(char, size * 6); /* 6, just in case. */ |
147 | BOOL bDefCharUsed = FALSE; |
148 | |
149 | /* Dither down to a codepage and hope for the best. */ |
150 | if (!utf16 || |
151 | !WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)utf16, -1, filenameA, size*6, 0, &bDefCharUsed) || |
152 | bDefCharUsed) { |
153 | SDL_stack_free(filenameA); |
154 | SDL_free(utf16); |
155 | SDL_free(context->hidden.win32io.buffer.data); |
156 | context->hidden.win32io.buffer.data = NULL; |
157 | SDL_SetError("Unable to convert filename to Unicode"); |
158 | return -1; |
159 | } |
160 | |
161 | /* Do not open a dialog box if failure */ |
162 | old_error_mode = SetErrorMode(SEM_NOOPENFILEERRORBOX|SEM_FAILCRITICALERRORS); |
163 | h = CreateFile(filenameA, (w_right|r_right), (w_right)? 0 : FILE_SHARE_READ, |
164 | NULL, (must_exist|truncate|a_mode), FILE_ATTRIBUTE_NORMAL,NULL); |
165 | /* restore old behaviour */ |
166 | SetErrorMode(old_error_mode); |
167 | |
168 | SDL_stack_free(filenameA); |
169 | SDL_free(utf16); |
170 | } |
171 | |
172 | } |
173 | #endif /* _WIN32_WCE */ |
174 | |
175 | if (h==INVALID_HANDLE_VALUE) { |
176 | SDL_free(context->hidden.win32io.buffer.data); |
177 | context->hidden.win32io.buffer.data = NULL; |
178 | SDL_SetError("Couldn't open %s",filename); |
179 | return -2; /* failed (CreateFile) */ |
180 | } |
181 | context->hidden.win32io.h = h; |
182 | context->hidden.win32io.append = a_mode; |
183 | |
184 | return 0; /* ok */ |
185 | } |
186 | static int SDLCALL win32_file_seek(SDL_RWops *context, int offset, int whence) |
187 | { |
188 | DWORD win32whence; |
189 | int file_pos; |
190 | |
191 | if (!context || context->hidden.win32io.h == INVALID_HANDLE_VALUE) { |
192 | SDL_SetError("win32_file_seek: invalid context/file not opened"); |
193 | return -1; |
194 | } |
195 | |
196 | /* FIXME: We may be able to satisfy the seek within buffered data */ |
197 | if (whence == RW_SEEK_CUR && context->hidden.win32io.buffer.left) { |
198 | offset -= context->hidden.win32io.buffer.left; |
199 | } |
200 | context->hidden.win32io.buffer.left = 0; |
201 | |
202 | switch (whence) { |
203 | case RW_SEEK_SET: |
204 | win32whence = FILE_BEGIN; break; |
205 | case RW_SEEK_CUR: |
206 | win32whence = FILE_CURRENT; break; |
207 | case RW_SEEK_END: |
208 | win32whence = FILE_END; break; |
209 | default: |
210 | SDL_SetError("win32_file_seek: Unknown value for 'whence'"); |
211 | return -1; |
212 | } |
213 | |
214 | file_pos = SetFilePointer(context->hidden.win32io.h,offset,NULL,win32whence); |
215 | |
216 | if ( file_pos != INVALID_SET_FILE_POINTER ) |
217 | return file_pos; /* success */ |
218 | |
219 | SDL_Error(SDL_EFSEEK); |
220 | return -1; /* error */ |
221 | } |
222 | static int SDLCALL win32_file_read(SDL_RWops *context, void *ptr, int size, int maxnum) |
223 | { |
224 | int total_need; |
225 | int total_read = 0; |
226 | int read_ahead; |
227 | DWORD byte_read; |
228 | |
229 | total_need = size*maxnum; |
230 | |
231 | if (!context || context->hidden.win32io.h == INVALID_HANDLE_VALUE || total_need<=0 || !size) |
232 | return 0; |
233 | |
234 | if (context->hidden.win32io.buffer.left > 0) { |
235 | void *data = (char *)context->hidden.win32io.buffer.data + |
236 | context->hidden.win32io.buffer.size - |
237 | context->hidden.win32io.buffer.left; |
238 | read_ahead = SDL_min(total_need, context->hidden.win32io.buffer.left); |
239 | SDL_memcpy(ptr, data, read_ahead); |
240 | context->hidden.win32io.buffer.left -= read_ahead; |
241 | |
242 | if (read_ahead == total_need) { |
243 | return maxnum; |
244 | } |
245 | ptr = (char *)ptr + read_ahead; |
246 | total_need -= read_ahead; |
247 | total_read += read_ahead; |
248 | } |
249 | |
250 | if (total_need < READAHEAD_BUFFER_SIZE) { |
251 | if (!ReadFile(context->hidden.win32io.h,context->hidden.win32io.buffer.data,READAHEAD_BUFFER_SIZE,&byte_read,NULL)) { |
252 | SDL_Error(SDL_EFREAD); |
253 | return 0; |
254 | } |
255 | read_ahead = SDL_min(total_need, (int)byte_read); |
256 | SDL_memcpy(ptr, context->hidden.win32io.buffer.data, read_ahead); |
257 | context->hidden.win32io.buffer.size = byte_read; |
258 | context->hidden.win32io.buffer.left = byte_read-read_ahead; |
259 | total_read += read_ahead; |
260 | } else { |
261 | if (!ReadFile(context->hidden.win32io.h,ptr,total_need,&byte_read,NULL)) { |
262 | SDL_Error(SDL_EFREAD); |
263 | return 0; |
264 | } |
265 | total_read += byte_read; |
266 | } |
267 | return (total_read/size); |
268 | } |
269 | static int SDLCALL win32_file_write(SDL_RWops *context, const void *ptr, int size, int num) |
270 | { |
271 | |
272 | int total_bytes; |
273 | DWORD byte_written,nwritten; |
274 | |
275 | total_bytes = size*num; |
276 | |
277 | if (!context || context->hidden.win32io.h==INVALID_HANDLE_VALUE || total_bytes<=0 || !size) |
278 | return 0; |
279 | |
280 | if (context->hidden.win32io.buffer.left) { |
281 | SetFilePointer(context->hidden.win32io.h,-context->hidden.win32io.buffer.left,NULL,FILE_CURRENT); |
282 | context->hidden.win32io.buffer.left = 0; |
283 | } |
284 | |
285 | /* if in append mode, we must go to the EOF before write */ |
286 | if (context->hidden.win32io.append) { |
287 | if ( SetFilePointer(context->hidden.win32io.h,0L,NULL,FILE_END) == INVALID_SET_FILE_POINTER ) { |
288 | SDL_Error(SDL_EFWRITE); |
289 | return 0; |
290 | } |
291 | } |
292 | |
293 | if (!WriteFile(context->hidden.win32io.h,ptr,total_bytes,&byte_written,NULL)) { |
294 | SDL_Error(SDL_EFWRITE); |
295 | return 0; |
296 | } |
297 | |
298 | nwritten = byte_written/size; |
299 | return nwritten; |
300 | } |
301 | static int SDLCALL win32_file_close(SDL_RWops *context) |
302 | { |
303 | |
304 | if ( context ) { |
305 | if (context->hidden.win32io.h != INVALID_HANDLE_VALUE) { |
306 | CloseHandle(context->hidden.win32io.h); |
307 | context->hidden.win32io.h = INVALID_HANDLE_VALUE; /* to be sure */ |
308 | } |
309 | if (context->hidden.win32io.buffer.data) { |
310 | SDL_free(context->hidden.win32io.buffer.data); |
311 | context->hidden.win32io.buffer.data = NULL; |
312 | } |
313 | SDL_FreeRW(context); |
314 | } |
315 | return(0); |
316 | } |
317 | #endif /* __WIN32__ */ |
318 | |
319 | #ifdef HAVE_STDIO_H |
320 | |
321 | /* Functions to read/write stdio file pointers */ |
322 | |
323 | static int SDLCALL stdio_seek(SDL_RWops *context, int offset, int whence) |
324 | { |
325 | if ( fseek(context->hidden.stdio.fp, offset, whence) == 0 ) { |
326 | return(ftell(context->hidden.stdio.fp)); |
327 | } else { |
328 | SDL_Error(SDL_EFSEEK); |
329 | return(-1); |
330 | } |
331 | } |
332 | static int SDLCALL stdio_read(SDL_RWops *context, void *ptr, int size, int maxnum) |
333 | { |
334 | size_t nread; |
335 | |
336 | nread = fread(ptr, size, maxnum, context->hidden.stdio.fp); |
337 | if ( nread == 0 && ferror(context->hidden.stdio.fp) ) { |
338 | SDL_Error(SDL_EFREAD); |
339 | } |
340 | return(nread); |
341 | } |
342 | static int SDLCALL stdio_write(SDL_RWops *context, const void *ptr, int size, int num) |
343 | { |
344 | size_t nwrote; |
345 | |
346 | nwrote = fwrite(ptr, size, num, context->hidden.stdio.fp); |
347 | if ( nwrote == 0 && ferror(context->hidden.stdio.fp) ) { |
348 | SDL_Error(SDL_EFWRITE); |
349 | } |
350 | return(nwrote); |
351 | } |
352 | static int SDLCALL stdio_close(SDL_RWops *context) |
353 | { |
354 | if ( context ) { |
355 | if ( context->hidden.stdio.autoclose ) { |
356 | /* WARNING: Check the return value here! */ |
357 | fclose(context->hidden.stdio.fp); |
358 | } |
359 | SDL_FreeRW(context); |
360 | } |
361 | return(0); |
362 | } |
363 | #endif /* !HAVE_STDIO_H */ |
364 | |
365 | /* Functions to read/write memory pointers */ |
366 | |
367 | static int SDLCALL mem_seek(SDL_RWops *context, int offset, int whence) |
368 | { |
369 | Uint8 *newpos; |
370 | |
371 | switch (whence) { |
372 | case RW_SEEK_SET: |
373 | newpos = context->hidden.mem.base+offset; |
374 | break; |
375 | case RW_SEEK_CUR: |
376 | newpos = context->hidden.mem.here+offset; |
377 | break; |
378 | case RW_SEEK_END: |
379 | newpos = context->hidden.mem.stop+offset; |
380 | break; |
381 | default: |
382 | SDL_SetError("Unknown value for 'whence'"); |
383 | return(-1); |
384 | } |
385 | if ( newpos < context->hidden.mem.base ) { |
386 | newpos = context->hidden.mem.base; |
387 | } |
388 | if ( newpos > context->hidden.mem.stop ) { |
389 | newpos = context->hidden.mem.stop; |
390 | } |
391 | context->hidden.mem.here = newpos; |
392 | return(context->hidden.mem.here-context->hidden.mem.base); |
393 | } |
394 | static int SDLCALL mem_read(SDL_RWops *context, void *ptr, int size, int maxnum) |
395 | { |
396 | size_t total_bytes; |
397 | size_t mem_available; |
398 | |
399 | total_bytes = (maxnum * size); |
400 | if ( (maxnum <= 0) || (size <= 0) || ((total_bytes / maxnum) != (size_t) size) ) { |
401 | return 0; |
402 | } |
403 | |
404 | mem_available = (context->hidden.mem.stop - context->hidden.mem.here); |
405 | if (total_bytes > mem_available) { |
406 | total_bytes = mem_available; |
407 | } |
408 | |
409 | SDL_memcpy(ptr, context->hidden.mem.here, total_bytes); |
410 | context->hidden.mem.here += total_bytes; |
411 | |
412 | return (total_bytes / size); |
413 | } |
414 | static int SDLCALL mem_write(SDL_RWops *context, const void *ptr, int size, int num) |
415 | { |
416 | if ( (context->hidden.mem.here + (num*size)) > context->hidden.mem.stop ) { |
417 | num = (context->hidden.mem.stop-context->hidden.mem.here)/size; |
418 | } |
419 | SDL_memcpy(context->hidden.mem.here, ptr, num*size); |
420 | context->hidden.mem.here += num*size; |
421 | return(num); |
422 | } |
423 | static int SDLCALL mem_writeconst(SDL_RWops *context, const void *ptr, int size, int num) |
424 | { |
425 | SDL_SetError("Can't write to read-only memory"); |
426 | return(-1); |
427 | } |
428 | static int SDLCALL mem_close(SDL_RWops *context) |
429 | { |
430 | if ( context ) { |
431 | SDL_FreeRW(context); |
432 | } |
433 | return(0); |
434 | } |
435 | |
436 | |
437 | /* Functions to create SDL_RWops structures from various data sources */ |
438 | |
439 | #ifdef __MACOS__ |
440 | /* |
441 | * translate unix-style slash-separated filename to mac-style colon-separated |
442 | * name; return malloced string |
443 | */ |
444 | static char *unix_to_mac(const char *file) |
445 | { |
446 | int flen = SDL_strlen(file); |
447 | char *path = SDL_malloc(flen + 2); |
448 | const char *src = file; |
449 | char *dst = path; |
450 | if(*src == '/') { |
451 | /* really depends on filesystem layout, hope for the best */ |
452 | src++; |
453 | } else { |
454 | /* Check if this is a MacOS path to begin with */ |
455 | if(*src != ':') |
456 | *dst++ = ':'; /* relative paths begin with ':' */ |
457 | } |
458 | while(src < file + flen) { |
459 | const char *end = SDL_strchr(src, '/'); |
460 | int len; |
461 | if(!end) |
462 | end = file + flen; /* last component */ |
463 | len = end - src; |
464 | if(len == 0 || (len == 1 && src[0] == '.')) { |
465 | /* remove repeated slashes and . */ |
466 | } else { |
467 | if(len == 2 && src[0] == '.' && src[1] == '.') { |
468 | /* replace .. with the empty string */ |
469 | } else { |
470 | SDL_memcpy(dst, src, len); |
471 | dst += len; |
472 | } |
473 | if(end < file + flen) |
474 | *dst++ = ':'; |
475 | } |
476 | src = end + 1; |
477 | } |
478 | *dst++ = '\0'; |
479 | return path; |
480 | } |
481 | #endif /* __MACOS__ */ |
482 | |
483 | SDL_RWops *SDL_RWFromFile(const char *file, const char *mode) |
484 | { |
485 | SDL_RWops *rwops = NULL; |
486 | #ifdef HAVE_STDIO_H |
487 | FILE *fp = NULL; |
488 | #endif |
489 | if ( !file || !*file || !mode || !*mode ) { |
490 | SDL_SetError("SDL_RWFromFile(): No file or no mode specified"); |
491 | return NULL; |
492 | } |
493 | |
494 | #if defined(__WIN32__) && !defined(__SYMBIAN32__) |
495 | rwops = SDL_AllocRW(); |
496 | if (!rwops) |
497 | return NULL; /* SDL_SetError already setup by SDL_AllocRW() */ |
498 | if (win32_file_open(rwops,file,mode) < 0) { |
499 | SDL_FreeRW(rwops); |
500 | return NULL; |
501 | } |
502 | rwops->seek = win32_file_seek; |
503 | rwops->read = win32_file_read; |
504 | rwops->write = win32_file_write; |
505 | rwops->close = win32_file_close; |
506 | |
507 | #elif HAVE_STDIO_H |
508 | |
509 | #ifdef __MACOS__ |
510 | { |
511 | char *mpath = unix_to_mac(file); |
512 | fp = fopen(mpath, mode); |
513 | SDL_free(mpath); |
514 | } |
515 | #else |
516 | fp = fopen(file, mode); |
517 | #endif |
518 | if ( fp == NULL ) { |
519 | SDL_SetError("Couldn't open %s", file); |
520 | } else { |
521 | rwops = SDL_RWFromFP(fp, 1); |
522 | } |
523 | #else |
524 | SDL_SetError("SDL not compiled with stdio support"); |
525 | #endif /* !HAVE_STDIO_H */ |
526 | |
527 | return(rwops); |
528 | } |
529 | |
530 | #ifdef HAVE_STDIO_H |
531 | SDL_RWops *SDL_RWFromFP(FILE *fp, int autoclose) |
532 | { |
533 | SDL_RWops *rwops = NULL; |
534 | |
535 | rwops = SDL_AllocRW(); |
536 | if ( rwops != NULL ) { |
537 | rwops->seek = stdio_seek; |
538 | rwops->read = stdio_read; |
539 | rwops->write = stdio_write; |
540 | rwops->close = stdio_close; |
541 | rwops->hidden.stdio.fp = fp; |
542 | rwops->hidden.stdio.autoclose = autoclose; |
543 | } |
544 | return(rwops); |
545 | } |
546 | #endif /* HAVE_STDIO_H */ |
547 | |
548 | SDL_RWops *SDL_RWFromMem(void *mem, int size) |
549 | { |
550 | SDL_RWops *rwops; |
551 | |
552 | rwops = SDL_AllocRW(); |
553 | if ( rwops != NULL ) { |
554 | rwops->seek = mem_seek; |
555 | rwops->read = mem_read; |
556 | rwops->write = mem_write; |
557 | rwops->close = mem_close; |
558 | rwops->hidden.mem.base = (Uint8 *)mem; |
559 | rwops->hidden.mem.here = rwops->hidden.mem.base; |
560 | rwops->hidden.mem.stop = rwops->hidden.mem.base+size; |
561 | } |
562 | return(rwops); |
563 | } |
564 | |
565 | SDL_RWops *SDL_RWFromConstMem(const void *mem, int size) |
566 | { |
567 | SDL_RWops *rwops; |
568 | |
569 | rwops = SDL_AllocRW(); |
570 | if ( rwops != NULL ) { |
571 | rwops->seek = mem_seek; |
572 | rwops->read = mem_read; |
573 | rwops->write = mem_writeconst; |
574 | rwops->close = mem_close; |
575 | rwops->hidden.mem.base = (Uint8 *)mem; |
576 | rwops->hidden.mem.here = rwops->hidden.mem.base; |
577 | rwops->hidden.mem.stop = rwops->hidden.mem.base+size; |
578 | } |
579 | return(rwops); |
580 | } |
581 | |
582 | SDL_RWops *SDL_AllocRW(void) |
583 | { |
584 | SDL_RWops *area; |
585 | |
586 | area = (SDL_RWops *)SDL_malloc(sizeof *area); |
587 | if ( area == NULL ) { |
588 | SDL_OutOfMemory(); |
589 | } |
590 | return(area); |
591 | } |
592 | |
593 | void SDL_FreeRW(SDL_RWops *area) |
594 | { |
595 | SDL_free(area); |
596 | } |
597 | |
598 | /* Functions for dynamically reading and writing endian-specific values */ |
599 | |
600 | Uint16 SDL_ReadLE16 (SDL_RWops *src) |
601 | { |
602 | Uint16 value; |
603 | |
604 | SDL_RWread(src, &value, (sizeof value), 1); |
605 | return(SDL_SwapLE16(value)); |
606 | } |
607 | Uint16 SDL_ReadBE16 (SDL_RWops *src) |
608 | { |
609 | Uint16 value; |
610 | |
611 | SDL_RWread(src, &value, (sizeof value), 1); |
612 | return(SDL_SwapBE16(value)); |
613 | } |
614 | Uint32 SDL_ReadLE32 (SDL_RWops *src) |
615 | { |
616 | Uint32 value; |
617 | |
618 | SDL_RWread(src, &value, (sizeof value), 1); |
619 | return(SDL_SwapLE32(value)); |
620 | } |
621 | Uint32 SDL_ReadBE32 (SDL_RWops *src) |
622 | { |
623 | Uint32 value; |
624 | |
625 | SDL_RWread(src, &value, (sizeof value), 1); |
626 | return(SDL_SwapBE32(value)); |
627 | } |
628 | Uint64 SDL_ReadLE64 (SDL_RWops *src) |
629 | { |
630 | Uint64 value; |
631 | |
632 | SDL_RWread(src, &value, (sizeof value), 1); |
633 | return(SDL_SwapLE64(value)); |
634 | } |
635 | Uint64 SDL_ReadBE64 (SDL_RWops *src) |
636 | { |
637 | Uint64 value; |
638 | |
639 | SDL_RWread(src, &value, (sizeof value), 1); |
640 | return(SDL_SwapBE64(value)); |
641 | } |
642 | |
643 | int SDL_WriteLE16 (SDL_RWops *dst, Uint16 value) |
644 | { |
645 | value = SDL_SwapLE16(value); |
646 | return(SDL_RWwrite(dst, &value, (sizeof value), 1)); |
647 | } |
648 | int SDL_WriteBE16 (SDL_RWops *dst, Uint16 value) |
649 | { |
650 | value = SDL_SwapBE16(value); |
651 | return(SDL_RWwrite(dst, &value, (sizeof value), 1)); |
652 | } |
653 | int SDL_WriteLE32 (SDL_RWops *dst, Uint32 value) |
654 | { |
655 | value = SDL_SwapLE32(value); |
656 | return(SDL_RWwrite(dst, &value, (sizeof value), 1)); |
657 | } |
658 | int SDL_WriteBE32 (SDL_RWops *dst, Uint32 value) |
659 | { |
660 | value = SDL_SwapBE32(value); |
661 | return(SDL_RWwrite(dst, &value, (sizeof value), 1)); |
662 | } |
663 | int SDL_WriteLE64 (SDL_RWops *dst, Uint64 value) |
664 | { |
665 | value = SDL_SwapLE64(value); |
666 | return(SDL_RWwrite(dst, &value, (sizeof value), 1)); |
667 | } |
668 | int SDL_WriteBE64 (SDL_RWops *dst, Uint64 value) |
669 | { |
670 | value = SDL_SwapBE64(value); |
671 | return(SDL_RWwrite(dst, &value, (sizeof value), 1)); |
672 | } |