libutil: initialize the base64 decode array only once

Previously, despite having a boolean that tracked initialization, the
decode characters have been "calculated" every single time a base64
string was being decoded.

With this change we only initialize the decode array once in a
thread-safe manner.
This commit is contained in:
Andreas Rammhold 2021-07-30 20:08:54 +02:00
parent 2b67cb7b8c
commit b9c9c25766
No known key found for this signature in database
GPG key ID: E432E410B5E48C86

View file

@ -6,14 +6,15 @@
#include <cctype> #include <cctype>
#include <cerrno> #include <cerrno>
#include <climits>
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
#include <climits> #include <future>
#include <iostream> #include <iostream>
#include <mutex>
#include <sstream> #include <sstream>
#include <thread> #include <thread>
#include <future>
#include <fcntl.h> #include <fcntl.h>
#include <grp.h> #include <grp.h>
@ -1447,7 +1448,7 @@ std::string filterANSIEscapes(const std::string & s, bool filterAll, unsigned in
static char base64Chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; static char base64Chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static std::array<char, 256> base64DecodeChars;
string base64Encode(std::string_view s) string base64Encode(std::string_view s)
{ {
@ -1472,15 +1473,12 @@ string base64Encode(std::string_view s)
string base64Decode(std::string_view s) string base64Decode(std::string_view s)
{ {
bool init = false; static std::once_flag flag;
char decode[256]; std::call_once(flag, [](){
if (!init) { base64DecodeChars = { (char)-1 };
// FIXME: not thread-safe.
memset(decode, -1, sizeof(decode));
for (int i = 0; i < 64; i++) for (int i = 0; i < 64; i++)
decode[(int) base64Chars[i]] = i; base64DecodeChars[(int) base64Chars[i]] = i;
init = true; });
}
string res; string res;
unsigned int d = 0, bits = 0; unsigned int d = 0, bits = 0;
@ -1489,7 +1487,7 @@ string base64Decode(std::string_view s)
if (c == '=') break; if (c == '=') break;
if (c == '\n') continue; if (c == '\n') continue;
char digit = decode[(unsigned char) c]; char digit = base64DecodeChars[(unsigned char) c];
if (digit == -1) if (digit == -1)
throw Error("invalid character in Base64 string: '%c'", c); throw Error("invalid character in Base64 string: '%c'", c);