|
5 | 5 | More information at |
6 | 6 | https://renenyffenegger.ch/notes/development/Base64/Encoding-and-decoding-base-64-with-cpp |
7 | 7 |
|
8 | | - Version: 2.rc.02 (release candidate) |
| 8 | + Version: 2.rc.03 (release candidate) |
9 | 9 |
|
10 | 10 | Copyright (C) 2004-2017, 2020 René Nyffenegger |
11 | 11 |
|
|
33 | 33 |
|
34 | 34 | #include "base64.h" |
35 | 35 |
|
36 | | -static std::string base64_chars = |
| 36 | + // |
| 37 | + // Depending on the url parameter in base64_chars, one of |
| 38 | + // two sets of base64 characters needs to be chosen. |
| 39 | + // They differ in their last two characters. |
| 40 | + // |
| 41 | +const char* base64_chars[2] = { |
37 | 42 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ" |
38 | 43 | "abcdefghijklmnopqrstuvwxyz" |
39 | 44 | "0123456789" |
40 | | - "??"; // These two question marks will be replaced based on the value of url in base64_encode |
| 45 | + "+/", |
41 | 46 |
|
| 47 | + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" |
| 48 | + "abcdefghijklmnopqrstuvwxyz" |
| 49 | + "0123456789" |
| 50 | + "-_"}; |
42 | 51 |
|
43 | 52 | static std::size_t pos_of_char(const unsigned char chr) { |
44 | 53 | // |
45 | | - // Return the position of chr within base64_chars. |
| 54 | + // Return the position of chr within base64_encode() |
46 | 55 | // |
47 | 56 |
|
48 | 57 | if (chr >= 'A' && chr <= 'Z') return chr - 'A'; |
@@ -93,45 +102,45 @@ static std::string encode(String s, bool url) { |
93 | 102 | } |
94 | 103 |
|
95 | 104 | std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len, bool url) { |
96 | | - // |
97 | | - // Replace question marks in base64_chars: |
98 | | - // |
99 | | - if (url) { |
100 | | - base64_chars[62] = '-'; |
101 | | - base64_chars[63] = '_'; |
102 | | - } |
103 | | - else { |
104 | | - base64_chars[62] = '+'; |
105 | | - base64_chars[63] = '/'; |
106 | | - } |
107 | 105 |
|
108 | 106 | unsigned int len_encoded = (in_len +2) / 3 * 4; |
109 | 107 |
|
110 | 108 | unsigned char trailing_char = url ? '.' : '='; |
111 | 109 |
|
| 110 | + // |
| 111 | + // Choose set of base64 characters. They differ |
| 112 | + // for the last two positions, depending on the url |
| 113 | + // parameter. |
| 114 | + // A bool (as is the parameter url) is guaranteed |
| 115 | + // to evaluate to either 0 or 1 in C++ therfore, |
| 116 | + // the correct character set is chosen by subscripting |
| 117 | + // base64_chars with url. |
| 118 | + // |
| 119 | + const char* base64_chars_ = base64_chars[url]; |
| 120 | + |
112 | 121 | std::string ret; |
113 | 122 | ret.reserve(len_encoded); |
114 | 123 |
|
115 | 124 | unsigned int pos = 0; |
116 | 125 |
|
117 | 126 | while (pos < in_len) { |
118 | | - ret.push_back(base64_chars[(bytes_to_encode[pos + 0] & 0xfc) >> 2]); |
| 127 | + ret.push_back(base64_chars_[(bytes_to_encode[pos + 0] & 0xfc) >> 2]); |
119 | 128 |
|
120 | 129 | if (pos+1 < in_len) { |
121 | | - ret.push_back(base64_chars[((bytes_to_encode[pos + 0] & 0x03) << 4) + ((bytes_to_encode[pos + 1] & 0xf0) >> 4)]); |
| 130 | + ret.push_back(base64_chars_[((bytes_to_encode[pos + 0] & 0x03) << 4) + ((bytes_to_encode[pos + 1] & 0xf0) >> 4)]); |
122 | 131 |
|
123 | 132 | if (pos+2 < in_len) { |
124 | | - ret.push_back(base64_chars[((bytes_to_encode[pos + 1] & 0x0f) << 2) + ((bytes_to_encode[pos + 2] & 0xc0) >> 6)]); |
125 | | - ret.push_back(base64_chars[ bytes_to_encode[pos + 2] & 0x3f]); |
| 133 | + ret.push_back(base64_chars_[((bytes_to_encode[pos + 1] & 0x0f) << 2) + ((bytes_to_encode[pos + 2] & 0xc0) >> 6)]); |
| 134 | + ret.push_back(base64_chars_[ bytes_to_encode[pos + 2] & 0x3f]); |
126 | 135 | } |
127 | 136 | else { |
128 | | - ret.push_back(base64_chars[(bytes_to_encode[pos + 1] & 0x0f) << 2]); |
| 137 | + ret.push_back(base64_chars_[(bytes_to_encode[pos + 1] & 0x0f) << 2]); |
129 | 138 | ret.push_back(trailing_char); |
130 | 139 | } |
131 | 140 | } |
132 | 141 | else { |
133 | 142 |
|
134 | | - ret.push_back(base64_chars[(bytes_to_encode[pos + 0] & 0x03) << 4]); |
| 143 | + ret.push_back(base64_chars_[(bytes_to_encode[pos + 0] & 0x03) << 4]); |
135 | 144 | ret.push_back(trailing_char); |
136 | 145 | ret.push_back(trailing_char); |
137 | 146 | } |
|
0 commit comments