Added an API to get the size of a file - WARNING! ABI CHANGE!
authorSam Lantinga <slouken@libsdl.org>
Sat, 03 Nov 2012 18:43:36 -0700
changeset 6642 b716011e53ce
parent 6641 45187a87d35b
child 6643 673aed697ce6
Added an API to get the size of a file - WARNING! ABI CHANGE!
configure
configure.in
include/SDL_config.h.in
include/SDL_rwops.h
src/core/android/SDL_android.cpp
src/core/android/SDL_android.h
src/file/SDL_rwops.c
--- a/configure	Sat Nov 03 12:11:49 2012 -0400
+++ b/configure	Sat Nov 03 18:43:36 2012 -0700
@@ -16688,7 +16688,7 @@
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 fi
 
-    for ac_func in malloc calloc realloc free getenv setenv putenv unsetenv qsort abs bcopy memset memcpy memmove strlen strlcpy strlcat strdup _strrev _strupr _strlwr strchr strrchr strstr itoa _ltoa _uitoa _ultoa strtol strtoul _i64toa _ui64toa strtoll strtoull atoi atof strcmp strncmp _stricmp strcasecmp _strnicmp strncasecmp sscanf snprintf vsnprintf sigaction setjmp nanosleep sysconf sysctlbyname
+    for ac_func in malloc calloc realloc free getenv setenv putenv unsetenv qsort abs bcopy memset memcpy memmove strlen strlcpy strlcat strdup _strrev _strupr _strlwr strchr strrchr strstr itoa _ltoa _uitoa _ultoa strtol strtoul _i64toa _ui64toa strtoll strtoull atoi atof strcmp strncmp _stricmp strcasecmp _strnicmp strncasecmp sscanf snprintf vsnprintf fseeko fseeko64 sigaction setjmp nanosleep sysconf sysctlbyname
 do :
   as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
 ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
--- a/configure.in	Sat Nov 03 12:11:49 2012 -0400
+++ b/configure.in	Sat Nov 03 18:43:36 2012 -0700
@@ -237,7 +237,7 @@
         AC_DEFINE(HAVE_MPROTECT, 1, [ ])
         ]),
     )
