[vlc-commits] strings: clean up base64 encoding

Rémi Denis-Courmont git at videolan.org
Thu Mar 28 16:51:48 CET 2019


vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Thu Mar 28 17:16:35 2019 +0200| [8d3c52593e2c5e07e6c821d03160cd2ab4c35fa2] | committer: Rémi Denis-Courmont

strings: clean up base64 encoding

Document, split main loop from tail handling, add missing qualifiers.

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=8d3c52593e2c5e07e6c821d03160cd2ab4c35fa2
---

 include/vlc_strings.h | 25 ++++++++++++++--
 src/text/strings.c    | 83 ++++++++++++++++++++++++++-------------------------
 2 files changed, 65 insertions(+), 43 deletions(-)

diff --git a/include/vlc_strings.h b/include/vlc_strings.h
index 5d6e5d50ff..fb33f18723 100644
--- a/include/vlc_strings.h
+++ b/include/vlc_strings.h
@@ -116,8 +116,29 @@ VLC_API void vlc_xml_decode(char *st);
  */
 VLC_API char *vlc_xml_encode(const char *str) VLC_MALLOC;
 
-VLC_API char * vlc_b64_encode_binary( const uint8_t *, size_t );
-VLC_API char * vlc_b64_encode( const char * );
+/**
+ * Base64 encoding.
+ *
+ * Encodes a buffer into base64 as a (nul-terminated) string.
+ *
+ * \param base start address of buffer to encode
+ * \param length length in bytes of buffer to encode
+ * \return a heap-allocated nul-terminated string
+ * (or NULL on allocation error).
+ */
+VLC_API char *vlc_b64_encode_binary(const void *base, size_t length)
+VLC_USED VLC_MALLOC;
+
+/**
+ * Base64 encoding (string).
+ *
+ * Encodes a nul-terminated string into Base64.
+ *
+ * \param str nul-terminated string to encode
+ * \return a heap-allocated nul-terminated string
+ * (or NULL on allocation error).
+ */
+VLC_API char *vlc_b64_encode(const char *str) VLC_USED VLC_MALLOC;
 
 VLC_API size_t vlc_b64_decode_binary_to_buffer( uint8_t *p_dst, size_t i_dst_max, const char *psz_src );
 VLC_API size_t vlc_b64_decode_binary( uint8_t **pp_dst, const char *psz_src );
diff --git a/src/text/strings.c b/src/text/strings.c
index 6fc57d5d92..6987daed0e 100644
--- a/src/text/strings.c
+++ b/src/text/strings.c
@@ -347,58 +347,59 @@ char *vlc_xml_encode (const char *str)
 }
 
 /* Base64 encoding */
-char *vlc_b64_encode_binary( const uint8_t *src, size_t i_src )
+char *vlc_b64_encode_binary(const void *src, size_t length)
 {
     static const char b64[] =
-           "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+    const unsigned char *in = src;
+    char *dst = malloc((((length + 2) / 3) * 4) + 1);
+    char *out = dst;
 
-    char *ret = malloc( ( i_src + 4 ) * 4 / 3 );
-    char *dst = ret;
-
-    if( dst == NULL )
+    if (unlikely(dst == NULL))
         return NULL;
 
-    while( i_src > 0 )
-    {
-        /* pops (up to) 3 bytes of input, push 4 bytes */
-        uint32_t v;
-
-        /* 1/3 -> 1/4 */
-        v = ((unsigned)*src++) << 24;
-        *dst++ = b64[v >> 26];
-        v = v << 6;
-
-        /* 2/3 -> 2/4 */
-        if( i_src >= 2 )
-            v |= *src++ << 22;
-        *dst++ = b64[v >> 26];
-        v = v << 6;
-
-        /* 3/3 -> 3/4 */
-        if( i_src >= 3 )
-            v |= *src++ << 20; // 3/3
-        *dst++ = ( i_src >= 2 ) ? b64[v >> 26] : '='; // 3/4
-        v = v << 6;
-
-        /* -> 4/4 */
-        *dst++ = ( i_src >= 3 ) ? b64[v >> 26] : '='; // 4/4
-
-        if( i_src <= 3 )
-            break;
-        i_src -= 3;
+    while (length >= 3) { /* pops (up to) 3 bytes of input, push 4 bytes */
+        uint_fast32_t v = (in[0] << 16) | (in[1] << 8) | in[2];
+
+        *(out++) = b64[(v >> 18)];
+        *(out++) = b64[(v >> 12) & 0x3f];
+        *(out++) = b64[(v >>  6) & 0x3f];
+        *(out++) = b64[(v >>  0) & 0x3f];
+        in += 3;
+        length -= 3;
     }
 
-    *dst = '\0';
+    switch (length) {
+        case 2: {
+            uint_fast16_t v = (in[0] << 8) | in[1];
+
+            *(out++) = b64[(v >> 10)];
+            *(out++) = b64[(v >>  4) & 0x3f];
+            *(out++) = b64[(v <<  2) & 0x3f];
+            *(out++) = '=';
+            break;
+        }
+
+        case 1: {
+            uint_fast8_t v = in[0];
+
+            *(out++) = b64[(v >>  2)];
+            *(out++) = b64[(v <<  4) & 0x3f];
+            *(out++) = '=';
+            *(out++) = '=';
+            break;
+        }
+    }
 
-    return ret;
+    *out = '\0';
+    return dst;
 }
 
-char *vlc_b64_encode( const char *src )
+char *vlc_b64_encode(const char *src)
 {
-    if( src )
-        return vlc_b64_encode_binary( (const uint8_t*)src, strlen(src) );
-    else
-        return vlc_b64_encode_binary( (const uint8_t*)"", 0 );
+    if (src == NULL)
+        src = "";
+    return vlc_b64_encode_binary(src, strlen(src));
 }
 
 /* Base64 decoding */



More information about the vlc-commits mailing list