- Timestamp:
- May 18, 2020 5:35:01 PM (5 years ago)
- Location:
- trunk
- Files:
-
- 3 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/com/string.h
r84287 r84339 664 664 * @{ */ 665 665 /** 666 * Encodes the give data as BASE64.666 * Encodes the given data as BASE64. 667 667 * 668 668 * @returns S_OK or E_OUTOFMEMORY. … … 671 671 * @param fLineBreaks Whether to add line breaks (true) or just encode it 672 672 * as a continuous string. 673 * @sa RTBase64EncodeUtf16 673 674 */ 674 675 HRESULT base64Encode(const void *pvData, size_t cbData, bool fLineBreaks = false); 676 677 /** 678 * Decodes the string as BASE64. 679 * 680 * @returns IPRT status code, see RTBase64DecodeUtf16Ex. 681 * @param pvData Where to return the decoded bytes. 682 * @param cbData Size of the @a pvData return buffer. 683 * @param pcbActual Where to return number of bytes actually decoded. 684 * This is optional and if not specified, the request 685 * will fail unless @a cbData matches the data size 686 * exactly. 687 * @param ppwszEnd Where to return pointer to the first non-base64 688 * character following the encoded data. This is 689 * optional and if NULL, the request will fail if there 690 * are anything trailing the encoded bytes in the 691 * string. 692 * @sa base64DecodedSize, RTBase64DecodeUtf16 693 */ 694 int base64Decode(void *pvData, size_t cbData, size_t *pcbActual = NULL, PRTUTF16 *ppwszEnd = NULL); 695 696 /** 697 * Determins the size of the BASE64 encoded data in the string. 698 * 699 * @returns The length in bytes. -1 if the encoding is bad. 700 * 701 * @param pwszString The Base64 encoded UTF-16 string. 702 * @param ppwszEnd If not NULL, this will point to the first char 703 * following the Base64 encoded text block. If 704 * NULL the entire string is assumed to be Base64. 705 * @sa base64Decode, RTBase64DecodedUtf16Size 706 */ 707 ssize_t base64DecodedSize(PRTUTF16 *ppwszEnd = NULL); 675 708 /** @} */ 676 709 -
trunk/src/VBox/Main/Makefile.kmk
r83820 r84339 1206 1206 glue/initterm.cpp \ 1207 1207 glue/string.cpp \ 1208 glue/string-base64.cpp \ 1208 1209 glue/AutoLock.cpp \ 1209 1210 glue/EventQueue.cpp \ -
trunk/src/VBox/Main/glue/string-base64.cpp
r84331 r84339 1 1 /* $Id$ */ 2 2 /** @file 3 * MS COM / XPCOM Abstraction Layer - UTF-8 and UTF-16 string classes .3 * MS COM / XPCOM Abstraction Layer - UTF-8 and UTF-16 string classes, BASE64 bits. 4 4 */ 5 5 … … 19 19 20 20 #include <iprt/base64.h> 21 #include <iprt/err.h> 22 #include <iprt/log.h> 23 #include <iprt/path.h> 24 #include <iprt/string.h> 25 #include <iprt/uni.h> 21 #include <iprt/errcore.h> 22 26 23 27 24 namespace com 28 25 { 29 30 // BSTR representing a null wide char with 32 bits of length prefix (0);31 // this will work on Windows as well as other platforms where BSTR does32 // not use length prefixes33 const OLECHAR g_achEmptyBstr[3] = { 0, 0, 0 };34 const BSTR g_bstrEmpty = (BSTR)&g_achEmptyBstr[2];35 36 /* static */37 const Bstr Bstr::Empty; /* default ctor is OK */38 39 40 Bstr &Bstr::printf(const char *pszFormat, ...)41 {42 va_list va;43 va_start(va, pszFormat);44 HRESULT hrc = printfVNoThrow(pszFormat, va);45 va_end(va);46 if (hrc == S_OK)47 { /* likely */ }48 else49 throw std::bad_alloc();50 return *this;51 }52 53 HRESULT Bstr::printfNoThrow(const char *pszFormat, ...) RT_NOEXCEPT54 {55 va_list va;56 va_start(va, pszFormat);57 HRESULT hrc = printfVNoThrow(pszFormat, va);58 va_end(va);59 return hrc;60 }61 62 63 Bstr &Bstr::printfV(const char *pszFormat, va_list va)64 {65 HRESULT hrc = printfVNoThrow(pszFormat, va);66 if (hrc == S_OK)67 { /* likely */ }68 else69 throw std::bad_alloc();70 return *this;71 }72 73 struct BSTRNOTHROW74 {75 Bstr *pThis;76 size_t cwcAlloc;77 size_t offDst;78 HRESULT hrc;79 };80 81 /**82 * Callback used with RTStrFormatV by Bstr::printfVNoThrow.83 *84 * @returns The number of bytes added (not used).85 *86 * @param pvArg Pointer to a BSTRNOTHROW structure.87 * @param pachChars The characters to append.88 * @param cbChars The number of characters. 0 on the final callback.89 */90 /*static*/ DECLCALLBACK(size_t)91 Bstr::printfOutputCallbackNoThrow(void *pvArg, const char *pachChars, size_t cbChars) RT_NOEXCEPT92 {93 BSTRNOTHROW *pArgs = (BSTRNOTHROW *)pvArg;94 if (cbChars)95 {96 size_t cwcAppend;97 int rc = ::RTStrCalcUtf16LenEx(pachChars, cbChars, &cwcAppend);98 AssertRCReturnStmt(rc, pArgs->hrc = E_UNEXPECTED, 0);99 100 /*101 * Ensure we've got sufficient memory.102 */103 Bstr *pThis = pArgs->pThis;104 size_t const cwcBoth = pArgs->offDst + cwcAppend;105 if (cwcBoth >= pArgs->cwcAlloc)106 {107 if (pArgs->hrc == S_OK)108 {109 /* Double the buffer size, if it's less that _1M. Align sizes like110 for append. */111 size_t cwcAlloc = RT_ALIGN_Z(pArgs->cwcAlloc, 128);112 cwcAlloc += RT_MIN(cwcAlloc, _1M);113 if (cwcAlloc <= cwcBoth)114 cwcAlloc = RT_ALIGN_Z(cwcBoth + 1, 512);115 pArgs->hrc = pThis->reserveNoThrow(cwcAlloc, true /*fForce*/);116 AssertMsgReturn(pArgs->hrc == S_OK, ("cwcAlloc=%#zx\n", cwcAlloc), 0);117 pArgs->cwcAlloc = cwcAlloc;118 }119 else120 return 0;121 }122 123 /*124 * Do the conversion.125 */126 PRTUTF16 pwszDst = pThis->m_bstr + pArgs->offDst;127 Assert(pArgs->cwcAlloc > pArgs->offDst);128 rc = ::RTStrToUtf16Ex(pachChars, cbChars, &pwszDst, pArgs->cwcAlloc - pArgs->offDst, &cwcAppend);129 AssertRCReturnStmt(rc, pArgs->hrc = E_UNEXPECTED, 0);130 pArgs->offDst += cwcAppend;131 }132 return cbChars;133 }134 135 HRESULT Bstr::printfVNoThrow(const char *pszFormat, va_list va) RT_NOEXCEPT136 {137 cleanup();138 139 BSTRNOTHROW Args = { this, 0, 0, S_OK };140 RTStrFormatV(printfOutputCallbackNoThrow, &Args, NULL, NULL, pszFormat, va);141 if (Args.hrc == S_OK)142 {143 Args.hrc = joltNoThrow(Args.offDst);144 if (Args.hrc == S_OK)145 return S_OK;146 }147 148 cleanup();149 return Args.hrc;150 }151 152 void Bstr::copyFromN(const char *a_pszSrc, size_t a_cchMax)153 {154 /*155 * Initialize m_bstr first in case of throws further down in the code, then156 * check for empty input (m_bstr == NULL means empty, there are no NULL157 * strings).158 */159 m_bstr = NULL;160 if (!a_cchMax || !a_pszSrc || !*a_pszSrc)161 return;162 163 /*164 * Calculate the length and allocate a BSTR string buffer of the right165 * size, i.e. optimize heap usage.166 */167 size_t cwc;168 int vrc = ::RTStrCalcUtf16LenEx(a_pszSrc, a_cchMax, &cwc);169 if (RT_SUCCESS(vrc))170 {171 m_bstr = ::SysAllocStringByteLen(NULL, (unsigned)(cwc * sizeof(OLECHAR)));172 if (RT_LIKELY(m_bstr))173 {174 PRTUTF16 pwsz = (PRTUTF16)m_bstr;175 vrc = ::RTStrToUtf16Ex(a_pszSrc, a_cchMax, &pwsz, cwc + 1, NULL);176 if (RT_SUCCESS(vrc))177 return;178 179 /* This should not happen! */180 AssertRC(vrc);181 cleanup();182 }183 }184 else /* ASSUME: input is valid Utf-8. Fake out of memory error. */185 AssertLogRelMsgFailed(("%Rrc %.*Rhxs\n", vrc, RTStrNLen(a_pszSrc, a_cchMax), a_pszSrc));186 throw std::bad_alloc();187 }188 189 int Bstr::compareUtf8(const char *a_pszRight, CaseSensitivity a_enmCase /*= CaseSensitive*/) const190 {191 PCRTUTF16 pwszLeft = m_bstr;192 193 /*194 * Special case for null/empty strings. Unlike RTUtf16Cmp we195 * treat null and empty equally.196 */197 if (!pwszLeft)198 return !a_pszRight || *a_pszRight == '\0' ? 0 : -1;199 if (!a_pszRight)200 return *pwszLeft == '\0' ? 0 : 1;201 202 /*203 * Compare with a UTF-8 string by enumerating them char by char.204 */205 for (;;)206 {207 RTUNICP ucLeft;208 int rc = RTUtf16GetCpEx(&pwszLeft, &ucLeft);209 AssertRCReturn(rc, 1);210 211 RTUNICP ucRight;212 rc = RTStrGetCpEx(&a_pszRight, &ucRight);213 AssertRCReturn(rc, -1);214 if (ucLeft == ucRight)215 {216 if (ucLeft)217 continue;218 return 0;219 }220 221 if (a_enmCase == CaseInsensitive)222 {223 if (RTUniCpToUpper(ucLeft) == RTUniCpToUpper(ucRight))224 continue;225 if (RTUniCpToLower(ucLeft) == RTUniCpToLower(ucRight))226 continue;227 }228 229 return ucLeft < ucRight ? -1 : 1;230 }231 }232 26 233 27 HRESULT Bstr::base64Encode(const void *pvData, size_t cbData, bool fLineBreaks /*= false*/) … … 245 39 } 246 40 247 248 #ifndef VBOX_WITH_XPCOM 249 250 HRESULT Bstr::joltNoThrow(ssize_t cwcNew /* = -1*/) RT_NOEXCEPT 41 int Bstr::base64Decode(void *pvData, size_t cbData, size_t *pcbActual /*= NULL*/, PRTUTF16 *ppwszEnd /*= NULL*/) 251 42 { 252 if (m_bstr) 253 { 254 size_t const cwcAlloc = ::SysStringLen(m_bstr); 255 size_t const cwcActual = cwcNew < 0 ? ::RTUtf16Len(m_bstr) : (size_t)cwcNew; 256 Assert(cwcNew < 0 || cwcActual == ::RTUtf16Len(m_bstr)); 257 if (cwcActual != cwcAlloc) 258 { 259 Assert(cwcActual <= cwcAlloc); 260 Assert((unsigned int)cwcActual == cwcActual); 261 262 /* Official way: Reallocate the string. We could of course just update the size-prefix if we dared... */ 263 if (!::SysReAllocStringLen(&m_bstr, NULL, (unsigned int)cwcActual)) 264 { 265 AssertFailed(); 266 return E_OUTOFMEMORY; 267 } 268 } 269 } 270 else 271 Assert(cwcNew <= 0); 272 return S_OK; 43 return RTBase64DecodeUtf16Ex(raw(), RTSTR_MAX, pvData, cbData, pcbActual, ppwszEnd); 273 44 } 274 45 275 276 void Bstr::jolt(ssize_t cwcNew /* = -1*/) 46 ssize_t Bstr::base64DecodedSize(PRTUTF16 *ppwszEnd /*= NULL*/) 277 47 { 278 HRESULT hrc = joltNoThrow(cwcNew); 279 if (hrc != S_OK) 280 throw std::bad_alloc(); 281 } 282 283 #endif /* !VBOX_WITH_XPCOM */ 284 285 286 HRESULT Bstr::reserveNoThrow(size_t cwcMin, bool fForce /*= false*/) RT_NOEXCEPT 287 { 288 /* If not forcing the string to the cwcMin length, check cwcMin against the 289 current string length: */ 290 if (!fForce) 291 { 292 size_t cwcCur = m_bstr ? ::SysStringLen(m_bstr) : 0; 293 if (cwcCur >= cwcMin) 294 return S_OK; 295 } 296 297 /* The documentation for SysReAllocStringLen hints about it being allergic 298 to NULL in some way or another, so we call SysAllocStringLen directly 299 when appropriate: */ 300 if (m_bstr) 301 AssertReturn(::SysReAllocStringLen(&m_bstr, NULL, (unsigned int)cwcMin) != FALSE, E_OUTOFMEMORY); 302 else if (cwcMin > 0) 303 { 304 m_bstr = ::SysAllocStringLen(NULL, (unsigned int)cwcMin); 305 AssertReturn(m_bstr, E_OUTOFMEMORY); 306 } 307 308 return S_OK; 309 } 310 311 312 void Bstr::reserve(size_t cwcMin, bool fForce /*= false*/) 313 { 314 HRESULT hrc = reserveNoThrow(cwcMin, fForce); 315 if (hrc != S_OK) 316 throw std::bad_alloc(); 317 } 318 319 320 Bstr &Bstr::append(const Bstr &rThat) 321 { 322 if (rThat.isNotEmpty()) 323 return appendWorkerUtf16(rThat.m_bstr, rThat.length()); 324 return *this; 325 } 326 327 328 HRESULT Bstr::appendNoThrow(const Bstr &rThat) RT_NOEXCEPT 329 { 330 if (rThat.isNotEmpty()) 331 return appendWorkerUtf16NoThrow(rThat.m_bstr, rThat.length()); 332 return S_OK; 333 } 334 335 336 Bstr &Bstr::append(const RTCString &rThat) 337 { 338 if (rThat.isNotEmpty()) 339 return appendWorkerUtf8(rThat.c_str(), rThat.length()); 340 return *this; 341 } 342 343 344 HRESULT Bstr::appendNoThrow(const RTCString &rThat) RT_NOEXCEPT 345 { 346 if (rThat.isNotEmpty()) 347 return appendWorkerUtf8NoThrow(rThat.c_str(), rThat.length()); 348 return S_OK; 349 } 350 351 352 Bstr &Bstr::append(CBSTR pwszSrc) 353 { 354 if (pwszSrc && *pwszSrc) 355 return appendWorkerUtf16(pwszSrc, RTUtf16Len(pwszSrc)); 356 return *this; 357 } 358 359 360 HRESULT Bstr::appendNoThrow(CBSTR pwszSrc) RT_NOEXCEPT 361 { 362 if (pwszSrc && *pwszSrc) 363 return appendWorkerUtf16NoThrow(pwszSrc, RTUtf16Len(pwszSrc)); 364 return S_OK; 365 } 366 367 368 Bstr &Bstr::append(const char *pszSrc) 369 { 370 if (pszSrc && *pszSrc) 371 return appendWorkerUtf8(pszSrc, strlen(pszSrc)); 372 return *this; 373 } 374 375 376 HRESULT Bstr::appendNoThrow(const char *pszSrc) RT_NOEXCEPT 377 { 378 if (pszSrc && *pszSrc) 379 return appendWorkerUtf8NoThrow(pszSrc, strlen(pszSrc)); 380 return S_OK; 381 } 382 383 384 Bstr &Bstr::append(const Bstr &rThat, size_t offStart, size_t cwcMax /*= RTSTR_MAX*/) 385 { 386 size_t cwcSrc = rThat.length(); 387 if (offStart < cwcSrc) 388 return appendWorkerUtf16(rThat.raw() + offStart, RT_MIN(cwcSrc - offStart, cwcMax)); 389 return *this; 390 } 391 392 393 HRESULT Bstr::appendNoThrow(const Bstr &rThat, size_t offStart, size_t cwcMax /*= RTSTR_MAX*/) RT_NOEXCEPT 394 { 395 size_t cwcSrc = rThat.length(); 396 if (offStart < cwcSrc) 397 return appendWorkerUtf16NoThrow(rThat.raw() + offStart, RT_MIN(cwcSrc - offStart, cwcMax)); 398 return S_OK; 399 } 400 401 402 Bstr &Bstr::append(const RTCString &rThat, size_t offStart, size_t cchMax /*= RTSTR_MAX*/) 403 { 404 if (offStart < rThat.length()) 405 return appendWorkerUtf8(rThat.c_str() + offStart, RT_MIN(rThat.length() - offStart, cchMax)); 406 return *this; 407 } 408 409 410 HRESULT Bstr::appendNoThrow(const RTCString &rThat, size_t offStart, size_t cchMax /*= RTSTR_MAX*/) RT_NOEXCEPT 411 { 412 if (offStart < rThat.length()) 413 return appendWorkerUtf8NoThrow(rThat.c_str() + offStart, RT_MIN(rThat.length() - offStart, cchMax)); 414 return S_OK; 415 } 416 417 418 Bstr &Bstr::append(CBSTR pwszThat, size_t cchMax) 419 { 420 return appendWorkerUtf16(pwszThat, RTUtf16NLen(pwszThat, cchMax)); 421 } 422 423 424 HRESULT Bstr::appendNoThrow(CBSTR pwszThat, size_t cchMax) RT_NOEXCEPT 425 { 426 return appendWorkerUtf16NoThrow(pwszThat, RTUtf16NLen(pwszThat, cchMax)); 427 } 428 429 430 Bstr &Bstr::append(const char *pszThat, size_t cchMax) 431 { 432 return appendWorkerUtf8(pszThat, RTStrNLen(pszThat, cchMax)); 433 } 434 435 436 HRESULT Bstr::appendNoThrow(const char *pszThat, size_t cchMax) RT_NOEXCEPT 437 { 438 return appendWorkerUtf8NoThrow(pszThat, RTStrNLen(pszThat, cchMax)); 439 } 440 441 442 Bstr &Bstr::append(char ch) 443 { 444 AssertMsg(ch > 0 && ch < 127, ("%#x\n", ch)); 445 return appendWorkerUtf8(&ch, 1); 446 } 447 448 449 HRESULT Bstr::appendNoThrow(char ch) RT_NOEXCEPT 450 { 451 AssertMsg(ch > 0 && ch < 127, ("%#x\n", ch)); 452 return appendWorkerUtf8NoThrow(&ch, 1); 453 } 454 455 456 Bstr &Bstr::appendCodePoint(RTUNICP uc) 457 { 458 RTUTF16 wszTmp[3]; 459 PRTUTF16 pwszEnd = RTUtf16PutCp(wszTmp, uc); 460 *pwszEnd = '\0'; 461 return appendWorkerUtf16(&wszTmp[0], pwszEnd - &wszTmp[0]); 462 } 463 464 465 HRESULT Bstr::appendCodePointNoThrow(RTUNICP uc) RT_NOEXCEPT 466 { 467 RTUTF16 wszTmp[3]; 468 PRTUTF16 pwszEnd = RTUtf16PutCp(wszTmp, uc); 469 *pwszEnd = '\0'; 470 return appendWorkerUtf16NoThrow(&wszTmp[0], pwszEnd - &wszTmp[0]); 471 } 472 473 474 Bstr &Bstr::appendWorkerUtf16(PCRTUTF16 pwszSrc, size_t cwcSrc) 475 { 476 size_t cwcOld = length(); 477 size_t cwcTotal = cwcOld + cwcSrc; 478 reserve(cwcTotal, true /*fForce*/); 479 if (cwcSrc) 480 memcpy(&m_bstr[cwcOld], pwszSrc, cwcSrc * sizeof(RTUTF16)); 481 m_bstr[cwcTotal] = '\0'; 482 return *this; 483 } 484 485 486 HRESULT Bstr::appendWorkerUtf16NoThrow(PCRTUTF16 pwszSrc, size_t cwcSrc) RT_NOEXCEPT 487 { 488 size_t cwcOld = length(); 489 size_t cwcTotal = cwcOld + cwcSrc; 490 HRESULT hrc = reserveNoThrow(cwcTotal, true /*fForce*/); 491 if (hrc == S_OK) 492 { 493 if (cwcSrc) 494 memcpy(&m_bstr[cwcOld], pwszSrc, cwcSrc * sizeof(RTUTF16)); 495 m_bstr[cwcTotal] = '\0'; 496 } 497 return hrc; 498 } 499 500 501 Bstr &Bstr::appendWorkerUtf8(const char *pszSrc, size_t cchSrc) 502 { 503 size_t cwcSrc; 504 int rc = RTStrCalcUtf16LenEx(pszSrc, cchSrc, &cwcSrc); 505 AssertRCStmt(rc, throw std::bad_alloc()); 506 507 size_t cwcOld = length(); 508 size_t cwcTotal = cwcOld + cwcSrc; 509 reserve(cwcTotal, true /*fForce*/); 510 if (cwcSrc) 511 { 512 PRTUTF16 pwszDst = &m_bstr[cwcOld]; 513 rc = RTStrToUtf16Ex(pszSrc, cchSrc, &pwszDst, cwcSrc + 1, NULL); 514 AssertRCStmt(rc, throw std::bad_alloc()); 515 } 516 m_bstr[cwcTotal] = '\0'; 517 return *this; 518 } 519 520 521 HRESULT Bstr::appendWorkerUtf8NoThrow(const char *pszSrc, size_t cchSrc) RT_NOEXCEPT 522 { 523 size_t cwcSrc; 524 int rc = RTStrCalcUtf16LenEx(pszSrc, cchSrc, &cwcSrc); 525 AssertRCStmt(rc, E_INVALIDARG); 526 527 size_t cwcOld = length(); 528 size_t cwcTotal = cwcOld + cwcSrc; 529 HRESULT hrc = reserveNoThrow(cwcTotal, true /*fForce*/); 530 AssertReturn(hrc == S_OK, hrc); 531 if (cwcSrc) 532 { 533 PRTUTF16 pwszDst = &m_bstr[cwcOld]; 534 rc = RTStrToUtf16Ex(pszSrc, cchSrc, &pwszDst, cwcSrc + 1, NULL); 535 AssertRCStmt(rc, E_INVALIDARG); 536 } 537 m_bstr[cwcTotal] = '\0'; 538 return S_OK; 539 } 540 541 542 Bstr &Bstr::appendPrintf(const char *pszFormat, ...) 543 { 544 va_list va; 545 va_start(va, pszFormat); 546 HRESULT hrc = appendPrintfVNoThrow(pszFormat, va); 547 va_end(va); 548 if (hrc != S_OK) 549 throw std::bad_alloc(); 550 return *this; 551 } 552 553 554 HRESULT Bstr::appendPrintfNoThrow(const char *pszFormat, ...) RT_NOEXCEPT 555 { 556 va_list va; 557 va_start(va, pszFormat); 558 HRESULT hrc = appendPrintfVNoThrow(pszFormat, va); 559 va_end(va); 560 return hrc; 561 } 562 563 564 Bstr &Bstr::appendPrintfV(const char *pszFormat, va_list va) 565 { 566 HRESULT hrc = appendPrintfVNoThrow(pszFormat, va); 567 if (hrc != S_OK) 568 throw std::bad_alloc(); 569 return *this; 570 } 571 572 573 HRESULT Bstr::appendPrintfVNoThrow(const char *pszFormat, va_list va) RT_NOEXCEPT 574 { 575 size_t const cwcOld = length(); 576 BSTRNOTHROW Args = { this, cwcOld, cwcOld, S_OK }; 577 578 RTStrFormatV(printfOutputCallbackNoThrow, &Args, NULL, NULL, pszFormat, va); 579 if (Args.hrc == S_OK) 580 { 581 Args.hrc = joltNoThrow(Args.offDst); 582 if (Args.hrc == S_OK) 583 return S_OK; 584 } 585 586 if (m_bstr) 587 m_bstr[cwcOld] = '\0'; 588 return Args.hrc; 589 } 590 591 592 Bstr &Bstr::erase(size_t offStart /*= 0*/, size_t cwcLength /*= RTSTR_MAX*/) RT_NOEXCEPT 593 { 594 size_t cwc = length(); 595 if (offStart < cwc) 596 { 597 if (cwcLength >= cwc - offStart) 598 { 599 if (!offStart) 600 cleanup(); 601 else 602 { 603 /* Trail removal, nothing to move. */ 604 m_bstr[offStart] = '\0'; 605 joltNoThrow(offStart); /* not entirely optimal... */ 606 } 607 } 608 else if (cwcLength > 0) 609 { 610 /* Pull up the tail to offStart. */ 611 size_t cwcAfter = cwc - offStart - cwcLength; 612 memmove(&m_bstr[offStart], &m_bstr[offStart + cwcLength], cwcAfter * sizeof(*m_bstr)); 613 cwc -= cwcLength; 614 m_bstr[cwc] = '\0'; 615 joltNoThrow(cwc); /* not entirely optimal... */ 616 } 617 } 618 return *this; 619 } 620 621 622 void Bstr::cleanup() 623 { 624 if (m_bstr) 625 { 626 ::SysFreeString(m_bstr); 627 m_bstr = NULL; 628 } 629 } 630 631 632 void Bstr::copyFrom(const OLECHAR *a_bstrSrc) 633 { 634 if (a_bstrSrc && *a_bstrSrc) 635 { 636 m_bstr = ::SysAllocString(a_bstrSrc); 637 if (!m_bstr) 638 throw std::bad_alloc(); 639 } 640 else 641 m_bstr = NULL; 642 } 643 644 645 void Bstr::cleanupAndCopyFrom(const OLECHAR *a_bstrSrc) 646 { 647 cleanup(); 648 copyFrom(a_bstrSrc); 649 } 650 651 652 653 /********************************************************************************************************************************* 654 * Utf8Str Implementation * 655 *********************************************************************************************************************************/ 656 657 /* static */ 658 const Utf8Str Utf8Str::Empty; /* default ctor is OK */ 659 660 #if defined(VBOX_WITH_XPCOM) 661 void Utf8Str::cloneTo(char **pstr) const 662 { 663 size_t cb = length() + 1; 664 *pstr = (char *)nsMemory::Alloc(cb); 665 if (RT_LIKELY(*pstr)) 666 memcpy(*pstr, c_str(), cb); 667 else 668 throw std::bad_alloc(); 669 } 670 671 HRESULT Utf8Str::cloneToEx(char **pstr) const 672 { 673 size_t cb = length() + 1; 674 *pstr = (char *)nsMemory::Alloc(cb); 675 if (RT_LIKELY(*pstr)) 676 { 677 memcpy(*pstr, c_str(), cb); 678 return S_OK; 679 } 680 return E_OUTOFMEMORY; 681 } 682 #endif 683 684 Utf8Str& Utf8Str::stripTrailingSlash() 685 { 686 if (length()) 687 { 688 ::RTPathStripTrailingSlash(m_psz); 689 jolt(); 690 } 691 return *this; 692 } 693 694 Utf8Str& Utf8Str::stripFilename() 695 { 696 if (length()) 697 { 698 RTPathStripFilename(m_psz); 699 jolt(); 700 } 701 return *this; 702 } 703 704 Utf8Str& Utf8Str::stripPath() 705 { 706 if (length()) 707 { 708 char *pszName = ::RTPathFilename(m_psz); 709 if (pszName) 710 { 711 size_t cchName = length() - (pszName - m_psz); 712 memmove(m_psz, pszName, cchName + 1); 713 jolt(); 714 } 715 else 716 cleanup(); 717 } 718 return *this; 719 } 720 721 Utf8Str& Utf8Str::stripSuffix() 722 { 723 if (length()) 724 { 725 RTPathStripSuffix(m_psz); 726 jolt(); 727 } 728 return *this; 729 } 730 731 size_t Utf8Str::parseKeyValue(Utf8Str &a_rKey, Utf8Str &a_rValue, size_t a_offStart /* = 0*/, 732 const Utf8Str &a_rPairSeparator /*= ","*/, const Utf8Str &a_rKeyValueSeparator /*= "="*/) const 733 { 734 /* Find the end of the next pair, skipping empty pairs. 735 Note! The skipping allows us to pass the return value of a parseKeyValue() 736 call as offStart to the next call. */ 737 size_t offEnd; 738 while ( a_offStart == (offEnd = find(&a_rPairSeparator, a_offStart)) 739 && offEnd != npos) 740 a_offStart++; 741 742 /* Look for a key/value separator before the end of the pair. 743 ASSUMES npos value returned by find when the substring is not found is 744 really high. */ 745 size_t offKeyValueSep = find(&a_rKeyValueSeparator, a_offStart); 746 if (offKeyValueSep < offEnd) 747 { 748 a_rKey = substr(a_offStart, offKeyValueSep - a_offStart); 749 if (offEnd == npos) 750 offEnd = m_cch; /* No confusing npos when returning strings. */ 751 a_rValue = substr(offKeyValueSep + 1, offEnd - offKeyValueSep - 1); 752 } 753 else 754 { 755 a_rKey.setNull(); 756 a_rValue.setNull(); 757 } 758 759 return offEnd; 760 } 761 762 /** 763 * Internal function used in Utf8Str copy constructors and assignment when 764 * copying from a UTF-16 string. 765 * 766 * As with the RTCString::copyFrom() variants, this unconditionally sets the 767 * members to a copy of the given other strings and makes no assumptions about 768 * previous contents. This can therefore be used both in copy constructors, 769 * when member variables have no defined value, and in assignments after having 770 * called cleanup(). 771 * 772 * This variant converts from a UTF-16 string, most probably from 773 * a Bstr assignment. 774 * 775 * @param a_pbstr The source string. The caller guarantees that this 776 * is valid UTF-16. 777 * @param a_cwcMax The number of characters to be copied. If set to RTSTR_MAX, 778 * the entire string will be copied. 779 * 780 * @sa RTCString::copyFromN 781 */ 782 void Utf8Str::copyFrom(CBSTR a_pbstr, size_t a_cwcMax) 783 { 784 if (a_pbstr && *a_pbstr) 785 { 786 int vrc = RTUtf16ToUtf8Ex((PCRTUTF16)a_pbstr, 787 a_cwcMax, // size_t cwcString: translate entire string 788 &m_psz, // char **ppsz: output buffer 789 0, // size_t cch: if 0, func allocates buffer in *ppsz 790 &m_cch); // size_t *pcch: receives the size of the output string, excluding the terminator. 791 if (RT_SUCCESS(vrc)) 792 m_cbAllocated = m_cch + 1; 793 else 794 { 795 if ( vrc != VERR_NO_STR_MEMORY 796 && vrc != VERR_NO_MEMORY) 797 { 798 /* ASSUME: input is valid Utf-16. Fake out of memory error. */ 799 AssertLogRelMsgFailed(("%Rrc %.*Rhxs\n", vrc, RTUtf16Len(a_pbstr) * sizeof(RTUTF16), a_pbstr)); 800 } 801 802 m_cch = 0; 803 m_cbAllocated = 0; 804 m_psz = NULL; 805 806 throw std::bad_alloc(); 807 } 808 } 809 else 810 { 811 m_cch = 0; 812 m_cbAllocated = 0; 813 m_psz = NULL; 814 } 815 } 816 817 /** 818 * A variant of Utf8Str::copyFrom that does not throw any exceptions but returns 819 * E_OUTOFMEMORY instead. 820 * 821 * @param a_pbstr The source string. 822 * @returns S_OK or E_OUTOFMEMORY. 823 */ 824 HRESULT Utf8Str::copyFromEx(CBSTR a_pbstr) 825 { 826 if (a_pbstr && *a_pbstr) 827 { 828 int vrc = RTUtf16ToUtf8Ex((PCRTUTF16)a_pbstr, 829 RTSTR_MAX, // size_t cwcString: translate entire string 830 &m_psz, // char **ppsz: output buffer 831 0, // size_t cch: if 0, func allocates buffer in *ppsz 832 &m_cch); // size_t *pcch: receives the size of the output string, excluding the terminator. 833 if (RT_SUCCESS(vrc)) 834 m_cbAllocated = m_cch + 1; 835 else 836 { 837 if ( vrc != VERR_NO_STR_MEMORY 838 && vrc != VERR_NO_MEMORY) 839 { 840 /* ASSUME: input is valid Utf-16. Fake out of memory error. */ 841 AssertLogRelMsgFailed(("%Rrc %.*Rhxs\n", vrc, RTUtf16Len(a_pbstr) * sizeof(RTUTF16), a_pbstr)); 842 } 843 844 m_cch = 0; 845 m_cbAllocated = 0; 846 m_psz = NULL; 847 848 return E_OUTOFMEMORY; 849 } 850 } 851 else 852 { 853 m_cch = 0; 854 m_cbAllocated = 0; 855 m_psz = NULL; 856 } 857 return S_OK; 858 } 859 860 861 /** 862 * A variant of Utf8Str::copyFromN that does not throw any exceptions but 863 * returns E_OUTOFMEMORY instead. 864 * 865 * @param a_pcszSrc The source string. 866 * @param a_offSrc Start offset to copy from. 867 * @param a_cchSrc How much to copy 868 * @returns S_OK or E_OUTOFMEMORY. 869 * 870 * @remarks This calls cleanup() first, so the caller doesn't have to. (Saves 871 * code space.) 872 */ 873 HRESULT Utf8Str::copyFromExNComRC(const char *a_pcszSrc, size_t a_offSrc, size_t a_cchSrc) 874 { 875 Assert(!a_cchSrc || !m_psz || (uintptr_t)&a_pcszSrc[a_offSrc] - (uintptr_t)m_psz >= (uintptr_t)m_cbAllocated); 876 cleanup(); 877 if (a_cchSrc) 878 { 879 m_psz = RTStrAlloc(a_cchSrc + 1); 880 if (RT_LIKELY(m_psz)) 881 { 882 m_cch = a_cchSrc; 883 m_cbAllocated = a_cchSrc + 1; 884 memcpy(m_psz, a_pcszSrc + a_offSrc, a_cchSrc); 885 m_psz[a_cchSrc] = '\0'; 886 } 887 else 888 { 889 m_cch = 0; 890 m_cbAllocated = 0; 891 return E_OUTOFMEMORY; 892 } 893 } 894 else 895 { 896 m_cch = 0; 897 m_cbAllocated = 0; 898 m_psz = NULL; 899 } 900 return S_OK; 48 return RTBase64DecodedUtf16SizeEx(raw(), RTSTR_MAX, ppwszEnd); 901 49 } 902 50 -
trunk/src/VBox/Main/glue/string.cpp
r84287 r84339 18 18 #include "VBox/com/string.h" 19 19 20 #include <iprt/base64.h>21 20 #include <iprt/err.h> 22 21 #include <iprt/log.h> … … 231 230 } 232 231 233 HRESULT Bstr::base64Encode(const void *pvData, size_t cbData, bool fLineBreaks /*= false*/)234 {235 uint32_t const fFlags = fLineBreaks ? RTBASE64_FLAGS_EOL_LF : RTBASE64_FLAGS_NO_LINE_BREAKS;236 size_t cwcEncoded = RTBase64EncodedUtf16LengthEx(cbData, fFlags);237 HRESULT hrc = reserveNoThrow(cwcEncoded + 1);238 if (SUCCEEDED(hrc))239 {240 int vrc = RTBase64EncodeUtf16Ex(pvData, cbData, fFlags, mutableRaw(), cwcEncoded, &cwcEncoded);241 AssertRCReturnStmt(vrc, setNull(), E_FAIL);242 hrc = joltNoThrow(cwcEncoded);243 }244 return hrc;245 }246 247 232 248 233 #ifndef VBOX_WITH_XPCOM
Note:
See TracChangeset
for help on using the changeset viewer.