-    AC_CHECK_FUNCS(malloc calloc realloc free getenv setenv putenv unsetenv qsort abs bcopy memset memcpy memmove strlen strlcpy strlcat strdup _strrev _strupr _strlwr strchr strrchr strstr itoa _ltoa _uitoa _ultoa strtol strtoul _i64toa _ui64toa strtoll strtoull atoi atof strcmp strncmp _stricmp strcasecmp _strnicmp strncasecmp sscanf snprintf vsnprintf sigaction setjmp nanosleep sysconf sysctlbyname)
+    AC_CHECK_FUNCS(malloc calloc realloc free getenv setenv putenv unsetenv qsort abs bcopy memset memcpy memmove strlen strlcpy strlcat strdup _strrev _strupr _strlwr strchr strrchr strstr itoa _ltoa _uitoa _ultoa strtol strtoul _i64toa _ui64toa strtoll strtoull atoi atof strcmp strncmp _stricmp strcasecmp _strnicmp strncasecmp sscanf snprintf vsnprintf fseeko fseeko64 sigaction setjmp nanosleep sysconf sysctlbyname)
 
     AC_CHECK_LIB(m, pow, [LIBS="$LIBS -lm"; EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lm"])
     AC_CHECK_FUNCS(atan atan2 ceil copysign cos cosf fabs floor log pow scalbn sin sinf sqrt)
--- a/include/SDL_config.h.in	Sat Nov 03 12:11:49 2012 -0400
+++ b/include/SDL_config.h.in	Sat Nov 03 18:43:36 2012 -0700
@@ -139,6 +139,8 @@
 #undef HAVE_SIN
 #undef HAVE_SINF
 #undef HAVE_SQRT
+#undef HAVE_FSEEKO
+#undef HAVE_FSEEKO64
 #undef HAVE_SIGACTION
 #undef HAVE_SA_SIGACTION
 #undef HAVE_SETJMP
--- a/include/SDL_rwops.h	Sat Nov 03 12:11:49 2012 -0400
+++ b/include/SDL_rwops.h	Sat Nov 03 18:43:36 2012 -0700
@@ -46,13 +46,18 @@
 typedef struct SDL_RWops
 {
     /**
+     *  Return the size of the file in this rwops, or -1 if unknown
+     */
+    Sint64 (SDLCALL * size) (struct SDL_RWops * context);
+
+    /**
      *  Seek to \c offset relative to \c whence, one of stdio's whence values:
      *  RW_SEEK_SET, RW_SEEK_CUR, RW_SEEK_END
      *  
      *  \return the final offset in the data stream.
      */
-    long (SDLCALL * seek) (struct SDL_RWops * context, long offset,
-                           int whence);
+    Sint64 (SDLCALL * seek) (struct SDL_RWops * context, Sint64 offset,
+                             int whence);
 
     /**
      *  Read up to \c maxnum objects each of size \c size from the data
@@ -60,8 +65,8 @@
      *  
      *  \return the number of objects read, or 0 at error or end of file.
      */
-    size_t(SDLCALL * read) (struct SDL_RWops * context, void *ptr,
-                            size_t size, size_t maxnum);
+    size_t (SDLCALL * read) (struct SDL_RWops * context, void *ptr,
+                             size_t size, size_t maxnum);
 
     /**
      *  Write exactly \c num objects each of size \c size from the area
@@ -69,8 +74,8 @@
      *  
      *  \return the number of objects written, or 0 at error or end of file.
      */
-    size_t(SDLCALL * write) (struct SDL_RWops * context, const void *ptr,
-                             size_t size, size_t num);
+    size_t (SDLCALL * write) (struct SDL_RWops * context, const void *ptr,
+                              size_t size, size_t num);
 
     /**
      *  Close and free an allocated SDL_RWops structure.
@@ -166,6 +171,7 @@
  *  Macros to easily read and write from an SDL_RWops structure.
  */
 /*@{*/
+#define SDL_RWsize(ctx)	        (ctx)->size(ctx)
 #define SDL_RWseek(ctx, offset, whence)	(ctx)->seek(ctx, offset, whence)
 #define SDL_RWtell(ctx)			(ctx)->seek(ctx, 0, RW_SEEK_CUR)
 #define SDL_RWread(ctx, ptr, size, n)	(ctx)->read(ctx, ptr, size, n)
--- a/src/core/android/SDL_android.cpp	Sat Nov 03 12:11:49 2012 -0400
+++ b/src/core/android/SDL_android.cpp	Sat Nov 03 18:43:36 2012 -0700
@@ -696,9 +696,14 @@
 }
 
 
-extern "C" long Android_JNI_FileSeek(SDL_RWops* ctx, long offset, int whence)
+extern "C" Sint64 Android_JNI_FileSize(SDL_RWops* ctx)
 {
-    long newPosition;
+    return ctx->hidden.androidio.size;
+}
+
+extern "C" Sint64 Android_JNI_FileSeek(SDL_RWops* ctx, Sint64 offset, int whence)
+{
+    Sint64 newPosition;
 
     switch (whence) {
         case RW_SEEK_SET:
@@ -714,27 +719,27 @@
             SDL_SetError("Unknown value for 'whence'");
             return -1;
     }
+
+    /* Validate the new position */
     if (newPosition < 0) {
-        newPosition = 0;
+        SDL_Error(SDL_EFSEEK);
+        return -1;
     }
     if (newPosition > ctx->hidden.androidio.size) {
         newPosition = ctx->hidden.androidio.size;
     }
 
-    long movement = newPosition - ctx->hidden.androidio.position;
-    jobject inputStream = (jobject)ctx->hidden.androidio.inputStreamRef;
-
+    Sint64 movement = newPosition - ctx->hidden.androidio.position;
     if (movement > 0) {
         unsigned char buffer[1024];
 
         // The easy case where we're seeking forwards
         while (movement > 0) {
-            long amount = (long) sizeof (buffer);
+            Sint64 amount = sizeof (buffer);
             if (amount > movement) {
                 amount = movement;
             }
             size_t result = Android_JNI_FileRead(ctx, buffer, 1, amount);
-
             if (result <= 0) {
                 // Failed to read/skip the required amount, so fail
                 return -1;
@@ -742,6 +747,7 @@
 
             movement -= result;
         }
+
     } else if (movement < 0) {
         // We can't seek backwards so we have to reopen the file and seek
         // forwards which obviously isn't very efficient
@@ -750,8 +756,6 @@
         Android_JNI_FileSeek(ctx, newPosition, RW_SEEK_SET);
     }
 
-    ctx->hidden.androidio.position = newPosition;
-
     return ctx->hidden.androidio.position;
 }
 
--- a/src/core/android/SDL_android.h	Sat Nov 03 12:11:49 2012 -0400
+++ b/src/core/android/SDL_android.h	Sat Nov 03 18:43:36 2012 -0700
@@ -45,7 +45,8 @@
 #include "SDL_rwops.h"
 
 int Android_JNI_FileOpen(SDL_RWops* ctx, const char* fileName, const char* mode);
-long Android_JNI_FileSeek(SDL_RWops* ctx, long offset, int whence);
+Sint64 Android_JNI_FileSize(SDL_RWops* ctx);
+Sint64 Android_JNI_FileSeek(SDL_RWops* ctx, Sint64 offset, int whence);
 size_t Android_JNI_FileRead(SDL_RWops* ctx, void* buffer, size_t size, size_t maxnum);
 size_t Android_JNI_FileWrite(SDL_RWops* ctx, const void* buffer, size_t size, size_t num);
 int Android_JNI_FileClose(SDL_RWops* ctx);
--- a/src/file/SDL_rwops.c	Sat Nov 03 12:11:49 2012 -0400
+++ b/src/file/SDL_rwops.c	Sat Nov 03 18:43:36 2012 -0700
@@ -121,11 +121,29 @@
     return 0;                   /* ok */
 }
 
-static long SDLCALL
-windows_file_seek(SDL_RWops * context, long offset, int whence)
+static Sint64 SDLCALL
+windows_file_size(SDL_RWops * context)
+{
+    LARGE_INTEGER size;
+
+    if (!context || context->hidden.windowsio.h == INVALID_HANDLE_VALUE) {
+        SDL_SetError("windows_file_size: invalid context/file not opened");
+        return -1;
+    }
+
+    if (!GetFileSizeEx(context->hidden.windowsio.h, &size)) {
+        WIN_SetError("windows_file_size");
+        return -1;
+    }
+
+    return size.QuadPart;
+}
+
+static Sint64 SDLCALL
+windows_file_seek(SDL_RWops * context, Sint64 offset, int whence)
 {
     DWORD windowswhence;
-    long file_pos;
+    LARGE_INTEGER windowsoffset;
 
     if (!context || context->hidden.windowsio.h == INVALID_HANDLE_VALUE) {
         SDL_SetError("windows_file_seek: invalid context/file not opened");
@@ -153,14 +171,12 @@
         return -1;
     }
 
-    file_pos =
-        SetFilePointer(context->hidden.windowsio.h, offset, NULL, windowswhence);
-
-    if (file_pos != INVALID_SET_FILE_POINTER)
-        return file_pos;        /* success */
-
-    SDL_Error(SDL_EFSEEK);
-    return -1;                  /* error */
+    windowsoffset.QuadPart = offset;
+    if (!SetFilePointerEx(context->hidden.windowsio.h, windowsoffset, &windowsoffset, windowswhence)) {
+        WIN_SetError("windows_file_seek");
+        return -1;
+    }
+    return windowsoffset.QuadPart;
 }
 
 static size_t SDLCALL
@@ -281,15 +297,39 @@
 
 /* Functions to read/write stdio file pointers */
 
-static long SDLCALL
-stdio_seek(SDL_RWops * context, long offset, int whence)
+static Sint64 SDLCALL
+stdio_size(SDL_RWops * context)
 {
+    Sint64 pos, size;
+
+    pos = SDL_RWseek(context, 0, RW_SEEK_CUR);
+    if (pos < 0) {
+        return -1;
+    }
+    size = SDL_RWseek(context, 0, RW_SEEK_END);
+
+    SDL_RWseek(context, pos, RW_SEEK_SET);
+    return size;
+}
+
+static Sint64 SDLCALL
+stdio_seek(SDL_RWops * context, Sint64 offset, int whence)
+{
+#ifdef HAVE_FSEEKO64
+    if (fseek64o(context->hidden.stdio.fp, (off64_t)offset, whence) == 0) {
+        return ftell64o(context->hidden.stdio.fp);
+    }
+#elif defined(HAVE_FSEEKO)
+    if (fseeko(context->hidden.stdio.fp, (off_t)offset, whence) == 0) {
+        return ftello(context->hidden.stdio.fp);
+    }
+#else
     if (fseek(context->hidden.stdio.fp, offset, whence) == 0) {
         return (ftell(context->hidden.stdio.fp));
-    } else {
-        SDL_Error(SDL_EFSEEK);
-        return (-1);
     }
+#endif
+    SDL_Error(SDL_EFSEEK);
+    return (-1);
 }
 
 static size_t SDLCALL
@@ -336,8 +376,14 @@
 
 /* Functions to read/write memory pointers */
 
-static long SDLCALL
-mem_seek(SDL_RWops * context, long offset, int whence)
+static Sint64 SDLCALL
+mem_size(SDL_RWops * context)
+{
+    return (Sint64)(context->hidden.mem.stop - context->hidden.mem.base);
+}
+
+static Sint64 SDLCALL
+mem_seek(SDL_RWops * context, Sint64 offset, int whence)
 {
     Uint8 *newpos;
 
@@ -362,7 +408,7 @@
         newpos = context->hidden.mem.stop;
     }
     context->hidden.mem.here = newpos;
-    return (long)(context->hidden.mem.here - context->hidden.mem.base);
+    return (Sint64)(context->hidden.mem.here - context->hidden.mem.base);
 }
 
 static size_t SDLCALL
@@ -460,6 +506,7 @@
         SDL_FreeRW(rwops);
         return NULL;
     }
+    rwops->size = Android_JNI_FileSize;
     rwops->seek = Android_JNI_FileSeek;
     rwops->read = Android_JNI_FileRead;
     rwops->write = Android_JNI_FileWrite;
@@ -473,6 +520,7 @@
         SDL_FreeRW(rwops);
         return NULL;
     }
+    rwops->size = windows_file_size;
     rwops->seek = windows_file_seek;
     rwops->read = windows_file_read;
     rwops->write = windows_file_write;
@@ -513,6 +561,7 @@
 
     rwops = SDL_AllocRW();
     if (rwops != NULL) {
+        rwops->size = stdio_size;
         rwops->seek = stdio_seek;
         rwops->read = stdio_read;
         rwops->write = stdio_write;
@@ -538,6 +587,7 @@
 
     rwops = SDL_AllocRW();
     if (rwops != NULL) {
+        rwops->size = mem_size;
         rwops->seek = mem_seek;
         rwops->read = mem_read;
         rwops->write = mem_write;
@@ -556,6 +606,7 @@
 
     rwops = SDL_AllocRW();
     if (rwops != NULL) {
+        rwops->size = mem_size;
         rwops->seek = mem_seek;
         rwops->read = mem_read;
         rwops->write = mem_writeconst;