comparison Resources/ThirdParty/base64/base64.cpp @ 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 f0544ab9396b
children b21d4cc8e5d1
comparison
equal deleted inserted replaced
3323:a15a4b9d8c00 3325:2e7c5c15ba25
36 36
37 static inline bool is_base64(unsigned char c) { 37 static inline bool is_base64(unsigned char c) {
38 return (isalnum(c) || (c == '+') || (c == '/')); 38 return (isalnum(c) || (c == '+') || (c == '/'));
39 } 39 }
40 40
41 std::string base64_encode(const std::string& stringToEncode) 41 void base64_encode(std::string& result, const std::string& stringToEncode)
42 { 42 {
43 const unsigned char* bytes_to_encode = reinterpret_cast<const unsigned char*> 43 const unsigned char* bytes_to_encode = reinterpret_cast<const unsigned char*>
44 (stringToEncode.size() > 0 ? &stringToEncode[0] : NULL); 44 (stringToEncode.size() > 0 ? &stringToEncode[0] : NULL);
45 unsigned int in_len = stringToEncode.size(); 45 size_t in_len = stringToEncode.size();
46 46
47 std::string ret; 47 result.reserve(result.size() + in_len * 4 / 3 + 10);
48
48 int i = 0; 49 int i = 0;
49 int j = 0; 50 int j = 0;
50 unsigned char char_array_3[3]; 51 unsigned char char_array_3[3];
51 unsigned char char_array_4[4]; 52 unsigned char char_array_4[4];
52 53
57 char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); 58 char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
58 char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); 59 char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
59 char_array_4[3] = char_array_3[2] & 0x3f; 60 char_array_4[3] = char_array_3[2] & 0x3f;
60 61
61 for(i = 0; (i <4) ; i++) 62 for(i = 0; (i <4) ; i++)
62 ret += base64_chars[char_array_4[i]]; 63 result += base64_chars[char_array_4[i]];
63 i = 0; 64 i = 0;
64 } 65 }
65 } 66 }
66 67
67 if (i) 68 if (i)
73 char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); 74 char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
74 char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); 75 char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
75 char_array_4[3] = char_array_3[2] & 0x3f; 76 char_array_4[3] = char_array_3[2] & 0x3f;
76 77
77 for (j = 0; (j < i + 1); j++) 78 for (j = 0; (j < i + 1); j++)
78 ret += base64_chars[char_array_4[j]]; 79 result += base64_chars[char_array_4[j]];
79 80
80 while((i++ < 3)) 81 while((i++ < 3))
81 ret += '='; 82 result += '=';
82 83
83 } 84 }
84
85 return ret;
86 } 85 }
87 86
88 87
89 std::string base64_decode(const std::string& encoded_string) { 88 void base64_decode(std::string& result, const std::string& encoded_string) {
90 int in_len = encoded_string.size(); 89 size_t in_len = encoded_string.size();
91 int i = 0; 90 int i = 0;
92 int j = 0; 91 int j = 0;
93 int in_ = 0; 92 int in_ = 0;
94 unsigned char char_array_4[4], char_array_3[3]; 93 unsigned char char_array_4[4], char_array_3[3];
95 std::string ret; 94
95 result.reserve(result.size() + in_len * 3 / 4 + 10);
96 96
97 while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) { 97 while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
98 char_array_4[i++] = encoded_string[in_]; in_++; 98 char_array_4[i++] = encoded_string[in_]; in_++;
99 if (i ==4) { 99 if (i ==4) {
100 for (i = 0; i <4; i++) 100 for (i = 0; i <4; i++)
103 char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); 103 char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
104 char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); 104 char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
105 char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; 105 char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
106 106
107 for (i = 0; (i < 3); i++) 107 for (i = 0; (i < 3); i++)
108 ret += char_array_3[i]; 108 result += char_array_3[i];
109 i = 0; 109 i = 0;
110 } 110 }
111 } 111 }
112 112
113 if (i) { 113 if (i) {
119 119
120 char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); 120 char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
121 char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); 121 char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
122 char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; 122 char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
123 123
124 for (j = 0; (j < i - 1); j++) ret += char_array_3[j]; 124 for (j = 0; (j < i - 1); j++)
125 result += char_array_3[j];
125 } 126 }
126
127 return ret;
128 } 127 }