/home/ntakagi/work/STLport-5.1.5/src/fstream.cppGo to the documentation of this file.00001 /* 00002 * Copyright (c) 1999 00003 * Silicon Graphics Computer Systems, Inc. 00004 * 00005 * Copyright (c) 1999 00006 * Boris Fomitchev 00007 * 00008 * This material is provided "as is", with absolutely no warranty expressed 00009 * or implied. Any use is at your own risk. 00010 * 00011 * Permission to use or copy this software for any purpose is hereby granted 00012 * without fee, provided the above notices are retained on all copies. 00013 * Permission to modify the code and to distribute modified code is granted, 00014 * provided the above notices are retained, and a notice that the code was 00015 * modified is included with the above copyright notice. 00016 * 00017 */ 00018 00019 00020 #include "stlport_prefix.h" 00021 00022 #if defined (__SUNPPRO_CC) && !defined (_STLP_NO_NEW_C_HEADERS) 00023 # include <time.h> 00024 // For sunpro, it chokes if time.h is included through stat.h 00025 #endif 00026 00027 #include <fstream> 00028 00029 #ifdef __CYGWIN__ 00030 # define __int64 long long 00031 #endif 00032 00033 #if defined (_STLP_USE_UNIX_IO) 00034 extern "C" { 00035 // open/close/read/write 00036 # include <sys/stat.h> // For stat 00037 # if !defined (_CRAY) && ! defined (__EMX__) 00038 # include <sys/mman.h> // For mmap 00039 # endif 00040 00041 // on HP-UX 11, this one contradicts with pthread.h on pthread_atfork, unless we unset this 00042 # if defined (__hpux) && defined (__GNUC__) 00043 # undef _INCLUDE_POSIX1C_SOURCE 00044 # endif 00045 00046 # include <unistd.h> 00047 # include <fcntl.h> 00048 } 00049 # ifdef __APPLE__ 00050 # include <sys/sysctl.h> 00051 # endif 00052 #elif defined (_STLP_USE_WIN32_IO) 00053 # define WIN32_LEAN_AND_MEAN 00054 # include <windows.h> 00055 00056 # ifdef __BORLANDC__ 00057 # include <cfcntl.h> // For _O_RDONLY, etc 00058 # include <sys/stat.h> // For _fstat 00059 # elif !defined(_STLP_WCE) 00060 # include <io.h> // For _get_osfhandle 00061 # include <fcntl.h> // For _O_RDONLY, etc 00062 # include <sys/stat.h> // For _fstat 00063 # endif 00064 # define _TEXTBUF_SIZE 0x1000 00065 #elif defined (_STLP_USE_UNIX_EMULATION_IO) 00066 # if defined( __MSL__ ) 00067 # include <unistd.h> 00068 # else 00069 # include <io.h> 00070 # endif 00071 # include <fcntl.h> 00072 # include <sys/stat.h> 00073 #elif defined (_STLP_USE_STDIO_IO) 00074 # include <cstdio> 00075 # if !(defined(__MRC__) || defined(__SC__) || defined(__ISCPP__) ) 00076 extern "C" { 00077 # include <sys/stat.h> 00078 } 00079 # endif 00080 # if defined( __MSL__ ) 00081 # include <unix.h> 00082 # endif 00083 # if defined(__ISCPP__) 00084 # include <c_locale_is/filestat.h> 00085 # endif 00086 # if defined(__BEOS__) && defined(__INTEL__) 00087 # include <fcntl.h> 00088 # include <sys/stat.h> // For _fstat 00089 # define _S_IREAD S_IREAD 00090 # define _S_IWRITE S_IWRITE 00091 # define _S_IFREG S_IFREG 00092 # endif 00093 #else 00094 # error "Configure i/o !" 00095 #endif 00096 00097 #if defined (_STLP_USE_WIN32_IO) 00098 const _STLP_fd INVALID_STLP_FD = INVALID_HANDLE_VALUE; 00099 # if !defined (INVALID_SET_FILE_POINTER) 00100 # define INVALID_SET_FILE_POINTER 0xffffffff 00101 # endif 00102 #elif defined (_STLP_USE_UNIX_EMULATION_IO) || defined (_STLP_USE_STDIO_IO) || defined (_STLP_USE_UNIX_IO) 00103 const _STLP_fd INVALID_STLP_FD = -1; 00104 #else 00105 # error "Configure i/o !" 00106 #endif 00107 00108 // map permission masks 00109 #if defined (_STLP_USE_UNIX_EMULATION_IO) || defined (_STLP_USE_STDIO_IO) 00110 # ifndef S_IRUSR 00111 # define S_IRUSR _S_IREAD 00112 # define S_IWUSR _S_IWRITE 00113 # define S_IRGRP _S_IREAD 00114 # define S_IWGRP _S_IWRITE 00115 # define S_IROTH _S_IREAD 00116 # define S_IWOTH _S_IWRITE 00117 # endif 00118 # ifndef O_RDONLY 00119 # define O_RDONLY _O_RDONLY 00120 # define O_WRONLY _O_WRONLY 00121 # define O_RDWR _O_RDWR 00122 # define O_APPEND _O_APPEND 00123 # define O_CREAT _O_CREAT 00124 # define O_TRUNC _O_TRUNC 00125 # define O_TEXT _O_TEXT 00126 # define O_BINARY _O_BINARY 00127 # endif 00128 00129 # ifdef __MSL__ 00130 # define _O_TEXT 0x0 00131 # if !defined( O_TEXT ) 00132 # define O_TEXT _O_TEXT 00133 # endif 00134 # define _S_IFREG S_IFREG 00135 # define S_IREAD S_IRUSR 00136 # define S_IWRITE S_IWUSR 00137 # define S_IEXEC S_IXUSR 00138 # define _S_IWRITE S_IWRITE 00139 # define _S_IREAD S_IREAD 00140 # define _open open 00141 # define _lseek lseek 00142 # define _close close 00143 # define _read read 00144 # define _write write 00145 # endif 00146 #endif 00147 00148 #ifndef O_ACCMODE 00149 # define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR) 00150 #endif 00151 00152 #include "fstream_impl.h" 00153 00154 #ifdef _STLP_LONG_LONG 00155 # define ULL(x) ((unsigned _STLP_LONG_LONG)x) 00156 #elif defined(__MRC__) || defined(__SC__) //*TY 02/25/2000 - added support for MPW compilers 00157 # include <Math64.h> 00158 # define ULL(x) (U64SetU(x)) 00159 #elif defined(__ISCPP__) 00160 # include "uint64.h" 00161 #else 00162 # error "there should be some long long type on the system!" 00163 #endif 00164 00165 _STLP_BEGIN_NAMESPACE 00166 // Compare with streamoff definition in stl/char_traits.h! 00167 00168 #ifdef _STLP_USE_DEFAULT_FILE_OFFSET 00169 # define FOPEN fopen 00170 # define FSEEK fseek 00171 # define FSTAT fstat 00172 # define STAT stat 00173 # define FTELL ftell 00174 # define LSEEK lseek 00175 # define MMAP mmap 00176 # define OPEN open 00177 #elif defined(_LARGEFILE_SOURCE) || defined(_LARGEFILE64_SOURCE) /* || defined(__USE_FILE_OFFSET64) */ \ 00178 /* || (defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64)) */ /* || defined(__sgi) */ 00179 # define FOPEN fopen64 00180 # define FSEEK fseeko64 00181 # define FSTAT fstat64 00182 # define STAT stat64 00183 # define FTELL ftello64 00184 # define LSEEK lseek64 00185 # define MMAP mmap64 00186 # define OPEN open64 00187 #else 00188 # define OPEN open 00189 # define FSEEK fseek 00190 # define FSTAT fstat 00191 # define STAT stat 00192 # define FTELL ftell 00193 # define LSEEK lseek 00194 # define MMAP mmap 00195 # define OPEN open 00196 #endif 00197 #ifdef _STLP_USE_UNIX_IO 00198 # ifndef MAP_FAILED /* MMAP failure return code */ 00199 # define MAP_FAILED -1 00200 # endif 00201 #elif defined (_STLP_USE_UNIX_EMULATION_IO) 00202 # define LSEEK _lseek 00203 #endif 00204 00205 #if !defined(__MSL__) && !defined(__MRC__) && !defined(__SC__) && !defined(_STLP_WCE) //*TY 04/15/2000 - exclude mpw compilers also 00206 static ios_base::openmode flag_to_openmode(int mode) { 00207 ios_base::openmode ret = ios_base::__default_mode; 00208 00209 switch(mode & O_ACCMODE) { 00210 case O_RDONLY: 00211 ret = ios_base::in; break; 00212 case O_WRONLY: 00213 ret = ios_base::out; break; 00214 case O_RDWR: 00215 ret = ios_base::in | ios_base::out; break; 00216 } 00217 00218 if (mode & O_APPEND) 00219 ret |= ios_base::app; 00220 00221 # if defined (_STLP_USE_WIN32_IO) 00222 if (mode & O_BINARY) 00223 ret |= ios_base::binary; 00224 # endif 00225 00226 return ret; 00227 } 00228 #endif /* MSL */ 00229 00230 _STLP_MOVE_TO_PRIV_NAMESPACE 00231 00232 // Helper functions for _Filebuf_base. 00233 00234 bool __is_regular_file(_STLP_fd fd) { 00235 00236 #if defined (_STLP_UNIX) 00237 00238 struct STAT buf; 00239 return FSTAT(fd, &buf) == 0 && S_ISREG(buf.st_mode); 00240 00241 #elif defined(__MRC__) || defined(__SC__) //*TY 02/25/2000 - added support for MPW compilers 00242 00243 # pragma unused(fd) 00244 return true; // each file is a regular file under mac os, isn't it? (we don't have fstat()) 00245 00246 #elif defined(_STLP_USE_UNIX_EMULATION_IO) || defined (_STLP_USE_STDIO_IO) 00247 00248 struct STAT buf; 00249 return FSTAT(fd, &buf) == 0 && (buf.st_mode & _S_IFREG) != 0 ; 00250 00251 #elif defined (_STLP_USE_WIN32_IO) && !defined(_STLP_WCE) 00252 00253 return (GetFileType(fd) & ~FILE_TYPE_REMOTE) == FILE_TYPE_DISK; 00254 00255 #else 00256 (void)fd; // dwa 4/27/00 - suppress unused parameter warning 00257 return false; 00258 #endif 00259 } 00260 00261 // Number of characters in the file. 00262 streamoff __file_size(_STLP_fd fd) { 00263 streamoff ret = 0; 00264 00265 #if defined (_STLP_UNIX) 00266 00267 struct STAT buf; 00268 if (FSTAT(fd, &buf) == 0 && S_ISREG(buf.st_mode)) 00269 ret = buf.st_size > 0 ? buf.st_size : 0; 00270 00271 #elif defined(__MRC__) || defined(__SC__) //*TY 02/25/2000 - added support for MPW compilers 00272 00273 # pragma unused(fd) 00274 00275 #elif defined(_STLP_USE_UNIX_EMULATION_IO) || defined (_STLP_USE_STDIO_IO) 00276 00277 struct STAT buf; 00278 if (FSTAT(fd, &buf) == 0 && (buf.st_mode & _S_IFREG) != 0) 00279 ret = buf.st_size > 0 ? buf.st_size : 0; 00280 00281 #elif defined (_STLP_USE_WIN32_IO) 00282 00283 LARGE_INTEGER li; 00284 li.LowPart = GetFileSize(fd, (unsigned long*) &li.HighPart); 00285 if (li.LowPart != INVALID_FILE_SIZE || GetLastError() == NO_ERROR) 00286 ret = li.QuadPart; 00287 00288 #else 00289 (void)fd; // dwa 4/27/00 - suppress unused parameter warning 00290 #endif 00291 return ret; 00292 } 00293 00294 _STLP_MOVE_TO_STD_NAMESPACE 00295 00296 // Visual C++ and Intel use this, but not Metrowerks 00297 // Also MinGW, msvcrt.dll (but not crtdll.dll) dependent version 00298 #if (!defined (__MSL__) && !defined (_STLP_WCE) && defined (_STLP_MSVC_LIB) && defined (_WIN32)) || \ 00299 (defined (__MINGW32__) && defined (__MSVCRT__)) 00300 00301 // fcntl(fileno, F_GETFL) for Microsoft library 00302 // 'semi-documented' defines: 00303 # define IOINFO_L2E 5 00304 # define IOINFO_ARRAY_ELTS (1 << IOINFO_L2E) 00305 # define _pioinfo(i) ( __pioinfo[(i) >> IOINFO_L2E] + \ 00306 ((i) & (IOINFO_ARRAY_ELTS - 1)) ) 00307 # define FAPPEND 0x20 // O_APPEND flag 00308 # define FTEXT 0x80 // O_TEXT flag 00309 // end of 'semi-documented' defines 00310 00311 // 'semi-documented' internal structure 00312 extern "C" { 00313 struct ioinfo { 00314 long osfhnd; // the real os HANDLE 00315 char osfile; // file handle flags 00316 char pipech; // pipe buffer 00317 # if defined (_MT) 00318 // multi-threaded locking 00319 int lockinitflag; 00320 CRITICAL_SECTION lock; 00321 # endif /* _MT */ 00322 }; 00323 # if defined (__MINGW32__) 00324 __MINGW_IMPORT ioinfo * __pioinfo[]; 00325 # else 00326 extern _CRTIMP ioinfo * __pioinfo[]; 00327 # endif 00328 } // extern "C" 00329 // end of 'semi-documented' declarations 00330 00331 static ios_base::openmode _get_osfflags(int fd, HANDLE oshandle) { 00332 char dosflags = 0; 00333 if (fd >= 0) 00334 dosflags = _pioinfo(fd)->osfile; 00335 //else 00336 //the file will be considered as open in binary mode with no append attribute 00337 // end of 'semi-documented' stuff 00338 00339 int mode = 0; 00340 if (dosflags & FAPPEND) 00341 mode |= O_APPEND; 00342 00343 if (dosflags & FTEXT) 00344 mode |= O_TEXT; 00345 else 00346 mode |= O_BINARY; 00347 00348 // For Read/Write access we have to guess 00349 DWORD dummy, dummy2; 00350 BOOL writeOk = WriteFile(oshandle, &dummy2, 0, &dummy, 0); 00351 BOOL readOk = ReadFile(oshandle, &dummy2, 0, &dummy, NULL); 00352 if (writeOk && readOk) 00353 mode |= O_RDWR; 00354 else if (readOk) 00355 mode |= O_RDONLY; 00356 else 00357 mode |= O_WRONLY; 00358 00359 return flag_to_openmode(mode); 00360 } 00361 00362 #elif defined (__DMC__) 00363 00364 # define FHND_APPEND 0x04 00365 # define FHND_DEVICE 0x08 00366 # define FHND_TEXT 0x10 00367 00368 extern "C" unsigned char __fhnd_info[_NFILE]; 00369 00370 static ios_base::openmode _get_osfflags(int fd, HANDLE oshandle) { 00371 int mode = 0; 00372 00373 if (__fhnd_info[fd] & FHND_APPEND) 00374 mode |= O_APPEND; 00375 00376 if (__fhnd_info[fd] & FHND_TEXT == 0) 00377 mode |= O_BINARY; 00378 00379 for (FILE *fp = &_iob[0]; fp < &_iob[_NFILE]; fp++) { 00380 if ((fileno(fp) == fd) && (fp->_flag & (_IOREAD | _IOWRT | _IORW))) { 00381 const int osflags = fp->_flag; 00382 00383 if ((osflags & _IOREAD) && !(osflags & _IOWRT) && !(osflags & _IORW)) 00384 mode |= O_RDONLY; 00385 else if ((osflags & _IOWRT) && !(osflags & _IOREAD) && !(osflags & _IORW)) 00386 mode |= O_WRONLY; 00387 else 00388 mode |= O_RDWR; 00389 break; 00390 } 00391 } 00392 00393 return flag_to_openmode(mode); 00394 } 00395 #endif 00396 00397 size_t _Filebuf_base::_M_page_size = 4096; 00398 00399 _Filebuf_base::_Filebuf_base() 00400 : _M_file_id(INVALID_STLP_FD), 00401 #if defined (_STLP_USE_WIN32_IO) 00402 _M_view_id(0), 00403 #endif 00404 _M_openmode(0), 00405 _M_is_open(false), 00406 _M_should_close(false) 00407 {} 00408 00409 void _Filebuf_base::_S_initialize() { 00410 #if defined (_STLP_UNIX) && !defined (__DJGPP) && !defined (_CRAY) 00411 # if defined (__APPLE__) 00412 int mib[2]; 00413 size_t pagesize, len; 00414 mib[0] = CTL_HW; 00415 mib[1] = HW_PAGESIZE; 00416 len = sizeof(pagesize); 00417 sysctl(mib, 2, &pagesize, &len, NULL, 0); 00418 _M_page_size = pagesize; 00419 # elif defined (__DJGPP) && defined (_CRAY) 00420 _M_page_size = BUFSIZ; 00421 # else 00422 _M_page_size = sysconf(_SC_PAGESIZE); 00423 # endif 00424 #elif defined (_STLP_USE_WIN32_IO) 00425 SYSTEM_INFO SystemInfo; 00426 GetSystemInfo(&SystemInfo); 00427 _M_page_size = SystemInfo.dwPageSize; 00428 // might be .dwAllocationGranularity 00429 #endif 00430 } 00431 00432 // Return the size of the file. This is a wrapper for stat. 00433 // Returns zero if the size cannot be determined or is ill-defined. 00434 streamoff _Filebuf_base::_M_file_size() { 00435 return _STLP_PRIV __file_size(_M_file_id); 00436 } 00437 00438 bool _Filebuf_base::_M_open(const char* name, ios_base::openmode openmode, 00439 long permission) { 00440 _STLP_fd file_no; 00441 00442 if (_M_is_open) 00443 return false; 00444 00445 #if defined (_STLP_USE_UNIX_IO) || defined (_STLP_USE_UNIX_EMULATION_IO) 00446 int flags = 0; 00447 00448 // Unix makes no distinction between text and binary files. 00449 switch(openmode & (~ios_base::ate & ~ios_base::binary)) { 00450 case ios_base::out: 00451 case ios_base::out | ios_base::trunc: 00452 flags = O_WRONLY | O_CREAT | O_TRUNC; 00453 break; 00454 case ios_base::out | ios_base::app: 00455 flags = O_WRONLY | O_CREAT | O_APPEND; 00456 break; 00457 case ios_base::in: 00458 flags = O_RDONLY; 00459 permission = 0; // Irrelevant unless we're writing. 00460 break; 00461 case ios_base::in | ios_base::out: 00462 flags = O_RDWR; 00463 break; 00464 case ios_base::in | ios_base::out | ios_base::trunc: 00465 flags = O_RDWR | O_CREAT | O_TRUNC; 00466 break; 00467 default: // The above are the only combinations of 00468 return false; // flags allowed by the C++ standard. 00469 } 00470 00471 # if defined (_STLP_USE_UNIX_EMULATION_IO) 00472 if (openmode & ios_base::binary) 00473 flags |= O_BINARY; 00474 else 00475 flags |= O_TEXT; 00476 00477 file_no = _open(name, flags, permission); 00478 # else 00479 file_no = OPEN(name, flags, permission); 00480 # endif /* _STLP_USE_UNIX_EMULATION_IO */ 00481 00482 if (file_no < 0) 00483 return false; 00484 00485 _M_is_open = true; 00486 00487 if (openmode & ios_base::ate) 00488 if (LSEEK(file_no, 0, SEEK_END) == -1) 00489 _M_is_open = false; 00490 00491 #elif defined (_STLP_USE_STDIO_IO) 00492 // use FILE-based i/o 00493 const char* flags; 00494 00495 switch(openmode & (~ios_base::ate)) { 00496 case ios_base::out: 00497 case ios_base::out | ios_base::trunc: 00498 flags = "w"; 00499 break; 00500 00501 case ios_base::out | ios_base::binary: 00502 case ios_base::out | ios_base::trunc | ios_base::binary: 00503 flags = "wb"; 00504 break; 00505 00506 case ios_base::out | ios_base::app: 00507 flags = "a"; 00508 break; 00509 00510 case ios_base::out | ios_base::app | ios_base::binary: 00511 flags = "ab"; 00512 break; 00513 00514 case ios_base::in: 00515 flags = "r"; 00516 break; 00517 00518 case ios_base::in | ios_base::binary: 00519 flags = "rb"; 00520 break; 00521 00522 case ios_base::in | ios_base::out: 00523 flags = "r+"; 00524 break; 00525 00526 case ios_base::in | ios_base::out | ios_base::binary: 00527 flags = "r+b"; 00528 break; 00529 00530 00531 case ios_base::in | ios_base::out | ios_base::trunc: 00532 flags = "w+"; 00533 break; 00534 00535 case ios_base::in | ios_base::out | ios_base::trunc | ios_base::binary: 00536 flags = "w+b"; 00537 break; 00538 00539 default: // The above are the only combinations of 00540 return false; // flags allowed by the C++ standard. 00541 } 00542 00543 // fbp : TODO : set permissions ! 00544 (void)permission; // currently unused //*TY 02/26/2000 - added to suppress warning message 00545 _M_file = FOPEN(name, flags); 00546 00547 if (_M_file) { 00548 file_no = fileno(_M_file); 00549 } 00550 else 00551 return false; 00552 00553 // unset buffering immediately 00554 setbuf(_M_file, 0); 00555 00556 _M_is_open = true; 00557 00558 if (openmode & ios_base::ate) { 00559 if (FSEEK(_M_file, 0, SEEK_END) == -1) 00560 _M_is_open = false; 00561 } 00562 00563 #elif defined (_STLP_USE_WIN32_IO) 00564 DWORD dwDesiredAccess, dwCreationDisposition; 00565 bool doTruncate = false; 00566 00567 switch (openmode & (~ios_base::ate & ~ios_base::binary)) { 00568 case ios_base::out: 00569 case ios_base::out | ios_base::trunc: 00570 dwDesiredAccess = GENERIC_WRITE; 00571 dwCreationDisposition = OPEN_ALWAYS; 00572 // boris : even though it is very non-intuitive, standard 00573 // requires them both to behave same. 00574 doTruncate = true; 00575 break; 00576 case ios_base::out | ios_base::app: 00577 dwDesiredAccess = GENERIC_WRITE; 00578 dwCreationDisposition = OPEN_ALWAYS; 00579 break; 00580 case ios_base::in: 00581 dwDesiredAccess = GENERIC_READ; 00582 dwCreationDisposition = OPEN_EXISTING; 00583 permission = 0; // Irrelevant unless we're writing. 00584 break; 00585 case ios_base::in | ios_base::out: 00586 dwDesiredAccess = GENERIC_READ | GENERIC_WRITE; 00587 dwCreationDisposition = OPEN_EXISTING; 00588 break; 00589 case ios_base::in | ios_base::out | ios_base::trunc: 00590 dwDesiredAccess = GENERIC_READ | GENERIC_WRITE; 00591 dwCreationDisposition = OPEN_ALWAYS; 00592 doTruncate = true; 00593 break; 00594 default: // The above are the only combinations of 00595 return false; // flags allowed by the C++ standard. 00596 } 00597 00598 DWORD dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; 00599 00600 # if defined(_STLP_USE_WIDE_INTERFACE) 00601 file_no = CreateFile (_STLP_PRIV __ASCIIToWide(name).c_str(), 00602 # else 00603 file_no = CreateFileA(name, 00604 # endif 00605 dwDesiredAccess, dwShareMode, 0, 00606 dwCreationDisposition, permission, 0); 00607 00608 if (file_no == INVALID_STLP_FD) 00609 return false; 00610 00611 if ((doTruncate && SetEndOfFile(file_no) == 0) || 00612 (((openmode & ios_base::ate) != 0) && 00613 (SetFilePointer(file_no, 0, NULL, FILE_END) == INVALID_SET_FILE_POINTER))) { 00614 CloseHandle(file_no); 00615 return false; 00616 } 00617 00618 _M_is_open = true; 00619 00620 #else 00621 # error "Port!" 00622 #endif /* __unix */ 00623 00624 _M_file_id = file_no; 00625 _M_should_close = _M_is_open; 00626 _M_openmode = openmode; 00627 00628 if (_M_is_open) 00629 _M_regular_file = _STLP_PRIV __is_regular_file(_M_file_id); 00630 00631 return (_M_is_open != 0); 00632 } 00633 00634 00635 bool _Filebuf_base::_M_open(const char* name, ios_base::openmode openmode) { 00636 // This doesn't really grant everyone in the world read/write 00637 // access. On Unix, file-creation system calls always clear 00638 // bits that are set in the umask from the permissions flag. 00639 #ifdef _STLP_USE_WIN32_IO 00640 return this->_M_open(name, openmode, FILE_ATTRIBUTE_NORMAL); 00641 #elif defined(__MRC__) || defined(__SC__) //*TY 02/26/2000 - added support for MPW compilers 00642 return this->_M_open(name, openmode, 0); 00643 #else 00644 return this->_M_open(name, openmode, S_IRUSR | S_IWUSR | S_IRGRP | 00645 S_IWGRP | S_IROTH | S_IWOTH); 00646 #endif 00647 } 00648 00649 00650 #if defined (_STLP_USE_WIN32_IO) 00651 bool _Filebuf_base::_M_open(_STLP_fd __id, ios_base::openmode init_mode) { 00652 # if (defined (_STLP_MSVC_LIB) && !defined (_STLP_WCE)) || \ 00653 (defined (__MINGW32__) && defined (__MSVCRT__)) || defined (__DMC__) 00654 00655 if (_M_is_open || __id == INVALID_STLP_FD) 00656 return false; 00657 00658 if (init_mode != ios_base::__default_mode) 00659 _M_openmode = init_mode; 00660 else 00661 _M_openmode = _get_osfflags(-1, __id); 00662 00663 _M_is_open = true; 00664 _M_file_id = __id; 00665 _M_should_close = false; 00666 _M_regular_file = _STLP_PRIV __is_regular_file(_M_file_id); 00667 00668 return true; 00669 # else 00670 (void)__id; 00671 (void)init_mode; // dwa 4/27/00 - suppress unused parameter warning 00672 00673 // not available for the API 00674 return false; 00675 00676 # endif 00677 } 00678 #endif /* _STLP_USE_WIN32_IO */ 00679 00680 // Associated the filebuf with a file descriptor pointing to an already- 00681 // open file. Mode is set to be consistent with the way that the file 00682 // was opened. 00683 bool _Filebuf_base::_M_open(int file_no, ios_base::openmode init_mode) { 00684 if (_M_is_open || file_no < 0) 00685 return false; 00686 00687 #if defined (_STLP_UNIX) 00688 (void)init_mode; // dwa 4/27/00 - suppress unused parameter warning 00689 int mode ; 00690 mode = fcntl(file_no, F_GETFL); 00691 00692 if (mode == -1) 00693 return false; 00694 00695 _M_openmode = flag_to_openmode(mode); 00696 _M_file_id = file_no; 00697 #elif defined(__MRC__) || defined(__SC__) //*TY 02/26/2000 - added support for MPW compilers 00698 (void)init_mode; // dwa 4/27/00 - suppress unused parameter warning 00699 switch (_iob[file_no]._flag & (_IOREAD|_IOWRT|_IORW) ) 00700 { 00701 case _IOREAD: 00702 _M_openmode = ios_base::in; break; 00703 case _IOWRT: 00704 _M_openmode = ios_base::out; break; 00705 case _IORW: 00706 _M_openmode = ios_base::in | ios_base::out; break; 00707 default: 00708 return false; 00709 } 00710 _M_file_id = file_no; 00711 #elif defined (_STLP_USE_UNIX_EMULATION_IO) || defined (_STLP_USE_STDIO_IO) 00712 (void)init_mode; // dwa 4/27/00 - suppress unused parameter warning 00713 int mode ; 00714 struct STAT buf; 00715 if (FSTAT(file_no, &buf) != 0) 00716 return false; 00717 mode = buf.st_mode; 00718 00719 switch(mode & (_S_IWRITE | _S_IREAD) ) { 00720 case _S_IREAD: 00721 _M_openmode = ios_base::in; break; 00722 case _S_IWRITE: 00723 _M_openmode = ios_base::out; break; 00724 case (_S_IWRITE | _S_IREAD): 00725 _M_openmode = ios_base::in | ios_base::out; break; 00726 default: 00727 return false; 00728 } 00729 _M_file_id = file_no; 00730 #elif (defined (_STLP_USE_WIN32_IO) && defined (_STLP_MSVC_LIB) && !defined (_STLP_WCE) ) || \ 00731 (defined (__MINGW32__) && defined (__MSVCRT__)) || \ 00732 defined (__DMC__) 00733 00734 HANDLE oshandle = (HANDLE)_get_osfhandle(file_no); 00735 if (oshandle == INVALID_STLP_FD) 00736 return false; 00737 00738 if (init_mode != ios_base::__default_mode) 00739 _M_openmode = init_mode; 00740 else 00741 _M_openmode = _get_osfflags(file_no, oshandle); 00742 00743 _M_file_id = oshandle; 00744 #else 00745 (void)init_mode; // dwa 4/27/00 - suppress unused parameter warning 00746 // not available for the API 00747 # define _STLP_NO_IMPLEMENTATION 00748 #endif 00749 00750 #if !defined (_STLP_NO_IMPLEMENTATION) 00751 _M_is_open = true; 00752 _M_should_close = false; 00753 _M_regular_file = _STLP_PRIV __is_regular_file(_M_file_id); 00754 return true; 00755 #else 00756 # undef _STLP_NO_IMPLEMENTATION 00757 return false; 00758 #endif 00759 } 00760 00761 bool _Filebuf_base::_M_close() { 00762 if (!_M_is_open) 00763 return false; 00764 00765 bool ok; 00766 00767 if (!_M_should_close) 00768 ok = true; 00769 else { 00770 00771 #if defined (_STLP_USE_UNIX_IO) 00772 00773 ok = (close(_M_file_id) == 0); 00774 00775 #elif defined (_STLP_USE_UNIX_EMULATION_IO) 00776 00777 ok = (_close(_M_file_id) == 0); 00778 00779 #elif defined (_STLP_USE_STDIO_IO) 00780 00781 ok = (fclose(_M_file) == 0); 00782 00783 #elif defined (_STLP_USE_WIN32_IO) 00784 00785 if (_M_file_id != INVALID_STLP_FD) { 00786 ok = (CloseHandle(_M_file_id) != 0); 00787 } 00788 else { 00789 ok = false; 00790 } 00791 00792 #else 00793 00794 ok = false; 00795 00796 #endif /* _STLP_USE_UNIX_IO */ 00797 } 00798 00799 _M_is_open = _M_should_close = false; 00800 _M_openmode = 0; 00801 return ok; 00802 } 00803 00804 00805 #define _STLP_LF 10 00806 #define _STLP_CR 13 00807 #define _STLP_CTRLZ 26 00808 00809 // Read up to n characters into a buffer. Return value is number of 00810 // characters read. 00811 ptrdiff_t _Filebuf_base::_M_read(char* buf, ptrdiff_t n) { 00812 #if defined (_STLP_USE_UNIX_IO) 00813 00814 return read(_M_file_id, buf, n); 00815 00816 #elif defined (_STLP_USE_UNIX_EMULATION_IO) 00817 00818 return _read(_M_file_id, buf, n); 00819 00820 #elif defined (_STLP_USE_WIN32_IO) 00821 ptrdiff_t readen = 0; 00822 //Here cast to size_t is safe as n cannot be negative. 00823 size_t chunkSize = (min)(size_t(0xffffffff), __STATIC_CAST(size_t, n)); 00824 // The following, while validating that we are still able to extract chunkSize 00825 // charaters to the buffer, avoids extraction of too small chunk of datas 00826 // which would be counter performant. 00827 while (__STATIC_CAST(size_t, (n - readen)) >= chunkSize) { 00828 DWORD numberOfBytesRead; 00829 ReadFile(_M_file_id, buf + readen, __STATIC_CAST(DWORD, chunkSize), &numberOfBytesRead, 0); 00830 00831 if (numberOfBytesRead == 0) 00832 break; 00833 00834 if (!(_M_openmode & ios_base::binary)) { 00835 // translate CR-LFs to LFs in the buffer 00836 char *to = buf + readen; 00837 char *from = to; 00838 char *last = from + numberOfBytesRead - 1; 00839 for (; from <= last && *from != _STLP_CTRLZ; ++from) { 00840 if (*from != _STLP_CR) 00841 *to++ = *from; 00842 else { // found CR 00843 if (from < last) { // not at buffer end 00844 if (*(from + 1) != _STLP_LF) 00845 *to++ = _STLP_CR; 00846 } 00847 else { // last char is CR, peek for LF 00848 char peek = ' '; 00849 DWORD NumberOfBytesPeeked; 00850 ReadFile(_M_file_id, (LPVOID)&peek, 1, &NumberOfBytesPeeked, 0); 00851 if (NumberOfBytesPeeked != 0) { 00852 if (peek != _STLP_LF) { //not a <CR><LF> combination 00853 *to++ = _STLP_CR; 00854 if ((to < buf + n) && (peek != _STLP_CR)) 00855 //We have enough place to store peek and it is no a special 00856 //_STLP_CR character, we can store it. 00857 *to++ = peek; 00858 else 00859 SetFilePointer(_M_file_id, (LONG)-1, 0, SEEK_CUR); 00860 } 00861 else { 00862 // A <CR><LF> combination, we keep the <LF>: 00863 *to++ = _STLP_LF; 00864 } 00865 } 00866 else { 00867 /* This case is tedious, we could 00868 * - put peek back in the file but this would then generate an infinite loop 00869 * - report an error as we don't know if in a future call to ReadFile we won't then 00870 * get a <LF>. Doing so would make all files with a <CR> last an invalid file 00871 * for STLport, a hard solution for STLport clients. 00872 * - store the <CR> in the returned buffer, the chosen solution, even if in this 00873 * case we could miss a <CR><LF> combination. 00874 */ 00875 *to++ = _STLP_CR; 00876 } 00877 } 00878 } // found CR 00879 } // for 00880 readen = to - buf; 00881 // seek back to TEXT end of file if hit CTRL-Z 00882 if (from <= last) { // terminated due to CTRLZ 00883 SetFilePointer(_M_file_id, -(LONG)((last + 1) - from), 0, SEEK_CUR); 00884 break; 00885 } 00886 } 00887 else 00888 readen += numberOfBytesRead; 00889 } 00890 return readen; 00891 00892 #elif defined (_STLP_USE_STDIO_IO) 00893 00894 return fread(buf, 1, n, _M_file); 00895 00896 #else 00897 # error "Port!" 00898 #endif /* __unix */ 00899 } 00900 00901 // Write n characters from a buffer. Return value: true if we managed 00902 // to write the entire buffer, false if we didn't. 00903 bool _Filebuf_base::_M_write(char* buf, ptrdiff_t n) { 00904 for (;;) { 00905 ptrdiff_t written; 00906 00907 #if defined (_STLP_USE_UNIX_IO) 00908 00909 written = write(_M_file_id, buf, n); 00910 00911 #elif defined (_STLP_USE_UNIX_EMULATION_IO) 00912 00913 written = _write(_M_file_id, buf, n); 00914 00915 #elif defined (_STLP_USE_WIN32_IO) 00916 00917 //In the following implementation we are going to cast most of the ptrdiff_t 00918 //values in size_t to work with coherent unsigned values. Doing so make code 00919 //more simple especially in the min function call. 00920 00921 // In append mode, every write does an implicit seek to the end 00922 // of the file. 00923 if (_M_openmode & ios_base::app) 00924 _M_seek(0, ios_base::end); 00925 00926 if (_M_openmode & ios_base::binary) { 00927 // binary mode 00928 size_t bytes_to_write = (size_t)n; 00929 DWORD NumberOfBytesWritten; 00930 written = 0; 00931 for (; bytes_to_write != 0;) { 00932 WriteFile(_M_file_id, buf + written, 00933 __STATIC_CAST(DWORD, (min)(size_t(0xffffffff), bytes_to_write)), 00934 &NumberOfBytesWritten, 0); 00935 if (NumberOfBytesWritten == 0) 00936 return false; 00937 bytes_to_write -= NumberOfBytesWritten; 00938 written += NumberOfBytesWritten; 00939 } 00940 } 00941 else { 00942 char textbuf[_TEXTBUF_SIZE + 1]; // extra 1 in case LF at end 00943 char * nextblock = buf, * ptrtextbuf = textbuf; 00944 char * endtextbuf = textbuf + _TEXTBUF_SIZE; 00945 char * endblock = buf + n; 00946 ptrdiff_t nextblocksize = (min) (n, (ptrdiff_t)_TEXTBUF_SIZE); 00947 char * nextlf; 00948 00949 while ( (nextblocksize > 0) && 00950 (nextlf = (char *)memchr(nextblock, _STLP_LF, nextblocksize)) != 0) { 00951 ptrdiff_t linelength = nextlf - nextblock; 00952 memcpy(ptrtextbuf, nextblock, linelength); 00953 ptrtextbuf += linelength; 00954 nextblock += (linelength + 1); 00955 * ptrtextbuf ++ = _STLP_CR; 00956 * ptrtextbuf ++ = _STLP_LF; 00957 nextblocksize = (min) (ptrdiff_t(endblock - nextblock), 00958 (max) (ptrdiff_t(0), ptrdiff_t(endtextbuf - ptrtextbuf))); 00959 } 00960 // write out what's left, > condition is here since for LF at the end , 00961 // endtextbuf may get < ptrtextbuf ... 00962 if (nextblocksize > 0) { 00963 memcpy(ptrtextbuf, nextblock, nextblocksize); 00964 ptrtextbuf += nextblocksize; 00965 nextblock += nextblocksize; 00966 } 00967 // now write out the translated buffer 00968 char * writetextbuf = textbuf; 00969 for (size_t NumberOfBytesToWrite = (size_t)(ptrtextbuf - textbuf); 00970 NumberOfBytesToWrite;) { 00971 DWORD NumberOfBytesWritten; 00972 WriteFile((HANDLE)_M_file_id, writetextbuf, 00973 __STATIC_CAST(DWORD, (min)(size_t(0xffffffff), NumberOfBytesToWrite)), 00974 &NumberOfBytesWritten, 0); 00975 if (!NumberOfBytesWritten) // write shortfall 00976 return false; 00977 writetextbuf += NumberOfBytesWritten; 00978 NumberOfBytesToWrite -= NumberOfBytesWritten; 00979 } 00980 // count non-translated characters 00981 written = (nextblock - buf); 00982 } 00983 00984 #elif defined (_STLP_USE_STDIO_IO) 00985 00986 written = fwrite(buf, 1, n, _M_file); 00987 00988 #else 00989 # error "Port!" 00990 #endif /* __unix */ 00991 00992 if (n == written) 00993 return true; 00994 else if (written > 0 && written < n) { 00995 n -= written; 00996 buf += written; 00997 } 00998 else 00999 return false; 01000 } 01001 } 01002 01003 01004 #ifdef _STLP_USE_WIN32_IO 01005 # define STL_SEEK_SET FILE_BEGIN 01006 # define STL_SEEK_CUR FILE_CURRENT 01007 # define STL_SEEK_END FILE_END 01008 #else 01009 # define STL_SEEK_SET SEEK_SET 01010 # define STL_SEEK_CUR SEEK_CUR 01011 # define STL_SEEK_END SEEK_END 01012 #endif 01013 01014 // Wrapper for lseek or the like. 01015 streamoff _Filebuf_base::_M_seek(streamoff offset, ios_base::seekdir dir) { 01016 streamoff result = -1; 01017 int whence; 01018 01019 switch(dir) { 01020 case ios_base::beg: 01021 if (offset < 0 /* || offset > _M_file_size() */ ) 01022 return streamoff(-1); 01023 whence = STL_SEEK_SET; 01024 break; 01025 case ios_base::cur: 01026 whence = STL_SEEK_CUR; 01027 break; 01028 case ios_base::end: 01029 if (/* offset > 0 || */ -offset > _M_file_size() ) 01030 return streamoff(-1); 01031 whence = STL_SEEK_END; 01032 break; 01033 default: 01034 return streamoff(-1); 01035 } 01036 01037 #if defined (_STLP_USE_UNIX_IO) || defined (_STLP_USE_UNIX_EMULATION_IO) 01038 01039 result = LSEEK(_M_file_id, offset, whence); 01040 01041 #elif defined (_STLP_USE_STDIO_IO) 01042 01043 result = FSEEK(_M_file, offset, whence); 01044 01045 #elif defined (_STLP_USE_WIN32_IO) 01046 01047 LARGE_INTEGER li; 01048 li.QuadPart = offset; 01049 li.LowPart = SetFilePointer(_M_file_id, li.LowPart, &li.HighPart, whence); 01050 if (li.LowPart != INVALID_SET_FILE_POINTER || GetLastError() == NO_ERROR) 01051 result = li.QuadPart; 01052 01053 #else 01054 # error "Port!" 01055 #endif 01056 01057 return result; 01058 } 01059 01060 01061 // Attempts to memory-map len bytes of the current file, starting 01062 // at position offset. Precondition: offset is a multiple of the 01063 // page size. Postcondition: return value is a null pointer if the 01064 // memory mapping failed. Otherwise the return value is a pointer to 01065 // the memory-mapped file and the file position is set to offset. 01066 void* _Filebuf_base::_M_mmap(streamoff offset, streamoff len) { 01067 void* base; 01068 #if defined (_STLP_UNIX) && !defined(__DJGPP) && !defined(_CRAY) 01069 base = MMAP(0, len, PROT_READ, MAP_PRIVATE, _M_file_id, offset); 01070 if (base != (void*)MAP_FAILED) { 01071 if (LSEEK(_M_file_id, offset + len, SEEK_SET) < 0) { 01072 this->_M_unmap(base, len); 01073 base = 0; 01074 } 01075 } else 01076 base =0; 01077 01078 #elif defined (_STLP_USE_WIN32_IO) 01079 _M_view_id = CreateFileMapping(_M_file_id, (PSECURITY_ATTRIBUTES)0 , 01080 PAGE_READONLY, 0 /* len >> 32 */ , 01081 0 /* len & 0xFFFFFFFF */ , // low-order DWORD of size 01082 0); 01083 01084 if (_M_view_id) { 01085 # if 0 01086 /* 01087 printf("view %x created from file %x, error = %d, size = %d, map_offset = %d map_len = %d\n", 01088 _M_view_id, _M_file_id, GetLastError(), 01089 (int)cur_filesize, ULL(offset) & 0xffffffff, len); 01090 */ 01091 # endif 01092 base = MapViewOfFile(_M_view_id, FILE_MAP_READ, __STATIC_CAST(DWORD, ULL(offset) >> 32), 01093 __STATIC_CAST(DWORD, ULL(offset) & 0xffffffff), 01094 # if !defined (__DMC__) 01095 __STATIC_CAST(SIZE_T, len)); 01096 # else 01097 __STATIC_CAST(DWORD, len)); 01098 # endif 01099 // check if mapping succeded and is usable 01100 if (base == 0 || _M_seek(offset + len, ios_base::beg) < 0) { 01101 this->_M_unmap(base, len); 01102 base = 0; 01103 } 01104 } else 01105 base = 0; 01106 #else 01107 (void)len; //*TY 02/26/2000 - unused variables 01108 (void)offset; //*TY 02/26/2000 - 01109 base = 0; 01110 #endif 01111 return base; 01112 } 01113 01114 void _Filebuf_base::_M_unmap(void* base, streamoff len) { 01115 // precondition : there is a valid mapping at the moment 01116 #if defined (_STLP_UNIX) && !defined(__DJGPP) && !defined(_CRAY) 01117 munmap((char*)base, len); 01118 #elif defined (_STLP_USE_WIN32_IO) 01119 if (base != NULL) 01120 UnmapViewOfFile(base); 01121 // destroy view handle as well 01122 if (_M_view_id != NULL) 01123 CloseHandle(_M_view_id); 01124 _M_view_id = NULL; 01125 (void)len; //unused variable 01126 #else 01127 (void)len; //*TY 02/26/2000 - unused variables 01128 (void)base; //*TY 02/26/2000 - 01129 #endif 01130 } 01131 01132 // fbp : let us map 1 MB maximum, just be sure not to trash VM 01133 #define MMAP_CHUNK 0x100000L 01134 01135 int _STLP_CALL 01136 _Underflow<char, char_traits<char> >::_M_doit (basic_filebuf<char, char_traits<char> >* __this) { 01137 if (!__this->_M_in_input_mode) { 01138 if (!__this->_M_switch_to_input_mode()) 01139 return traits_type::eof(); 01140 } 01141 else if (__this->_M_in_putback_mode) { 01142 __this->_M_exit_putback_mode(); 01143 if (__this->gptr() != __this->egptr()) { 01144 int_type __c = traits_type::to_int_type(*__this->gptr()); 01145 return __c; 01146 } 01147 } 01148 01149 // If it's a disk file, and if the internal and external character 01150 // sequences are guaranteed to be identical, then try to use memory 01151 // mapped I/O. Otherwise, revert to ordinary read. 01152 if (__this->_M_base.__regular_file() 01153 && __this->_M_always_noconv 01154 && __this->_M_base._M_in_binary_mode()) { 01155 // If we've mmapped part of the file already, then unmap it. 01156 if (__this->_M_mmap_base) 01157 __this->_M_base._M_unmap(__this->_M_mmap_base, __this->_M_mmap_len); 01158 01159 // Determine the position where we start mapping. It has to be 01160 // a multiple of the page size. 01161 streamoff __cur = __this->_M_base._M_seek(0, ios_base::cur); 01162 streamoff __size = __this->_M_base._M_file_size(); 01163 if (__size > 0 && __cur >= 0 && __cur < __size) { 01164 streamoff __offset = (__cur / __this->_M_base.__page_size()) * __this->_M_base.__page_size(); 01165 streamoff __remainder = __cur - __offset; 01166 01167 __this->_M_mmap_len = __size - __offset; 01168 01169 if (__this->_M_mmap_len > MMAP_CHUNK) 01170 __this->_M_mmap_len = MMAP_CHUNK; 01171 01172 if ((__this->_M_mmap_base = 01173 __this->_M_base._M_mmap(__offset, __this->_M_mmap_len)) != 0) { 01174 __this->setg((char*) __this->_M_mmap_base, 01175 (char*) __this->_M_mmap_base + __STATIC_CAST(ptrdiff_t, __remainder), 01176 (char*) __this->_M_mmap_base + __STATIC_CAST(ptrdiff_t, __this->_M_mmap_len)); 01177 return traits_type::to_int_type(*__this->gptr()); 01178 } else 01179 __this->_M_mmap_len = 0; 01180 } 01181 else { 01182 __this->_M_mmap_base = 0; 01183 __this->_M_mmap_len = 0; 01184 } 01185 } 01186 01187 return __this->_M_underflow_aux(); 01188 } 01189 01190 01191 //---------------------------------------------------------------------- 01192 // Force instantiation of filebuf and fstream classes. 01193 #if !defined(_STLP_NO_FORCE_INSTANTIATE) 01194 01195 template class basic_filebuf<char, char_traits<char> >; 01196 template class basic_ifstream<char, char_traits<char> >; 01197 template class basic_ofstream<char, char_traits<char> >; 01198 template class basic_fstream<char, char_traits<char> >; 01199 01200 # if !defined (_STLP_NO_WCHAR_T) 01201 template class _Underflow<wchar_t, char_traits<wchar_t> >; 01202 template class basic_filebuf<wchar_t, char_traits<wchar_t> >; 01203 template class basic_ifstream<wchar_t, char_traits<wchar_t> >; 01204 template class basic_ofstream<wchar_t, char_traits<wchar_t> >; 01205 template class basic_fstream<wchar_t, char_traits<wchar_t> >; 01206 # endif /* _STLP_NO_WCHAR_T */ 01207 01208 #endif 01209 01210 _STLP_END_NAMESPACE 01211 01212 // Local Variables: 01213 // mode:C++ 01214 // End:
Generated on Mon Mar 10 15:32:16 2008 by ![]() |