Base 64 encoding and decoding
vector<char> Bin2Base64(vector<uint8_t> const& _bin) {
????static char const convert_table[] = "ABCDEFGHIGKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
????vector<char> output;
????output.reserve((_bin.size() * 4) / 3);
????auto con_3bytes_to_4bytes = [&](uint8_t const * _3bytes_bin_data) {
????????output.push_back(convert_table[_3bytes_bin_data[0] >> 2]);
????????output.push_back(convert_table[((_3bytes_bin_data[0] & 0x03) << 4) | ((_3bytes_bin_data[1] >> 4) & 0x0f)]);
????????output.push_back(convert_table[((_3bytes_bin_data[1] << 2) & 0x3c) | (_3bytes_bin_data[2] >> 6)]);
????????output.push_back(convert_table[_3bytes_bin_data[2] & 0x3f]);
????};
????auto i = 0u;
????for (; (i + 3) <= _bin.size(); i += 3) {
????????con_3bytes_to_4bytes(&_bin[i]);
????}
????if (i != _bin.size()) {
????????uint8_t left_data[3] = { 0 };
????????std::copy(begin(_bin) + i, end(_bin), left_data);
????????con_3bytes_to_4bytes(left_data);
????????std::fill(rbegin(output), rbegin(output) + (3 - (_bin.size() % 3)), '=');
????}????
????return output;
}
vector<uint8_t> Base64ToBin(vector<char> const & _base64stream) {
????vector<uint8_t> output;
????output.reserve(_base64stream.size() * 3 / 4);
????static hash_map<char, uint8_t> convert_table = {
????????????{ 'A', 0??}, { 'B', 1??}, { 'C', 2??}, { 'D', 3??}, { 'E', 4??}, { 'F', 5??}, { 'G', 6??}, { 'H', 7??},
????????????{ 'I', 8??}, { 'J', 9??}, { 'K', 10 }, { 'L', 11 }, { 'M', 12 }, { 'N', 13 }, { 'O', 14 }, { 'P', 15 },
????????????{ 'Q', 16 }, { 'R', 17 }, { 'S', 18 }, { 'T', 19 }, { 'U', 20 }, { 'V', 21 }, { 'W', 22 }, { 'X', 23 },
????????????{ 'Y', 24 }, { 'Z', 25 }, { 'a', 26 }, { 'b', 27 }, { 'c', 28 }, { 'd', 29 }, { 'e', 30 }, { 'f', 31 },
????????????{ 'g', 32 }, { 'h', 33 }, { 'i', 34 }, { 'j', 35 }, { 'k', 36 }, { 'l', 37 }, { 'm', 38 }, { 'n', 39 },
????????????{ 'o', 40 }, { 'p', 41 }, { 'q', 42 }, { 'r', 43 }, { 's', 44 }, { 't', 45 }, { 'u', 46 }, { 'v', 47 },
????????????{ 'w', 48 }, { 'x', 49 }, { 'y', 50 }, { 'z', 51 }, { '0', 52 }, { '1', 53 }, { '2', 54 }, { '3', 55 },
????????????{ '4', 56 }, { '5', 57 }, { '6', 58 }, { '7', 59 }, { '8', 60 }, { '9', 61 }, { '+', 62 }, { '/', 63 },
????????????{ '=', 0 },
????};
????auto i = 0u;
????for ( ; i < _base64stream.size(); i += 4) {
????????auto const byte1 = convert_table[_base64stream[i]];
????????auto const byte2 = convert_table[_base64stream[i + 1]];
????????auto const byte3 = convert_table[_base64stream[i + 2]];
????????auto const byte4 = convert_table[_base64stream[i + 3]];
????????output.push_back((byte1 << 2) | (byte2 >> 4));
????????output.push_back(((byte2 & 0x0f) << 4) | (byte3 >> 2));
????????output.push_back(((byte3 & 0x03) << 6) | byte4);
????}
????output.erase(end(output) - count(rbegin(_base64stream), rbegin(_base64stream) + 4, '='),
?????????????????end(output));
????return output;
}