changeset 3325:2e7c5c15ba25

reserve size for base64 decoding + avoid copy. In a test in WASM, encoding 3MB took 110ms instead of 1400ms previously
author Alain Mazy <alain@mazy.be>
date Thu, 21 Mar 2019 09:57:31 +0100
parents a15a4b9d8c00
children b21d4cc8e5d1
files Core/Toolbox.cpp Resources/ThirdParty/base64/base64.cpp Resources/ThirdParty/base64/base64.h
diffstat 3 files changed, 20 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/Core/Toolbox.cpp	Tue Mar 19 09:00:34 2019 +0100
+++ b/Core/Toolbox.cpp	Thu Mar 21 09:57:31 2019 +0100
@@ -398,7 +398,7 @@
   void Toolbox::EncodeBase64(std::string& result, 
                              const std::string& data)
   {
-    result = base64_encode(data);
+    base64_encode(result, data);
   }
 
   void Toolbox::DecodeBase64(std::string& result, 
@@ -416,7 +416,7 @@
       }
     }
 
-    result = base64_decode(data);
+    base64_decode(result, data);
   }
 
 
@@ -445,7 +445,8 @@
                                     const std::string& mime,
                                     const std::string& content)
   {
-    result = "data:" + mime + ";base64," + base64_encode(content);
+    result = "data:" + mime + ";base64,";
+    base64_encode(result, content);
   }
 
 #endif
--- a/Resources/ThirdParty/base64/base64.cpp	Tue Mar 19 09:00:34 2019 +0100
+++ b/Resources/ThirdParty/base64/base64.cpp	Thu Mar 21 09:57:31 2019 +0100
@@ -38,13 +38,14 @@
   return (isalnum(c) || (c == '+') || (c == '/'));
 }
 
-std::string base64_encode(const std::string& stringToEncode) 
+void base64_encode(std::string& result, const std::string& stringToEncode)
 {
   const unsigned char* bytes_to_encode = reinterpret_cast<const unsigned char*>
     (stringToEncode.size() > 0 ? &stringToEncode[0] : NULL);
-  unsigned int in_len = stringToEncode.size();
+  size_t in_len = stringToEncode.size();
   
-  std::string ret;
+  result.reserve(result.size() + in_len * 4 / 3 + 10);
+
   int i = 0;
   int j = 0;
   unsigned char char_array_3[3];
@@ -59,7 +60,7 @@
       char_array_4[3] = char_array_3[2] & 0x3f;
 
       for(i = 0; (i <4) ; i++)
-        ret += base64_chars[char_array_4[i]];
+        result += base64_chars[char_array_4[i]];
       i = 0;
     }
   }
@@ -75,24 +76,23 @@
     char_array_4[3] = char_array_3[2] & 0x3f;
 
     for (j = 0; (j < i + 1); j++)
-      ret += base64_chars[char_array_4[j]];
+      result += base64_chars[char_array_4[j]];
 
     while((i++ < 3))
-      ret += '=';
+      result += '=';
 
   }
-
-  return ret;
 }
 
 
-std::string base64_decode(const std::string& encoded_string) {
-  int in_len = encoded_string.size();
+void base64_decode(std::string& result, const std::string& encoded_string) {
+  size_t in_len = encoded_string.size();
   int i = 0;
   int j = 0;
   int in_ = 0;
   unsigned char char_array_4[4], char_array_3[3];
-  std::string ret;
+
+  result.reserve(result.size() + in_len * 3 / 4 + 10);
 
   while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
     char_array_4[i++] = encoded_string[in_]; in_++;
@@ -105,7 +105,7 @@
       char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
 
       for (i = 0; (i < 3); i++)
-        ret += char_array_3[i];
+        result += char_array_3[i];
       i = 0;
     }
   }
@@ -121,8 +121,7 @@
     char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
     char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
 
-    for (j = 0; (j < i - 1); j++) ret += char_array_3[j];
+    for (j = 0; (j < i - 1); j++)
+      result += char_array_3[j];
   }
-
-  return ret;
 }
--- a/Resources/ThirdParty/base64/base64.h	Tue Mar 19 09:00:34 2019 +0100
+++ b/Resources/ThirdParty/base64/base64.h	Thu Mar 21 09:57:31 2019 +0100
@@ -1,4 +1,4 @@
 #include <string>
 
-std::string base64_encode(const std::string& stringToEncode);
-std::string base64_decode(const std::string& s);
+void base64_encode(std::string& result, const std::string& stringToEncode);
+void base64_decode(std::string& result, const std::string& s);