src/file/SDL_rwops.c
changeset 2159 dd4753e47ed4
parent 1978 542c78b6fb12
child 2160 00adbaed3910
     1.1 --- a/src/file/SDL_rwops.c	Tue Jul 10 04:45:50 2007 +0000
     1.2 +++ b/src/file/SDL_rwops.c	Tue Jul 10 05:01:22 2007 +0000
     1.3 @@ -29,7 +29,7 @@
     1.4  #include "SDL_rwops.h"
     1.5  
     1.6  
     1.7 -#if defined(__WIN32__)
     1.8 +#ifdef __WIN32__
     1.9  
    1.10  /* Functions to read/write Win32 API file pointers */
    1.11  /* Will not use it on WinCE because stdio is buffered, it means
    1.12 @@ -43,6 +43,8 @@
    1.13  #define INVALID_SET_FILE_POINTER 0xFFFFFFFF
    1.14  #endif
    1.15  
    1.16 +#define READAHEAD_BUFFER_SIZE	1024
    1.17 +
    1.18  static int SDLCALL
    1.19  win32_file_open(SDL_RWops * context, const char *filename, const char *mode)
    1.20  {
    1.21 @@ -59,6 +61,15 @@
    1.22  
    1.23      context->hidden.win32io.h = INVALID_HANDLE_VALUE;   /* mark this as unusable */
    1.24  
    1.25 +    context->hidden.win32io.buffer.data =
    1.26 +        (char *) SDL_malloc(READAHEAD_BUFFER_SIZE);
    1.27 +    if (!context->hidden.win32io.buffer.data) {
    1.28 +        SDL_OutOfMemory();
    1.29 +        return -1;
    1.30 +    }
    1.31 +    context->hidden.win32io.buffer.size = 0;
    1.32 +    context->hidden.win32io.buffer.left = 0;
    1.33 +
    1.34      /* "r" = reading, file must exist */
    1.35      /* "w" = writing, truncate existing, file may not exist */
    1.36      /* "r+"= reading or writing, file must exist            */
    1.37 @@ -128,6 +139,12 @@
    1.38          return -1;
    1.39      }
    1.40  
    1.41 +    /* FIXME: We may be able to satisfy the seek within buffered data */
    1.42 +    if (whence == RW_SEEK_CUR && context->hidden.win32io.buffer.left) {
    1.43 +        offset -= context->hidden.win32io.buffer.left;
    1.44 +    }
    1.45 +    context->hidden.win32io.buffer.left = 0;
    1.46 +
    1.47      switch (whence) {
    1.48      case RW_SEEK_SET:
    1.49          win32whence = FILE_BEGIN;
    1.50 @@ -155,23 +172,54 @@
    1.51  static int SDLCALL
    1.52  win32_file_read(SDL_RWops * context, void *ptr, int size, int maxnum)
    1.53  {
    1.54 +    int total_need;
    1.55 +    int total_read = 0;
    1.56 +    int read_ahead;
    1.57 +    DWORD byte_read;
    1.58  
    1.59 -    int total_bytes;
    1.60 -    DWORD byte_read, nread;
    1.61 -
    1.62 -    total_bytes = size * maxnum;
    1.63 +    total_need = size * maxnum;
    1.64  
    1.65      if (!context || context->hidden.win32io.h == INVALID_HANDLE_VALUE
    1.66 -        || total_bytes <= 0 || !size)
    1.67 +        || total_need <= 0 || !size)
    1.68          return 0;
    1.69  
    1.70 -    if (!ReadFile
    1.71 -        (context->hidden.win32io.h, ptr, total_bytes, &byte_read, NULL)) {
    1.72 -        SDL_Error(SDL_EFREAD);
    1.73 -        return 0;
    1.74 +    if (context->hidden.win32io.buffer.left > 0) {
    1.75 +        void *data = (char *) context->hidden.win32io.buffer.data +
    1.76 +            context->hidden.win32io.buffer.size -
    1.77 +            context->hidden.win32io.buffer.left;
    1.78 +        read_ahead = SDL_min(total_need, context->hidden.win32io.buffer.left);
    1.79 +        SDL_memcpy(ptr, data, read_ahead);
    1.80 +        context->hidden.win32io.buffer.left -= read_ahead;
    1.81 +
    1.82 +        if (read_ahead == total_need) {
    1.83 +            return maxnum;
    1.84 +        }
    1.85 +        ptr = (char *) ptr + read_ahead;
    1.86 +        total_need -= read_ahead;
    1.87 +        total_read += read_ahead;
    1.88      }
    1.89 -    nread = byte_read / size;
    1.90 -    return nread;
    1.91 +
    1.92 +    if (total_need < READAHEAD_BUFFER_SIZE) {
    1.93 +        if (!ReadFile
    1.94 +            (context->hidden.win32io.h, context->hidden.win32io.buffer.data,
    1.95 +             READAHEAD_BUFFER_SIZE, &byte_read, NULL)) {
    1.96 +            SDL_Error(SDL_EFREAD);
    1.97 +            return 0;
    1.98 +        }
    1.99 +        read_ahead = SDL_min(total_need, (int) byte_read);
   1.100 +        SDL_memcpy(ptr, context->hidden.win32io.buffer.data, read_ahead);
   1.101 +        context->hidden.win32io.buffer.size = byte_read;
   1.102 +        context->hidden.win32io.buffer.left = byte_read - read_ahead;
   1.103 +        total_read += read_ahead;
   1.104 +    } else {
   1.105 +        if (!ReadFile
   1.106 +            (context->hidden.win32io.h, ptr, total_need, &byte_read, NULL)) {
   1.107 +            SDL_Error(SDL_EFREAD);
   1.108 +            return 0;
   1.109 +        }
   1.110 +        total_read += byte_read;
   1.111 +    }
   1.112 +    return (total_read / size);
   1.113  }
   1.114  static int SDLCALL
   1.115  win32_file_write(SDL_RWops * context, const void *ptr, int size, int num)
   1.116 @@ -186,10 +234,17 @@
   1.117          || total_bytes <= 0 || !size)
   1.118          return 0;
   1.119  
   1.120 +    if (context->hidden.win32io.buffer.left) {
   1.121 +        SetFilePointer(context->hidden.win32io.h,
   1.122 +                       -context->hidden.win32io.buffer.left, NULL,
   1.123 +                       FILE_CURRENT);
   1.124 +        context->hidden.win32io.buffer.left = 0;
   1.125 +    }
   1.126 +
   1.127      /* if in append mode, we must go to the EOF before write */
   1.128      if (context->hidden.win32io.append) {
   1.129 -        if (SetFilePointer(context->hidden.win32io.h, 0L, NULL, FILE_END)
   1.130 -            == INVALID_SET_FILE_POINTER) {
   1.131 +        if (SetFilePointer(context->hidden.win32io.h, 0L, NULL, FILE_END) ==
   1.132 +            INVALID_SET_FILE_POINTER) {
   1.133              SDL_Error(SDL_EFWRITE);
   1.134              return 0;
   1.135          }
   1.136 @@ -213,6 +268,10 @@
   1.137              CloseHandle(context->hidden.win32io.h);
   1.138              context->hidden.win32io.h = INVALID_HANDLE_VALUE;   /* to be sure */
   1.139          }
   1.140 +        if (context->hidden.win32io.buffer.data) {
   1.141 +            SDL_free(context->hidden.win32io.buffer.data);
   1.142 +            context->hidden.win32io.buffer.data = NULL;
   1.143 +        }
   1.144          SDL_FreeRW(context);
   1.145      }
   1.146      return (0);