Skip to content
Permalink
Browse files

Added read-ahead support for Win32 file IO

  • Loading branch information
slouken committed Jul 10, 2007
1 parent 104464a commit 2d3f920aa68fd4ff74b54cb8688eb3b8b3347524
Showing with 76 additions and 17 deletions.
  1. +8 −3 include/SDL_rwops.h
  2. +68 −14 src/file/SDL_rwops.c
@@ -62,10 +62,15 @@ typedef struct SDL_RWops {

Uint32 type;
union {
#ifdef __WIN32__
#if defined(__WIN32__) && !defined(__SYMBIAN32__)
struct {
int append;
void* h;
int append;
void *h;
struct {
void *data;
int size;
int left;
} buffer;
} win32io;
#endif
#ifdef HAVE_STDIO_H
@@ -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)
{
#ifndef _WIN32_WCE
@@ -58,6 +60,14 @@ static int SDLCALL win32_file_open(SDL_RWops *context, const char *filename, con

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 */
@@ -117,7 +127,13 @@ static int SDLCALL win32_file_seek(SDL_RWops *context, int offset, int whence)
SDL_SetError("win32_file_seek: invalid context/file not opened");
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; break;
@@ -129,7 +145,7 @@ static int SDLCALL win32_file_seek(SDL_RWops *context, int offset, int whence)
SDL_SetError("win32_file_seek: Unknown value for 'whence'");
return -1;
}

file_pos = SetFilePointer(context->hidden.win32io.h,offset,NULL,win32whence);

if ( file_pos != INVALID_SET_FILE_POINTER )
@@ -140,21 +156,50 @@ static int SDLCALL 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)
return 0;

if (!ReadFile(context->hidden.win32io.h,ptr,total_bytes,&byte_read,NULL)) {
SDL_Error(SDL_EFREAD);
if (!context || context->hidden.win32io.h == INVALID_HANDLE_VALUE || total_need<=0 || !size)
return 0;
}
nread = byte_read/size;
return nread;

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, 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;
}
return (total_read/size);
}
static int SDLCALL win32_file_write(SDL_RWops *context, const void *ptr, int size, int num)
{
@@ -167,6 +212,11 @@ static int SDLCALL win32_file_write(SDL_RWops *context, const void *ptr, int siz
if (!context || context->hidden.win32io.h==INVALID_HANDLE_VALUE || 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 ) {
@@ -191,6 +241,10 @@ static int SDLCALL 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);

0 comments on commit 2d3f920

Please sign in to comment.