Commit 8daaa10d authored by Sam Lantinga's avatar Sam Lantinga

Merged read-ahead support for Win32 file I/O from SDL 1.2 revision 3183

--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%402456
parent f7d87960
...@@ -76,6 +76,12 @@ typedef struct SDL_RWops ...@@ -76,6 +76,12 @@ typedef struct SDL_RWops
{ {
int append; int append;
void *h; void *h;
struct
{
void *data;
int size;
int left;
} buffer;
} win32io; } win32io;
#endif #endif
#ifdef HAVE_STDIO_H #ifdef HAVE_STDIO_H
......
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
#include "SDL_rwops.h" #include "SDL_rwops.h"
#if defined(__WIN32__) #ifdef __WIN32__
/* Functions to read/write Win32 API file pointers */ /* Functions to read/write Win32 API file pointers */
/* Will not use it on WinCE because stdio is buffered, it means /* Will not use it on WinCE because stdio is buffered, it means
...@@ -43,6 +43,8 @@ ...@@ -43,6 +43,8 @@
#define INVALID_SET_FILE_POINTER 0xFFFFFFFF #define INVALID_SET_FILE_POINTER 0xFFFFFFFF
#endif #endif
#define READAHEAD_BUFFER_SIZE 1024
static int SDLCALL static int SDLCALL
win32_file_open(SDL_RWops * context, const char *filename, const char *mode) 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) ...@@ -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.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 */ /* "r" = reading, file must exist */
/* "w" = writing, truncate existing, file may not exist */ /* "w" = writing, truncate existing, file may not exist */
/* "r+"= reading or writing, file must exist */ /* "r+"= reading or writing, file must exist */
...@@ -128,6 +139,12 @@ win32_file_seek(SDL_RWops * context, int offset, int whence) ...@@ -128,6 +139,12 @@ win32_file_seek(SDL_RWops * context, int offset, int whence)
return -1; 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) { switch (whence) {
case RW_SEEK_SET: case RW_SEEK_SET:
win32whence = FILE_BEGIN; win32whence = FILE_BEGIN;
...@@ -155,23 +172,54 @@ win32_file_seek(SDL_RWops * context, int offset, int whence) ...@@ -155,23 +172,54 @@ win32_file_seek(SDL_RWops * context, int offset, int whence)
static int SDLCALL static int SDLCALL
win32_file_read(SDL_RWops * context, void *ptr, int size, int maxnum) 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; total_need = size * maxnum;
DWORD byte_read, nread;
total_bytes = size * maxnum;
if (!context || context->hidden.win32io.h == INVALID_HANDLE_VALUE if (!context || context->hidden.win32io.h == INVALID_HANDLE_VALUE
|| total_bytes <= 0 || !size) || total_need <= 0 || !size)
return 0; return 0;
if (!ReadFile if (context->hidden.win32io.buffer.left > 0) {
(context->hidden.win32io.h, ptr, total_bytes, &byte_read, NULL)) { void *data = (char *) context->hidden.win32io.buffer.data +
SDL_Error(SDL_EFREAD); context->hidden.win32io.buffer.size -
return 0; 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 (total_read / size);
return nread;
} }
static int SDLCALL static int SDLCALL
win32_file_write(SDL_RWops * context, const void *ptr, int size, int num) 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) ...@@ -186,10 +234,17 @@ win32_file_write(SDL_RWops * context, const void *ptr, int size, int num)
|| total_bytes <= 0 || !size) || total_bytes <= 0 || !size)
return 0; 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 in append mode, we must go to the EOF before write */
if (context->hidden.win32io.append) { if (context->hidden.win32io.append) {
if (SetFilePointer(context->hidden.win32io.h, 0L, NULL, FILE_END) if (SetFilePointer(context->hidden.win32io.h, 0L, NULL, FILE_END) ==
== INVALID_SET_FILE_POINTER) { INVALID_SET_FILE_POINTER) {
SDL_Error(SDL_EFWRITE); SDL_Error(SDL_EFWRITE);
return 0; return 0;
} }
...@@ -213,6 +268,10 @@ win32_file_close(SDL_RWops * context) ...@@ -213,6 +268,10 @@ win32_file_close(SDL_RWops * context)
CloseHandle(context->hidden.win32io.h); CloseHandle(context->hidden.win32io.h);
context->hidden.win32io.h = INVALID_HANDLE_VALUE; /* to be sure */ 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); SDL_FreeRW(context);
} }
return (0); return (0);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment