comparison src/file/SDL_rwops.c @ 4026:255b0469ca83 SDL-1.2

Added read-ahead support for Win32 file IO
author Sam Lantinga <slouken@libsdl.org>
date Tue, 10 Jul 2007 04:01:46 +0000
parents e85e65aec22f
children 407ecf3ad3b3
comparison
equal deleted inserted replaced
4025:3ee8c808638b 4026:255b0469ca83
40 #include <windows.h> 40 #include <windows.h>
41 41
42 #ifndef INVALID_SET_FILE_POINTER 42 #ifndef INVALID_SET_FILE_POINTER
43 #define INVALID_SET_FILE_POINTER 0xFFFFFFFF 43 #define INVALID_SET_FILE_POINTER 0xFFFFFFFF
44 #endif 44 #endif
45
46 #define READAHEAD_BUFFER_SIZE 1024
45 47
46 static int SDLCALL win32_file_open(SDL_RWops *context, const char *filename, const char *mode) 48 static int SDLCALL win32_file_open(SDL_RWops *context, const char *filename, const char *mode)
47 { 49 {
48 #ifndef _WIN32_WCE 50 #ifndef _WIN32_WCE
49 UINT old_error_mode; 51 UINT old_error_mode;
55 57
56 if (!context) 58 if (!context)
57 return -1; 59 return -1;
58 60
59 context->hidden.win32io.h = INVALID_HANDLE_VALUE; /* mark this as unusable */ 61 context->hidden.win32io.h = INVALID_HANDLE_VALUE; /* mark this as unusable */
62
63 context->hidden.win32io.buffer.data = (char *)SDL_malloc(READAHEAD_BUFFER_SIZE);
64 if (!context->hidden.win32io.buffer.data) {
65 SDL_OutOfMemory();
66 return -1;
67 }
68 context->hidden.win32io.buffer.size = 0;
69 context->hidden.win32io.buffer.left = 0;
60 70
61 /* "r" = reading, file must exist */ 71 /* "r" = reading, file must exist */
62 /* "w" = writing, truncate existing, file may not exist */ 72 /* "w" = writing, truncate existing, file may not exist */
63 /* "r+"= reading or writing, file must exist */ 73 /* "r+"= reading or writing, file must exist */
64 /* "a" = writing, append file may not exist */ 74 /* "a" = writing, append file may not exist */
115 125
116 if (!context || context->hidden.win32io.h == INVALID_HANDLE_VALUE) { 126 if (!context || context->hidden.win32io.h == INVALID_HANDLE_VALUE) {
117 SDL_SetError("win32_file_seek: invalid context/file not opened"); 127 SDL_SetError("win32_file_seek: invalid context/file not opened");
118 return -1; 128 return -1;
119 } 129 }
120 130
131 /* FIXME: We may be able to satisfy the seek within buffered data */
132 if (whence == RW_SEEK_CUR && context->hidden.win32io.buffer.left) {
133 offset -= context->hidden.win32io.buffer.left;
134 }
135 context->hidden.win32io.buffer.left = 0;
136
121 switch (whence) { 137 switch (whence) {
122 case RW_SEEK_SET: 138 case RW_SEEK_SET:
123 win32whence = FILE_BEGIN; break; 139 win32whence = FILE_BEGIN; break;
124 case RW_SEEK_CUR: 140 case RW_SEEK_CUR:
125 win32whence = FILE_CURRENT; break; 141 win32whence = FILE_CURRENT; break;
127 win32whence = FILE_END; break; 143 win32whence = FILE_END; break;
128 default: 144 default:
129 SDL_SetError("win32_file_seek: Unknown value for 'whence'"); 145 SDL_SetError("win32_file_seek: Unknown value for 'whence'");
130 return -1; 146 return -1;
131 } 147 }
132 148
133 file_pos = SetFilePointer(context->hidden.win32io.h,offset,NULL,win32whence); 149 file_pos = SetFilePointer(context->hidden.win32io.h,offset,NULL,win32whence);
134 150
135 if ( file_pos != INVALID_SET_FILE_POINTER ) 151 if ( file_pos != INVALID_SET_FILE_POINTER )
136 return file_pos; /* success */ 152 return file_pos; /* success */
137 153
138 SDL_Error(SDL_EFSEEK); 154 SDL_Error(SDL_EFSEEK);
139 return -1; /* error */ 155 return -1; /* error */
140 } 156 }
141 static int SDLCALL win32_file_read(SDL_RWops *context, void *ptr, int size, int maxnum) 157 static int SDLCALL win32_file_read(SDL_RWops *context, void *ptr, int size, int maxnum)
142 { 158 {
143 159 int total_need;
144 int total_bytes; 160 int total_read = 0;
145 DWORD byte_read,nread; 161 int read_ahead;
146 162 DWORD byte_read;
147 total_bytes = size*maxnum; 163
148 164 total_need = size*maxnum;
149 if (!context || context->hidden.win32io.h == INVALID_HANDLE_VALUE || total_bytes<=0 || !size) 165
166 if (!context || context->hidden.win32io.h == INVALID_HANDLE_VALUE || total_need<=0 || !size)
150 return 0; 167 return 0;
151 168
152 if (!ReadFile(context->hidden.win32io.h,ptr,total_bytes,&byte_read,NULL)) { 169 if (context->hidden.win32io.buffer.left > 0) {
153 SDL_Error(SDL_EFREAD); 170 void *data = (char *)context->hidden.win32io.buffer.data +
154 return 0; 171 context->hidden.win32io.buffer.size -
155 } 172 context->hidden.win32io.buffer.left;
156 nread = byte_read/size; 173 read_ahead = SDL_min(total_need, context->hidden.win32io.buffer.left);
157 return nread; 174 SDL_memcpy(ptr, data, read_ahead);
175 context->hidden.win32io.buffer.left -= read_ahead;
176
177 if (read_ahead == total_need) {
178 return maxnum;
179 }
180 ptr = (char *)ptr + read_ahead;
181 total_need -= read_ahead;
182 total_read += read_ahead;
183 }
184
185 if (total_need < READAHEAD_BUFFER_SIZE) {
186 if (!ReadFile(context->hidden.win32io.h,context->hidden.win32io.buffer.data,READAHEAD_BUFFER_SIZE,&byte_read,NULL)) {
187 SDL_Error(SDL_EFREAD);
188 return 0;
189 }
190 read_ahead = SDL_min(total_need, byte_read);
191 SDL_memcpy(ptr, context->hidden.win32io.buffer.data, read_ahead);
192 context->hidden.win32io.buffer.size = byte_read;
193 context->hidden.win32io.buffer.left = byte_read-read_ahead;
194 total_read += read_ahead;
195 } else {
196 if (!ReadFile(context->hidden.win32io.h,ptr,total_need,&byte_read,NULL)) {
197 SDL_Error(SDL_EFREAD);
198 return 0;
199 }
200 total_read += byte_read;
201 }
202 return (total_read/size);
158 } 203 }
159 static int SDLCALL win32_file_write(SDL_RWops *context, const void *ptr, int size, int num) 204 static int SDLCALL win32_file_write(SDL_RWops *context, const void *ptr, int size, int num)
160 { 205 {
161 206
162 int total_bytes; 207 int total_bytes;
164 209
165 total_bytes = size*num; 210 total_bytes = size*num;
166 211
167 if (!context || context->hidden.win32io.h==INVALID_HANDLE_VALUE || total_bytes<=0 || !size) 212 if (!context || context->hidden.win32io.h==INVALID_HANDLE_VALUE || total_bytes<=0 || !size)
168 return 0; 213 return 0;
214
215 if (context->hidden.win32io.buffer.left) {
216 SetFilePointer(context->hidden.win32io.h,-context->hidden.win32io.buffer.left,NULL,FILE_CURRENT);
217 context->hidden.win32io.buffer.left = 0;
218 }
169 219
170 /* if in append mode, we must go to the EOF before write */ 220 /* if in append mode, we must go to the EOF before write */
171 if (context->hidden.win32io.append) { 221 if (context->hidden.win32io.append) {
172 if ( SetFilePointer(context->hidden.win32io.h,0L,NULL,FILE_END) == INVALID_SET_FILE_POINTER ) { 222 if ( SetFilePointer(context->hidden.win32io.h,0L,NULL,FILE_END) == INVALID_SET_FILE_POINTER ) {
173 SDL_Error(SDL_EFWRITE); 223 SDL_Error(SDL_EFWRITE);
188 238
189 if ( context ) { 239 if ( context ) {
190 if (context->hidden.win32io.h != INVALID_HANDLE_VALUE) { 240 if (context->hidden.win32io.h != INVALID_HANDLE_VALUE) {
191 CloseHandle(context->hidden.win32io.h); 241 CloseHandle(context->hidden.win32io.h);
192 context->hidden.win32io.h = INVALID_HANDLE_VALUE; /* to be sure */ 242 context->hidden.win32io.h = INVALID_HANDLE_VALUE; /* to be sure */
243 }
244 if (context->hidden.win32io.buffer.data) {
245 SDL_free(context->hidden.win32io.buffer.data);
246 context->hidden.win32io.buffer.data = NULL;
193 } 247 }
194 SDL_FreeRW(context); 248 SDL_FreeRW(context);
195 } 249 }
196 return(0); 250 return(0);
197 } 251 }