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

View File

@ -231,6 +231,9 @@ TEST(Misc, base64) {
ASSERT_TRUE(base64_encode(" /'.;.';≤.];,].',[.;/,.;/]/..;!@#!*(%?::;!%\";") == ASSERT_TRUE(base64_encode(" /'.;.';≤.];,].',[.;/,.;/]/..;!@#!*(%?::;!%\";") ==
"ICAgICAgLycuOy4nO+KJpC5dOyxdLicsWy47LywuOy9dLy4uOyFAIyEqKCU/" "ICAgICAgLycuOy4nO+KJpC5dOyxdLicsWy47LywuOy9dLy4uOyFAIyEqKCU/"
"Ojo7ISUiOw=="); "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> template <class T>