Common base64_decode implementation.
GitOrigin-RevId: 87bdf798a181799b2f51be9831d77fabf41e3820
This commit is contained in:
parent
09d359cdc4
commit
1703cee349
@ -66,6 +66,14 @@ string base64_encode_impl(Slice input) {
|
|||||||
return base64;
|
return base64;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string base64_encode(Slice input) {
|
||||||
|
return base64_encode_impl<false>(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
string base64url_encode(Slice input) {
|
||||||
|
return base64_encode_impl<true>(input);
|
||||||
|
}
|
||||||
|
|
||||||
template <bool is_url>
|
template <bool is_url>
|
||||||
Result<Slice> base64_drop_padding(Slice base64) {
|
Result<Slice> base64_drop_padding(Slice base64) {
|
||||||
size_t padding_length = 0;
|
size_t padding_length = 0;
|
||||||
@ -85,9 +93,7 @@ Result<Slice> base64_drop_padding(Slice base64) {
|
|||||||
return base64;
|
return base64;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <bool is_url, class F>
|
static Status do_base64_decode_impl(Slice base64, const unsigned char *table, char *ptr) {
|
||||||
Status base64_do_decode(Slice base64, F &&append) {
|
|
||||||
auto table = get_character_table<is_url>();
|
|
||||||
for (size_t i = 0; i < base64.size();) {
|
for (size_t i = 0; i < base64.size();) {
|
||||||
size_t left = min(base64.size() - i, static_cast<size_t>(4));
|
size_t left = min(base64.size() - i, static_cast<size_t>(4));
|
||||||
int c = 0;
|
int c = 0;
|
||||||
@ -98,58 +104,57 @@ Status base64_do_decode(Slice base64, F &&append) {
|
|||||||
}
|
}
|
||||||
c |= value << ((3 - t) * 6);
|
c |= value << ((3 - t) * 6);
|
||||||
}
|
}
|
||||||
append(static_cast<char>(static_cast<unsigned char>(c >> 16))); // implementation-defined
|
*ptr++ = static_cast<char>(static_cast<unsigned char>(c >> 16)); // implementation-defined
|
||||||
if (left == 2) {
|
if (left == 2) {
|
||||||
if ((c & ((1 << 16) - 1)) != 0) {
|
if ((c & ((1 << 16) - 1)) != 0) {
|
||||||
return Status::Error("Wrong padding in the string");
|
return Status::Error("Wrong padding in the string");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
append(static_cast<char>(static_cast<unsigned char>(c >> 8))); // implementation-defined
|
*ptr++ = static_cast<char>(static_cast<unsigned char>(c >> 8)); // implementation-defined
|
||||||
if (left == 3) {
|
if (left == 3) {
|
||||||
if ((c & ((1 << 8) - 1)) != 0) {
|
if ((c & ((1 << 8) - 1)) != 0) {
|
||||||
return Status::Error("Wrong padding in the string");
|
return Status::Error("Wrong padding in the string");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
append(static_cast<char>(static_cast<unsigned char>(c))); // implementation-defined
|
*ptr++ = static_cast<char>(static_cast<unsigned char>(c)); // implementation-defined
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Status::OK();
|
return Status::OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<string> base64_decode(Slice base64) {
|
template <class T>
|
||||||
TRY_RESULT_ASSIGN(base64, base64_drop_padding<false>(base64));
|
static T create_empty(size_t size);
|
||||||
|
|
||||||
string output;
|
template <>
|
||||||
output.reserve((base64.size() >> 2) * 3 + (((base64.size() & 3) + 1) >> 1));
|
string create_empty<string>(size_t size) {
|
||||||
TRY_STATUS(base64_do_decode<false>(base64, [&output](char c) { output += c; }));
|
return string(size, '\0');
|
||||||
return output;
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
SecureString create_empty<SecureString>(size_t size) {
|
||||||
|
return SecureString{size};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <bool is_url, class T>
|
||||||
|
static Result<T> base64_decode_impl(Slice base64) {
|
||||||
|
TRY_RESULT_ASSIGN(base64, base64_drop_padding<is_url>(base64));
|
||||||
|
|
||||||
|
T result = create_empty<T>(base64.size() / 4 * 3 + ((base64.size() & 3) + 1) / 2);
|
||||||
|
TRY_STATUS(do_base64_decode_impl(base64, get_character_table<is_url>(), as_mutable_slice(result).begin()));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<string> base64_decode(Slice base64) {
|
||||||
|
return base64_decode_impl<false, string>(base64);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<SecureString> base64_decode_secure(Slice base64) {
|
Result<SecureString> base64_decode_secure(Slice base64) {
|
||||||
TRY_RESULT_ASSIGN(base64, base64_drop_padding<false>(base64));
|
return base64_decode_impl<false, SecureString>(base64);
|
||||||
|
|
||||||
SecureString output((base64.size() >> 2) * 3 + (((base64.size() & 3) + 1) >> 1));
|
|
||||||
char *ptr = output.as_mutable_slice().begin();
|
|
||||||
TRY_STATUS(base64_do_decode<false>(base64, [&ptr](char c) { *ptr++ = c; }));
|
|
||||||
return std::move(output);
|
|
||||||
}
|
|
||||||
|
|
||||||
string base64_encode(Slice input) {
|
|
||||||
return base64_encode_impl<false>(input);
|
|
||||||
}
|
|
||||||
|
|
||||||
string base64url_encode(Slice input) {
|
|
||||||
return base64_encode_impl<true>(input);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<string> base64url_decode(Slice base64) {
|
Result<string> base64url_decode(Slice base64) {
|
||||||
TRY_RESULT_ASSIGN(base64, base64_drop_padding<true>(base64));
|
return base64_decode_impl<true, string>(base64);
|
||||||
|
|
||||||
string output;
|
|
||||||
output.reserve((base64.size() >> 2) * 3 + (((base64.size() & 3) + 1) >> 1));
|
|
||||||
TRY_STATUS(base64_do_decode<true>(base64, [&output](char c) { output += c; }));
|
|
||||||
return output;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <bool is_url>
|
template <bool is_url>
|
||||||
|
@ -32,6 +32,7 @@ template <>
|
|||||||
BufferSlice create_empty<BufferSlice>(size_t size) {
|
BufferSlice create_empty<BufferSlice>(size_t size) {
|
||||||
return BufferSlice{size};
|
return BufferSlice{size};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
SecureString create_empty<SecureString>(size_t size) {
|
SecureString create_empty<SecureString>(size_t size) {
|
||||||
return SecureString{size};
|
return SecureString{size};
|
||||||
|
Reference in New Issue
Block a user