Common base64_encode implementation.

GitOrigin-RevId: ed4f31cfc6f83e81f03bd8e71dc8d48ced530255
This commit is contained in:
levlam 2020-01-09 21:05:43 +03:00
parent 9ea68914cf
commit 529f925d40
2 changed files with 23 additions and 31 deletions

View File

@ -16,14 +16,17 @@
namespace td {
//TODO: fix copypaste
static const char *const symbols64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static const char *const url_symbols64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
template <bool is_url>
static const char *get_characters() {
return is_url ? "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
}
template <bool is_url>
static const unsigned char *get_character_table() {
static unsigned char char_to_value[256];
static bool is_inited = [] {
auto characters = is_url ? url_symbols64 : symbols64;
auto characters = get_characters<is_url>();
std::fill(std::begin(char_to_value), std::end(char_to_value), static_cast<unsigned char>(64));
for (unsigned char i = 0; i < 64; i++) {
char_to_value[static_cast<size_t>(characters[i])] = i;
@ -34,34 +37,40 @@ static const unsigned char *get_character_table() {
return char_to_value;
}
string base64_encode(Slice input) {
template <bool is_url>
string base64_encode_impl(Slice input) {
auto characters = get_characters<is_url>();
string base64;
base64.reserve((input.size() + 2) / 3 * 4);
for (size_t i = 0; i < input.size();) {
size_t left = min(input.size() - i, static_cast<size_t>(3));
int c = input.ubegin()[i++] << 16;
base64 += symbols64[c >> 18];
base64 += characters[c >> 18];
if (left != 1) {
c |= input.ubegin()[i++] << 8;
}
base64 += symbols64[(c >> 12) & 63];
base64 += characters[(c >> 12) & 63];
if (left == 3) {
c |= input.ubegin()[i++];
}
if (left != 1) {
base64 += symbols64[(c >> 6) & 63];
} else {
base64 += characters[(c >> 6) & 63];
} else if (!is_url) {
base64 += '=';
}
if (left == 3) {
base64 += symbols64[c & 63];
} else {
base64 += characters[c & 63];
} else if (!is_url) {
base64 += '=';
}
}
return base64;
}
string base64_encode(Slice input) {
return base64_encode_impl<false>(input);
}
Result<Slice> base64_drop_padding(Slice base64) {
if ((base64.size() & 3) != 0) {
return Status::Error("Wrong string length");
@ -133,27 +142,7 @@ Result<SecureString> base64_decode_secure(Slice base64) {
}
string base64url_encode(Slice input) {
string base64;
base64.reserve((input.size() + 2) / 3 * 4);
for (size_t i = 0; i < input.size();) {
size_t left = min(input.size() - i, static_cast<size_t>(3));
int c = input.ubegin()[i++] << 16;
base64 += url_symbols64[c >> 18];
if (left != 1) {
c |= input.ubegin()[i++] << 8;
}
base64 += url_symbols64[(c >> 12) & 63];
if (left == 3) {
c |= input.ubegin()[i++];
}
if (left != 1) {
base64 += url_symbols64[(c >> 6) & 63];
}
if (left == 3) {
base64 += url_symbols64[c & 63];
}
}
return base64;
return base64_encode_impl<true>(input);
}
Result<string> base64url_decode(Slice base64) {

View File

@ -231,6 +231,9 @@ TEST(Misc, base64) {
ASSERT_TRUE(base64_encode(" /'.;.';≤.];,].',[.;/,.;/]/..;!@#!*(%?::;!%\";") ==
"ICAgICAgLycuOy4nO+KJpC5dOyxdLicsWy47LywuOy9dLy4uOyFAIyEqKCU/"
"Ojo7ISUiOw==");
ASSERT_TRUE(base64url_encode("ab><") == "YWI-PA");
ASSERT_TRUE(base64url_encode("ab><c") == "YWI-PGM");
ASSERT_TRUE(base64url_encode("ab><cd") == "YWI-PGNk");
}
template <class T>