From db3b805655c4690a2467f7980d69ef9c6338eb27 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 10 Jul 2007 05:01:22 +0000 Subject: [PATCH] Merged read-ahead support for Win32 file I/O from SDL 1.2 revision 3183 --- include/SDL_rwops.h | 6 +++ src/file/SDL_rwops.c | 87 +++++++++++++++++++++++++++++++++++++------- 2 files changed, 79 insertions(+), 14 deletions(-) diff --git a/include/SDL_rwops.h b/include/SDL_rwops.h index d9d600026..e65c1fe46 100644 --- a/include/SDL_rwops.h +++ b/include/SDL_rwops.h @@ -76,6 +76,12 @@ typedef struct SDL_RWops { int append; void *h; + struct + { + void *data; + int size; + int left; + } buffer; } win32io; #endif #ifdef HAVE_STDIO_H diff --git a/src/file/SDL_rwops.c b/src/file/SDL_rwops.c index 3bdb44152..b995ba54d 100644 --- a/src/file/SDL_rwops.c +++ b/src/file/SDL_rwops.c @@ -29,7 +29,7 @@ #include "SDL_rwops.h" -#if defined(__WIN32__) +#ifdef __WIN32__ /* Functions to read/write Win32 API file pointers */ /* Will not use it on WinCE because stdio is buffered, it means @@ -43,6 +43,8 @@ #define INVALID_SET_FILE_POINTER 0xFFFFFFFF #endif +#define READAHEAD_BUFFER_SIZE 1024 + static int SDLCALL win32_file_open(SDL_RWops * context, const char *filename, const char *mode) { @@ -59,6 +61,15 @@ win32_file_open(SDL_RWops * context, const char *filename, const char *mode) context->hidden.win32io.h = INVALID_HANDLE_VALUE; /* mark this as unusable */ + context->hidden.win32io.buffer.data = + (char *) SDL_malloc(READAHEAD_BUFFER_SIZE); + if (!context->hidden.win32io.buffer.data) { + SDL_OutOfMemory(); + return -1; + } + context->hidden.win32io.buffer.size = 0; + context->hidden.win32io.buffer.left = 0; + /* "r" = reading, file must exist */ /* "w" = writing, truncate existing, file may not exist */ /* "r+"= reading or writing, file must exist */ @@ -128,6 +139,12 @@ win32_file_seek(SDL_RWops * context, int offset, int whence) return -1; } + /* FIXME: We may be able to satisfy the seek within buffered data */ + if (whence == RW_SEEK_CUR && context->hidden.win32io.buffer.left) { + offset -= context->hidden.win32io.buffer.left; + } + context->hidden.win32io.buffer.left = 0; + switch (whence) { case RW_SEEK_SET: win32whence = FILE_BEGIN; @@ -155,23 +172,54 @@ win32_file_seek(SDL_RWops * context, int offset, int whence) static int SDLCALL win32_file_read(SDL_RWops * context, void *ptr, int size, int maxnum) { + int total_need; + int total_read = 0; + int read_ahead; + DWORD byte_read; - int total_bytes; - DWORD byte_read, nread; - - total_bytes = size * maxnum; + total_need = size * maxnum; if (!context || context->hidden.win32io.h == INVALID_HANDLE_VALUE - || total_bytes <= 0 || !size) + || total_need <= 0 || !size) return 0; - if (!ReadFile - (context->hidden.win32io.h, ptr, total_bytes, &byte_read, NULL)) { - SDL_Error(SDL_EFREAD); - return 0; + if (context->hidden.win32io.buffer.left > 0) { + void *data = (char *) context->hidden.win32io.buffer.data + + context->hidden.win32io.buffer.size - + context->hidden.win32io.buffer.left; + read_ahead = SDL_min(total_need, context->hidden.win32io.buffer.left); + SDL_memcpy(ptr, data, read_ahead); + context->hidden.win32io.buffer.left -= read_ahead; + + if (read_ahead == total_need) { + return maxnum; + } + ptr = (char *) ptr + read_ahead; + total_need -= read_ahead; + total_read += read_ahead; + } + + if (total_need < READAHEAD_BUFFER_SIZE) { + if (!ReadFile + (context->hidden.win32io.h, context->hidden.win32io.buffer.data, + READAHEAD_BUFFER_SIZE, &byte_read, NULL)) { + SDL_Error(SDL_EFREAD); + return 0; + } + read_ahead = SDL_min(total_need, (int) byte_read); + SDL_memcpy(ptr, context->hidden.win32io.buffer.data, read_ahead); + context->hidden.win32io.buffer.size = byte_read; + context->hidden.win32io.buffer.left = byte_read - read_ahead; + total_read += read_ahead; + } else { + if (!ReadFile + (context->hidden.win32io.h, ptr, total_need, &byte_read, NULL)) { + SDL_Error(SDL_EFREAD); + return 0; + } + total_read += byte_read; } - nread = byte_read / size; - return nread; + return (total_read / size); } static int SDLCALL win32_file_write(SDL_RWops * context, const void *ptr, int size, int num) @@ -186,10 +234,17 @@ win32_file_write(SDL_RWops * context, const void *ptr, int size, int num) || total_bytes <= 0 || !size) return 0; + if (context->hidden.win32io.buffer.left) { + SetFilePointer(context->hidden.win32io.h, + -context->hidden.win32io.buffer.left, NULL, + FILE_CURRENT); + context->hidden.win32io.buffer.left = 0; + } + /* if in append mode, we must go to the EOF before write */ if (context->hidden.win32io.append) { - if (SetFilePointer(context->hidden.win32io.h, 0L, NULL, FILE_END) - == INVALID_SET_FILE_POINTER) { + if (SetFilePointer(context->hidden.win32io.h, 0L, NULL, FILE_END) == + INVALID_SET_FILE_POINTER) { SDL_Error(SDL_EFWRITE); return 0; } @@ -213,6 +268,10 @@ win32_file_close(SDL_RWops * context) CloseHandle(context->hidden.win32io.h); context->hidden.win32io.h = INVALID_HANDLE_VALUE; /* to be sure */ } + if (context->hidden.win32io.buffer.data) { + SDL_free(context->hidden.win32io.buffer.data); + context->hidden.win32io.buffer.data = NULL; + } SDL_FreeRW(context); } return (0);