Added read-ahead support for Win32 file IO SDL-1.2
authorSam Lantinga <slouken@libsdl.org>
Tue, 10 Jul 2007 04:01:46 +0000
branchSDL-1.2
changeset 4026255b0469ca83
parent 4025 3ee8c808638b
child 4027 407ecf3ad3b3
Added read-ahead support for Win32 file IO
include/SDL_rwops.h
src/file/SDL_rwops.c
     1.1 --- a/include/SDL_rwops.h	Mon Jul 09 00:26:21 2007 +0000
     1.2 +++ b/include/SDL_rwops.h	Tue Jul 10 04:01:46 2007 +0000
     1.3 @@ -62,10 +62,15 @@
     1.4  
     1.5  	Uint32 type;
     1.6  	union {
     1.7 -#ifdef __WIN32__
     1.8 +#if defined(__WIN32__) && !defined(__SYMBIAN32__)
     1.9  	    struct {
    1.10 -		int    append;
    1.11 -		void*  h;
    1.12 +		int   append;
    1.13 +		void *h;
    1.14 +		struct {
    1.15 +		    void *data;
    1.16 +		    int size;
    1.17 +		    int left;
    1.18 +		} buffer;
    1.19  	    } win32io;
    1.20  #endif
    1.21  #ifdef HAVE_STDIO_H 
     2.1 --- a/src/file/SDL_rwops.c	Mon Jul 09 00:26:21 2007 +0000
     2.2 +++ b/src/file/SDL_rwops.c	Tue Jul 10 04:01:46 2007 +0000
     2.3 @@ -43,6 +43,8 @@
     2.4  #define INVALID_SET_FILE_POINTER 0xFFFFFFFF
     2.5  #endif
     2.6  
     2.7 +#define READAHEAD_BUFFER_SIZE	1024
     2.8 +
     2.9  static int SDLCALL win32_file_open(SDL_RWops *context, const char *filename, const char *mode)
    2.10  {
    2.11  #ifndef _WIN32_WCE
    2.12 @@ -58,6 +60,14 @@
    2.13  		
    2.14  	context->hidden.win32io.h = INVALID_HANDLE_VALUE; /* mark this as unusable */
    2.15  
    2.16 +	context->hidden.win32io.buffer.data = (char *)SDL_malloc(READAHEAD_BUFFER_SIZE);
    2.17 +	if (!context->hidden.win32io.buffer.data) {
    2.18 +		SDL_OutOfMemory();
    2.19 +		return -1;
    2.20 +	}
    2.21 +	context->hidden.win32io.buffer.size = 0;
    2.22 +	context->hidden.win32io.buffer.left = 0;
    2.23 +
    2.24  	/* "r" = reading, file must exist */
    2.25  	/* "w" = writing, truncate existing, file may not exist */
    2.26  	/* "r+"= reading or writing, file must exist            */
    2.27 @@ -117,7 +127,13 @@
    2.28  		SDL_SetError("win32_file_seek: invalid context/file not opened");
    2.29  		return -1;
    2.30  	}
    2.31 -	
    2.32 +
    2.33 +	/* FIXME: We may be able to satisfy the seek within buffered data */
    2.34 +	if (whence == RW_SEEK_CUR && context->hidden.win32io.buffer.left) {
    2.35 +		offset -= context->hidden.win32io.buffer.left;
    2.36 +    }
    2.37 +    context->hidden.win32io.buffer.left = 0;
    2.38 +
    2.39  	switch (whence) {
    2.40  		case RW_SEEK_SET:		
    2.41  			win32whence = FILE_BEGIN; break;
    2.42 @@ -129,7 +145,7 @@
    2.43  			SDL_SetError("win32_file_seek: Unknown value for 'whence'");			
    2.44  			return -1;
    2.45  	}
    2.46 -	
    2.47 +
    2.48  	file_pos = SetFilePointer(context->hidden.win32io.h,offset,NULL,win32whence);
    2.49  
    2.50  	if ( file_pos != INVALID_SET_FILE_POINTER )
    2.51 @@ -140,21 +156,50 @@
    2.52  }
    2.53  static int SDLCALL win32_file_read(SDL_RWops *context, void *ptr, int size, int maxnum)
    2.54  {
    2.55 -	
    2.56 -	int		total_bytes; 
    2.57 -	DWORD	byte_read,nread;
    2.58 +	int		total_need; 
    2.59 +	int		total_read = 0; 
    2.60 +    int     read_ahead;
    2.61 +	DWORD	byte_read;
    2.62  	
    2.63 -	total_bytes = size*maxnum;
    2.64 +	total_need = size*maxnum;
    2.65  	
    2.66 -	if (!context || context->hidden.win32io.h == INVALID_HANDLE_VALUE || total_bytes<=0 || !size) 	
    2.67 +	if (!context || context->hidden.win32io.h == INVALID_HANDLE_VALUE || total_need<=0 || !size) 	
    2.68  		return 0;
    2.69 -	
    2.70 -	if (!ReadFile(context->hidden.win32io.h,ptr,total_bytes,&byte_read,NULL)) {
    2.71 -		SDL_Error(SDL_EFREAD);
    2.72 -		return 0;
    2.73 -	}
    2.74 -	nread = byte_read/size;
    2.75 -	return nread;
    2.76 +
    2.77 +    if (context->hidden.win32io.buffer.left > 0) {
    2.78 +        void *data = (char *)context->hidden.win32io.buffer.data +
    2.79 +                             context->hidden.win32io.buffer.size -
    2.80 +                             context->hidden.win32io.buffer.left;
    2.81 +        read_ahead = SDL_min(total_need, context->hidden.win32io.buffer.left); 
    2.82 +        SDL_memcpy(ptr, data, read_ahead);
    2.83 +        context->hidden.win32io.buffer.left -= read_ahead;
    2.84 +
    2.85 +        if (read_ahead == total_need) {
    2.86 +            return maxnum;
    2.87 +        }
    2.88 +        ptr = (char *)ptr + read_ahead;
    2.89 +        total_need -= read_ahead;       
    2.90 +		total_read += read_ahead;
    2.91 +    }
    2.92 +
    2.93 +    if (total_need < READAHEAD_BUFFER_SIZE) {
    2.94 +        if (!ReadFile(context->hidden.win32io.h,context->hidden.win32io.buffer.data,READAHEAD_BUFFER_SIZE,&byte_read,NULL)) {
    2.95 +            SDL_Error(SDL_EFREAD);
    2.96 +            return 0;
    2.97 +        }
    2.98 +        read_ahead = SDL_min(total_need, byte_read);
    2.99 +        SDL_memcpy(ptr, context->hidden.win32io.buffer.data, read_ahead);
   2.100 +        context->hidden.win32io.buffer.size = byte_read;
   2.101 +        context->hidden.win32io.buffer.left = byte_read-read_ahead;
   2.102 +        total_read += read_ahead;
   2.103 +    } else {
   2.104 +        if (!ReadFile(context->hidden.win32io.h,ptr,total_need,&byte_read,NULL)) {
   2.105 +            SDL_Error(SDL_EFREAD);
   2.106 +            return 0;
   2.107 +        }
   2.108 +        total_read += byte_read;
   2.109 +    }
   2.110 +	return (total_read/size);
   2.111  }
   2.112  static int SDLCALL win32_file_write(SDL_RWops *context, const void *ptr, int size, int num)
   2.113  {
   2.114 @@ -167,6 +212,11 @@
   2.115  	if (!context || context->hidden.win32io.h==INVALID_HANDLE_VALUE || total_bytes<=0 || !size) 	
   2.116  		return 0;
   2.117  
   2.118 +	if (context->hidden.win32io.buffer.left) {
   2.119 +		SetFilePointer(context->hidden.win32io.h,-context->hidden.win32io.buffer.left,NULL,FILE_CURRENT);
   2.120 +		context->hidden.win32io.buffer.left = 0;
   2.121 +	}
   2.122 +
   2.123  	/* if in append mode, we must go to the EOF before write */
   2.124  	if (context->hidden.win32io.append) {
   2.125  		if ( SetFilePointer(context->hidden.win32io.h,0L,NULL,FILE_END) == INVALID_SET_FILE_POINTER ) {
   2.126 @@ -191,6 +241,10 @@
   2.127  			CloseHandle(context->hidden.win32io.h);
   2.128  			context->hidden.win32io.h = INVALID_HANDLE_VALUE; /* to be sure */
   2.129  		}
   2.130 +		if (context->hidden.win32io.buffer.data) {
   2.131 +			SDL_free(context->hidden.win32io.buffer.data);
   2.132 +			context->hidden.win32io.buffer.data = NULL;
   2.133 +		}
   2.134  		SDL_FreeRW(context);
   2.135  	}
   2.136  	return(0);