@@ -30,28 +30,40 @@ namespace {
3030// When `pad` is true, the output is padded with '=' to a multiple of 4 characters.
3131std::string Base64EncodeWithAlphabet (std::string_view input, std::string_view alphabet,
3232 bool pad) {
33- std::string output;
34- output.reserve ((input.size () + 2 ) / 3 * 4 );
33+ const size_t full_blocks = input.size () / 3 ;
34+ const size_t remainder = input.size () % 3 ;
35+ const size_t output_size =
36+ full_blocks * 4 + (remainder == 0 ? 0 : (pad ? 4 : remainder + 1 ));
37+ std::string output (output_size, ' \0 ' );
38+
39+ const auto * bytes = reinterpret_cast <const uint8_t *>(input.data ());
40+ size_t out = 0 ;
41+ for (size_t i = 0 ; i < full_blocks * 3 ; i += 3 ) {
42+ const uint32_t block = (static_cast <uint32_t >(bytes[i]) << 16 ) |
43+ (static_cast <uint32_t >(bytes[i + 1 ]) << 8 ) |
44+ static_cast <uint32_t >(bytes[i + 2 ]);
45+ output[out++] = alphabet[(block >> 18 ) & 0x3F ];
46+ output[out++] = alphabet[(block >> 12 ) & 0x3F ];
47+ output[out++] = alphabet[(block >> 6 ) & 0x3F ];
48+ output[out++] = alphabet[block & 0x3F ];
49+ }
3550
36- uint32_t buffer = 0 ;
37- int bits_collected = 0 ;
38- for (unsigned char byte : input) {
39- buffer = (buffer << 8 ) | byte;
40- bits_collected += 8 ;
41- while (bits_collected >= 6 ) {
42- bits_collected -= 6 ;
43- output.push_back (alphabet[(buffer >> bits_collected) & 0x3F ]);
51+ if (remainder > 0 ) {
52+ const size_t i = full_blocks * 3 ;
53+ uint32_t block = static_cast <uint32_t >(bytes[i]) << 16 ;
54+ if (remainder == 2 ) {
55+ block |= static_cast <uint32_t >(bytes[i + 1 ]) << 8 ;
4456 }
45- }
46- if (bits_collected > 0 ) {
47- // Pad the remaining bits on the right to form the final 6-bit group.
48- output.push_back (alphabet[(buffer << (6 - bits_collected)) & 0x3F ]);
49- }
50- if (pad) {
51- while (output.size () % 4 != 0 ) {
52- output.push_back (' =' );
57+ output[out++] = alphabet[(block >> 18 ) & 0x3F ];
58+ output[out++] = alphabet[(block >> 12 ) & 0x3F ];
59+ if (remainder == 2 ) {
60+ output[out++] = alphabet[(block >> 6 ) & 0x3F ];
61+ }
62+ while (out < output_size) {
63+ output[out++] = ' =' ;
5364 }
5465 }
66+
5567 return output;
5668}
5769
0 commit comments