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;
}