src/file/SDL_rwops.c
changeset 2159 dd4753e47ed4
parent 1978 542c78b6fb12
child 2160 00adbaed3910
equal deleted inserted replaced
2158:eff395617ed8 2159:dd4753e47ed4
    27 
    27 
    28 #include "SDL_endian.h"
    28 #include "SDL_endian.h"
    29 #include "SDL_rwops.h"
    29 #include "SDL_rwops.h"
    30 
    30 
    31 
    31 
    32 #if defined(__WIN32__)
    32 #ifdef __WIN32__
    33 
    33 
    34 /* Functions to read/write Win32 API file pointers */
    34 /* Functions to read/write Win32 API file pointers */
    35 /* Will not use it on WinCE because stdio is buffered, it means
    35 /* Will not use it on WinCE because stdio is buffered, it means
    36    faster, and all stdio functions anyway are embedded in coredll.dll - 
    36    faster, and all stdio functions anyway are embedded in coredll.dll - 
    37    the main wince dll*/
    37    the main wince dll*/
    40 #include <windows.h>
    40 #include <windows.h>
    41 
    41 
    42 #ifndef INVALID_SET_FILE_POINTER
    42 #ifndef INVALID_SET_FILE_POINTER
    43 #define INVALID_SET_FILE_POINTER 0xFFFFFFFF
    43 #define INVALID_SET_FILE_POINTER 0xFFFFFFFF
    44 #endif
    44 #endif
       
    45 
       
    46 #define READAHEAD_BUFFER_SIZE	1024
    45 
    47 
    46 static int SDLCALL
    48 static int SDLCALL
    47 win32_file_open(SDL_RWops * context, const char *filename, const char *mode)
    49 win32_file_open(SDL_RWops * context, const char *filename, const char *mode)
    48 {
    50 {
    49 #ifndef _WIN32_WCE
    51 #ifndef _WIN32_WCE
    57     if (!context)
    59     if (!context)
    58         return -1;
    60         return -1;
    59 
    61 
    60     context->hidden.win32io.h = INVALID_HANDLE_VALUE;   /* mark this as unusable */
    62     context->hidden.win32io.h = INVALID_HANDLE_VALUE;   /* mark this as unusable */
    61 
    63 
       
    64     context->hidden.win32io.buffer.data =
       
    65         (char *) SDL_malloc(READAHEAD_BUFFER_SIZE);
       
    66     if (!context->hidden.win32io.buffer.data) {
       
    67         SDL_OutOfMemory();
       
    68         return -1;
       
    69     }
       
    70     context->hidden.win32io.buffer.size = 0;
       
    71     context->hidden.win32io.buffer.left = 0;
       
    72 
    62     /* "r" = reading, file must exist */
    73     /* "r" = reading, file must exist */
    63     /* "w" = writing, truncate existing, file may not exist */
    74     /* "w" = writing, truncate existing, file may not exist */
    64     /* "r+"= reading or writing, file must exist            */
    75     /* "r+"= reading or writing, file must exist            */
    65     /* "a" = writing, append file may not exist             */
    76     /* "a" = writing, append file may not exist             */
    66     /* "a+"= append + read, file may not exist              */
    77     /* "a+"= append + read, file may not exist              */
   125 
   136 
   126     if (!context || context->hidden.win32io.h == INVALID_HANDLE_VALUE) {
   137     if (!context || context->hidden.win32io.h == INVALID_HANDLE_VALUE) {
   127         SDL_SetError("win32_file_seek: invalid context/file not opened");
   138         SDL_SetError("win32_file_seek: invalid context/file not opened");
   128         return -1;
   139         return -1;
   129     }
   140     }
       
   141 
       
   142     /* FIXME: We may be able to satisfy the seek within buffered data */
       
   143     if (whence == RW_SEEK_CUR && context->hidden.win32io.buffer.left) {
       
   144         offset -= context->hidden.win32io.buffer.left;
       
   145     }
       
   146     context->hidden.win32io.buffer.left = 0;
   130 
   147 
   131     switch (whence) {
   148     switch (whence) {
   132     case RW_SEEK_SET:
   149     case RW_SEEK_SET:
   133         win32whence = FILE_BEGIN;
   150         win32whence = FILE_BEGIN;
   134         break;
   151         break;
   153     return -1;                  /* error */
   170     return -1;                  /* error */
   154 }
   171 }
   155 static int SDLCALL
   172 static int SDLCALL
   156 win32_file_read(SDL_RWops * context, void *ptr, int size, int maxnum)
   173 win32_file_read(SDL_RWops * context, void *ptr, int size, int maxnum)
   157 {
   174 {
       
   175     int total_need;
       
   176     int total_read = 0;
       
   177     int read_ahead;
       
   178     DWORD byte_read;
       
   179 
       
   180     total_need = size * maxnum;
       
   181 
       
   182     if (!context || context->hidden.win32io.h == INVALID_HANDLE_VALUE
       
   183         || total_need <= 0 || !size)
       
   184         return 0;
       
   185 
       
   186     if (context->hidden.win32io.buffer.left > 0) {
       
   187         void *data = (char *) context->hidden.win32io.buffer.data +
       
   188             context->hidden.win32io.buffer.size -
       
   189             context->hidden.win32io.buffer.left;
       
   190         read_ahead = SDL_min(total_need, context->hidden.win32io.buffer.left);
       
   191         SDL_memcpy(ptr, data, read_ahead);
       
   192         context->hidden.win32io.buffer.left -= read_ahead;
       
   193 
       
   194         if (read_ahead == total_need) {
       
   195             return maxnum;
       
   196         }
       
   197         ptr = (char *) ptr + read_ahead;
       
   198         total_need -= read_ahead;
       
   199         total_read += read_ahead;
       
   200     }
       
   201 
       
   202     if (total_need < READAHEAD_BUFFER_SIZE) {
       
   203         if (!ReadFile
       
   204             (context->hidden.win32io.h, context->hidden.win32io.buffer.data,
       
   205              READAHEAD_BUFFER_SIZE, &byte_read, NULL)) {
       
   206             SDL_Error(SDL_EFREAD);
       
   207             return 0;
       
   208         }
       
   209         read_ahead = SDL_min(total_need, (int) byte_read);
       
   210         SDL_memcpy(ptr, context->hidden.win32io.buffer.data, read_ahead);
       
   211         context->hidden.win32io.buffer.size = byte_read;
       
   212         context->hidden.win32io.buffer.left = byte_read - read_ahead;
       
   213         total_read += read_ahead;
       
   214     } else {
       
   215         if (!ReadFile
       
   216             (context->hidden.win32io.h, ptr, total_need, &byte_read, NULL)) {
       
   217             SDL_Error(SDL_EFREAD);
       
   218             return 0;
       
   219         }
       
   220         total_read += byte_read;
       
   221     }
       
   222     return (total_read / size);
       
   223 }
       
   224 static int SDLCALL
       
   225 win32_file_write(SDL_RWops * context, const void *ptr, int size, int num)
       
   226 {
   158 
   227 
   159     int total_bytes;
   228     int total_bytes;
   160     DWORD byte_read, nread;
   229     DWORD byte_written, nwritten;
   161 
   230 
   162     total_bytes = size * maxnum;
   231     total_bytes = size * num;
   163 
   232 
   164     if (!context || context->hidden.win32io.h == INVALID_HANDLE_VALUE
   233     if (!context || context->hidden.win32io.h == INVALID_HANDLE_VALUE
   165         || total_bytes <= 0 || !size)
   234         || total_bytes <= 0 || !size)
   166         return 0;
   235         return 0;
   167 
   236 
   168     if (!ReadFile
   237     if (context->hidden.win32io.buffer.left) {
   169         (context->hidden.win32io.h, ptr, total_bytes, &byte_read, NULL)) {
   238         SetFilePointer(context->hidden.win32io.h,
   170         SDL_Error(SDL_EFREAD);
   239                        -context->hidden.win32io.buffer.left, NULL,
   171         return 0;
   240                        FILE_CURRENT);
   172     }
   241         context->hidden.win32io.buffer.left = 0;
   173     nread = byte_read / size;
   242     }
   174     return nread;
       
   175 }
       
   176 static int SDLCALL
       
   177 win32_file_write(SDL_RWops * context, const void *ptr, int size, int num)
       
   178 {
       
   179 
       
   180     int total_bytes;
       
   181     DWORD byte_written, nwritten;
       
   182 
       
   183     total_bytes = size * num;
       
   184 
       
   185     if (!context || context->hidden.win32io.h == INVALID_HANDLE_VALUE
       
   186         || total_bytes <= 0 || !size)
       
   187         return 0;
       
   188 
   243 
   189     /* if in append mode, we must go to the EOF before write */
   244     /* if in append mode, we must go to the EOF before write */
   190     if (context->hidden.win32io.append) {
   245     if (context->hidden.win32io.append) {
   191         if (SetFilePointer(context->hidden.win32io.h, 0L, NULL, FILE_END)
   246         if (SetFilePointer(context->hidden.win32io.h, 0L, NULL, FILE_END) ==
   192             == INVALID_SET_FILE_POINTER) {
   247             INVALID_SET_FILE_POINTER) {
   193             SDL_Error(SDL_EFWRITE);
   248             SDL_Error(SDL_EFWRITE);
   194             return 0;
   249             return 0;
   195         }
   250         }
   196     }
   251     }
   197 
   252 
   210 
   265 
   211     if (context) {
   266     if (context) {
   212         if (context->hidden.win32io.h != INVALID_HANDLE_VALUE) {
   267         if (context->hidden.win32io.h != INVALID_HANDLE_VALUE) {
   213             CloseHandle(context->hidden.win32io.h);
   268             CloseHandle(context->hidden.win32io.h);
   214             context->hidden.win32io.h = INVALID_HANDLE_VALUE;   /* to be sure */
   269             context->hidden.win32io.h = INVALID_HANDLE_VALUE;   /* to be sure */
       
   270         }
       
   271         if (context->hidden.win32io.buffer.data) {
       
   272             SDL_free(context->hidden.win32io.buffer.data);
       
   273             context->hidden.win32io.buffer.data = NULL;
   215         }
   274         }
   216         SDL_FreeRW(context);
   275         SDL_FreeRW(context);
   217     }
   276     }
   218     return (0);
   277     return (0);
   219 }
   278 }