SDL_rwops.c
上传用户:sun1608
上传日期:2007-02-02
资源大小:6116k
文件大小:7k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  1. /*
  2.     SDL - Simple DirectMedia Layer
  3.     Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002  Sam Lantinga
  4.     This library is free software; you can redistribute it and/or
  5.     modify it under the terms of the GNU Library General Public
  6.     License as published by the Free Software Foundation; either
  7.     version 2 of the License, or (at your option) any later version.
  8.     This library is distributed in the hope that it will be useful,
  9.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  11.     Library General Public License for more details.
  12.     You should have received a copy of the GNU Library General Public
  13.     License along with this library; if not, write to the Free
  14.     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  15.     Sam Lantinga
  16.     slouken@libsdl.org
  17. */
  18. #ifdef SAVE_RCSID
  19. static char rcsid =
  20.  "@(#) $Id: SDL_rwops.c,v 1.4 2002/04/22 21:38:02 wmay Exp $";
  21. #endif
  22. /* This file provides a general interface for SDL to read and write
  23.    data sources.  It can easily be extended to files, memory, etc.
  24. */
  25. #include <stdlib.h>
  26. #include <stdio.h>
  27. #include <string.h>
  28. #include "SDL_error.h"
  29. #include "SDL_rwops.h"
  30. /* Functions to read/write stdio file pointers */
  31. static int stdio_seek(SDL_RWops *context, int offset, int whence)
  32. {
  33. if ( fseek(context->hidden.stdio.fp, offset, whence) == 0 ) {
  34. return(ftell(context->hidden.stdio.fp));
  35. } else {
  36. SDL_Error(SDL_EFSEEK);
  37. return(-1);
  38. }
  39. }
  40. static int stdio_read(SDL_RWops *context, void *ptr, int size, int maxnum)
  41. {
  42. size_t nread;
  43. nread = fread(ptr, size, maxnum, context->hidden.stdio.fp); 
  44. if ( nread == 0 && ferror(context->hidden.stdio.fp) ) {
  45. SDL_Error(SDL_EFREAD);
  46. }
  47. return(nread);
  48. }
  49. static int stdio_write(SDL_RWops *context, const void *ptr, int size, int num)
  50. {
  51. size_t nwrote;
  52. nwrote = fwrite(ptr, size, num, context->hidden.stdio.fp);
  53. if ( nwrote == 0 && ferror(context->hidden.stdio.fp) ) {
  54. SDL_Error(SDL_EFWRITE);
  55. }
  56. return(nwrote);
  57. }
  58. static int stdio_close(SDL_RWops *context)
  59. {
  60. if ( context ) {
  61. if ( context->hidden.stdio.autoclose ) {
  62. /* WARNING:  Check the return value here! */
  63. fclose(context->hidden.stdio.fp);
  64. }
  65. free(context);
  66. }
  67. return(0);
  68. }
  69. /* Functions to read/write memory pointers */
  70. static int mem_seek(SDL_RWops *context, int offset, int whence)
  71. {
  72. Uint8 *newpos;
  73. switch (whence) {
  74. case SEEK_SET:
  75. newpos = context->hidden.mem.base+offset;
  76. break;
  77. case SEEK_CUR:
  78. newpos = context->hidden.mem.here+offset;
  79. break;
  80. case SEEK_END:
  81. newpos = context->hidden.mem.stop+offset;
  82. break;
  83. default:
  84. SDL_SetError("Unknown value for 'whence'");
  85. return(-1);
  86. }
  87. if ( newpos < context->hidden.mem.base ) {
  88. newpos = context->hidden.mem.base;
  89. }
  90. if ( newpos > context->hidden.mem.stop ) {
  91. newpos = context->hidden.mem.stop;
  92. }
  93. context->hidden.mem.here = newpos;
  94. return(context->hidden.mem.here-context->hidden.mem.base);
  95. }
  96. static int mem_read(SDL_RWops *context, void *ptr, int size, int maxnum)
  97. {
  98. int num;
  99. num = maxnum;
  100. if ( (context->hidden.mem.here + (num*size)) > context->hidden.mem.stop ) {
  101. num = (context->hidden.mem.stop-context->hidden.mem.here)/size;
  102. }
  103. memcpy(ptr, context->hidden.mem.here, num*size);
  104. context->hidden.mem.here += num*size;
  105. return(num);
  106. }
  107. static int mem_write(SDL_RWops *context, const void *ptr, int size, int num)
  108. {
  109. if ( (context->hidden.mem.here + (num*size)) > context->hidden.mem.stop ) {
  110. num = (context->hidden.mem.stop-context->hidden.mem.here)/size;
  111. }
  112. memcpy(context->hidden.mem.here, ptr, num*size);
  113. context->hidden.mem.here += num*size;
  114. return(num);
  115. }
  116. static int mem_close(SDL_RWops *context)
  117. {
  118. if ( context ) {
  119. free(context);
  120. }
  121. return(0);
  122. }
  123. /* Functions to create SDL_RWops structures from various data sources */
  124. #ifdef WIN32
  125. /* Aggh.  You can't (apparently) open a file in an application and
  126.    read from it in a DLL.
  127. */
  128. static int in_sdl = 0;
  129. #endif
  130. #ifdef macintosh
  131. /*
  132.  * translate unix-style slash-separated filename to mac-style colon-separated
  133.  * name; return malloced string
  134.  */
  135. static char *unix_to_mac(const char *file)
  136. {
  137. int flen = strlen(file);
  138. char *path = malloc(flen + 2);
  139. const char *src = file;
  140. char *dst = path;
  141. if(*src == '/') {
  142. /* really depends on filesystem layout, hope for the best */
  143. src++;
  144. } else {
  145. /* Check if this is a MacOS path to begin with */
  146. if(*src != ':')
  147. *dst++ = ':';   /* relative paths begin with ':' */
  148. }
  149. while(src < file + flen) {
  150. const char *end = strchr(src, '/');
  151. int len;
  152. if(!end)
  153. end = file + flen; /* last component */
  154. len = end - src;
  155. if(len == 0 || (len == 1 && src[0] == '.')) {
  156. /* remove repeated slashes and . */
  157. } else {
  158. if(len == 2 && src[0] == '.' && src[1] == '.') {
  159. /* replace .. with the empty string */
  160. } else {
  161. memcpy(dst, src, len);
  162. dst += len;
  163. }
  164. if(end < file + flen)
  165. *dst++ = ':';
  166. }
  167. src = end + 1;
  168. }
  169. *dst++ = '';
  170. return path;
  171. }
  172. #endif /* macintosh */
  173. SDL_RWops *SDL_RWFromFile(const char *file, const char *mode)
  174. {
  175. FILE *fp;
  176. SDL_RWops *rwops;
  177. rwops = NULL;
  178. #ifdef macintosh
  179. {
  180. char *mpath = unix_to_mac(file);
  181. fp = fopen(mpath, mode);
  182. free(mpath);
  183. }
  184. #else
  185. fp = fopen(file, mode);
  186. #endif
  187. if ( fp == NULL ) {
  188. SDL_SetError("Couldn't open %s", file);
  189. } else {
  190. #ifdef WIN32
  191. in_sdl = 1;
  192. rwops = SDL_RWFromFP(fp, 1);
  193. in_sdl = 0;
  194. #else
  195. rwops = SDL_RWFromFP(fp, 1);
  196. #endif
  197. }
  198. return(rwops);
  199. }
  200. SDL_RWops *SDL_RWFromFP(FILE *fp, int autoclose)
  201. {
  202. SDL_RWops *rwops;
  203. #ifdef WIN32
  204. if ( ! in_sdl ) {
  205. SDL_SetError("You can't pass a FILE pointer to a DLL (??)");
  206. /*return(NULL);*/
  207. }
  208. #endif
  209. rwops = SDL_AllocRW();
  210. if ( rwops != NULL ) {
  211. rwops->seek = stdio_seek;
  212. rwops->read = stdio_read;
  213. rwops->write = stdio_write;
  214. rwops->close = stdio_close;
  215. rwops->hidden.stdio.fp = fp;
  216. rwops->hidden.stdio.autoclose = autoclose;
  217. }
  218. return(rwops);
  219. }
  220. SDL_RWops *SDL_RWFromMem(void *mem, int size)
  221. {
  222. SDL_RWops *rwops;
  223. rwops = SDL_AllocRW();
  224. if ( rwops != NULL ) {
  225. rwops->seek = mem_seek;
  226. rwops->read = mem_read;
  227. rwops->write = mem_write;
  228. rwops->close = mem_close;
  229. rwops->hidden.mem.base = (Uint8 *)mem;
  230. rwops->hidden.mem.here = rwops->hidden.mem.base;
  231. rwops->hidden.mem.stop = rwops->hidden.mem.base+size;
  232. }
  233. return(rwops);
  234. }
  235. SDL_RWops *SDL_AllocRW(void)
  236. {
  237. SDL_RWops *area;
  238. area = (SDL_RWops *)malloc(sizeof *area);
  239. if ( area == NULL ) {
  240. SDL_OutOfMemory();
  241. }
  242. return(area);
  243. }
  244. void SDL_FreeRW(SDL_RWops *area)
  245. {
  246. free(area);
  247. }