src/file/SDL_rwops.c
changeset 8337 4a67a3cca43d
parent 8317 4eec049a8b7c
parent 6644 eacc8b228cef
child 8340 e470405f3ae9
     1.1 --- a/src/file/SDL_rwops.c	Sun Nov 04 09:02:58 2012 -0500
     1.2 +++ b/src/file/SDL_rwops.c	Sun Nov 04 09:46:59 2012 -0500
     1.3 @@ -18,6 +18,8 @@
     1.4       misrepresented as being the original software.
     1.5    3. This notice may not be removed or altered from any source distribution.
     1.6  */
     1.7 +/* Need this so Linux systems define fseek64o, ftell64o and off64_t */
     1.8 +#define _LARGEFILE64_SOURCE
     1.9  #include "SDL_config.h"
    1.10  
    1.11  /* This file provides a general interface for SDL to read and write
    1.12 @@ -121,11 +123,29 @@
    1.13      return 0;                   /* ok */
    1.14  }
    1.15  
    1.16 -static long SDLCALL
    1.17 -windows_file_seek(SDL_RWops * context, long offset, int whence)
    1.18 +static Sint64 SDLCALL
    1.19 +windows_file_size(SDL_RWops * context)
    1.20 +{
    1.21 +    LARGE_INTEGER size;
    1.22 +
    1.23 +    if (!context || context->hidden.windowsio.h == INVALID_HANDLE_VALUE) {
    1.24 +        SDL_SetError("windows_file_size: invalid context/file not opened");
    1.25 +        return -1;
    1.26 +    }
    1.27 +
    1.28 +    if (!GetFileSizeEx(context->hidden.windowsio.h, &size)) {
    1.29 +        WIN_SetError("windows_file_size");
    1.30 +        return -1;
    1.31 +    }
    1.32 +
    1.33 +    return size.QuadPart;
    1.34 +}
    1.35 +
    1.36 +static Sint64 SDLCALL
    1.37 +windows_file_seek(SDL_RWops * context, Sint64 offset, int whence)
    1.38  {
    1.39      DWORD windowswhence;
    1.40 -    long file_pos;
    1.41 +    LARGE_INTEGER windowsoffset;
    1.42  
    1.43      if (!context || context->hidden.windowsio.h == INVALID_HANDLE_VALUE) {
    1.44          SDL_SetError("windows_file_seek: invalid context/file not opened");
    1.45 @@ -153,14 +173,12 @@
    1.46          return -1;
    1.47      }
    1.48  
    1.49 -    file_pos =
    1.50 -        SetFilePointer(context->hidden.windowsio.h, offset, NULL, windowswhence);
    1.51 -
    1.52 -    if (file_pos != INVALID_SET_FILE_POINTER)
    1.53 -        return file_pos;        /* success */
    1.54 -
    1.55 -    SDL_Error(SDL_EFSEEK);
    1.56 -    return -1;                  /* error */
    1.57 +    windowsoffset.QuadPart = offset;
    1.58 +    if (!SetFilePointerEx(context->hidden.windowsio.h, windowsoffset, &windowsoffset, windowswhence)) {
    1.59 +        WIN_SetError("windows_file_seek");
    1.60 +        return -1;
    1.61 +    }
    1.62 +    return windowsoffset.QuadPart;
    1.63  }
    1.64  
    1.65  static size_t SDLCALL
    1.66 @@ -281,15 +299,39 @@
    1.67  
    1.68  /* Functions to read/write stdio file pointers */
    1.69  
    1.70 -static long SDLCALL
    1.71 -stdio_seek(SDL_RWops * context, long offset, int whence)
    1.72 +static Sint64 SDLCALL
    1.73 +stdio_size(SDL_RWops * context)
    1.74  {
    1.75 +    Sint64 pos, size;
    1.76 +
    1.77 +    pos = SDL_RWseek(context, 0, RW_SEEK_CUR);
    1.78 +    if (pos < 0) {
    1.79 +        return -1;
    1.80 +    }
    1.81 +    size = SDL_RWseek(context, 0, RW_SEEK_END);
    1.82 +
    1.83 +    SDL_RWseek(context, pos, RW_SEEK_SET);
    1.84 +    return size;
    1.85 +}
    1.86 +
    1.87 +static Sint64 SDLCALL
    1.88 +stdio_seek(SDL_RWops * context, Sint64 offset, int whence)
    1.89 +{
    1.90 +#ifdef HAVE_FSEEKO64
    1.91 +    if (fseeko64(context->hidden.stdio.fp, (off64_t)offset, whence) == 0) {
    1.92 +        return ftello64(context->hidden.stdio.fp);
    1.93 +    }
    1.94 +#elif defined(HAVE_FSEEKO)
    1.95 +    if (fseeko(context->hidden.stdio.fp, (off_t)offset, whence) == 0) {
    1.96 +        return ftello(context->hidden.stdio.fp);
    1.97 +    }
    1.98 +#else
    1.99      if (fseek(context->hidden.stdio.fp, offset, whence) == 0) {
   1.100          return (ftell(context->hidden.stdio.fp));
   1.101 -    } else {
   1.102 -        SDL_Error(SDL_EFSEEK);
   1.103 -        return (-1);
   1.104      }
   1.105 +#endif
   1.106 +    SDL_Error(SDL_EFSEEK);
   1.107 +    return (-1);
   1.108  }
   1.109  
   1.110  static size_t SDLCALL
   1.111 @@ -336,8 +378,14 @@
   1.112  
   1.113  /* Functions to read/write memory pointers */
   1.114  
   1.115 -static long SDLCALL
   1.116 -mem_seek(SDL_RWops * context, long offset, int whence)
   1.117 +static Sint64 SDLCALL
   1.118 +mem_size(SDL_RWops * context)
   1.119 +{
   1.120 +    return (Sint64)(context->hidden.mem.stop - context->hidden.mem.base);
   1.121 +}
   1.122 +
   1.123 +static Sint64 SDLCALL
   1.124 +mem_seek(SDL_RWops * context, Sint64 offset, int whence)
   1.125  {
   1.126      Uint8 *newpos;
   1.127  
   1.128 @@ -362,7 +410,7 @@
   1.129          newpos = context->hidden.mem.stop;
   1.130      }
   1.131      context->hidden.mem.here = newpos;
   1.132 -    return (long)(context->hidden.mem.here - context->hidden.mem.base);
   1.133 +    return (Sint64)(context->hidden.mem.here - context->hidden.mem.base);
   1.134  }
   1.135  
   1.136  static size_t SDLCALL
   1.137 @@ -427,6 +475,32 @@
   1.138          return NULL;
   1.139      }
   1.140  #if defined(ANDROID)
   1.141 +#ifdef HAVE_STDIO_H
   1.142 +    /* Try to open the file on the filesystem first */
   1.143 +    if (*file == '/') {
   1.144 +        FILE *fp = fopen(file, mode);
   1.145 +        if (fp) {
   1.146 +            return SDL_RWFromFP(fp, 1);
   1.147 +        }
   1.148 +    } else {
   1.149 +        /* Try opening it from internal storage if it's a relative path */
   1.150 +        char *path;
   1.151 +        FILE *fp;
   1.152 +
   1.153 +        path = SDL_stack_alloc(char, PATH_MAX);
   1.154 +        if (path) {
   1.155 +            SDL_snprintf(path, PATH_MAX, "%s/%s",
   1.156 +                         SDL_AndroidGetInternalStoragePath(), file);
   1.157 +            fp = fopen(path, mode);
   1.158 +            SDL_stack_free(path);
   1.159 +            if (fp) {
   1.160 +                return SDL_RWFromFP(fp, 1);
   1.161 +            }
   1.162 +        }
   1.163 +    }
   1.164 +#endif /* HAVE_STDIO_H */
   1.165 +
   1.166 +    /* Try to open the file from the asset system */
   1.167      rwops = SDL_AllocRW();
   1.168      if (!rwops)
   1.169          return NULL;            /* SDL_SetError already setup by SDL_AllocRW() */
   1.170 @@ -434,6 +508,7 @@
   1.171          SDL_FreeRW(rwops);
   1.172          return NULL;
   1.173      }
   1.174 +    rwops->size = Android_JNI_FileSize;
   1.175      rwops->seek = Android_JNI_FileSeek;
   1.176      rwops->read = Android_JNI_FileRead;
   1.177      rwops->write = Android_JNI_FileWrite;
   1.178 @@ -447,6 +522,7 @@
   1.179          SDL_FreeRW(rwops);
   1.180          return NULL;
   1.181      }
   1.182 +    rwops->size = windows_file_size;
   1.183      rwops->seek = windows_file_seek;
   1.184      rwops->read = windows_file_read;
   1.185      rwops->write = windows_file_write;
   1.186 @@ -490,6 +566,7 @@
   1.187  
   1.188      rwops = SDL_AllocRW();
   1.189      if (rwops != NULL) {
   1.190 +        rwops->size = stdio_size;
   1.191          rwops->seek = stdio_seek;
   1.192          rwops->read = stdio_read;
   1.193          rwops->write = stdio_write;
   1.194 @@ -515,6 +592,7 @@
   1.195  
   1.196      rwops = SDL_AllocRW();
   1.197      if (rwops != NULL) {
   1.198 +        rwops->size = mem_size;
   1.199          rwops->seek = mem_seek;
   1.200          rwops->read = mem_read;
   1.201          rwops->write = mem_write;
   1.202 @@ -533,6 +611,7 @@
   1.203  
   1.204      rwops = SDL_AllocRW();
   1.205      if (rwops != NULL) {
   1.206 +        rwops->size = mem_size;
   1.207          rwops->seek = mem_seek;
   1.208          rwops->read = mem_read;
   1.209          rwops->write = mem_writeconst;