VirtualBox

Ignore:
Timestamp:
May 13, 2020 1:58:21 PM (5 years ago)
Author:
vboxsync
Message:

IPRT/base64: Added UTF-16 versions of the encoding functions. bugref:9224

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/string/base64.cpp

    r84274 r84286  
    416416
    417417
    418 /**
    419  * Calculates the length of the Base64 encoding of a given number of bytes of
    420  * data produced by RTBase64Encode().
    421  *
    422  * @returns The Base64 string length.
    423  * @param   cbData      The number of bytes to encode.
    424  */
    425418RTDECL(size_t) RTBase64EncodedLength(size_t cbData)
    426419{
     
    430423
    431424
    432 /**
    433  * Calculates the length of the Base64 encoding of a given number of bytes of
    434  * 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  */
    440425RTDECL(size_t) RTBase64EncodedLengthEx(size_t cbData, uint32_t fFlags)
    441426{
     
    463448
    464449
    465 /**
    466  * Encodes the specifed data into a Base64 string, the caller supplies the
    467  * 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 buffer
    473  *          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  */
    481450RTDECL(int) RTBase64Encode(const void *pvData, size_t cbData, char *pszBuf, size_t cbBuf, size_t *pcchActual)
    482451{
     
    486455
    487456
    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.
    501461 */
    502462RTDECL(int) RTBase64EncodeEx(const void *pvData, size_t cbData, uint32_t fFlags,
     
    515475    uint8_t         u8B;
    516476    uint8_t         u8C;
    517     size_t          cbLineFeed = cbBuf - RTBASE64_LINE_LEN;
     477    size_t          cbLineFeed = cchEol ? cbBuf - RTBASE64_LINE_LEN : ~(size_t)0;
    518478    const uint8_t  *pbSrc      = (const uint8_t *)pvData;
    519479    char           *pchDst     = pszBuf;
     
    538498        pbSrc  += 3;
    539499
    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;
    553510        }
    554511    }
     
    589546}
    590547RT_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 */
     555RTDECL(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}
     640RT_EXPORT_SYMBOL(RTBase64EncodeUtf16Ex);
     641
     642
     643RTDECL(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}
     647RT_EXPORT_SYMBOL(RTBase64EncodeUtf16);
     648
     649
     650RTDECL(size_t) RTBase64EncodedUtf16Length(size_t cbData)
     651{
     652    return RTBase64EncodedLengthEx(cbData, 0);
     653}
     654RT_EXPORT_SYMBOL(RTBase64EncodedUtf16Length);
     655
     656
     657RTDECL(size_t) RTBase64EncodedUtf16LengthEx(size_t cbData, uint32_t fFlags)
     658{
     659    return RTBase64EncodedLengthEx(cbData, fFlags);
     660}
     661RT_EXPORT_SYMBOL(RTBase64EncodedUtf16LengthEx);
     662
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette