VirtualBox

Changeset 84286 in vbox


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

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

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/iprt/base64.h

    r84210 r84286  
    143143 * data produced by RTBase64Encode().
    144144 *
    145  * @returns The Base64 string length.
     145 * @returns The Base64 string length, excluding the terminator.
    146146 * @param   cbData      The number of bytes to encode.
    147147 */
    148148RTDECL(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 */
     158RTDECL(size_t) RTBase64EncodedUtf16Length(size_t cbData);
    149159
    150160/**
     
    152162 * data produced by RTBase64EncodeEx() with the same @a fFlags.
    153163 *
    154  * @returns The Base64 string length.
     164 * @returns The Base64 string length, excluding the terminator.
    155165 * @param   cbData      The number of bytes to encode.
    156166 * @param   fFlags      Flags, any combination of the RTBASE64_FLAGS \#defines.
    157167 */
    158168RTDECL(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 */
     179RTDECL(size_t) RTBase64EncodedUtf16LengthEx(size_t cbData, uint32_t fFlags);
    159180
    160181/**
     
    177198
    178199/**
     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 */
     217RTDECL(int) RTBase64EncodeUtf16(const void *pvData, size_t cbData, PRTUTF16 pwszBuf, size_t cwcBuf, size_t *pcwcActual);
     218
     219/**
    179220 * Encodes the specifed data into a Base64 string, the caller supplies the
    180221 * output buffer.
     
    189230 * @param   pszBuf      Where to put the Base64 string.
    190231 * @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.
    192234 */
    193235RTDECL(int) RTBase64EncodeEx(const void *pvData, size_t cbData, uint32_t fFlags,
    194236                             char *pszBuf, size_t cbBuf, size_t *pcchActual);
    195237
     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 */
     255RTDECL(int) RTBase64EncodeUtf16Ex(const void *pvData, size_t cbData, uint32_t fFlags,
     256                                  PRTUTF16 pwszBuf, size_t cwcBuf, size_t *pcwcActual);
     257
     258
    196259/** @}  */
    197260
  • trunk/include/iprt/mangling.h

    r84248 r84286  
    581581# define RTBase64EncodedLength                          RT_MANGLER(RTBase64EncodedLength)
    582582# 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)
    583587# define RTBldCfgCompiler                               RT_MANGLER(RTBldCfgCompiler)
    584588# define RTBldCfgRevision                               RT_MANGLER(RTBldCfgRevision)
  • 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
  • trunk/src/VBox/Runtime/testcase/tstRTBase64.cpp

    r82968 r84286  
    3636#include <iprt/stream.h>
    3737#include <iprt/string.h>
     38#include <iprt/utf16.h>
    3839#include <iprt/test.h>
    3940
     
    5859                      int fTextData, int fNormalEnc)
    5960{
    60     char    szOut[0x10000];
     61    union
     62    {
     63        char    szOut[0x10000];
     64        RTUTF16 wszOut[0x10000];
     65    };
    6166    size_t  cchOut = 0;
    6267
     
    103108
    104109    /** @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);
    105132}
    106133
     
    182209    for (size_t cbSrc = 1; cbSrc <= sizeof(s_abData4); cbSrc++)
    183210    {
    184         char szEnc[49152];
     211        union
     212        {
     213            char    szEnc[49152];
     214            RTUTF16 wszEnc[49152];
     215        };
    185216        memset(szEnc, '\0', sizeof(szEnc));
    186217        size_t cchEnc = RTBase64EncodedLength(cbSrc);
    187218        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);
    189220        size_t cchOut = 0;
    190221        rc = RTBase64Encode(s_abData4, cbSrc, szEnc, cchEnc, &cchOut);
     
    197228            RTTestIFailed("RTBase64EncodedLength(%zu) returned %zu bytes, expected %zu.\n",
    198229                          cbSrc, cchEnc, cchOut);
    199         if (szEnc[cchOut + 1] != '\0')
     230        if (szEnc[cchOut] != '\0')
    200231            RTTestIFailed("RTBase64Encode(,%zu,) returned string which is not zero terminated\n", cbSrc);
    201232        if (strlen(szEnc) != cchOut)
    202233            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);
    203255    }
    204256
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