Mercurial > sdl-ios-xcode
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 } |