|
1 /* |
|
2 * Copyright (c) 1999 |
|
3 * Silicon Graphics Computer Systems, Inc. |
|
4 * |
|
5 * Copyright (c) 1999 |
|
6 * Boris Fomitchev |
|
7 * |
|
8 * This material is provided "as is", with absolutely no warranty expressed |
|
9 * or implied. Any use is at your own risk. |
|
10 * |
|
11 * Permission to use or copy this software for any purpose is hereby granted |
|
12 * without fee, provided the above notices are retained on all copies. |
|
13 * Permission to modify the code and to distribute modified code is granted, |
|
14 * provided the above notices are retained, and a notice that the code was |
|
15 * modified is included with the above copyright notice. |
|
16 * |
|
17 */ |
|
18 |
|
19 #include <fstream> |
|
20 |
|
21 #if !defined (_STLP_WCE) |
|
22 # ifdef __BORLANDC__ |
|
23 # include <cfcntl.h> // For _O_RDONLY, etc |
|
24 # else |
|
25 # include <io.h> // For _get_osfhandle |
|
26 # include <fcntl.h> // For _O_RDONLY, etc |
|
27 # endif |
|
28 # include <sys/stat.h> // For _fstat |
|
29 #endif |
|
30 |
|
31 #define _TEXTBUF_SIZE 0x1000 |
|
32 |
|
33 const _STLP_fd INVALID_STLP_FD = INVALID_HANDLE_VALUE; |
|
34 |
|
35 #if !defined (INVALID_SET_FILE_POINTER) |
|
36 # define INVALID_SET_FILE_POINTER 0xffffffff |
|
37 #endif |
|
38 |
|
39 #ifndef O_ACCMODE |
|
40 # define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR) |
|
41 #endif |
|
42 |
|
43 _STLP_BEGIN_NAMESPACE |
|
44 |
|
45 #if !defined(__MSL__) && !defined(_STLP_WCE) |
|
46 static ios_base::openmode flag_to_openmode(int mode) { |
|
47 ios_base::openmode ret = ios_base::__default_mode; |
|
48 |
|
49 switch (mode & O_ACCMODE) { |
|
50 case O_RDONLY: |
|
51 ret = ios_base::in; break; |
|
52 case O_WRONLY: |
|
53 ret = ios_base::out; break; |
|
54 case O_RDWR: |
|
55 ret = ios_base::in | ios_base::out; break; |
|
56 } |
|
57 |
|
58 if (mode & O_APPEND) |
|
59 ret |= ios_base::app; |
|
60 |
|
61 if (mode & O_BINARY) |
|
62 ret |= ios_base::binary; |
|
63 |
|
64 return ret; |
|
65 } |
|
66 #endif |
|
67 |
|
68 _STLP_MOVE_TO_PRIV_NAMESPACE |
|
69 |
|
70 // Helper functions for _Filebuf_base. |
|
71 |
|
72 static bool __is_regular_file(_STLP_fd fd) { |
|
73 BY_HANDLE_FILE_INFORMATION info; |
|
74 |
|
75 // Return true if the file handle isn't a directory. |
|
76 return GetFileInformationByHandle(fd, &info) && |
|
77 ((info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0); |
|
78 } |
|
79 |
|
80 // Number of characters in the file. |
|
81 static streamoff __file_size(_STLP_fd fd) { |
|
82 streamoff ret = 0; |
|
83 |
|
84 LARGE_INTEGER li; |
|
85 li.LowPart = GetFileSize(fd, (unsigned long*) &li.HighPart); |
|
86 if (li.LowPart != INVALID_FILE_SIZE || GetLastError() == NO_ERROR) |
|
87 ret = li.QuadPart; |
|
88 |
|
89 return ret; |
|
90 } |
|
91 |
|
92 _STLP_MOVE_TO_STD_NAMESPACE |
|
93 |
|
94 // Visual C++ and Intel use this, but not Metrowerks |
|
95 // Also MinGW, msvcrt.dll (but not crtdll.dll) dependent version |
|
96 #if (defined (_STLP_MSVC_LIB) && !defined (_STLP_WCE)) || \ |
|
97 (defined (__MINGW32__) && defined (__MSVCRT__)) |
|
98 |
|
99 // fcntl(fileno, F_GETFL) for Microsoft library |
|
100 // 'semi-documented' defines: |
|
101 # define IOINFO_L2E 5 |
|
102 # define IOINFO_ARRAY_ELTS (1 << IOINFO_L2E) |
|
103 # define _pioinfo(i) ( __pioinfo[(i) >> IOINFO_L2E] + \ |
|
104 ((i) & (IOINFO_ARRAY_ELTS - 1)) ) |
|
105 # define FAPPEND 0x20 // O_APPEND flag |
|
106 # define FTEXT 0x80 // O_TEXT flag |
|
107 // end of 'semi-documented' defines |
|
108 |
|
109 // 'semi-documented' internal structure |
|
110 extern "C" { |
|
111 struct ioinfo { |
|
112 long osfhnd; // the real os HANDLE |
|
113 char osfile; // file handle flags |
|
114 char pipech; // pipe buffer |
|
115 # if defined (_MT) |
|
116 // multi-threaded locking |
|
117 int lockinitflag; |
|
118 CRITICAL_SECTION lock; |
|
119 # endif |
|
120 }; |
|
121 # if defined (__MINGW32__) |
|
122 __MINGW_IMPORT ioinfo * __pioinfo[]; |
|
123 # else |
|
124 extern _CRTIMP ioinfo * __pioinfo[]; |
|
125 # endif |
|
126 } // extern "C" |
|
127 // end of 'semi-documented' declarations |
|
128 |
|
129 static ios_base::openmode _get_osfflags(int fd, HANDLE oshandle) { |
|
130 char dosflags = 0; |
|
131 if (fd >= 0) |
|
132 dosflags = _pioinfo(fd)->osfile; |
|
133 //else |
|
134 //the file will be considered as open in binary mode with no append attribute |
|
135 // end of 'semi-documented' stuff |
|
136 |
|
137 int mode = 0; |
|
138 if (dosflags & FAPPEND) |
|
139 mode |= O_APPEND; |
|
140 |
|
141 if (dosflags & FTEXT) |
|
142 mode |= O_TEXT; |
|
143 else |
|
144 mode |= O_BINARY; |
|
145 |
|
146 // For Read/Write access we have to guess |
|
147 DWORD dummy, dummy2; |
|
148 BOOL writeOk = WriteFile(oshandle, &dummy2, 0, &dummy, 0); |
|
149 BOOL readOk = ReadFile(oshandle, &dummy2, 0, &dummy, NULL); |
|
150 if (writeOk && readOk) |
|
151 mode |= O_RDWR; |
|
152 else if (readOk) |
|
153 mode |= O_RDONLY; |
|
154 else |
|
155 mode |= O_WRONLY; |
|
156 |
|
157 return flag_to_openmode(mode); |
|
158 } |
|
159 |
|
160 #elif defined (__DMC__) |
|
161 |
|
162 # define FHND_APPEND 0x04 |
|
163 # define FHND_DEVICE 0x08 |
|
164 # define FHND_TEXT 0x10 |
|
165 |
|
166 extern "C" unsigned char __fhnd_info[_NFILE]; |
|
167 |
|
168 static ios_base::openmode _get_osfflags(int fd, HANDLE oshandle) { |
|
169 int mode = 0; |
|
170 |
|
171 if (__fhnd_info[fd] & FHND_APPEND) |
|
172 mode |= O_APPEND; |
|
173 |
|
174 if (__fhnd_info[fd] & FHND_TEXT == 0) |
|
175 mode |= O_BINARY; |
|
176 |
|
177 for (FILE *fp = &_iob[0]; fp < &_iob[_NFILE]; fp++) { |
|
178 if ((fileno(fp) == fd) && (fp->_flag & (_IOREAD | _IOWRT | _IORW))) { |
|
179 const int osflags = fp->_flag; |
|
180 |
|
181 if ((osflags & _IOREAD) && !(osflags & _IOWRT) && !(osflags & _IORW)) |
|
182 mode |= O_RDONLY; |
|
183 else if ((osflags & _IOWRT) && !(osflags & _IOREAD) && !(osflags & _IORW)) |
|
184 mode |= O_WRONLY; |
|
185 else |
|
186 mode |= O_RDWR; |
|
187 break; |
|
188 } |
|
189 } |
|
190 |
|
191 return flag_to_openmode(mode); |
|
192 } |
|
193 #endif |
|
194 |
|
195 size_t _Filebuf_base::_M_page_size = 4096; |
|
196 |
|
197 _Filebuf_base::_Filebuf_base() |
|
198 : _M_file_id(INVALID_STLP_FD), |
|
199 _M_openmode(0), |
|
200 _M_is_open(false), |
|
201 _M_should_close(false), |
|
202 _M_view_id(0) |
|
203 {} |
|
204 |
|
205 void _Filebuf_base::_S_initialize() { |
|
206 SYSTEM_INFO SystemInfo; |
|
207 GetSystemInfo(&SystemInfo); |
|
208 _M_page_size = SystemInfo.dwPageSize; |
|
209 // might be .dwAllocationGranularity |
|
210 } |
|
211 |
|
212 // Return the size of the file. This is a wrapper for stat. |
|
213 // Returns zero if the size cannot be determined or is ill-defined. |
|
214 streamoff _Filebuf_base::_M_file_size() { |
|
215 return _STLP_PRIV __file_size(_M_file_id); |
|
216 } |
|
217 |
|
218 bool _Filebuf_base::_M_open(const char* name, ios_base::openmode openmode, |
|
219 long permission) { |
|
220 _STLP_fd file_no; |
|
221 |
|
222 if (_M_is_open) |
|
223 return false; |
|
224 |
|
225 DWORD dwDesiredAccess, dwCreationDisposition; |
|
226 bool doTruncate = false; |
|
227 |
|
228 switch (openmode & (~ios_base::ate & ~ios_base::binary)) { |
|
229 case ios_base::out: |
|
230 case ios_base::out | ios_base::trunc: |
|
231 dwDesiredAccess = GENERIC_WRITE; |
|
232 dwCreationDisposition = OPEN_ALWAYS; |
|
233 // boris : even though it is very non-intuitive, standard |
|
234 // requires them both to behave same. |
|
235 doTruncate = true; |
|
236 break; |
|
237 case ios_base::out | ios_base::app: |
|
238 dwDesiredAccess = GENERIC_WRITE; |
|
239 dwCreationDisposition = OPEN_ALWAYS; |
|
240 break; |
|
241 case ios_base::in: |
|
242 dwDesiredAccess = GENERIC_READ; |
|
243 dwCreationDisposition = OPEN_EXISTING; |
|
244 permission = 0; // Irrelevant unless we're writing. |
|
245 break; |
|
246 case ios_base::in | ios_base::out: |
|
247 dwDesiredAccess = GENERIC_READ | GENERIC_WRITE; |
|
248 dwCreationDisposition = OPEN_EXISTING; |
|
249 break; |
|
250 case ios_base::in | ios_base::out | ios_base::trunc: |
|
251 dwDesiredAccess = GENERIC_READ | GENERIC_WRITE; |
|
252 dwCreationDisposition = OPEN_ALWAYS; |
|
253 doTruncate = true; |
|
254 break; |
|
255 default: // The above are the only combinations of |
|
256 return false; // flags allowed by the C++ standard. |
|
257 } |
|
258 |
|
259 DWORD dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; |
|
260 |
|
261 #if defined(_STLP_USE_WIDE_INTERFACE) |
|
262 file_no = CreateFile (_STLP_PRIV __ASCIIToWide(name).c_str(), |
|
263 #else |
|
264 file_no = CreateFileA(name, |
|
265 #endif |
|
266 dwDesiredAccess, dwShareMode, 0, |
|
267 dwCreationDisposition, permission, 0); |
|
268 |
|
269 if (file_no == INVALID_STLP_FD) |
|
270 return false; |
|
271 |
|
272 if ( |
|
273 #if !defined (_STLP_WCE) |
|
274 GetFileType(file_no) == FILE_TYPE_DISK && |
|
275 #endif |
|
276 ((doTruncate && SetEndOfFile(file_no) == 0) || |
|
277 (((openmode & ios_base::ate) != 0) && |
|
278 (SetFilePointer(file_no, 0, NULL, FILE_END) == INVALID_SET_FILE_POINTER)))) { |
|
279 CloseHandle(file_no); |
|
280 return false; |
|
281 } |
|
282 |
|
283 _M_is_open = true; |
|
284 _M_file_id = file_no; |
|
285 _M_should_close = _M_is_open; |
|
286 _M_openmode = openmode; |
|
287 |
|
288 if (_M_is_open) |
|
289 _M_regular_file = _STLP_PRIV __is_regular_file(_M_file_id); |
|
290 |
|
291 return (_M_is_open != 0); |
|
292 } |
|
293 |
|
294 bool _Filebuf_base::_M_open(const char* name, ios_base::openmode openmode) { |
|
295 // This doesn't really grant everyone in the world read/write |
|
296 // access. On Unix, file-creation system calls always clear |
|
297 // bits that are set in the umask from the permissions flag. |
|
298 return this->_M_open(name, openmode, FILE_ATTRIBUTE_NORMAL); |
|
299 } |
|
300 |
|
301 bool _Filebuf_base::_M_open(_STLP_fd __id, ios_base::openmode init_mode) { |
|
302 #if (defined (_STLP_MSVC_LIB) && !defined (_STLP_WCE)) || \ |
|
303 (defined (__MINGW32__) && defined (__MSVCRT__)) || defined (__DMC__) |
|
304 |
|
305 if (_M_is_open || __id == INVALID_STLP_FD) |
|
306 return false; |
|
307 |
|
308 if (init_mode != ios_base::__default_mode) |
|
309 _M_openmode = init_mode; |
|
310 else |
|
311 _M_openmode = _get_osfflags(-1, __id); |
|
312 |
|
313 _M_is_open = true; |
|
314 _M_file_id = __id; |
|
315 _M_should_close = false; |
|
316 _M_regular_file = _STLP_PRIV __is_regular_file(_M_file_id); |
|
317 |
|
318 return true; |
|
319 #else |
|
320 (void)__id; |
|
321 (void)init_mode; // dwa 4/27/00 - suppress unused parameter warning |
|
322 |
|
323 // not available for the API |
|
324 return false; |
|
325 |
|
326 #endif |
|
327 } |
|
328 |
|
329 // Associated the filebuf with a file descriptor pointing to an already- |
|
330 // open file. Mode is set to be consistent with the way that the file |
|
331 // was opened. |
|
332 bool _Filebuf_base::_M_open(int file_no, ios_base::openmode init_mode) { |
|
333 if (_M_is_open || file_no < 0) |
|
334 return false; |
|
335 |
|
336 #if (defined (_STLP_MSVC_LIB) && !defined (_STLP_WCE)) || \ |
|
337 (defined (__MINGW32__) && defined (__MSVCRT__)) || defined (__DMC__) |
|
338 |
|
339 HANDLE oshandle = (HANDLE)_get_osfhandle(file_no); |
|
340 if (oshandle == INVALID_STLP_FD) |
|
341 return false; |
|
342 |
|
343 if (init_mode != ios_base::__default_mode) |
|
344 _M_openmode = init_mode; |
|
345 else |
|
346 _M_openmode = _get_osfflags(file_no, oshandle); |
|
347 |
|
348 _M_file_id = oshandle; |
|
349 _M_is_open = true; |
|
350 _M_should_close = false; |
|
351 _M_regular_file = _STLP_PRIV __is_regular_file(_M_file_id); |
|
352 return true; |
|
353 #else |
|
354 _STLP_MARK_PARAMETER_AS_UNUSED(&init_mode) |
|
355 // not available for the API |
|
356 return false; |
|
357 #endif |
|
358 } |
|
359 |
|
360 bool _Filebuf_base::_M_close() { |
|
361 if (!_M_is_open) |
|
362 return false; |
|
363 |
|
364 bool ok; |
|
365 |
|
366 if (!_M_should_close) |
|
367 ok = true; |
|
368 else { |
|
369 if (_M_file_id != INVALID_STLP_FD) { |
|
370 ok = (CloseHandle(_M_file_id) != 0); |
|
371 } |
|
372 else { |
|
373 ok = false; |
|
374 } |
|
375 } |
|
376 |
|
377 _M_is_open = _M_should_close = false; |
|
378 _M_openmode = 0; |
|
379 return ok; |
|
380 } |
|
381 |
|
382 |
|
383 #define _STLP_LF 10 |
|
384 #define _STLP_CR 13 |
|
385 #define _STLP_CTRLZ 26 |
|
386 |
|
387 // Read up to n characters into a buffer. Return value is number of |
|
388 // characters read. |
|
389 ptrdiff_t _Filebuf_base::_M_read(char* buf, ptrdiff_t n) { |
|
390 ptrdiff_t readen = 0; |
|
391 //Here cast to size_t is safe as n cannot be negative. |
|
392 size_t chunkSize = (min)(size_t(0xffffffff), __STATIC_CAST(size_t, n)); |
|
393 // The following, while validating that we are still able to extract chunkSize |
|
394 // charaters to the buffer, avoids extraction of too small chunk of datas |
|
395 // which would be counter performant. |
|
396 while (__STATIC_CAST(size_t, (n - readen)) >= chunkSize) { |
|
397 DWORD numberOfBytesRead; |
|
398 ReadFile(_M_file_id, buf + readen, __STATIC_CAST(DWORD, chunkSize), &numberOfBytesRead, 0); |
|
399 |
|
400 if (numberOfBytesRead == 0) |
|
401 break; |
|
402 |
|
403 if (!(_M_openmode & ios_base::binary)) { |
|
404 // translate CR-LFs to LFs in the buffer |
|
405 char *to = buf + readen; |
|
406 char *from = to; |
|
407 char *last = from + numberOfBytesRead - 1; |
|
408 for (; from <= last && *from != _STLP_CTRLZ; ++from) { |
|
409 if (*from != _STLP_CR) |
|
410 *to++ = *from; |
|
411 else { // found CR |
|
412 if (from < last) { // not at buffer end |
|
413 if (*(from + 1) != _STLP_LF) |
|
414 *to++ = _STLP_CR; |
|
415 } |
|
416 else { // last char is CR, peek for LF |
|
417 char peek = ' '; |
|
418 DWORD NumberOfBytesPeeked; |
|
419 ReadFile(_M_file_id, (LPVOID)&peek, 1, &NumberOfBytesPeeked, 0); |
|
420 if (NumberOfBytesPeeked != 0) { |
|
421 if (peek != _STLP_LF) { //not a <CR><LF> combination |
|
422 *to++ = _STLP_CR; |
|
423 if ((to < buf + n) && (peek != _STLP_CR)) |
|
424 //We have enough place to store peek and it is no a special |
|
425 //_STLP_CR character, we can store it. |
|
426 *to++ = peek; |
|
427 else |
|
428 SetFilePointer(_M_file_id, (LONG)-1, 0, FILE_CURRENT); |
|
429 } |
|
430 else { |
|
431 // A <CR><LF> combination, we keep the <LF>: |
|
432 *to++ = _STLP_LF; |
|
433 } |
|
434 } |
|
435 else { |
|
436 /* This case is tedious, we could |
|
437 * - put peek back in the file but this would then generate an infinite loop |
|
438 * - report an error as we don't know if in a future call to ReadFile we won't then |
|
439 * get a <LF>. Doing so would make all files with a <CR> last an invalid file |
|
440 * for STLport, a hard solution for STLport clients. |
|
441 * - store the <CR> in the returned buffer, the chosen solution, even if in this |
|
442 * case we could miss a <CR><LF> combination. |
|
443 */ |
|
444 *to++ = _STLP_CR; |
|
445 } |
|
446 } |
|
447 } // found CR |
|
448 } // for |
|
449 readen = to - buf; |
|
450 // seek back to TEXT end of file if hit CTRL-Z |
|
451 if (from <= last) { // terminated due to CTRLZ |
|
452 SetFilePointer(_M_file_id, -(LONG)((last + 1) - from), 0, FILE_CURRENT); |
|
453 break; |
|
454 } |
|
455 } |
|
456 else |
|
457 readen += numberOfBytesRead; |
|
458 } |
|
459 return readen; |
|
460 } |
|
461 |
|
462 // Write n characters from a buffer. Return value: true if we managed |
|
463 // to write the entire buffer, false if we didn't. |
|
464 bool _Filebuf_base::_M_write(char* buf, ptrdiff_t n) { |
|
465 for (;;) { |
|
466 ptrdiff_t written; |
|
467 |
|
468 //In the following implementation we are going to cast most of the ptrdiff_t |
|
469 //values in size_t to work with coherent unsigned values. Doing so make code |
|
470 //more simple especially in the min function call. |
|
471 |
|
472 // In append mode, every write does an implicit seek to the end |
|
473 // of the file. |
|
474 if (_M_openmode & ios_base::app) |
|
475 _M_seek(0, ios_base::end); |
|
476 |
|
477 if (_M_openmode & ios_base::binary) { |
|
478 // binary mode |
|
479 size_t bytes_to_write = (size_t)n; |
|
480 DWORD NumberOfBytesWritten; |
|
481 written = 0; |
|
482 for (; bytes_to_write != 0;) { |
|
483 WriteFile(_M_file_id, buf + written, |
|
484 __STATIC_CAST(DWORD, (min)(size_t(0xffffffff), bytes_to_write)), |
|
485 &NumberOfBytesWritten, 0); |
|
486 if (NumberOfBytesWritten == 0) |
|
487 return false; |
|
488 bytes_to_write -= NumberOfBytesWritten; |
|
489 written += NumberOfBytesWritten; |
|
490 } |
|
491 } |
|
492 else { |
|
493 char textbuf[_TEXTBUF_SIZE + 1]; // extra 1 in case LF at end |
|
494 char * nextblock = buf, * ptrtextbuf = textbuf; |
|
495 char * endtextbuf = textbuf + _TEXTBUF_SIZE; |
|
496 char * endblock = buf + n; |
|
497 ptrdiff_t nextblocksize = (min) (n, (ptrdiff_t)_TEXTBUF_SIZE); |
|
498 char * nextlf; |
|
499 |
|
500 while ( (nextblocksize > 0) && |
|
501 (nextlf = (char *)memchr(nextblock, _STLP_LF, nextblocksize)) != 0) { |
|
502 ptrdiff_t linelength = nextlf - nextblock; |
|
503 memcpy(ptrtextbuf, nextblock, linelength); |
|
504 ptrtextbuf += linelength; |
|
505 nextblock += (linelength + 1); |
|
506 * ptrtextbuf ++ = _STLP_CR; |
|
507 * ptrtextbuf ++ = _STLP_LF; |
|
508 nextblocksize = (min) (ptrdiff_t(endblock - nextblock), |
|
509 (max) (ptrdiff_t(0), ptrdiff_t(endtextbuf - ptrtextbuf))); |
|
510 } |
|
511 // write out what's left, > condition is here since for LF at the end , |
|
512 // endtextbuf may get < ptrtextbuf ... |
|
513 if (nextblocksize > 0) { |
|
514 memcpy(ptrtextbuf, nextblock, nextblocksize); |
|
515 ptrtextbuf += nextblocksize; |
|
516 nextblock += nextblocksize; |
|
517 } |
|
518 // now write out the translated buffer |
|
519 char * writetextbuf = textbuf; |
|
520 for (size_t NumberOfBytesToWrite = (size_t)(ptrtextbuf - textbuf); |
|
521 NumberOfBytesToWrite;) { |
|
522 DWORD NumberOfBytesWritten; |
|
523 WriteFile((HANDLE)_M_file_id, writetextbuf, |
|
524 __STATIC_CAST(DWORD, (min)(size_t(0xffffffff), NumberOfBytesToWrite)), |
|
525 &NumberOfBytesWritten, 0); |
|
526 if (!NumberOfBytesWritten) // write shortfall |
|
527 return false; |
|
528 writetextbuf += NumberOfBytesWritten; |
|
529 NumberOfBytesToWrite -= NumberOfBytesWritten; |
|
530 } |
|
531 // count non-translated characters |
|
532 written = (nextblock - buf); |
|
533 } |
|
534 |
|
535 if (n == written) |
|
536 return true; |
|
537 else if (written > 0 && written < n) { |
|
538 n -= written; |
|
539 buf += written; |
|
540 } |
|
541 else |
|
542 return false; |
|
543 } |
|
544 } |
|
545 |
|
546 // Wrapper for lseek or the like. |
|
547 streamoff _Filebuf_base::_M_seek(streamoff offset, ios_base::seekdir dir) { |
|
548 streamoff result = -1; |
|
549 int whence; |
|
550 |
|
551 switch(dir) { |
|
552 case ios_base::beg: |
|
553 if (offset < 0 /* || offset > _M_file_size() */ ) |
|
554 return streamoff(-1); |
|
555 whence = FILE_BEGIN; |
|
556 break; |
|
557 case ios_base::cur: |
|
558 whence = FILE_CURRENT; |
|
559 break; |
|
560 case ios_base::end: |
|
561 if (/* offset > 0 || */ -offset > _M_file_size() ) |
|
562 return streamoff(-1); |
|
563 whence = FILE_END; |
|
564 break; |
|
565 default: |
|
566 return streamoff(-1); |
|
567 } |
|
568 |
|
569 LARGE_INTEGER li; |
|
570 li.QuadPart = offset; |
|
571 li.LowPart = SetFilePointer(_M_file_id, li.LowPart, &li.HighPart, whence); |
|
572 if (li.LowPart != INVALID_SET_FILE_POINTER || GetLastError() == NO_ERROR) |
|
573 result = li.QuadPart; |
|
574 |
|
575 return result; |
|
576 } |
|
577 |
|
578 |
|
579 // Attempts to memory-map len bytes of the current file, starting |
|
580 // at position offset. Precondition: offset is a multiple of the |
|
581 // page size. Postcondition: return value is a null pointer if the |
|
582 // memory mapping failed. Otherwise the return value is a pointer to |
|
583 // the memory-mapped file and the file position is set to offset. |
|
584 void* _Filebuf_base::_M_mmap(streamoff offset, streamoff len) { |
|
585 void* base; |
|
586 _M_view_id = CreateFileMapping(_M_file_id, (PSECURITY_ATTRIBUTES)0 , |
|
587 PAGE_READONLY, 0 /* len >> 32 */ , |
|
588 0 /* len & 0xFFFFFFFF */ , // low-order DWORD of size |
|
589 0); |
|
590 |
|
591 if (_M_view_id) { |
|
592 #if 0 |
|
593 /* |
|
594 printf("view %x created from file %x, error = %d, size = %d, map_offset = %d map_len = %d\n", |
|
595 _M_view_id, _M_file_id, GetLastError(), |
|
596 (int)cur_filesize, ULL(offset) & 0xffffffff, len); |
|
597 */ |
|
598 #endif |
|
599 LARGE_INTEGER li; |
|
600 li.QuadPart = offset; |
|
601 base = MapViewOfFile(_M_view_id, FILE_MAP_READ, li.HighPart, li.LowPart, |
|
602 #if !defined (__DMC__) |
|
603 __STATIC_CAST(SIZE_T, len)); |
|
604 #else |
|
605 __STATIC_CAST(DWORD, len)); |
|
606 #endif |
|
607 // check if mapping succeded and is usable |
|
608 if (base == 0 || _M_seek(offset + len, ios_base::beg) < 0) { |
|
609 this->_M_unmap(base, len); |
|
610 base = 0; |
|
611 } |
|
612 } else |
|
613 base = 0; |
|
614 |
|
615 return base; |
|
616 } |
|
617 |
|
618 void _Filebuf_base::_M_unmap(void* base, streamoff len) { |
|
619 // precondition : there is a valid mapping at the moment |
|
620 if (base != NULL) |
|
621 UnmapViewOfFile(base); |
|
622 // destroy view handle as well |
|
623 if (_M_view_id != NULL) |
|
624 CloseHandle(_M_view_id); |
|
625 _M_view_id = NULL; |
|
626 (void)len; //unused variable |
|
627 } |
|
628 |
|
629 _STLP_END_NAMESPACE |