AK: Make static constexpr variables to avoid stack copy in Base64

Alphabet and lookup table are created and copied to the stack on each
call. Create them and store them in static memory.
This commit is contained in:
Lenny Maiorani 2022-03-13 20:59:29 -06:00 committed by Linus Groh
parent d00b79568f
commit 8d1d4d4f09
Notes: sideshowbarker 2024-07-17 17:18:13 +09:00

View file

@ -13,24 +13,19 @@
namespace AK { namespace AK {
static constexpr auto make_alphabet() static constexpr Array alphabet = {
{ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
Array alphabet = { 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'w', 'x', 'y', 'z', '0', '1', '2', '3',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v', '4', '5', '6', '7', '8', '9', '+', '/'
'w', 'x', 'y', 'z', '0', '1', '2', '3', };
'4', '5', '6', '7', '8', '9', '+', '/'
};
return alphabet;
}
static constexpr auto make_lookup_table() static consteval auto make_lookup_table()
{ {
constexpr auto alphabet = make_alphabet();
Array<i16, 256> table; Array<i16, 256> table;
table.fill(-1); table.fill(-1);
for (size_t i = 0; i < alphabet.size(); ++i) { for (size_t i = 0; i < alphabet.size(); ++i) {
@ -39,6 +34,8 @@ static constexpr auto make_lookup_table()
return table; return table;
} }
static constexpr auto alphabet_lookup_table = make_lookup_table();
size_t calculate_base64_decoded_length(StringView input) size_t calculate_base64_decoded_length(StringView input)
{ {
return input.length() * 3 / 4; return input.length() * 3 / 4;
@ -52,7 +49,6 @@ size_t calculate_base64_encoded_length(ReadonlyBytes input)
ErrorOr<ByteBuffer> decode_base64(StringView input) ErrorOr<ByteBuffer> decode_base64(StringView input)
{ {
auto get = [&](size_t& offset, bool* is_padding, bool& parsed_something) -> ErrorOr<u8> { auto get = [&](size_t& offset, bool* is_padding, bool& parsed_something) -> ErrorOr<u8> {
constexpr auto table = make_lookup_table();
while (offset < input.length() && is_ascii_space(input[offset])) while (offset < input.length() && is_ascii_space(input[offset]))
++offset; ++offset;
if (offset >= input.length()) if (offset >= input.length())
@ -65,7 +61,7 @@ ErrorOr<ByteBuffer> decode_base64(StringView input)
*is_padding = true; *is_padding = true;
return 0; return 0;
} }
i16 result = table[ch]; i16 result = alphabet_lookup_table[ch];
if (result < 0) if (result < 0)
return Error::from_string_literal("Invalid character in base64 data"); return Error::from_string_literal("Invalid character in base64 data");
VERIFY(result < 256); VERIFY(result < 256);
@ -106,7 +102,6 @@ ErrorOr<ByteBuffer> decode_base64(StringView input)
String encode_base64(ReadonlyBytes input) String encode_base64(ReadonlyBytes input)
{ {
constexpr auto alphabet = make_alphabet();
StringBuilder output(calculate_base64_encoded_length(input)); StringBuilder output(calculate_base64_encoded_length(input));
auto get = [&](const size_t offset, bool* need_padding = nullptr) -> u8 { auto get = [&](const size_t offset, bool* need_padding = nullptr) -> u8 {