Common base64_encode implementation.
GitOrigin-RevId: ed4f31cfc6f83e81f03bd8e71dc8d48ced530255
This commit is contained in:
parent
9ea68914cf
commit
529f925d40
@ -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) {
|
||||||
|
@ -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>
|
||||||
|
Loading…
Reference in New Issue
Block a user