Changeset 84286 in vbox
- Timestamp:
- May 13, 2020 1:58:21 PM (4 years ago)
- Location:
- trunk
- Files:
-
- 4 edited
-
include/iprt/base64.h (modified) (4 diffs)
-
include/iprt/mangling.h (modified) (1 diff)
-
src/VBox/Runtime/common/string/base64.cpp (modified) (7 diffs)
-
src/VBox/Runtime/testcase/tstRTBase64.cpp (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/iprt/base64.h
r84210 r84286 143 143 * data produced by RTBase64Encode(). 144 144 * 145 * @returns The Base64 string length .145 * @returns The Base64 string length, excluding the terminator. 146 146 * @param cbData The number of bytes to encode. 147 147 */ 148 148 RTDECL(size_t) RTBase64EncodedLength(size_t cbData); 149 150 /** 151 * Calculates the UTF-16 length of the Base64 encoding of a given number of 152 * bytes of data produced by RTBase64EncodeUtf16(). 153 * 154 * @returns The Base64 UTF-16 string length (in RTUTF16 units), excluding the 155 * terminator. 156 * @param cbData The number of bytes to encode. 157 */ 158 RTDECL(size_t) RTBase64EncodedUtf16Length(size_t cbData); 149 159 150 160 /** … … 152 162 * data produced by RTBase64EncodeEx() with the same @a fFlags. 153 163 * 154 * @returns The Base64 string length .164 * @returns The Base64 string length, excluding the terminator. 155 165 * @param cbData The number of bytes to encode. 156 166 * @param fFlags Flags, any combination of the RTBASE64_FLAGS \#defines. 157 167 */ 158 168 RTDECL(size_t) RTBase64EncodedLengthEx(size_t cbData, uint32_t fFlags); 169 170 /** 171 * Calculates the UTF-16 length of the Base64 encoding of a given number of 172 * bytes of data produced by RTBase64EncodeUtf16Ex() with the same @a fFlags. 173 * 174 * @returns The Base64 UTF-16 string length (in RTUTF16 units), excluding the 175 * terminator. 176 * @param cbData The number of bytes to encode. 177 * @param fFlags Flags, any combination of the RTBASE64_FLAGS \#defines. 178 */ 179 RTDECL(size_t) RTBase64EncodedUtf16LengthEx(size_t cbData, uint32_t fFlags); 159 180 160 181 /** … … 177 198 178 199 /** 200 * Encodes the specifed data into a Base64 UTF-16 string, the caller supplies 201 * the output buffer. 202 * 203 * This is equivalent to calling RTBase64EncodeUtf16Ex() with no flags. 204 * 205 * @returns IRPT status code. 206 * @retval VERR_BUFFER_OVERFLOW if the output buffer is too small. The buffer 207 * may contain an invalid Base64 string. 208 * 209 * @param pvData The data to encode. 210 * @param cbData The number of bytes to encode. 211 * @param pwszBuf Where to put the Base64 UTF-16 string. 212 * @param cwcBuf The size of the output buffer in RTUTF16 units, 213 * including the terminator. 214 * @param pcwcActual The actual number of characters returned (excluding the 215 * terminator). Optional. 216 */ 217 RTDECL(int) RTBase64EncodeUtf16(const void *pvData, size_t cbData, PRTUTF16 pwszBuf, size_t cwcBuf, size_t *pcwcActual); 218 219 /** 179 220 * Encodes the specifed data into a Base64 string, the caller supplies the 180 221 * output buffer. … … 189 230 * @param pszBuf Where to put the Base64 string. 190 231 * @param cbBuf The size of the output buffer, including the terminator. 191 * @param pcchActual The actual number of characters returned. 232 * @param pcchActual The actual number of characters returned (excluding the 233 * terminator). Optional. 192 234 */ 193 235 RTDECL(int) RTBase64EncodeEx(const void *pvData, size_t cbData, uint32_t fFlags, 194 236 char *pszBuf, size_t cbBuf, size_t *pcchActual); 195 237 238 /** 239 * Encodes the specifed data into a Base64 UTF-16 string, the caller supplies 240 * the output buffer. 241 * 242 * @returns IRPT status code. 243 * @retval VERR_BUFFER_OVERFLOW if the output buffer is too small. The buffer 244 * may contain an invalid Base64 string. 245 * 246 * @param pvData The data to encode. 247 * @param cbData The number of bytes to encode. 248 * @param fFlags Flags, any combination of the RTBASE64_FLAGS \#defines. 249 * @param pwszBuf Where to put the Base64 UTF-16 string. 250 * @param cwcBuf The size of the output buffer in RTUTF16 units, 251 * including the terminator. 252 * @param pcwcActual The actual number of characters returned (excluding the 253 * terminator). Optional. 254 */ 255 RTDECL(int) RTBase64EncodeUtf16Ex(const void *pvData, size_t cbData, uint32_t fFlags, 256 PRTUTF16 pwszBuf, size_t cwcBuf, size_t *pcwcActual); 257 258 196 259 /** @} */ 197 260 -
trunk/include/iprt/mangling.h
r84248 r84286 581 581 # define RTBase64EncodedLength RT_MANGLER(RTBase64EncodedLength) 582 582 # define RTBase64EncodedLengthEx RT_MANGLER(RTBase64EncodedLengthEx) 583 # define RTBase64EncodeUtf16 RT_MANGLER(RTBase64EncodeUtf16) 584 # define RTBase64EncodeUtf16Ex RT_MANGLER(RTBase64EncodeUtf16Ex) 585 # define RTBase64EncodedUtf16Length RT_MANGLER(RTBase64EncodedUtf16Length) 586 # define RTBase64EncodedUtf16LengthEx RT_MANGLER(RTBase64EncodedUtf16LengthEx) 583 587 # define RTBldCfgCompiler RT_MANGLER(RTBldCfgCompiler) 584 588 # define RTBldCfgRevision RT_MANGLER(RTBldCfgRevision) -
trunk/src/VBox/Runtime/common/string/base64.cpp
r84274 r84286 416 416 417 417 418 /**419 * Calculates the length of the Base64 encoding of a given number of bytes of420 * data produced by RTBase64Encode().421 *422 * @returns The Base64 string length.423 * @param cbData The number of bytes to encode.424 */425 418 RTDECL(size_t) RTBase64EncodedLength(size_t cbData) 426 419 { … … 430 423 431 424 432 /**433 * Calculates the length of the Base64 encoding of a given number of bytes of434 * data produced by RTBase64EncodeEx() with the same @a fFlags.435 *436 * @returns The Base64 string length.437 * @param cbData The number of bytes to encode.438 * @param fFlags Flags, any combination of the RTBASE64_FLAGS \#defines.439 */440 425 RTDECL(size_t) RTBase64EncodedLengthEx(size_t cbData, uint32_t fFlags) 441 426 { … … 463 448 464 449 465 /**466 * Encodes the specifed data into a Base64 string, the caller supplies the467 * output buffer.468 *469 * This is equivalent to calling RTBase64EncodeEx() with no flags.470 *471 * @returns IRPT status code.472 * @retval VERR_BUFFER_OVERFLOW if the output buffer is too small. The buffer473 * may contain an invalid Base64 string.474 *475 * @param pvData The data to encode.476 * @param cbData The number of bytes to encode.477 * @param pszBuf Where to put the Base64 string.478 * @param cbBuf The size of the output buffer, including the terminator.479 * @param pcchActual The actual number of characters returned.480 */481 450 RTDECL(int) RTBase64Encode(const void *pvData, size_t cbData, char *pszBuf, size_t cbBuf, size_t *pcchActual) 482 451 { … … 486 455 487 456 488 /** 489 * Encodes the specifed data into a Base64 string, the caller supplies the 490 * output buffer. 491 * 492 * @returns IRPT status code. 493 * @retval VERR_BUFFER_OVERFLOW if the output buffer is too small. The buffer 494 * may contain an invalid Base64 string. 495 * 496 * @param pvData The data to encode. 497 * @param cbData The number of bytes to encode. 498 * @param pszBuf Where to put the Base64 string. 499 * @param cbBuf The size of the output buffer, including the terminator. 500 * @param pcchActual The actual number of characters returned. 457 /* 458 * Please note that RTBase64EncodeUtf16Ex contains an almost exact copy of 459 * this code, just using different output character type and variable prefixes. 460 * So, all fixes must be applied to both versions of the code. 501 461 */ 502 462 RTDECL(int) RTBase64EncodeEx(const void *pvData, size_t cbData, uint32_t fFlags, … … 515 475 uint8_t u8B; 516 476 uint8_t u8C; 517 size_t cbLineFeed = c bBuf - RTBASE64_LINE_LEN;477 size_t cbLineFeed = cchEol ? cbBuf - RTBASE64_LINE_LEN : ~(size_t)0; 518 478 const uint8_t *pbSrc = (const uint8_t *)pvData; 519 479 char *pchDst = pszBuf; … … 538 498 pbSrc += 3; 539 499 540 if (cchEol > 0) 541 { 542 /* deal out end-of-line */ 543 if (cbBuf == cbLineFeed && cbData) 544 { 545 if (cbBuf < cchEol + 1) 546 return VERR_BUFFER_OVERFLOW; 547 cbBuf -= cchEol; 548 *pchDst++ = chEol0; 549 if (chEol1) 550 *pchDst++ = chEol1; 551 cbLineFeed = cbBuf - RTBASE64_LINE_LEN; 552 } 500 /* deal out end-of-line */ 501 if (cbBuf == cbLineFeed && cbData && cchEol) 502 { 503 if (cbBuf < cchEol + 1) 504 return VERR_BUFFER_OVERFLOW; 505 cbBuf -= cchEol; 506 *pchDst++ = chEol0; 507 if (chEol1) 508 *pchDst++ = chEol1; 509 cbLineFeed = cbBuf - RTBASE64_LINE_LEN; 553 510 } 554 511 } … … 589 546 } 590 547 RT_EXPORT_SYMBOL(RTBase64EncodeEx); 548 549 550 /* 551 * Please note that RTBase64EncodeEx contains an almost exact copy of 552 * this code, just using different output character type and variable prefixes. 553 * So, all fixes must be applied to both versions of the code. 554 */ 555 RTDECL(int) RTBase64EncodeUtf16Ex(const void *pvData, size_t cbData, uint32_t fFlags, 556 PRTUTF16 pwszBuf, size_t cwcBuf, size_t *pcwcActual) 557 { 558 /* Expand the EOL style flags: */ 559 size_t const cchEol = g_acchEolStyles[fFlags & RTBASE64_FLAGS_EOL_STYLE_MASK]; 560 char const chEol0 = g_aachEolStyles[fFlags & RTBASE64_FLAGS_EOL_STYLE_MASK][0]; 561 char const chEol1 = g_aachEolStyles[fFlags & RTBASE64_FLAGS_EOL_STYLE_MASK][1]; 562 Assert(cchEol == (chEol0 != '\0' ? 1U : 0U) + (chEol1 != '\0' ? 1U : 0U)); 563 564 /* 565 * Process whole "trios" of input data. 566 */ 567 uint8_t u8A; 568 uint8_t u8B; 569 uint8_t u8C; 570 size_t cwcLineFeed = cchEol ? cwcBuf - RTBASE64_LINE_LEN : ~(size_t)0; 571 const uint8_t *pbSrc = (const uint8_t *)pvData; 572 PRTUTF16 pwcDst = pwszBuf; 573 while (cbData >= 3) 574 { 575 if (cwcBuf < 4 + 1) 576 return VERR_BUFFER_OVERFLOW; 577 578 /* encode */ 579 u8A = pbSrc[0]; 580 pwcDst[0] = g_szValToChar[u8A >> 2]; 581 u8B = pbSrc[1]; 582 pwcDst[1] = g_szValToChar[((u8A << 4) & 0x3f) | (u8B >> 4)]; 583 u8C = pbSrc[2]; 584 pwcDst[2] = g_szValToChar[((u8B << 2) & 0x3f) | (u8C >> 6)]; 585 pwcDst[3] = g_szValToChar[u8C & 0x3f]; 586 587 /* advance */ 588 cwcBuf -= 4; 589 pwcDst += 4; 590 cbData -= 3; 591 pbSrc += 3; 592 593 /* deal out end-of-line */ 594 if (cwcBuf == cwcLineFeed && cbData && cchEol) 595 { 596 if (cwcBuf < cchEol + 1) 597 return VERR_BUFFER_OVERFLOW; 598 cwcBuf -= cchEol; 599 *pwcDst++ = chEol0; 600 if (chEol1) 601 *pwcDst++ = chEol1; 602 cwcLineFeed = cwcBuf - RTBASE64_LINE_LEN; 603 } 604 } 605 606 /* 607 * Deal with the odd bytes and string termination. 608 */ 609 if (cbData) 610 { 611 if (cwcBuf < 4 + 1) 612 return VERR_BUFFER_OVERFLOW; 613 switch (cbData) 614 { 615 case 1: 616 u8A = pbSrc[0]; 617 pwcDst[0] = g_szValToChar[u8A >> 2]; 618 pwcDst[1] = g_szValToChar[(u8A << 4) & 0x3f]; 619 pwcDst[2] = '='; 620 pwcDst[3] = '='; 621 break; 622 case 2: 623 u8A = pbSrc[0]; 624 pwcDst[0] = g_szValToChar[u8A >> 2]; 625 u8B = pbSrc[1]; 626 pwcDst[1] = g_szValToChar[((u8A << 4) & 0x3f) | (u8B >> 4)]; 627 pwcDst[2] = g_szValToChar[(u8B << 2) & 0x3f]; 628 pwcDst[3] = '='; 629 break; 630 } 631 pwcDst += 4; 632 } 633 634 *pwcDst = '\0'; 635 636 if (pcwcActual) 637 *pcwcActual = pwcDst - pwszBuf; 638 return VINF_SUCCESS; 639 } 640 RT_EXPORT_SYMBOL(RTBase64EncodeUtf16Ex); 641 642 643 RTDECL(int) RTBase64EncodeUtf16(const void *pvData, size_t cbData, PRTUTF16 pwszBuf, size_t cwcBuf, size_t *pcwcActual) 644 { 645 return RTBase64EncodeUtf16Ex(pvData, cbData, 0, pwszBuf, cwcBuf, pcwcActual); 646 } 647 RT_EXPORT_SYMBOL(RTBase64EncodeUtf16); 648 649 650 RTDECL(size_t) RTBase64EncodedUtf16Length(size_t cbData) 651 { 652 return RTBase64EncodedLengthEx(cbData, 0); 653 } 654 RT_EXPORT_SYMBOL(RTBase64EncodedUtf16Length); 655 656 657 RTDECL(size_t) RTBase64EncodedUtf16LengthEx(size_t cbData, uint32_t fFlags) 658 { 659 return RTBase64EncodedLengthEx(cbData, fFlags); 660 } 661 RT_EXPORT_SYMBOL(RTBase64EncodedUtf16LengthEx); 662 -
trunk/src/VBox/Runtime/testcase/tstRTBase64.cpp
r82968 r84286 36 36 #include <iprt/stream.h> 37 37 #include <iprt/string.h> 38 #include <iprt/utf16.h> 38 39 #include <iprt/test.h> 39 40 … … 58 59 int fTextData, int fNormalEnc) 59 60 { 60 char szOut[0x10000]; 61 union 62 { 63 char szOut[0x10000]; 64 RTUTF16 wszOut[0x10000]; 65 }; 61 66 size_t cchOut = 0; 62 67 … … 103 108 104 109 /** @todo negative testing. */ 110 111 /* 112 * Same as above, but using the UTF-16 variant of the code. 113 */ 114 115 /* Decoding: later */ 116 117 /* Encoding UTF-16: */ 118 memset(wszOut, 0xaa, sizeof(wszOut)); 119 wszOut[sizeof(wszOut) / sizeof(wszOut[0]) - 1] = '\0'; 120 size_t cwcOut = 0; 121 rc = RTBase64EncodeUtf16(pvData, cbData, wszOut, cchEnc + 1, &cwcOut); 122 if (RT_FAILURE(rc)) 123 RTTestIFailed("RTBase64EncodeUtf16 -> %Rrc\n", rc); 124 else if (fNormalEnc && cwcOut != cchEnc) 125 RTTestIFailed("RTBase64EncodeUtf16 returned %zu bytes, expected %zu.\n", cwcOut, cchEnc); 126 else if (fNormalEnc && RTUtf16CmpUtf8(wszOut, pszEnc)) 127 RTTestIFailed("RTBase64EncodeUtf16 returned:\n%s\nexpected:\n%s\n", wszOut, pszEnc); 128 129 size_t cwcOut2 = RTBase64EncodedUtf16Length(cbData); 130 if (cwcOut != cwcOut2) 131 RTTestIFailed("RTBase64EncodedLength returned %zu RTUTF16 units, expected %zu.\n", cwcOut2, cwcOut); 105 132 } 106 133 … … 182 209 for (size_t cbSrc = 1; cbSrc <= sizeof(s_abData4); cbSrc++) 183 210 { 184 char szEnc[49152]; 211 union 212 { 213 char szEnc[49152]; 214 RTUTF16 wszEnc[49152]; 215 }; 185 216 memset(szEnc, '\0', sizeof(szEnc)); 186 217 size_t cchEnc = RTBase64EncodedLength(cbSrc); 187 218 if (cchEnc >= sizeof(szEnc)) 188 RTTestIFailed("RTBase64EncodedLength(%zu) returned %zu bytes ,too big\n", cbSrc, cchEnc);219 RTTestIFailed("RTBase64EncodedLength(%zu) returned %zu bytes - too big\n", cbSrc, cchEnc); 189 220 size_t cchOut = 0; 190 221 rc = RTBase64Encode(s_abData4, cbSrc, szEnc, cchEnc, &cchOut); … … 197 228 RTTestIFailed("RTBase64EncodedLength(%zu) returned %zu bytes, expected %zu.\n", 198 229 cbSrc, cchEnc, cchOut); 199 if (szEnc[cchOut + 1] != '\0')230 if (szEnc[cchOut] != '\0') 200 231 RTTestIFailed("RTBase64Encode(,%zu,) returned string which is not zero terminated\n", cbSrc); 201 232 if (strlen(szEnc) != cchOut) 202 233 RTTestIFailed("RTBase64Encode(,%zu,) returned incorrect string, length %lu\n", cbSrc, cchOut); 234 235 /* Ditto for UTF-16: */ 236 memset(wszEnc, '\0', sizeof(wszEnc)); 237 size_t cwcEnc = RTBase64EncodedUtf16Length(cbSrc); 238 if (cwcEnc >= RT_ELEMENTS(wszEnc)) 239 RTTestIFailed("RTBase64EncodedUtf16Length(%zu) returned %zu RTUTF16 units - too big\n", cbSrc, cwcEnc); 240 size_t cwcOut = 0; 241 rc = RTBase64EncodeUtf16(s_abData4, cbSrc, wszEnc, cwcEnc, &cwcOut); 242 if (rc != VERR_BUFFER_OVERFLOW) 243 RTTestIFailed("RTBase64EncodeUtf16(,%zu,) has no buffer overflow with too small buffer -> %Rrc\n", cbSrc, rc); 244 cwcOut = ~(size_t)0; 245 rc = RTBase64EncodeUtf16(s_abData4, cbSrc, wszEnc, cwcEnc + 1, &cwcOut); 246 if (RT_FAILURE(rc)) 247 RTTestIFailed("RTBase64EncodeUtf16 -> %Rrc\n", rc); 248 if (cchOut != cchEnc) 249 RTTestIFailed("RTBase64EncodedUtf16Length(%zu) returned %zu bytes, expected %zu.\n", 250 cbSrc, cwcEnc, cwcOut); 251 if (wszEnc[cwcOut] != '\0') 252 RTTestIFailed("RTBase64EncodeUtf16(,%zu,) returned string which is not zero terminated\n", cbSrc); 253 if (RTUtf16Len(wszEnc) != cwcOut) 254 RTTestIFailed("RTBase64EncodeUtf16(,%zu,) returned incorrect string, length %lu\n", cbSrc, cwcOut); 203 255 } 204 256
Note:
See TracChangeset
for help on using the changeset viewer.

