VirtualBox

Changeset 84293 in vbox


Ignore:
Timestamp:
May 13, 2020 4:23:25 PM (4 years ago)
Author:
vboxsync
Message:

IPRT/base64: Put the UTF-16 code in separate file. Implemented decoding of UTF-16 strings. bugref:9224

Location:
trunk
Files:
5 edited
1 copied

Legend:

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

    r84286 r84293  
    7474
    7575/**
     76 * Calculates the decoded data size for a Base64 encoded UTF-16 string.
     77 *
     78 * @returns The length in bytes. -1 if the encoding is bad.
     79 *
     80 * @param   pwszString      The Base64 encoded UTF-16 string.
     81 * @param   ppwszEnd        If not NULL, this will point to the first char
     82 *                          following the Base64 encoded text block. If
     83 *                          NULL the entire string is assumed to be Base64.
     84 */
     85RTDECL(ssize_t) RTBase64DecodedUtf16Size(PCRTUTF16 pwszString, PRTUTF16 *ppwszEnd);
     86
     87/**
    7688 * Calculates the decoded data size for a Base64 encoded string.
    7789 *
     
    8799 */
    88100RTDECL(ssize_t) RTBase64DecodedSizeEx(const char *pszString, size_t cchStringMax, char **ppszEnd);
     101
     102/**
     103 * Calculates the decoded data size for a Base64 encoded UTF-16 string.
     104 *
     105 * @returns The length in bytes. -1 if the encoding is bad.
     106 *
     107 * @param   pwszString      The Base64 encoded UTF-16 string.
     108 * @param   cwcStringMax    The max length to decode in RTUTF16 units, use
     109 *                          RTSTR_MAX if the length of @a pwszString is not
     110 *                          known and it is really zero terminated.
     111 * @param   ppwszEnd        If not NULL, this will point to the first char
     112 *                          following the Base64 encoded text block. If
     113 *                          NULL the entire string is assumed to be Base64.
     114 */
     115RTDECL(ssize_t) RTBase64DecodedSizeUtf16Ex(PCRTUTF16 pwszString, size_t cwcStringMax, PRTUTF16 *ppwszEnd);
    89116
    90117/**
     
    110137 */
    111138RTDECL(int) RTBase64Decode(const char *pszString, void *pvData, size_t cbData, size_t *pcbActual, char **ppszEnd);
     139
     140/**
     141 * Decodes a Base64 encoded UTF-16 string into the buffer supplied by the
     142 * caller.
     143 *
     144 * @returns IPRT status code.
     145 * @retval  VERR_BUFFER_OVERFLOW if the buffer is too small. pcbActual will not
     146 *          be set, nor will ppszEnd.
     147 * @retval  VERR_INVALID_BASE64_ENCODING if the encoding is wrong.
     148 *
     149 * @param   pwszString      The Base64 UTF-16 string. Whether the entire string
     150 *                          or just the start of the string is in Base64 depends
     151 *                          on whether ppwszEnd is specified or not.
     152 * @param   pvData          Where to store the decoded data.
     153 * @param   cbData          The size of the output buffer that pvData points to.
     154 * @param   pcbActual       Where to store the actual number of bytes returned.
     155 *                          Optional.
     156 * @param   ppwszEnd        Indicates that the string may contain other stuff
     157 *                          after the Base64 encoded data when not NULL. Will
     158 *                          be set to point to the first char that's not part of
     159 *                          the encoding. If NULL the entire string must be part
     160 *                          of the Base64 encoded data.
     161 */
     162RTDECL(int) RTBase64DecodeUtf16(PCRTUTF16 pwszString, void *pvData, size_t cbData, size_t *pcbActual, PRTUTF16 *ppwszEnd);
    112163
    113164/**
     
    138189                             size_t *pcbActual, char **ppszEnd);
    139190
     191/**
     192 * Decodes a Base64 encoded UTF-16 string into the buffer supplied by the
     193 * caller.
     194 *
     195 * @returns IPRT status code.
     196 * @retval  VERR_BUFFER_OVERFLOW if the buffer is too small. pcbActual will not
     197 *          be set, nor will ppszEnd.
     198 * @retval  VERR_INVALID_BASE64_ENCODING if the encoding is wrong.
     199 *
     200 * @param   pwszString      The Base64 UTF-16 string. Whether the entire string
     201 *                          or just the start of the string is in Base64 depends
     202 *                          on whether ppszEnd is specified or not.
     203 * @param   cwcStringMax    The max length to decode in RTUTF16 units, use
     204 *                          RTSTR_MAX if the length of @a pwszString is not
     205 *                          known and it is really zero terminated.
     206 * @param   pvData          Where to store the decoded data.
     207 * @param   cbData          The size of the output buffer that pvData points to.
     208 * @param   pcbActual       Where to store the actual number of bytes returned.
     209 *                          Optional.
     210 * @param   ppwszEnd        Indicates that the string may contain other stuff
     211 *                          after the Base64 encoded data when not NULL. Will
     212 *                          be set to point to the first char that's not part of
     213 *                          the encoding. If NULL the entire string must be part
     214 *                          of the Base64 encoded data.
     215 */
     216RTDECL(int) RTBase64DecodeUtf16Ex(PCRTUTF16 pwszString, size_t cwcStringMax, void *pvData, size_t cbData,
     217                                  size_t *pcbActual, PRTUTF16 *ppwszEnd);
     218
    140219
    141220/**
  • trunk/include/iprt/mangling.h

    r84286 r84293  
    577577# define RTBase64DecodedSize                            RT_MANGLER(RTBase64DecodedSize)
    578578# define RTBase64DecodedSizeEx                          RT_MANGLER(RTBase64DecodedSizeEx)
     579# define RTBase64DecodeUtf16                            RT_MANGLER(RTBase64DecodeUtf16)
     580# define RTBase64DecodeUtf16Ex                          RT_MANGLER(RTBase64DecodeUtf16Ex)
     581# define RTBase64DecodedUtf16Size                       RT_MANGLER(RTBase64DecodedUtf16Size)
     582# define RTBase64DecodedUtf16SizeEx                     RT_MANGLER(RTBase64DecodedUtf16SizeEx)
    579583# define RTBase64Encode                                 RT_MANGLER(RTBase64Encode)
    580584# define RTBase64EncodeEx                               RT_MANGLER(RTBase64EncodeEx)
  • trunk/src/VBox/Runtime/Makefile.kmk

    r84230 r84293  
    609609        common/string/RTUtf16PrintHexBytes.cpp \
    610610        common/string/base64.cpp \
     611        common/string/base64-utf16.cpp \
    611612        common/string/simplepattern.cpp \
    612613        common/string/straprintf.cpp \
  • trunk/src/VBox/Runtime/common/string/base64-utf16.cpp

    r84286 r84293  
    22/** @file
    33 * IPRT - Base64, MIME content transfer encoding.
     4 *
     5 * @note The base64.cpp file must be diffable with this one.
     6 *       Fixed typically applies to both files.
    47 */
    58
     
    3437#include <iprt/assert.h>
    3538#include <iprt/err.h>
    36 #include <iprt/ctype.h>
    3739#include <iprt/string.h>
     40#include <iprt/uni.h>
    3841#ifdef RT_STRICT
    3942# include <iprt/asm.h>
    4043#endif
    4144
    42 
    43 /*********************************************************************************************************************************
    44 *   Defined Constants And Macros                                                                                                 *
    45 *********************************************************************************************************************************/
    46 /** The line length used for encoding. */
    47 #define RTBASE64_LINE_LEN   64
    48 
    49 /** @name Special g_au8CharToVal values
    50  * @{ */
    51 #define BASE64_SPACE        0xc0
    52 #define BASE64_PAD          0xe0
    53 #define BASE64_INVALID      0xff
    54 /** @} */
    55 
    56 
    57 /*********************************************************************************************************************************
    58 *   Global Variables                                                                                                             *
    59 *********************************************************************************************************************************/
    60 /** Base64 character to value. (RFC 2045)
    61  * ASSUMES ASCII / UTF-8. */
    62 static const uint8_t    g_au8CharToVal[256] =
    63 {
    64     0xff, 0xff, 0xff, 0xff,   0xff, 0xff, 0xff, 0xff,   0xff, 0xc0, 0xc0, 0xc0,   0xc0, 0xc0, 0xff, 0xff, /* 0x00..0x0f */
    65     0xff, 0xff, 0xff, 0xff,   0xff, 0xff, 0xff, 0xff,   0xff, 0xff, 0xff, 0xff,   0xff, 0xff, 0xff, 0xff, /* 0x10..0x1f */
    66     0xc0, 0xff, 0xff, 0xff,   0xff, 0xff, 0xff, 0xff,   0xff, 0xff, 0xff,   62,   0xff, 0xff, 0xff,   63, /* 0x20..0x2f */
    67       52,   53,   54,   55,     56,   57,   58,   59,     60,   61, 0xff, 0xff,   0xff, 0xe0, 0xff, 0xff, /* 0x30..0x3f */
    68     0xff,    0,    1,    2,      3,    4,    5,    6,      7,    8,    9,   10,     11,   12,   13,   14, /* 0x40..0x4f */
    69       15,   16,   17,   18,     19,   20,   21,   22,     23,   24,   25, 0xff,   0xff, 0xff, 0xff, 0xff, /* 0x50..0x5f */
    70     0xff,   26,   27,   28,     29,   30,   31,   32,     33,   34,   35,   36,     37,   38,   39,   40, /* 0x60..0x6f */
    71       41,   42,   43,   44,     45,   46,   47,   48,     49,   50,   51, 0xff,   0xff, 0xff, 0xff, 0xff, /* 0x70..0x7f */
    72     0xff, 0xff, 0xff, 0xff,   0xff, 0xff, 0xff, 0xff,   0xff, 0xff, 0xff, 0xff,   0xff, 0xff, 0xff, 0xff, /* 0x80..0x8f */
    73     0xff, 0xff, 0xff, 0xff,   0xff, 0xff, 0xff, 0xff,   0xff, 0xff, 0xff, 0xff,   0xff, 0xff, 0xff, 0xff, /* 0x90..0x9f */
    74     0xff, 0xff, 0xff, 0xff,   0xff, 0xff, 0xff, 0xff,   0xff, 0xff, 0xff, 0xff,   0xff, 0xff, 0xff, 0xff, /* 0xa0..0xaf */
    75     0xff, 0xff, 0xff, 0xff,   0xff, 0xff, 0xff, 0xff,   0xff, 0xff, 0xff, 0xff,   0xff, 0xff, 0xff, 0xff, /* 0xb0..0xbf */
    76     0xff, 0xff, 0xff, 0xff,   0xff, 0xff, 0xff, 0xff,   0xff, 0xff, 0xff, 0xff,   0xff, 0xff, 0xff, 0xff, /* 0xc0..0xcf */
    77     0xff, 0xff, 0xff, 0xff,   0xff, 0xff, 0xff, 0xff,   0xff, 0xff, 0xff, 0xff,   0xff, 0xff, 0xff, 0xff, /* 0xd0..0xdf */
    78     0xff, 0xff, 0xff, 0xff,   0xff, 0xff, 0xff, 0xff,   0xff, 0xff, 0xff, 0xff,   0xff, 0xff, 0xff, 0xff, /* 0xe0..0xef */
    79     0xff, 0xff, 0xff, 0xff,   0xff, 0xff, 0xff, 0xff,   0xff, 0xff, 0xff, 0xff,   0xff, 0xff, 0xff, 0xff  /* 0xf0..0xff */
    80 };
    81 
    82 /** Value to Base64 character. (RFC 2045) */
    83 static const char       g_szValToChar[64+1] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    84 
    85 /** The end-of-line lengths (indexed by style flag value). */
    86 static const size_t     g_acchEolStyles[RTBASE64_FLAGS_EOL_STYLE_MASK + 1] =
    87 {
    88     /*[RTBASE64_FLAGS_EOL_NATIVE    ]:*/ RTBASE64_EOL_SIZE,
    89     /*[RTBASE64_FLAGS_NO_LINE_BREAKS]:*/ 0,
    90     /*[RTBASE64_FLAGS_EOL_LF        ]:*/ 1,
    91     /*[RTBASE64_FLAGS_EOL_CRLF      ]:*/ 2
    92 };
    93 
    94 /** The end-of-line characters (zero, one or two). */
    95 static const char       g_aachEolStyles[RTBASE64_FLAGS_EOL_STYLE_MASK + 1][2] =
    96 {
    97     /*[RTBASE64_FLAGS_EOL_NATIVE    ]:*/ { RTBASE64_EOL_SIZE == 1 ? '\n' : '\r', RTBASE64_EOL_SIZE == 1 ? '\0' : '\n', },
    98     /*[RTBASE64_FLAGS_NO_LINE_BREAKS]:*/ { '\0', '\0' },
    99     /*[RTBASE64_FLAGS_EOL_LF        ]:*/ { '\n', '\0' },
    100     /*[RTBASE64_FLAGS_EOL_CRLF      ]:*/ { '\r', '\n' },
    101 };
    102 
    103 
    104 
    105 #ifdef RT_STRICT
    106 /**
    107  * Perform table sanity checks on the first call.
     45#include "base64.h"
     46
     47
     48/** Translates the given character. */
     49DECL_FORCE_INLINE(uint8_t) rtBase64TranslateUtf16(RTUTF16 wc)
     50{
     51    if (wc < RT_ELEMENTS(g_au8RTBase64CharToVal))
     52        return g_au8RTBase64CharToVal[wc];
     53    if (RTUniCpIsSpace(wc))
     54        return BASE64_SPACE;
     55    return BASE64_INVALID;
     56}
     57
     58
     59/** Fetched the next character in the string and translates it. */
     60DECL_FORCE_INLINE(uint8_t) rtBase64TranslateNextUtf16(PCRTUTF16 pwszString, size_t cwcStringMax)
     61{
     62    if (cwcStringMax > 0)
     63        return rtBase64TranslateUtf16(*pwszString);
     64    return BASE64_INVALID;
     65}
     66
     67
     68/*
     69 * Mostly the same as RTBase64DecodedSizeEx, except for the wider character
     70 * type and therefore more careful handling of g_szRTBase64ValToChar and additional
     71 * space characters.  Fixes must be applied to both copies of the code.
    10872 */
    109 static void rtBase64Sanity(void)
    110 {
    111     static bool s_fSane = false;
    112     if (RT_UNLIKELY(!s_fSane))
    113     {
    114         for (unsigned i = 0; i < 64; i++)
    115         {
    116             unsigned ch = g_szValToChar[i];
    117             Assert(ch);
    118             Assert(g_au8CharToVal[ch] == i);
    119         }
    120 
    121         for (unsigned i = 0; i < 256; i++)
    122         {
    123             uint8_t u8 = g_au8CharToVal[i];
    124             Assert(   (     u8 == BASE64_INVALID
    125                        &&   !RT_C_IS_ALNUM(i)
    126                        &&   !RT_C_IS_SPACE(i))
    127                    || (     u8 == BASE64_PAD
    128                        &&   i  == '=')
    129                    || (     u8 == BASE64_SPACE
    130                        &&   RT_C_IS_SPACE(i))
    131                    || (     u8 < 64
    132                        &&   (unsigned)g_szValToChar[u8] == i));
    133         }
    134         ASMAtomicWriteBool(&s_fSane, true);
    135     }
    136 }
    137 #endif /* RT_STRICT */
    138 
    139 
    140 RTDECL(ssize_t) RTBase64DecodedSizeEx(const char *pszString, size_t cchStringMax, char **ppszEnd)
     73RTDECL(ssize_t) RTBase64DecodedUtf16SizeEx(PCRTUTF16 pwszString, size_t cwcStringMax, PRTUTF16 *ppwszEnd)
    14174{
    14275#ifdef RT_STRICT
     
    14982    uint32_t    c6Bits = 0;
    15083    uint8_t     u8     = BASE64_INVALID;
    151     unsigned    ch     = 0;
    152     AssertCompile(sizeof(char) == sizeof(uint8_t));
    153 
    154     while (cchStringMax > 0 && (ch = *pszString))
    155     {
    156         u8 = g_au8CharToVal[ch];
     84    RTUTF16     wc     = 0;
     85
     86    while (cwcStringMax > 0 && (wc = *pwszString))
     87    {
     88        u8 = rtBase64TranslateUtf16(wc);
    15789        if (u8 < 64)
    15890            c6Bits++;
     
    16193
    16294        /* advance */
    163         pszString++;
    164         cchStringMax--;
     95        pwszString++;
     96        cwcStringMax--;
    16597    }
    16698
     
    174106        cbPad = 1;
    175107        c6Bits++;
    176         pszString++;
    177         cchStringMax--;
    178         while (cchStringMax > 0 && (ch = *pszString))
    179         {
    180             u8 = g_au8CharToVal[ch];
     108        pwszString++;
     109        cwcStringMax--;
     110        while (cwcStringMax > 0 && (wc = *pwszString))
     111        {
     112            u8 = rtBase64TranslateUtf16(wc);
    181113            if (u8 != BASE64_SPACE)
    182114            {
     
    186118                cbPad++;
    187119            }
    188             pszString++;
    189             cchStringMax--;
     120            pwszString++;
     121            cwcStringMax--;
    190122        }
    191123        if (cbPad >= 3)
     
    198130     */
    199131    if (    u8 == BASE64_INVALID
    200         &&  !ppszEnd
    201         &&  ch)
     132        &&  !ppwszEnd
     133        &&  wc)
    202134        return -1;
    203135
     
    205137     * Recalc 6-bit to 8-bit and adjust for padding.
    206138     */
    207     size_t cb;
    208     if (c6Bits * 3 / 3 == c6Bits)
    209     {
    210         if ((c6Bits * 3 % 4) != 0)
    211             return -1;
    212         cb = c6Bits * 3 / 4;
    213     }
    214     else
    215     {
    216         if ((c6Bits * (uint64_t)3 % 4) != 0)
    217             return -1;
    218         cb = c6Bits * (uint64_t)3 / 4;
    219     }
    220 
    221     if (cb < cbPad)
    222         return -1;
    223     cb -= cbPad;
    224 
    225     if (ppszEnd)
    226         *ppszEnd = (char *)pszString;
    227     return cb;
    228 }
    229 RT_EXPORT_SYMBOL(RTBase64DecodedSizeEx);
    230 
    231 
    232 RTDECL(ssize_t) RTBase64DecodedSize(const char *pszString, char **ppszEnd)
    233 {
    234     return RTBase64DecodedSizeEx(pszString, RTSTR_MAX, ppszEnd);
    235 }
    236 RT_EXPORT_SYMBOL(RTBase64DecodedSize);
    237 
    238 
    239 RTDECL(int) RTBase64DecodeEx(const char *pszString, size_t cchStringMax, void *pvData, size_t cbData,
    240                              size_t *pcbActual, char **ppszEnd)
     139    if (ppwszEnd)
     140        *ppwszEnd = (PRTUTF16)pwszString;
     141    return rtBase64DecodedSizeRecalc(c6Bits, cbPad);
     142}
     143RT_EXPORT_SYMBOL(RTBase64DecodedUtf16SizeEx);
     144
     145
     146RTDECL(ssize_t) RTBase64DecodedUtf16Size(PCRTUTF16 pwszString, PRTUTF16 *ppwszEnd)
     147{
     148    return RTBase64DecodedUtf16SizeEx(pwszString, RTSTR_MAX, ppwszEnd);
     149}
     150RT_EXPORT_SYMBOL(RTBase64DecodedUtf16Size);
     151
     152
     153RTDECL(int) RTBase64DecodeUtf16Ex(PCRTUTF16 pwszString, size_t cwcStringMax, void *pvData, size_t cbData,
     154                                  size_t *pcbActual, PRTUTF16 *ppwszEnd)
    241155{
    242156#ifdef RT_STRICT
     
    249163    uint8_t     u8Trio[3] = { 0, 0, 0 }; /* shuts up gcc */
    250164    uint8_t    *pbData    = (uint8_t *)pvData;
    251     unsigned    ch;
    252165    uint8_t     u8;
    253166    unsigned    c6Bits    = 0;
     
    257170    {
    258171        /* The first 6-bit group. */
    259         while ((u8 = g_au8CharToVal[ch = cchStringMax > 0 ? (uint8_t)*pszString : 0]) == BASE64_SPACE)
    260             pszString++, cchStringMax--;
     172        while ((u8 = rtBase64TranslateNextUtf16(pwszString, cwcStringMax)) == BASE64_SPACE)
     173            pwszString++, cwcStringMax--;
    261174        if (u8 >= 64)
    262175        {
     
    265178        }
    266179        u8Trio[0] = u8 << 2;
    267         pszString++;
    268         cchStringMax--;
     180        pwszString++;
     181        cwcStringMax--;
    269182
    270183        /* The second 6-bit group. */
    271         while ((u8 = g_au8CharToVal[ch = cchStringMax > 0 ? (uint8_t)*pszString : 0]) == BASE64_SPACE)
    272             pszString++, cchStringMax--;
     184        while ((u8 = rtBase64TranslateNextUtf16(pwszString, cwcStringMax)) == BASE64_SPACE)
     185            pwszString++, cwcStringMax--;
    273186        if (u8 >= 64)
    274187        {
     
    278191        u8Trio[0] |= u8 >> 4;
    279192        u8Trio[1]  = u8 << 4;
    280         pszString++;
    281         cchStringMax--;
     193        pwszString++;
     194        cwcStringMax--;
    282195
    283196        /* The third 6-bit group. */
    284197        u8 = BASE64_INVALID;
    285         while ((u8 = g_au8CharToVal[ch = cchStringMax > 0 ? (uint8_t)*pszString : 0]) == BASE64_SPACE)
    286             pszString++, cchStringMax--;
     198        while ((u8 = rtBase64TranslateNextUtf16(pwszString, cwcStringMax)) == BASE64_SPACE)
     199            pwszString++, cwcStringMax--;
    287200        if (u8 >= 64)
    288201        {
     
    292205        u8Trio[1] |= u8 >> 2;
    293206        u8Trio[2]  = u8 << 6;
    294         pszString++;
    295         cchStringMax--;
     207        pwszString++;
     208        cwcStringMax--;
    296209
    297210        /* The fourth 6-bit group. */
    298211        u8 = BASE64_INVALID;
    299         while ((u8 = g_au8CharToVal[ch = cchStringMax > 0 ? (uint8_t)*pszString : 0]) == BASE64_SPACE)
    300             pszString++, cchStringMax--;
     212        while ((u8 = rtBase64TranslateNextUtf16(pwszString, cwcStringMax)) == BASE64_SPACE)
     213            pwszString++, cwcStringMax--;
    301214        if (u8 >= 64)
    302215        {
     
    305218        }
    306219        u8Trio[2] |= u8;
    307         pszString++;
    308         cchStringMax--;
     220        pwszString++;
     221        cwcStringMax--;
    309222
    310223        /* flush the trio */
     
    326239    {
    327240        cbPad = 1;
    328         pszString++;
    329         cchStringMax--;
    330         while (cchStringMax > 0 && (ch = (uint8_t)*pszString))
    331         {
    332             u8 = g_au8CharToVal[ch];
     241        pwszString++;
     242        cwcStringMax--;
     243        RTUTF16 wc;
     244        while (cwcStringMax > 0 && (wc = *pwszString))
     245        {
     246            u8 = rtBase64TranslateUtf16(wc);
    333247            if (u8 != BASE64_SPACE)
    334248            {
     
    337251                cbPad++;
    338252            }
    339             pszString++;
    340             cchStringMax--;
     253            pwszString++;
     254            cwcStringMax--;
    341255        }
    342256        if (cbPad >= 3)
     
    349263     */
    350264    if (    u8 == BASE64_INVALID
    351         &&  !ppszEnd
    352         &&  ch != '\0')
     265        &&  !ppwszEnd
     266        &&  cwcStringMax != 0
     267        &&  *pwszString != '\0')
    353268        return VERR_INVALID_BASE64_ENCODING;
    354269
     
    400315     * Set optional return values and return successfully.
    401316     */
    402     if (ppszEnd)
    403         *ppszEnd = (char *)pszString;
     317    if (ppwszEnd)
     318        *ppwszEnd = (PRTUTF16)pwszString;
    404319    if (pcbActual)
    405320        *pcbActual = pbData - (uint8_t *)pvData;
    406321    return VINF_SUCCESS;
    407322}
    408 RT_EXPORT_SYMBOL(RTBase64DecodeEx);
    409 
    410 
    411 RTDECL(int) RTBase64Decode(const char *pszString, void *pvData, size_t cbData, size_t *pcbActual, char **ppszEnd)
    412 {
    413     return RTBase64DecodeEx(pszString, RTSTR_MAX, pvData, cbData, pcbActual, ppszEnd);
    414 }
    415 RT_EXPORT_SYMBOL(RTBase64Decode);
    416 
    417 
    418 RTDECL(size_t) RTBase64EncodedLength(size_t cbData)
     323RT_EXPORT_SYMBOL(RTBase64DecodeUtf16Ex);
     324
     325
     326RTDECL(int) RTBase64DecodeUtf16(PCRTUTF16 pwszString, void *pvData, size_t cbData, size_t *pcbActual, PRTUTF16 *ppwszEnd)
     327{
     328    return RTBase64DecodeUtf16Ex(pwszString, RTSTR_MAX, pvData, cbData, pcbActual, ppwszEnd);
     329}
     330RT_EXPORT_SYMBOL(RTBase64DecodeUtf16);
     331
     332
     333RTDECL(size_t) RTBase64EncodedUtf16Length(size_t cbData)
    419334{
    420335    return RTBase64EncodedLengthEx(cbData, 0);
    421336}
    422 RT_EXPORT_SYMBOL(RTBase64EncodedLength);
    423 
    424 
    425 RTDECL(size_t) RTBase64EncodedLengthEx(size_t cbData, uint32_t fFlags)
    426 {
    427     size_t const cchEol = g_acchEolStyles[fFlags & RTBASE64_FLAGS_EOL_STYLE_MASK];
    428 
    429     if (cbData * 8 / 8 != cbData)
    430     {
    431         AssertReturn(sizeof(size_t) == sizeof(uint64_t), ~(size_t)0);
    432         uint64_t cch = cbData * (uint64_t)8;
    433         while (cch % 24)
    434             cch += 8;
    435         cch /= 6;
    436         cch += ((cch - 1) / RTBASE64_LINE_LEN) * cchEol;
    437         return cch;
    438     }
    439 
    440     size_t cch = cbData * 8;
    441     while (cch % 24)
    442         cch += 8;
    443     cch /= 6;
    444     cch += ((cch - 1) / RTBASE64_LINE_LEN) * cchEol;
    445     return cch;
    446 }
    447 RT_EXPORT_SYMBOL(RTBase64EncodedLengthEx);
    448 
    449 
    450 RTDECL(int) RTBase64Encode(const void *pvData, size_t cbData, char *pszBuf, size_t cbBuf, size_t *pcchActual)
    451 {
    452     return RTBase64EncodeEx(pvData, cbData, 0, pszBuf, cbBuf, pcchActual);
    453 }
    454 RT_EXPORT_SYMBOL(RTBase64Encode);
    455 
    456 
    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.
    461  */
    462 RTDECL(int) RTBase64EncodeEx(const void *pvData, size_t cbData, uint32_t fFlags,
    463                              char *pszBuf, size_t cbBuf, size_t *pcchActual)
    464 {
    465     /* Expand the EOL style flags: */
    466     size_t const    cchEol = g_acchEolStyles[fFlags & RTBASE64_FLAGS_EOL_STYLE_MASK];
    467     char const      chEol0 = g_aachEolStyles[fFlags & RTBASE64_FLAGS_EOL_STYLE_MASK][0];
    468     char const      chEol1 = g_aachEolStyles[fFlags & RTBASE64_FLAGS_EOL_STYLE_MASK][1];
    469     Assert(cchEol == (chEol0 != '\0' ? 1U : 0U) + (chEol1 != '\0' ? 1U : 0U));
    470 
    471     /*
    472      * Process whole "trios" of input data.
    473      */
    474     uint8_t         u8A;
    475     uint8_t         u8B;
    476     uint8_t         u8C;
    477     size_t          cbLineFeed = cchEol ? cbBuf - RTBASE64_LINE_LEN : ~(size_t)0;
    478     const uint8_t  *pbSrc      = (const uint8_t *)pvData;
    479     char           *pchDst     = pszBuf;
    480     while (cbData >= 3)
    481     {
    482         if (cbBuf < 4 + 1)
    483             return VERR_BUFFER_OVERFLOW;
    484 
    485         /* encode */
    486         u8A = pbSrc[0];
    487         pchDst[0] = g_szValToChar[u8A >> 2];
    488         u8B = pbSrc[1];
    489         pchDst[1] = g_szValToChar[((u8A << 4) & 0x3f) | (u8B >> 4)];
    490         u8C = pbSrc[2];
    491         pchDst[2] = g_szValToChar[((u8B << 2) & 0x3f) | (u8C >> 6)];
    492         pchDst[3] = g_szValToChar[u8C & 0x3f];
    493 
    494         /* advance */
    495         cbBuf  -= 4;
    496         pchDst += 4;
    497         cbData -= 3;
    498         pbSrc  += 3;
    499 
    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;
    510         }
    511     }
    512 
    513     /*
    514      * Deal with the odd bytes and string termination.
    515      */
    516     if (cbData)
    517     {
    518         if (cbBuf < 4 + 1)
    519             return VERR_BUFFER_OVERFLOW;
    520         switch (cbData)
    521         {
    522             case 1:
    523                 u8A = pbSrc[0];
    524                 pchDst[0] = g_szValToChar[u8A >> 2];
    525                 pchDst[1] = g_szValToChar[(u8A << 4) & 0x3f];
    526                 pchDst[2] = '=';
    527                 pchDst[3] = '=';
    528                 break;
    529             case 2:
    530                 u8A = pbSrc[0];
    531                 pchDst[0] = g_szValToChar[u8A >> 2];
    532                 u8B = pbSrc[1];
    533                 pchDst[1] = g_szValToChar[((u8A << 4) & 0x3f) | (u8B >> 4)];
    534                 pchDst[2] = g_szValToChar[(u8B << 2) & 0x3f];
    535                 pchDst[3] = '=';
    536                 break;
    537         }
    538         pchDst += 4;
    539     }
    540 
    541     *pchDst = '\0';
    542 
    543     if (pcchActual)
    544         *pcchActual = pchDst - pszBuf;
    545     return VINF_SUCCESS;
    546 }
    547 RT_EXPORT_SYMBOL(RTBase64EncodeEx);
     337RT_EXPORT_SYMBOL(RTBase64EncodedUtf16Length);
     338
     339
     340RTDECL(size_t) RTBase64EncodedUtf16LengthEx(size_t cbData, uint32_t fFlags)
     341{
     342    return RTBase64EncodedLengthEx(cbData, fFlags);
     343}
     344RT_EXPORT_SYMBOL(RTBase64EncodedUtf16LengthEx);
     345
     346
     347RTDECL(int) RTBase64EncodeUtf16(const void *pvData, size_t cbData, PRTUTF16 pwszBuf, size_t cwcBuf, size_t *pcwcActual)
     348{
     349    return RTBase64EncodeUtf16Ex(pvData, cbData, 0, pwszBuf, cwcBuf, pcwcActual);
     350}
     351RT_EXPORT_SYMBOL(RTBase64EncodeUtf16);
    548352
    549353
     
    557361{
    558362    /* 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];
     363    size_t const    cchEol = g_acchRTBase64EolStyles[fFlags & RTBASE64_FLAGS_EOL_STYLE_MASK];
     364    char const      chEol0 = g_aachRTBase64EolStyles[fFlags & RTBASE64_FLAGS_EOL_STYLE_MASK][0];
     365    char const      chEol1 = g_aachRTBase64EolStyles[fFlags & RTBASE64_FLAGS_EOL_STYLE_MASK][1];
    562366    Assert(cchEol == (chEol0 != '\0' ? 1U : 0U) + (chEol1 != '\0' ? 1U : 0U));
    563367
     
    578382        /* encode */
    579383        u8A = pbSrc[0];
    580         pwcDst[0] = g_szValToChar[u8A >> 2];
     384        pwcDst[0] = g_szRTBase64ValToChar[u8A >> 2];
    581385        u8B = pbSrc[1];
    582         pwcDst[1] = g_szValToChar[((u8A << 4) & 0x3f) | (u8B >> 4)];
     386        pwcDst[1] = g_szRTBase64ValToChar[((u8A << 4) & 0x3f) | (u8B >> 4)];
    583387        u8C = pbSrc[2];
    584         pwcDst[2] = g_szValToChar[((u8B << 2) & 0x3f) | (u8C >> 6)];
    585         pwcDst[3] = g_szValToChar[u8C & 0x3f];
     388        pwcDst[2] = g_szRTBase64ValToChar[((u8B << 2) & 0x3f) | (u8C >> 6)];
     389        pwcDst[3] = g_szRTBase64ValToChar[u8C & 0x3f];
    586390
    587391        /* advance */
     
    615419            case 1:
    616420                u8A = pbSrc[0];
    617                 pwcDst[0] = g_szValToChar[u8A >> 2];
    618                 pwcDst[1] = g_szValToChar[(u8A << 4) & 0x3f];
     421                pwcDst[0] = g_szRTBase64ValToChar[u8A >> 2];
     422                pwcDst[1] = g_szRTBase64ValToChar[(u8A << 4) & 0x3f];
    619423                pwcDst[2] = '=';
    620424                pwcDst[3] = '=';
     
    622426            case 2:
    623427                u8A = pbSrc[0];
    624                 pwcDst[0] = g_szValToChar[u8A >> 2];
     428                pwcDst[0] = g_szRTBase64ValToChar[u8A >> 2];
    625429                u8B = pbSrc[1];
    626                 pwcDst[1] = g_szValToChar[((u8A << 4) & 0x3f) | (u8B >> 4)];
    627                 pwcDst[2] = g_szValToChar[(u8B << 2) & 0x3f];
     430                pwcDst[1] = g_szRTBase64ValToChar[((u8A << 4) & 0x3f) | (u8B >> 4)];
     431                pwcDst[2] = g_szRTBase64ValToChar[(u8B << 2) & 0x3f];
    628432                pwcDst[3] = '=';
    629433                break;
     
    640444RT_EXPORT_SYMBOL(RTBase64EncodeUtf16Ex);
    641445
    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/common/string/base64.cpp

    r84286 r84293  
    22/** @file
    33 * IPRT - Base64, MIME content transfer encoding.
     4 *
     5 * @note The base64-utf16.cpp file must be diffable with this one.
     6 *       Fixed typically applies to both files.
    47 */
    58
     
    4043#endif
    4144
    42 
    43 /*********************************************************************************************************************************
    44 *   Defined Constants And Macros                                                                                                 *
    45 *********************************************************************************************************************************/
    46 /** The line length used for encoding. */
    47 #define RTBASE64_LINE_LEN   64
    48 
    49 /** @name Special g_au8CharToVal values
    50  * @{ */
    51 #define BASE64_SPACE        0xc0
    52 #define BASE64_PAD          0xe0
    53 #define BASE64_INVALID      0xff
    54 /** @} */
     45#include "base64.h"
    5546
    5647
     
    6051/** Base64 character to value. (RFC 2045)
    6152 * ASSUMES ASCII / UTF-8. */
    62 static const uint8_t    g_au8CharToVal[256] =
     53DECL_HIDDEN_CONST(const uint8_t)    g_au8RTBase64CharToVal[256] =
    6354{
    6455    0xff, 0xff, 0xff, 0xff,   0xff, 0xff, 0xff, 0xff,   0xff, 0xc0, 0xc0, 0xc0,   0xc0, 0xc0, 0xff, 0xff, /* 0x00..0x0f */
     
    8172
    8273/** Value to Base64 character. (RFC 2045) */
    83 static const char       g_szValToChar[64+1] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
     74DECL_HIDDEN_CONST(const char)   g_szRTBase64ValToChar[64+1] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    8475
    8576/** The end-of-line lengths (indexed by style flag value). */
    86 static const size_t     g_acchEolStyles[RTBASE64_FLAGS_EOL_STYLE_MASK + 1] =
     77DECL_HIDDEN_CONST(const size_t) g_acchRTBase64EolStyles[RTBASE64_FLAGS_EOL_STYLE_MASK + 1] =
    8778{
    8879    /*[RTBASE64_FLAGS_EOL_NATIVE    ]:*/ RTBASE64_EOL_SIZE,
     
    9384
    9485/** The end-of-line characters (zero, one or two). */
    95 static const char       g_aachEolStyles[RTBASE64_FLAGS_EOL_STYLE_MASK + 1][2] =
     86DECL_HIDDEN_CONST(const char)   g_aachRTBase64EolStyles[RTBASE64_FLAGS_EOL_STYLE_MASK + 1][2] =
    9687{
    9788    /*[RTBASE64_FLAGS_EOL_NATIVE    ]:*/ { RTBASE64_EOL_SIZE == 1 ? '\n' : '\r', RTBASE64_EOL_SIZE == 1 ? '\0' : '\n', },
     
    10798 * Perform table sanity checks on the first call.
    10899 */
    109 static void rtBase64Sanity(void)
     100DECLHIDDEN(void) rtBase64Sanity(void)
    110101{
    111102    static bool s_fSane = false;
     
    114105        for (unsigned i = 0; i < 64; i++)
    115106        {
    116             unsigned ch = g_szValToChar[i];
     107            unsigned ch = g_szRTBase64ValToChar[i];
    117108            Assert(ch);
    118             Assert(g_au8CharToVal[ch] == i);
     109            Assert(g_au8RTBase64CharToVal[ch] == i);
    119110        }
    120111
    121112        for (unsigned i = 0; i < 256; i++)
    122113        {
    123             uint8_t u8 = g_au8CharToVal[i];
     114            uint8_t u8 = g_au8RTBase64CharToVal[i];
    124115            Assert(   (     u8 == BASE64_INVALID
    125116                       &&   !RT_C_IS_ALNUM(i)
     
    130121                       &&   RT_C_IS_SPACE(i))
    131122                   || (     u8 < 64
    132                        &&   (unsigned)g_szValToChar[u8] == i));
     123                       &&   (unsigned)g_szRTBase64ValToChar[u8] == i));
    133124        }
    134125        ASMAtomicWriteBool(&s_fSane, true);
     
    138129
    139130
     131/*
     132 * Mostly the same as RTBase64DecodedUtf16SizeEx, except for the simpler
     133 * character type.  Fixes must be applied to both copies of the code.
     134 */
    140135RTDECL(ssize_t) RTBase64DecodedSizeEx(const char *pszString, size_t cchStringMax, char **ppszEnd)
    141136{
     
    154149    while (cchStringMax > 0 && (ch = *pszString))
    155150    {
    156         u8 = g_au8CharToVal[ch];
     151        u8 = g_au8RTBase64CharToVal[ch];
    157152        if (u8 < 64)
    158153            c6Bits++;
     
    178173        while (cchStringMax > 0 && (ch = *pszString))
    179174        {
    180             u8 = g_au8CharToVal[ch];
     175            u8 = g_au8RTBase64CharToVal[ch];
    181176            if (u8 != BASE64_SPACE)
    182177            {
     
    205200     * Recalc 6-bit to 8-bit and adjust for padding.
    206201     */
    207     size_t cb;
    208     if (c6Bits * 3 / 3 == c6Bits)
    209     {
    210         if ((c6Bits * 3 % 4) != 0)
    211             return -1;
    212         cb = c6Bits * 3 / 4;
    213     }
    214     else
    215     {
    216         if ((c6Bits * (uint64_t)3 % 4) != 0)
    217             return -1;
    218         cb = c6Bits * (uint64_t)3 / 4;
    219     }
    220 
    221     if (cb < cbPad)
    222         return -1;
    223     cb -= cbPad;
    224 
    225202    if (ppszEnd)
    226203        *ppszEnd = (char *)pszString;
    227     return cb;
     204    return rtBase64DecodedSizeRecalc(c6Bits, cbPad);
    228205}
    229206RT_EXPORT_SYMBOL(RTBase64DecodedSizeEx);
     
    257234    {
    258235        /* The first 6-bit group. */
    259         while ((u8 = g_au8CharToVal[ch = cchStringMax > 0 ? (uint8_t)*pszString : 0]) == BASE64_SPACE)
     236        while ((u8 = g_au8RTBase64CharToVal[ch = cchStringMax > 0 ? (uint8_t)*pszString : 0]) == BASE64_SPACE)
    260237            pszString++, cchStringMax--;
    261238        if (u8 >= 64)
     
    269246
    270247        /* The second 6-bit group. */
    271         while ((u8 = g_au8CharToVal[ch = cchStringMax > 0 ? (uint8_t)*pszString : 0]) == BASE64_SPACE)
     248        while ((u8 = g_au8RTBase64CharToVal[ch = cchStringMax > 0 ? (uint8_t)*pszString : 0]) == BASE64_SPACE)
    272249            pszString++, cchStringMax--;
    273250        if (u8 >= 64)
     
    283260        /* The third 6-bit group. */
    284261        u8 = BASE64_INVALID;
    285         while ((u8 = g_au8CharToVal[ch = cchStringMax > 0 ? (uint8_t)*pszString : 0]) == BASE64_SPACE)
     262        while ((u8 = g_au8RTBase64CharToVal[ch = cchStringMax > 0 ? (uint8_t)*pszString : 0]) == BASE64_SPACE)
    286263            pszString++, cchStringMax--;
    287264        if (u8 >= 64)
     
    297274        /* The fourth 6-bit group. */
    298275        u8 = BASE64_INVALID;
    299         while ((u8 = g_au8CharToVal[ch = cchStringMax > 0 ? (uint8_t)*pszString : 0]) == BASE64_SPACE)
     276        while ((u8 = g_au8RTBase64CharToVal[ch = cchStringMax > 0 ? (uint8_t)*pszString : 0]) == BASE64_SPACE)
    300277            pszString++, cchStringMax--;
    301278        if (u8 >= 64)
     
    330307        while (cchStringMax > 0 && (ch = (uint8_t)*pszString))
    331308        {
    332             u8 = g_au8CharToVal[ch];
     309            u8 = g_au8RTBase64CharToVal[ch];
    333310            if (u8 != BASE64_SPACE)
    334311            {
     
    425402RTDECL(size_t) RTBase64EncodedLengthEx(size_t cbData, uint32_t fFlags)
    426403{
    427     size_t const cchEol = g_acchEolStyles[fFlags & RTBASE64_FLAGS_EOL_STYLE_MASK];
     404    size_t const cchEol = g_acchRTBase64EolStyles[fFlags & RTBASE64_FLAGS_EOL_STYLE_MASK];
    428405
    429406    if (cbData * 8 / 8 != cbData)
     
    464441{
    465442    /* Expand the EOL style flags: */
    466     size_t const    cchEol = g_acchEolStyles[fFlags & RTBASE64_FLAGS_EOL_STYLE_MASK];
    467     char const      chEol0 = g_aachEolStyles[fFlags & RTBASE64_FLAGS_EOL_STYLE_MASK][0];
    468     char const      chEol1 = g_aachEolStyles[fFlags & RTBASE64_FLAGS_EOL_STYLE_MASK][1];
     443    size_t const    cchEol = g_acchRTBase64EolStyles[fFlags & RTBASE64_FLAGS_EOL_STYLE_MASK];
     444    char const      chEol0 = g_aachRTBase64EolStyles[fFlags & RTBASE64_FLAGS_EOL_STYLE_MASK][0];
     445    char const      chEol1 = g_aachRTBase64EolStyles[fFlags & RTBASE64_FLAGS_EOL_STYLE_MASK][1];
    469446    Assert(cchEol == (chEol0 != '\0' ? 1U : 0U) + (chEol1 != '\0' ? 1U : 0U));
    470447
     
    485462        /* encode */
    486463        u8A = pbSrc[0];
    487         pchDst[0] = g_szValToChar[u8A >> 2];
     464        pchDst[0] = g_szRTBase64ValToChar[u8A >> 2];
    488465        u8B = pbSrc[1];
    489         pchDst[1] = g_szValToChar[((u8A << 4) & 0x3f) | (u8B >> 4)];
     466        pchDst[1] = g_szRTBase64ValToChar[((u8A << 4) & 0x3f) | (u8B >> 4)];
    490467        u8C = pbSrc[2];
    491         pchDst[2] = g_szValToChar[((u8B << 2) & 0x3f) | (u8C >> 6)];
    492         pchDst[3] = g_szValToChar[u8C & 0x3f];
     468        pchDst[2] = g_szRTBase64ValToChar[((u8B << 2) & 0x3f) | (u8C >> 6)];
     469        pchDst[3] = g_szRTBase64ValToChar[u8C & 0x3f];
    493470
    494471        /* advance */
     
    522499            case 1:
    523500                u8A = pbSrc[0];
    524                 pchDst[0] = g_szValToChar[u8A >> 2];
    525                 pchDst[1] = g_szValToChar[(u8A << 4) & 0x3f];
     501                pchDst[0] = g_szRTBase64ValToChar[u8A >> 2];
     502                pchDst[1] = g_szRTBase64ValToChar[(u8A << 4) & 0x3f];
    526503                pchDst[2] = '=';
    527504                pchDst[3] = '=';
     
    529506            case 2:
    530507                u8A = pbSrc[0];
    531                 pchDst[0] = g_szValToChar[u8A >> 2];
     508                pchDst[0] = g_szRTBase64ValToChar[u8A >> 2];
    532509                u8B = pbSrc[1];
    533                 pchDst[1] = g_szValToChar[((u8A << 4) & 0x3f) | (u8B >> 4)];
    534                 pchDst[2] = g_szValToChar[(u8B << 2) & 0x3f];
     510                pchDst[1] = g_szRTBase64ValToChar[((u8A << 4) & 0x3f) | (u8B >> 4)];
     511                pchDst[2] = g_szRTBase64ValToChar[(u8B << 2) & 0x3f];
    535512                pchDst[3] = '=';
    536513                break;
     
    547524RT_EXPORT_SYMBOL(RTBase64EncodeEx);
    548525
    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

    r84286 r84293  
    113113     */
    114114
    115     /* Decoding: later */
    116 
    117115    /* Encoding UTF-16: */
    118116    memset(wszOut, 0xaa, sizeof(wszOut));
     
    130128    if (cwcOut != cwcOut2)
    131129        RTTestIFailed("RTBase64EncodedLength returned %zu RTUTF16 units, expected %zu.\n", cwcOut2, cwcOut);
     130
     131    /* Decoding UTF-16: */
     132    PRTUTF16 pwszEnc = NULL;
     133    RTTESTI_CHECK_RC_OK_RETV(RTStrToUtf16(pszEnc, &pwszEnc));
     134
     135    rc = RTBase64DecodeUtf16(pwszEnc, szOut, cbData, &cchOut, NULL);
     136    if (RT_FAILURE(rc))
     137        RTTestIFailed("RTBase64DecodeUtf16 -> %Rrc", rc);
     138    else if (cchOut != cbData)
     139        RTTestIFailed("RTBase64DecodeUtf16 returned %zu bytes, expected %zu.", cchOut, cbData);
     140    else if (memcmp(szOut, pvData, cchOut))
     141    {
     142        if (fTextData)
     143            RTTestIFailed("RTBase64Decode returned:\n%.*s\nexpected:\n%s\n", (int)cchOut, szOut, pvData);
     144        else
     145            RTTestIFailed("RTBase64Decode return mismatching output\n");
     146    }
     147
     148    cchOut = RTBase64DecodedUtf16Size(pwszEnc, NULL);
     149    if (cchOut != cbData)
     150        RTTestIFailed("RTBase64DecodedUtf16Size returned %zu bytes, expected %zu.\n", cchOut, cbData);
     151
     152    RTUtf16Free(pwszEnc);
    132153}
    133154
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