Merged read-ahead support for Win32 file I/O from SDL 1.2 revision 3183
authorSam Lantinga <slouken@libsdl.org>
Tue, 10 Jul 2007 05:01:22 +0000
changeset 2159dd4753e47ed4
parent 2158 eff395617ed8
child 2160 00adbaed3910
Merged read-ahead support for Win32 file I/O from SDL 1.2 revision 3183
include/SDL_rwops.h
src/file/SDL_rwops.c
     1.1 --- a/include/SDL_rwops.h	Tue Jul 10 04:45:50 2007 +0000
     1.2 +++ b/include/SDL_rwops.h	Tue Jul 10 05:01:22 2007 +0000
     1.3 @@ -76,6 +76,12 @@
     1.4          {
     1.5              int append;
     1.6              void *h;
     1.7 +            struct
     1.8 +            {
     1.9 +                void *data;
    1.10 +                int size;
    1.11 +                int left;
    1.12 +            } buffer;
    1.13          } win32io;
    1.14  #endif
    1.15  #ifdef HAVE_STDIO_H
     2.1 --- a/src/file/SDL_rwops.c	Tue Jul 10 04:45:50 2007 +0000
     2.2 +++ b/src/file/SDL_rwops.c	Tue Jul 10 05:01:22 2007 +0000
     2.3 @@ -29,7 +29,7 @@
     2.4  #include "SDL_rwops.h"
     2.5  
     2.6  
     2.7 -#if defined(__WIN32__)
     2.8 +#ifdef __WIN32__
     2.9  
    2.10  /* Functions to read/write Win32 API file pointers */
    2.11  /* Will not use it on WinCE because stdio is buffered, it means
    2.12 @@ -43,6 +43,8 @@
    2.13  #define INVALID_SET_FILE_POINTER 0xFFFFFFFF
    2.14  #endif
    2.15  
    2.16 +#define READAHEAD_BUFFER_SIZE	1024
    2.17 +
    2.18  static int SDLCALL
    2.19  win32_file_open(SDL_RWops * context, const char *filename, const char *mode)
    2.20  {
    2.21 @@ -59,6 +61,15 @@
    2.22  
    2.23      context->hidden.win32io.h = INVALID_HANDLE_VALUE;   /* mark this as unusable */
    2.24  
    2.25 +    context->hidden.win32io.buffer.data =
    2.26 +        (char *) SDL_malloc(READAHEAD_BUFFER_SIZE);
    2.27 +    if (!context->hidden.win32io.buffer.data) {
    2.28 +        SDL_OutOfMemory();
    2.29 +        return -1;
    2.30 +    }
    2.31 +    context->hidden.win32io.buffer.size = 0;
    2.32 +    context->hidden.win32io.buffer.left = 0;
    2.33 +
    2.34      /* "r" = reading, file must exist */
    2.35      /* "w" = writing, truncate existing, file may not exist */
    2.36      /* "r+"= reading or writing, file must exist            */
    2.37 @@ -128,6 +139,12 @@
    2.38          return -1;
    2.39      }
    2.40  
    2.41 +    /* FIXME: We may be able to satisfy the seek within buffered data */
    2.42 +    if (whence == RW_SEEK_CUR && context->hidden.win32io.buffer.left) {
    2.43 +        offset -= context->hidden.win32io.buffer.left;
    2.44 +    }
    2.45 +    context->hidden.win32io.buffer.left = 0;
    2.46 +
    2.47      switch (whence) {
    2.48      case RW_SEEK_SET:
    2.49          win32whence = FILE_BEGIN;
    2.50 @@ -155,23 +172,54 @@
    2.51  static int SDLCALL
    2.52  win32_file_read(SDL_RWops * context, void *ptr, int size, int maxnum)
    2.53  {
    2.54 +    int total_need;
    2.55 +    int total_read = 0;
    2.56 +    int read_ahead;
    2.57 +    DWORD byte_read;
    2.58  
    2.59 -    int total_bytes;
    2.60 -    DWORD byte_read, nread;
    2.61 -
    2.62 -    total_bytes = size * maxnum;
    2.63 +    total_need = size * maxnum;
    2.64  
    2.65      if (!context || context->hidden.win32io.h == INVALID_HANDLE_VALUE
    2.66 -        || total_bytes <= 0 || !size)
    2.67 +        || total_need <= 0 || !size)
    2.68          return 0;
    2.69  
    2.70 -    if (!ReadFile
    2.71 -        (context->hidden.win32io.h, ptr, total_bytes, &byte_read, NULL)) {
    2.72 -        SDL_Error(SDL_EFREAD);
    2.73 -        return 0;
    2.74 +    if (context->hidden.win32io.buffer.left > 0) {
    2.75 +        void *data = (char *) context->hidden.win32io.buffer.data +
    2.76 +            context->hidden.win32io.buffer.size -
    2.77 +            context->hidden.win32io.buffer.left;
    2.78 +        read_ahead = SDL_min(total_need, context->hidden.win32io.buffer.left);
    2.79 +        SDL_memcpy(ptr, data, read_ahead);
    2.80 +        context->hidden.win32io.buffer.left -= read_ahead;
    2.81 +
    2.82 +        if (read_ahead == total_need) {
    2.83 +            return maxnum;
    2.84 +        }
    2.85 +        ptr = (char *) ptr + read_ahead;
    2.86 +        total_need -= read_ahead;
    2.87 +        total_read += read_ahead;
    2.88      }
    2.89 -    nread = byte_read / size;
    2.90 -    return nread;
    2.91 +
    2.92 +    if (total_need < READAHEAD_BUFFER_SIZE) {
    2.93 +        if (!ReadFile
    2.94 +            (context->hidden.win32io.h, context->hidden.win32io.buffer.data,
    2.95 +             READAHEAD_BUFFER_SIZE, &byte_read, NULL)) {
    2.96 +            SDL_Error(SDL_EFREAD);
    2.97 +            return 0;
    2.98 +        }
    2.99 +        read_ahead = SDL_min(total_need, (int) byte_read);
   2.100 +        SDL_memcpy(ptr, context->hidden.win32io.buffer.data, read_ahead);
   2.101 +        context->hidden.win32io.buffer.size = byte_read;
   2.102 +        context->hidden.win32io.buffer.left = byte_read - read_ahead;
   2.103 +        total_read += read_ahead;
   2.104 +    } else {
   2.105 +        if (!ReadFile
   2.106 +            (context->hidden.win32io.h, ptr, total_need, &byte_read, NULL)) {
   2.107 +            SDL_Error(SDL_EFREAD);
   2.108 +            return 0;
   2.109 +        }
   2.110 +        total_read += byte_read;
   2.111 +    }
   2.112 +    return (total_read / size);
   2.113  }
   2.114  static int SDLCALL
   2.115  win32_file_write(SDL_RWops * context, const void *ptr, int size, int num)
   2.116 @@ -186,10 +234,17 @@
   2.117          || total_bytes <= 0 || !size)
   2.118          return 0;
   2.119  
   2.120 +    if (context->hidden.win32io.buffer.left) {
   2.121 +        SetFilePointer(context->hidden.win32io.h,
   2.122 +                       -context->hidden.win32io.buffer.left, NULL,
   2.123 +                       FILE_CURRENT);
   2.124 +        context->hidden.win32io.buffer.left = 0;
   2.125 +    }
   2.126 +
   2.127      /* if in append mode, we must go to the EOF before write */
   2.128      if (context->hidden.win32io.append) {
   2.129 -        if (SetFilePointer(context->hidden.win32io.h, 0L, NULL, FILE_END)
   2.130 -            == INVALID_SET_FILE_POINTER) {
   2.131 +        if (SetFilePointer(context->hidden.win32io.h, 0L, NULL, FILE_END) ==
   2.132 +            INVALID_SET_FILE_POINTER) {
   2.133              SDL_Error(SDL_EFWRITE);
   2.134              return 0;
   2.135          }
   2.136 @@ -213,6 +268,10 @@
   2.137              CloseHandle(context->hidden.win32io.h);
   2.138              context->hidden.win32io.h = INVALID_HANDLE_VALUE;   /* to be sure */
   2.139          }
   2.140 +        if (context->hidden.win32io.buffer.data) {
   2.141 +            SDL_free(context->hidden.win32io.buffer.data);
   2.142 +            context->hidden.win32io.buffer.data = NULL;
   2.143 +        }
   2.144          SDL_FreeRW(context);
   2.145      }
   2.146      return (0);