build/stlport/src/details/fstream_win32io.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial