src/file/SDL_rwops.c

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. stdio_seek
  2. stdio_read
  3. stdio_write
  4. stdio_close
  5. mem_seek
  6. mem_read
  7. mem_write
  8. mem_close
  9. unix_to_mac
  10. SDL_RWFromFile
  11. SDL_RWFromFP
  12. SDL_RWFromMem
  13. SDL_AllocRW
  14. SDL_FreeRW

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

/* [<][>][^][v][top][bottom][index][help] */