Changeset 38658 in vbox
- Timestamp:
- Sep 6, 2011 2:22:53 PM (13 years ago)
- svn:sync-xref-src-repo-rev:
- 73870
- Location:
- trunk
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/iprt/string.h
r37964 r38658 1451 1451 * - \%ls - Same as \%s except that the input is UTF-16 (output UTF-8). 1452 1452 * - \%Ls - Same as \%s except that the input is UCS-32 (output UTF-8). 1453 * - \%S - R3: Same as \%s except it is printed in the current codeset 1454 * instead of UTF-8 (source is still UTF-8). 1455 * Other contexts: Same as \%s. 1456 * - \%lS - Same as \%S except that the input is UTF-16 (output current 1457 * codeset). 1458 * - \%LS - Same as \%S except that the input is UCS-32 (output current 1459 * codeset). 1453 * - \%S - Same as \%s, used to convert to current codeset but this is 1454 * now done by the streams code. Deprecated, use \%s. 1455 * - \%lS - Ditto. Deprecated, use \%ls. 1456 * - \%LS - Ditto. Deprecated, use \%Ls. 1460 1457 * - \%c - Takes a char and prints it. 1461 1458 * - \%d - Takes a signed integer and prints it as decimal. Thousand -
trunk/src/VBox/Runtime/common/string/strformat.cpp
r33540 r38658 483 483 } 484 484 485 #ifndef IN_RING3 486 case 'S': /* Unicode string as current code page -> Unicode as UTF-8 in GC/R0. */ 487 chArgSize = 'l'; /** @todo this is nonsensical, isn't it? */ 488 /* fall thru */ 489 #endif 490 case 's': /* Unicode string as utf8 */ 485 case 'S': /* Legacy, conversion done by streams now. */ 486 case 's': 491 487 { 492 488 if (chArgSize == 'l') … … 508 504 while (cchStr-- > 0) 509 505 { 510 #if def IN_RING3506 #ifndef IN_RC 511 507 RTUNICP Cp; 512 508 RTUtf16GetCpEx(&pwszStr, &Cp); … … 541 537 while (cchStr-- > 0) 542 538 { 543 #if def IN_RING3539 #ifndef IN_RC 544 540 char szUtf8[8]; /* Cp=0x7fffffff -> 6 bytes. */ 545 541 char *pszEnd = RTStrPutCp(szUtf8, *puszStr++); … … 572 568 break; 573 569 } 574 575 #ifdef IN_RING3576 case 'S': /* Unicode string as current code page. */577 {578 if (chArgSize == 'l')579 {580 /* UTF-16 */581 int cchStr;582 PCRTUTF16 pwsz2Str = va_arg(args, PRTUTF16);583 if (!VALID_PTR(pwsz2Str))584 {585 static RTUTF16 s_wsz2Null[] = {'<', 'N', 'U', 'L', 'L', '>', '\0' };586 pwsz2Str = s_wsz2Null;587 }588 589 cchStr = _strnlenUtf16(pwsz2Str, (unsigned)cchPrecision);590 if (!(fFlags & RTSTR_F_LEFT))591 while (--cchWidth >= cchStr)592 cch += pfnOutput(pvArgOutput, " ", 1);593 594 if (cchStr)595 {596 /* allocate temporary buffer. */597 PRTUTF16 pwsz2Tmp = (PRTUTF16)RTMemTmpAlloc((cchStr + 1) * sizeof(RTUTF16));598 memcpy(pwsz2Tmp, pwsz2Str, cchStr * sizeof(RTUTF16));599 pwsz2Tmp[cchStr] = '\0';600 601 char *pszUtf8;602 int rc = RTUtf16ToUtf8(pwsz2Tmp, &pszUtf8);603 if (RT_SUCCESS(rc))604 {605 char *pszCurCp;606 rc = RTStrUtf8ToCurrentCP(&pszCurCp, pszUtf8);607 if (RT_SUCCESS(rc))608 {609 cch += pfnOutput(pvArgOutput, pszCurCp, strlen(pszCurCp));610 RTStrFree(pszCurCp);611 }612 RTStrFree(pszUtf8);613 }614 if (RT_FAILURE(rc))615 while (cchStr-- > 0)616 cch += pfnOutput(pvArgOutput, "\x7f", 1);617 RTMemTmpFree(pwsz2Tmp);618 }619 620 while (--cchWidth >= cchStr)621 cch += pfnOutput(pvArgOutput, " ", 1);622 }623 else if (chArgSize == 'L')624 {625 /* UCS-32 */626 AssertMsgFailed(("Not implemented yet\n"));627 }628 else629 {630 /* UTF-8 */631 int cchStr;632 const char *pszStr = va_arg(args, char *);633 634 if (!VALID_PTR(pszStr))635 pszStr = "<NULL>";636 cchStr = _strnlen(pszStr, (unsigned)cchPrecision);637 if (!(fFlags & RTSTR_F_LEFT))638 while (--cchWidth >= cchStr)639 cch += pfnOutput(pvArgOutput, " ", 1);640 641 if (cchStr)642 {643 /* allocate temporary buffer. */644 char *pszTmp = (char *)RTMemTmpAlloc(cchStr + 1);645 memcpy(pszTmp, pszStr, cchStr);646 pszTmp[cchStr] = '\0';647 648 char *pszCurCp;649 int rc = RTStrUtf8ToCurrentCP(&pszCurCp, pszTmp);650 if (RT_SUCCESS(rc))651 {652 cch += pfnOutput(pvArgOutput, pszCurCp, strlen(pszCurCp));653 RTStrFree(pszCurCp);654 }655 else656 while (cchStr-- > 0)657 cch += pfnOutput(pvArgOutput, "\x7f", 1);658 RTMemTmpFree(pszTmp);659 }660 661 while (--cchWidth >= cchStr)662 cch += pfnOutput(pvArgOutput, " ", 1);663 }664 break;665 }666 #endif667 668 570 669 571 /*-----------------*/ -
trunk/src/VBox/Runtime/r3/init.cpp
r38639 r38658 34 34 #ifdef RT_OS_WINDOWS 35 35 # include <process.h> 36 # include <Windows.h>37 36 #else 38 37 # include <unistd.h> … … 318 317 setlocale(LC_CTYPE, ""); 319 318 320 #ifdef RT_OS_WINDOWS321 /*322 * On windows, make sure we talk CP_ACP to the console. It frequently uses323 * a different code page, which would cause %[lL]S to fail.324 */325 if (!(fFlags & RTR3INIT_FLAGS_DLL))326 {327 SetConsoleCP(GetACP());328 SetConsoleOutputCP(GetACP());329 }330 #endif331 332 319 /* 333 320 * The Process ID. -
trunk/src/VBox/Runtime/r3/stream.cpp
r32464 r38658 53 53 #include <stdio.h> 54 54 #include <errno.h> 55 #ifdef RT_OS_WINDOWS 56 # include <io.h> 57 # include <fcntl.h> 58 # include <Windows.h> 59 #endif 55 60 56 61 … … 69 74 /** Pointer to the LIBC file stream. */ 70 75 FILE *pFile; 76 /** Stream is using the current process code set. */ 77 bool fCurrentCodeSet; 78 /** Whether the stream was opened in binary mode. */ 79 bool fBinary; 80 /** Whether to recheck the stream mode before writing.. */ 81 bool fRecheckMode; 71 82 #ifndef HAVE_FWRITE_UNLOCKED 72 83 /** Critical section for serializing access to the stream. */ … … 84 95 RTSTREAM_MAGIC, 85 96 0, 86 stdin 97 stdin, 98 true, 99 /*.fBinary = */ false, 100 /*.fRecheckMode = */ true 87 101 #ifndef HAVE_FWRITE_UNLOCKED 88 102 , NULL … … 95 109 RTSTREAM_MAGIC, 96 110 0, 97 stderr 111 stderr, 112 true, 113 /*.fBinary = */ false, 114 /*.fRecheckMode = */ true 98 115 #ifndef HAVE_FWRITE_UNLOCKED 99 116 , NULL … … 106 123 RTSTREAM_MAGIC, 107 124 0, 108 stdout 125 stdout, 126 true, 127 /*.fBinary = */ false, 128 /*.fRecheckMode = */ true 109 129 #ifndef HAVE_FWRITE_UNLOCKED 110 130 , NULL … … 223 243 } 224 244 bool fOk = true; 245 bool fBinary = false; 225 246 switch (*pszMode) 226 247 { … … 232 253 case '\0': 233 254 break; 255 234 256 case '+': 235 257 switch (pszMode[2]) 236 258 { 237 259 case '\0': 260 break; 261 238 262 //case 't': 263 // break; 264 239 265 case 'b': 266 fBinary = true; 240 267 break; 268 241 269 default: 242 270 fOk = false; … … 244 272 } 245 273 break; 274 246 275 //case 't': 276 // break; 277 247 278 case 'b': 279 fBinary = true; 248 280 break; 281 249 282 default: 250 283 fOk = false; … … 270 303 pStream->u32Magic = RTSTREAM_MAGIC; 271 304 pStream->i32Error = VINF_SUCCESS; 305 pStream->fCurrentCodeSet = false; 306 pStream->fBinary = fBinary; 272 307 #ifndef HAVE_FWRITE_UNLOCKED 273 308 pStream->pCritSect = NULL; … … 339 374 RTR3DECL(int) RTStrmClose(PRTSTREAM pStream) 340 375 { 341 if (pStream && pStream->u32Magic == RTSTREAM_MAGIC) 342 { 343 if (!fclose(pStream->pFile)) 376 if (!pStream) 377 return VINF_SUCCESS; 378 AssertReturn(RT_VALID_PTR(pStream) && pStream->u32Magic == RTSTREAM_MAGIC, VERR_INVALID_PARAMETER); 379 380 if (!fclose(pStream->pFile)) 381 { 382 pStream->u32Magic = 0xdeaddead; 383 pStream->pFile = NULL; 384 #ifndef HAVE_FWRITE_UNLOCKED 385 if (pStream->pCritSect) 344 386 { 345 pStream->u32Magic = 0xdeaddead; 346 pStream->pFile = NULL; 347 #ifndef HAVE_FWRITE_UNLOCKED 348 if (pStream->pCritSect) 349 { 350 RTCritSectEnter(pStream->pCritSect); 351 RTCritSectLeave(pStream->pCritSect); 352 RTCritSectDelete(pStream->pCritSect); 353 RTMemFree(pStream->pCritSect); 354 pStream->pCritSect = NULL; 355 } 356 #endif 357 RTMemFree(pStream); 358 return VINF_SUCCESS; 387 RTCritSectEnter(pStream->pCritSect); 388 RTCritSectLeave(pStream->pCritSect); 389 RTCritSectDelete(pStream->pCritSect); 390 RTMemFree(pStream->pCritSect); 391 pStream->pCritSect = NULL; 359 392 } 360 361 return RTErrConvertFromErrno(errno); 362 } 363 else 364 { 365 AssertMsgFailed(("Invalid stream!\n")); 366 return VERR_INVALID_PARAMETER; 367 } 393 #endif 394 RTMemFree(pStream); 395 return VINF_SUCCESS; 396 } 397 398 return RTErrConvertFromErrno(errno); 368 399 } 369 400 … … 377 408 RTR3DECL(int) RTStrmError(PRTSTREAM pStream) 378 409 { 379 int rc; 380 if (pStream && pStream->u32Magic == RTSTREAM_MAGIC) 381 rc = pStream->i32Error; 382 else 383 { 384 AssertMsgFailed(("Invalid stream!\n")); 385 rc = VERR_INVALID_PARAMETER; 386 } 387 return rc; 410 AssertReturn(RT_VALID_PTR(pStream) && pStream->u32Magic == RTSTREAM_MAGIC, VERR_INVALID_PARAMETER); 411 return pStream->i32Error; 388 412 } 389 413 … … 400 424 RTR3DECL(int) RTStrmClearError(PRTSTREAM pStream) 401 425 { 402 int rc; 403 if (pStream && pStream->u32Magic == RTSTREAM_MAGIC) 404 { 405 clearerr(pStream->pFile); 406 ASMAtomicXchgS32(&pStream->i32Error, VINF_SUCCESS); 407 rc = VINF_SUCCESS; 408 } 409 else 410 { 411 AssertMsgFailed(("Invalid stream!\n")); 412 rc = VERR_INVALID_PARAMETER; 413 } 414 return rc; 426 AssertReturn(RT_VALID_PTR(pStream) && pStream->u32Magic == RTSTREAM_MAGIC, VERR_INVALID_PARAMETER); 427 428 clearerr(pStream->pFile); 429 ASMAtomicWriteS32(&pStream->i32Error, VINF_SUCCESS); 430 return VINF_SUCCESS; 415 431 } 416 432 … … 438 454 if (!fseek(pStream->pFile, 0, SEEK_SET)) 439 455 { 440 ASMAtomic XchgS32(&pStream->i32Error, VINF_SUCCESS);456 ASMAtomicWriteS32(&pStream->i32Error, VINF_SUCCESS); 441 457 rc = VINF_SUCCESS; 442 458 } … … 444 460 { 445 461 rc = RTErrConvertFromErrno(errno); 446 ASMAtomic XchgS32(&pStream->i32Error, rc);462 ASMAtomicWriteS32(&pStream->i32Error, rc); 447 463 } 448 464 449 465 return rc; 466 } 467 468 469 /** 470 * Recheck the stream mode. 471 * 472 * @param pStream The stream (locked). 473 */ 474 static void rtStreamRecheckMode(PRTSTREAM pStream) 475 { 476 #if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2) 477 int fh = fileno(pStream->pFile); 478 if (fh >= 0) 479 { 480 int fExpected = pStream->fBinary ? _O_BINARY : _O_TEXT; 481 int fActual = _setmode(fh, fExpected); 482 if (fActual != -1 && fExpected != (fActual & (_O_BINARY | _O_TEXT))) 483 { 484 _setmode(fh, fActual & (_O_BINARY | _O_TEXT)); 485 pStream->fBinary = !(fActual & _O_TEXT); 486 } 487 } 488 #else 489 NOREF(pStream); 490 #endif 491 pStream->fRecheckMode = false; 450 492 } 451 493 … … 464 506 RTR3DECL(int) RTStrmReadEx(PRTSTREAM pStream, void *pvBuf, size_t cbRead, size_t *pcbRead) 465 507 { 466 int rc; 467 if (pStream && pStream->u32Magic == RTSTREAM_MAGIC) 468 { 469 rc = pStream->i32Error; 508 AssertReturn(RT_VALID_PTR(pStream) && pStream->u32Magic == RTSTREAM_MAGIC, VERR_INVALID_PARAMETER); 509 510 int rc = pStream->i32Error; 511 if (RT_SUCCESS(rc)) 512 { 513 if (pStream->fRecheckMode) 514 rtStreamRecheckMode(pStream); 515 516 if (pcbRead) 517 { 518 /* 519 * Can do with a partial read. 520 */ 521 *pcbRead = fread(pvBuf, 1, cbRead, pStream->pFile); 522 if ( *pcbRead == cbRead 523 || !ferror(pStream->pFile)) 524 return VINF_SUCCESS; 525 if (feof(pStream->pFile)) 526 { 527 if (*pcbRead) 528 return VINF_EOF; 529 rc = VERR_EOF; 530 } 531 else if (ferror(pStream->pFile)) 532 rc = VERR_READ_ERROR; 533 else 534 { 535 AssertMsgFailed(("This shouldn't happen\n")); 536 rc = VERR_INTERNAL_ERROR; 537 } 538 } 539 else 540 { 541 /* 542 * Must read it all! 543 */ 544 if (fread(pvBuf, cbRead, 1, pStream->pFile) == 1) 545 return VINF_SUCCESS; 546 547 /* possible error/eof. */ 548 if (feof(pStream->pFile)) 549 rc = VERR_EOF; 550 else if (ferror(pStream->pFile)) 551 rc = VERR_READ_ERROR; 552 else 553 { 554 AssertMsgFailed(("This shouldn't happen\n")); 555 rc = VERR_INTERNAL_ERROR; 556 } 557 } 558 ASMAtomicWriteS32(&pStream->i32Error, rc); 559 } 560 return rc; 561 } 562 563 564 /** 565 * Check if the input text is valid UTF-8. 566 * 567 * @returns true/false. 568 * @param pvBuf Pointer to the buffer. 569 * @param cbBuf Size of the buffer. 570 */ 571 static bool rtStrmIsUtf8Text(const void *pvBuf, size_t cbBuf) 572 { 573 NOREF(pvBuf); 574 NOREF(cbBuf); 575 /** @todo not sure this is a good idea... Better redefine RTStrmWrite. */ 576 return false; 577 } 578 579 580 #ifdef RT_OS_WINDOWS 581 /** 582 * Check if the stream is for a Window console. 583 * 584 * @returns true / false. 585 * @param pStream The stream. 586 * @param phCon Where to return the console handle. 587 */ 588 static bool rtStrmIsConsoleUnlocked(PRTSTREAM pStream, HANDLE *phCon) 589 { 590 int fh = fileno(pStream->pFile); 591 if (isatty(fh)) 592 { 593 DWORD dwMode; 594 HANDLE hCon = (HANDLE)_get_osfhandle(fh); 595 if (GetConsoleMode(hCon, &dwMode)) 596 { 597 *phCon = hCon; 598 return true; 599 } 600 } 601 return false; 602 } 603 #endif /* RT_OS_WINDOWS */ 604 605 606 /** 607 * Internal write API, stream lock already held. 608 * 609 * @returns IPRT status code. 610 * @param pStream The stream. 611 * @param pvBuf What to write. 612 * @param cbWrite How much to write. 613 * @param pcbWritten Where to optionally return the number of bytes 614 * written. 615 * @param fSureIsText Set if we're sure this is UTF-8 text already. 616 */ 617 static int rtStrmWriteLocked(PRTSTREAM pStream, const void *pvBuf, size_t cbWrite, size_t *pcbWritten, 618 bool fSureIsText) 619 { 620 int rc = pStream->i32Error; 621 if (RT_FAILURE(rc)) 622 return rc; 623 if (pStream->fRecheckMode) 624 rtStreamRecheckMode(pStream); 625 626 #ifdef RT_OS_WINDOWS 627 /* 628 * Use the unicode console API when possible in order to avoid stuff 629 * getting lost in unnecessary code page translations. 630 */ 631 HANDLE hCon; 632 if (rtStrmIsConsoleUnlocked(pStream, &hCon)) 633 { 634 # ifdef HAVE_FWRITE_UNLOCKED 635 if (!fflush_unlocked(pStream->pFile)) 636 # else 637 if (!fflush(pStream->pFile)) 638 # endif 639 { 640 /** @todo Consider buffering later. For now, we'd rather correct output than 641 * fast output. */ 642 DWORD cwcWritten = 0; 643 PRTUTF16 pwszSrc = NULL; 644 size_t cwcSrc = 0; 645 rc = RTStrToUtf16Ex((const char *)pvBuf, cbWrite, &pwszSrc, 0, &cwcSrc); 646 if (RT_SUCCESS(rc)) 647 { 648 if (!WriteConsoleW(hCon, pwszSrc, (DWORD)cwcSrc, &cwcWritten, NULL)) 649 { 650 /* try write char-by-char to avoid heap problem. */ 651 cwcWritten = 0; 652 while (cwcWritten != cwcSrc) 653 { 654 DWORD cwcThis; 655 if (!WriteConsoleW(hCon, &pwszSrc[cwcWritten], 1, &cwcThis, NULL)) 656 { 657 if (!pcbWritten || cwcWritten == 0) 658 rc = RTErrConvertFromErrno(GetLastError()); 659 break; 660 } 661 if (cwcThis != 0) 662 break; 663 cwcWritten++; 664 } 665 } 666 if (RT_SUCCESS(rc)) 667 { 668 if (cwcWritten == cwcSrc) 669 { 670 if (pcbWritten) 671 *pcbWritten = cbWrite; 672 } 673 else if (pcbWritten) 674 { 675 PCRTUTF16 pwszCur = pwszSrc; 676 const char *pszCur = (const char *)pvBuf; 677 while ((uintptr_t)(pwszCur - pwszSrc) < cwcWritten) 678 { 679 RTUNICP CpIgnored; 680 RTUtf16GetCpEx(&pwszCur, &CpIgnored); 681 RTStrGetCpEx(&pszCur, &CpIgnored); 682 } 683 *pcbWritten = pszCur - (const char *)pvBuf; 684 } 685 else 686 rc = VERR_WRITE_ERROR; 687 } 688 RTUtf16Free(pwszSrc); 689 } 690 } 691 else 692 rc = RTErrConvertFromErrno(errno); 693 if (RT_FAILURE(rc)) 694 ASMAtomicWriteS32(&pStream->i32Error, rc); 695 return rc; 696 } 697 #endif /* RT_OS_WINDOWS */ 698 699 /* 700 * If we're sure it's text output, convert it from UTF-8 to the current 701 * code page before printing it. 702 * 703 * Note! Partial writes are not supported in this scenario because we 704 * cannot easily report back a written length matching the input. 705 */ 706 /** @todo Skip this if the current code set is UTF-8. */ 707 if ( pStream->fCurrentCodeSet 708 && !pStream->fBinary 709 && ( fSureIsText 710 || rtStrmIsUtf8Text(pvBuf, cbWrite)) 711 ) 712 { 713 char *pszSrcFree = NULL; 714 const char *pszSrc = (const char *)pvBuf; 715 if (pszSrc[cbWrite]) 716 { 717 pszSrc = pszSrcFree = RTStrDupN(pszSrc, cbWrite); 718 if (pszSrc == NULL) 719 rc = VERR_NO_STR_MEMORY; 720 } 470 721 if (RT_SUCCESS(rc)) 471 722 { 472 if (pcbRead) 723 char *pszSrcCurCP; 724 rc = RTStrUtf8ToCurrentCP(&pszSrcCurCP, pszSrc); 725 if (RT_SUCCESS(rc)) 473 726 { 474 /* 475 * Can do with a partial read. 476 */ 477 *pcbRead = fread(pvBuf, 1, cbRead, pStream->pFile); 478 if ( *pcbRead == cbRead 479 || !ferror(pStream->pFile)) 480 return VINF_SUCCESS; 481 if (feof(pStream->pFile)) 727 size_t cchSrcCurCP = strlen(pszSrcCurCP); 728 IPRT_ALIGNMENT_CHECKS_DISABLE(); /* glibc / mempcpy again */ 729 #ifdef HAVE_FWRITE_UNLOCKED 730 ssize_t cbWritten = fwrite_unlocked(pszSrcCurCP, cchSrcCurCP, 1, pStream->pFile); 731 #else 732 ssize_t cbWritten = fwrite(pszSrcCurCP, cchSrcCurCP, 1, pStream->pFile); 733 #endif 734 IPRT_ALIGNMENT_CHECKS_ENABLE(); 735 if (cbWritten == 1) 482 736 { 483 if (*pcbRead) 484 return VINF_EOF; 485 rc = VERR_EOF; 737 if (pcbWritten) 738 *pcbWritten = cbWrite; 486 739 } 487 else if (ferror(pStream->pFile)) 488 rc = VERR_READ_ERROR; 740 #ifdef HAVE_FWRITE_UNLOCKED 741 else if (!ferror_unlocked(pStream->pFile)) 742 #else 743 else if (!ferror(pStream->pFile)) 744 #endif 745 { 746 if (pcbWritten) 747 *pcbWritten = 0; 748 } 489 749 else 490 { 491 AssertMsgFailed(("This shouldn't happen\n")); 492 rc = VERR_INTERNAL_ERROR; 493 } 750 rc = VERR_WRITE_ERROR; 751 RTStrFree(pszSrcCurCP); 494 752 } 495 else 496 { 497 /* 498 * Must read it all! 499 */ 500 if (fread(pvBuf, cbRead, 1, pStream->pFile) == 1) 501 return VINF_SUCCESS; 502 503 /* possible error/eof. */ 504 if (feof(pStream->pFile)) 505 rc = VERR_EOF; 506 else if (ferror(pStream->pFile)) 507 rc = VERR_READ_ERROR; 508 else 509 { 510 AssertMsgFailed(("This shouldn't happen\n")); 511 rc = VERR_INTERNAL_ERROR; 512 } 513 } 514 ASMAtomicXchgS32(&pStream->i32Error, rc); 753 RTStrFree(pszSrcFree); 515 754 } 755 756 if (RT_FAILURE(rc)) 757 ASMAtomicWriteS32(&pStream->i32Error, rc); 758 return rc; 759 } 760 761 /* 762 * Otherwise, just write it as-is. 763 */ 764 if (pcbWritten) 765 { 766 IPRT_ALIGNMENT_CHECKS_DISABLE(); /* glibc / mempcpy again */ 767 #ifdef HAVE_FWRITE_UNLOCKED 768 *pcbWritten = fwrite_unlocked(pvBuf, 1, cbWrite, pStream->pFile); 769 #else 770 *pcbWritten = fwrite(pvBuf, 1, cbWrite, pStream->pFile); 771 #endif 772 IPRT_ALIGNMENT_CHECKS_ENABLE(); 773 if ( *pcbWritten == cbWrite 774 #ifdef HAVE_FWRITE_UNLOCKED 775 || !ferror_unlocked(pStream->pFile)) 776 #else 777 || !ferror(pStream->pFile)) 778 #endif 779 return VINF_SUCCESS; 780 rc = VERR_WRITE_ERROR; 516 781 } 517 782 else 518 783 { 519 AssertMsgFailed(("Invalid stream!\n")); 520 rc = VERR_INVALID_PARAMETER; 521 } 784 /* Must write it all! */ 785 IPRT_ALIGNMENT_CHECKS_DISABLE(); /* glibc / mempcpy again */ 786 #ifdef HAVE_FWRITE_UNLOCKED 787 size_t cbWritten = fwrite_unlocked(pvBuf, cbWrite, 1, pStream->pFile); 788 #else 789 size_t cbWritten = fwrite(pvBuf, cbWrite, 1, pStream->pFile); 790 #endif 791 IPRT_ALIGNMENT_CHECKS_ENABLE(); 792 if (cbWritten == 1) 793 return VINF_SUCCESS; 794 #ifdef HAVE_FWRITE_UNLOCKED 795 if (!ferror_unlocked(pStream->pFile)) 796 #else 797 if (!ferror(pStream->pFile)) 798 #endif 799 return VINF_SUCCESS; /* WEIRD! But anyway... */ 800 801 rc = VERR_WRITE_ERROR; 802 } 803 ASMAtomicWriteS32(&pStream->i32Error, rc); 804 805 return rc; 806 } 807 808 809 /** 810 * Internal write API. 811 * 812 * @returns IPRT status code. 813 * @param pStream The stream. 814 * @param pvBuf What to write. 815 * @param cbWrite How much to write. 816 * @param pcbWritten Where to optionally return the number of bytes 817 * written. 818 * @param fSureIsText Set if we're sure this is UTF-8 text already. 819 */ 820 static int rtStrmWrite(PRTSTREAM pStream, const void *pvBuf, size_t cbWrite, size_t *pcbWritten, bool fSureIsText) 821 { 822 rtStrmLock(pStream); 823 int rc = rtStrmWriteLocked(pStream, pvBuf, cbWrite, pcbWritten, fSureIsText); 824 rtStrmUnlock(pStream); 522 825 return rc; 523 826 } … … 536 839 RTR3DECL(int) RTStrmWriteEx(PRTSTREAM pStream, const void *pvBuf, size_t cbWrite, size_t *pcbWritten) 537 840 { 538 int rc; 539 if (pStream && pStream->u32Magic == RTSTREAM_MAGIC) 540 { 541 rc = pStream->i32Error; 542 if (RT_SUCCESS(rc)) 543 { 544 if (pcbWritten) 545 { 546 IPRT_ALIGNMENT_CHECKS_DISABLE(); /* glibc / mempcpy again */ 547 *pcbWritten = fwrite(pvBuf, 1, cbWrite, pStream->pFile); 548 IPRT_ALIGNMENT_CHECKS_ENABLE(); 549 if ( *pcbWritten == cbWrite 550 || !ferror(pStream->pFile)) 551 return VINF_SUCCESS; 552 rc = VERR_WRITE_ERROR; 553 } 554 else 555 { 556 /* 557 * Must write it all! 558 */ 559 IPRT_ALIGNMENT_CHECKS_DISABLE(); /* glibc / mempcpy again */ 560 size_t cbWritten = fwrite(pvBuf, cbWrite, 1, pStream->pFile); 561 IPRT_ALIGNMENT_CHECKS_ENABLE(); 562 if (cbWritten == 1) 563 return VINF_SUCCESS; 564 if (!ferror(pStream->pFile)) 565 return VINF_SUCCESS; /* WEIRD! But anyway... */ 566 567 rc = VERR_WRITE_ERROR; 568 } 569 ASMAtomicXchgS32(&pStream->i32Error, rc); 570 } 571 } 572 else 573 { 574 AssertMsgFailed(("Invalid stream!\n")); 575 rc = VERR_INVALID_PARAMETER; 576 } 577 return rc; 841 AssertReturn(RT_VALID_PTR(pStream) && pStream->u32Magic == RTSTREAM_MAGIC, VERR_INVALID_PARAMETER); 842 return rtStrmWrite(pStream, pvBuf, cbWrite, pcbWritten, false); 578 843 } 579 844 … … 605 870 RTR3DECL(int) RTStrmPutCh(PRTSTREAM pStream, int ch) 606 871 { 607 return RTStrmWriteEx(pStream, &ch, 1, NULL);872 return rtStrmWrite(pStream, &ch, 1, NULL, true /*fSureIsText*/); 608 873 } 609 874 … … 621 886 { 622 887 size_t cch = strlen(pszString); 623 return RTStrmWriteEx(pStream, pszString, cch, NULL);888 return rtStrmWrite(pStream, pszString, cch, NULL, true /*fSureIsText*/); 624 889 } 625 890 … … 638 903 RTR3DECL(int) RTStrmGetLine(PRTSTREAM pStream, char *pszString, size_t cchString) 639 904 { 905 AssertReturn(RT_VALID_PTR(pStream) && pStream->u32Magic == RTSTREAM_MAGIC, VERR_INVALID_PARAMETER); 640 906 int rc; 641 if (pStream && pStream->u32Magic == RTSTREAM_MAGIC) 642 { 643 if (pszString && cchString > 1) 907 if (pszString && cchString > 1) 908 { 909 rc = pStream->i32Error; 910 if (RT_SUCCESS(rc)) 644 911 { 645 rc = pStream->i32Error; 646 if (RT_SUCCESS(rc)) 912 cchString--; /* save space for the terminator. */ 913 rtStrmLock(pStream); 914 for (;;) 647 915 { 648 cchString--; /* save space for the terminator. */ 649 rtStrmLock(pStream); 650 for (;;) 916 #ifdef HAVE_FWRITE_UNLOCKED /** @todo darwin + freebsd(?) has fgetc_unlocked but not fwrite_unlocked, optimize... */ 917 int ch = fgetc_unlocked(pStream->pFile); 918 #else 919 int ch = fgetc(pStream->pFile); 920 #endif 921 if (ch == EOF) 651 922 { 652 #ifdef HAVE_FWRITE_UNLOCKED /** @todo darwin + freebsd(?) has fgetc_unlocked but not fwrite_unlocked, optimize... */ 653 int ch = fgetc_unlocked(pStream->pFile); 654 #else 655 int ch = fgetc(pStream->pFile); 656 #endif 657 if (ch == EOF) 923 #ifdef HAVE_FWRITE_UNLOCKED 924 if (feof_unlocked(pStream->pFile)) 925 #else 926 if (feof(pStream->pFile)) 927 #endif 658 928 { 659 #ifdef HAVE_FWRITE_UNLOCKED 660 if (feof_unlocked(pStream->pFile)) 661 #else 662 if (feof(pStream->pFile)) 663 #endif 664 { 665 rc = VERR_EOF; 666 break; 667 } 668 #ifdef HAVE_FWRITE_UNLOCKED 669 if (ferror_unlocked(pStream->pFile)) 670 #else 671 if (ferror(pStream->pFile)) 672 #endif 673 rc = VERR_READ_ERROR; 674 else 675 { 676 AssertMsgFailed(("This shouldn't happen\n")); 677 rc = VERR_INTERNAL_ERROR; 678 } 929 rc = VERR_EOF; 679 930 break; 680 931 } 681 if (ch == '\0' || ch == '\n' || ch == '\r') 682 break; 683 *pszString++ = ch; 684 if (--cchString <= 0) 932 #ifdef HAVE_FWRITE_UNLOCKED 933 if (ferror_unlocked(pStream->pFile)) 934 #else 935 if (ferror(pStream->pFile)) 936 #endif 937 rc = VERR_READ_ERROR; 938 else 685 939 { 686 rc = VINF_BUFFER_OVERFLOW;687 break;940 AssertMsgFailed(("This shouldn't happen\n")); 941 rc = VERR_INTERNAL_ERROR; 688 942 } 943 break; 689 944 } 690 rtStrmUnlock(pStream); 691 692 *pszString = '\0'; 693 if (RT_FAILURE(rc)) 694 ASMAtomicXchgS32(&pStream->i32Error, rc); 945 if (ch == '\0' || ch == '\n' || ch == '\r') 946 break; 947 *pszString++ = ch; 948 if (--cchString <= 0) 949 { 950 rc = VINF_BUFFER_OVERFLOW; 951 break; 952 } 695 953 } 954 rtStrmUnlock(pStream); 955 956 *pszString = '\0'; 957 if (RT_FAILURE(rc)) 958 ASMAtomicWriteS32(&pStream->i32Error, rc); 696 959 } 697 else698 {699 AssertMsgFailed(("no buffer or too small buffer!\n"));700 rc = VERR_INVALID_PARAMETER;701 }702 960 } 703 961 else 704 962 { 705 AssertMsgFailed((" Invalid stream!\n"));963 AssertMsgFailed(("no buffer or too small buffer!\n")); 706 964 rc = VERR_INVALID_PARAMETER; 707 965 } … … 735 993 { 736 994 if (cchChars) 737 { 738 PRTSTREAM pStream = (PRTSTREAM)pvArg; 739 int rc = pStream->i32Error; 740 if (RT_SUCCESS(rc)) 741 { 742 IPRT_ALIGNMENT_CHECKS_DISABLE(); /* glibc / mempcpy again */ 743 #ifdef HAVE_FWRITE_UNLOCKED 744 if (fwrite_unlocked(pachChars, cchChars, 1, pStream->pFile) != 1) 745 #else 746 if (fwrite(pachChars, cchChars, 1, pStream->pFile) != 1) 747 #endif 748 ASMAtomicXchgS32(&pStream->i32Error, VERR_WRITE_ERROR); 749 IPRT_ALIGNMENT_CHECKS_ENABLE(); 750 } 751 } 995 rtStrmWriteLocked((PRTSTREAM)pvArg, pachChars, cchChars, NULL, true /*fSureIsText*/); 752 996 /* else: ignore termination call. */ 753 997 return cchChars; … … 765 1009 RTR3DECL(int) RTStrmPrintfV(PRTSTREAM pStream, const char *pszFormat, va_list args) 766 1010 { 767 int rc; 768 if (pStream && pStream->u32Magic == RTSTREAM_MAGIC) 769 { 770 rc = pStream->i32Error; 771 if (RT_SUCCESS(rc)) 772 { 773 rtStrmLock(pStream); 774 rc = (int)RTStrFormatV(rtstrmOutput, pStream, NULL, NULL, pszFormat, args); 775 rtStrmUnlock(pStream); 776 Assert(rc >= 0); 777 } 778 else 779 rc = -1; 1011 AssertReturn(RT_VALID_PTR(pStream) && pStream->u32Magic == RTSTREAM_MAGIC, VERR_INVALID_PARAMETER); 1012 int rc = pStream->i32Error; 1013 if (RT_SUCCESS(rc)) 1014 { 1015 rtStrmLock(pStream); 1016 // pStream->fShouldFlush = true; 1017 rc = (int)RTStrFormatV(rtstrmOutput, pStream, NULL, NULL, pszFormat, args); 1018 rtStrmUnlock(pStream); 1019 Assert(rc >= 0); 780 1020 } 781 1021 else 782 {783 AssertMsgFailed(("Invalid stream!\n"));784 1022 rc = -1; 785 }786 1023 return rc; 787 1024 }
Note:
See TracChangeset
for help on using the changeset viewer.