Mercurial > sdl-ios-xcode
diff src/file/SDL_rwops.c @ 0:74212992fb08
Initial revision
author | Sam Lantinga <slouken@lokigames.com> |
---|---|
date | Thu, 26 Apr 2001 16:45:43 +0000 |
parents | |
children | 13ee9f4834ea |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/file/SDL_rwops.c Thu Apr 26 16:45:43 2001 +0000 @@ -0,0 +1,274 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@devolution.com +*/ + +#ifdef SAVE_RCSID +static char rcsid = + "@(#) $Id$"; +#endif + +/* This file provides a general interface for SDL to read and write + data sources. It can easily be extended to files, memory, etc. +*/ + +#include <stdlib.h> +#include <string.h> + +#include "SDL_error.h" +#include "SDL_rwops.h" + +/* Functions to read/write stdio file pointers */ + +static int stdio_seek(SDL_RWops *context, int offset, int whence) +{ + if ( fseek(context->hidden.stdio.fp, offset, whence) == 0 ) { + return(ftell(context->hidden.stdio.fp)); + } else { + SDL_Error(SDL_EFSEEK); + return(-1); + } +} +static int stdio_read(SDL_RWops *context, void *ptr, int size, int maxnum) +{ + size_t nread; + + nread = fread(ptr, size, maxnum, context->hidden.stdio.fp); + if ( nread == 0 && ferror(context->hidden.stdio.fp) ) { + SDL_Error(SDL_EFREAD); + } + return(nread); +} +static int stdio_write(SDL_RWops *context, const void *ptr, int size, int num) +{ + size_t nwrote; + + nwrote = fwrite(ptr, size, num, context->hidden.stdio.fp); + if ( nwrote == 0 && ferror(context->hidden.stdio.fp) ) { + SDL_Error(SDL_EFWRITE); + } + return(nwrote); +} +static int stdio_close(SDL_RWops *context) +{ + if ( context ) { + if ( context->hidden.stdio.autoclose ) { + /* WARNING: Check the return value here! */ + fclose(context->hidden.stdio.fp); + } + free(context); + } + return(0); +} + +/* Functions to read/write memory pointers */ + +static int mem_seek(SDL_RWops *context, int offset, int whence) +{ + Uint8 *newpos; + + switch (whence) { + case SEEK_SET: + newpos = context->hidden.mem.base+offset; + break; + case SEEK_CUR: + newpos = context->hidden.mem.here+offset; + break; + case SEEK_END: + newpos = context->hidden.mem.stop+offset; + break; + default: + SDL_SetError("Unknown value for 'whence'"); + return(-1); + } + if ( newpos < context->hidden.mem.base ) { + newpos = context->hidden.mem.base; + } + if ( newpos > context->hidden.mem.stop ) { + newpos = context->hidden.mem.stop; + } + context->hidden.mem.here = newpos; + return(context->hidden.mem.here-context->hidden.mem.base); +} +static int mem_read(SDL_RWops *context, void *ptr, int size, int maxnum) +{ + int num; + + num = maxnum; + if ( (context->hidden.mem.here + (num*size)) > context->hidden.mem.stop ) { + num = (context->hidden.mem.stop-context->hidden.mem.here)/size; + } + memcpy(ptr, context->hidden.mem.here, num*size); + context->hidden.mem.here += num*size; + return(num); +} +static int mem_write(SDL_RWops *context, const void *ptr, int size, int num) +{ + if ( (context->hidden.mem.here + (num*size)) > context->hidden.mem.stop ) { + num = (context->hidden.mem.stop-context->hidden.mem.here)/size; + } + memcpy(context->hidden.mem.here, ptr, num*size); + context->hidden.mem.here += num*size; + return(num); +} +static int mem_close(SDL_RWops *context) +{ + if ( context ) { + free(context); + } + return(0); +} + +/* Functions to create SDL_RWops structures from various data sources */ +#ifdef WIN32 +/* Aggh. You can't (apparently) open a file in an application and + read from it in a DLL. +*/ +static int in_sdl = 0; +#endif + +#ifdef macintosh +/* + * translate unix-style slash-separated filename to mac-style colon-separated + * name; return malloced string + */ +static char *unix_to_mac(const char *file) +{ + int flen = strlen(file); + char *path = malloc(flen + 2); + const char *src = file; + char *dst = path; + if(*src == '/') { + /* really depends on filesystem layout, hope for the best */ + src++; + } else { + /* Check if this is a MacOS path to begin with */ + if(*src != ':') + *dst++ = ':'; /* relative paths begin with ':' */ + } + while(src < file + flen) { + const char *end = strchr(src, '/'); + int len; + if(!end) + end = file + flen; /* last component */ + len = end - src; + if(len == 0 || (len == 1 && src[0] == '.')) { + /* remove repeated slashes and . */ + } else { + if(len == 2 && src[0] == '.' && src[1] == '.') { + /* replace .. with the empty string */ + } else { + memcpy(dst, src, len); + dst += len; + } + if(end < file + flen) + *dst++ = ':'; + } + src = end + 1; + } + *dst++ = '\0'; + return path; +} +#endif /* macintosh */ + +SDL_RWops *SDL_RWFromFile(const char *file, const char *mode) +{ + FILE *fp; + SDL_RWops *rwops; + + rwops = NULL; + +#ifdef macintosh + { + char *mpath = unix_to_mac(file); + fp = fopen(mpath, mode); + free(mpath); + } +#else + fp = fopen(file, mode); +#endif + if ( fp == NULL ) { + SDL_SetError("Couldn't open %s", file); + } else { +#ifdef WIN32 + in_sdl = 1; + rwops = SDL_RWFromFP(fp, 1); + in_sdl = 0; +#else + rwops = SDL_RWFromFP(fp, 1); +#endif + } + return(rwops); +} + +SDL_RWops *SDL_RWFromFP(FILE *fp, int autoclose) +{ + SDL_RWops *rwops; + +#ifdef WIN32 + if ( ! in_sdl ) { + SDL_SetError("You can't pass a FILE pointer to a DLL (??)"); + /*return(NULL);*/ + } +#endif + rwops = SDL_AllocRW(); + if ( rwops != NULL ) { + rwops->seek = stdio_seek; + rwops->read = stdio_read; + rwops->write = stdio_write; + rwops->close = stdio_close; + rwops->hidden.stdio.fp = fp; + rwops->hidden.stdio.autoclose = autoclose; + } + return(rwops); +} + +SDL_RWops *SDL_RWFromMem(void *mem, int size) +{ + SDL_RWops *rwops; + + rwops = SDL_AllocRW(); + if ( rwops != NULL ) { + rwops->seek = mem_seek; + rwops->read = mem_read; + rwops->write = mem_write; + rwops->close = mem_close; + rwops->hidden.mem.base = (Uint8 *)mem; + rwops->hidden.mem.here = rwops->hidden.mem.base; + rwops->hidden.mem.stop = rwops->hidden.mem.base+size; + } + return(rwops); +} + +SDL_RWops *SDL_AllocRW(void) +{ + SDL_RWops *area; + + area = (SDL_RWops *)malloc(sizeof *area); + if ( area == NULL ) { + SDL_OutOfMemory(); + } + return(area); +} + +void SDL_FreeRW(SDL_RWops *area) +{ + free(area); +}