Practical Tools for Simple Design
Loading...
Searching...
No Matches
Base64.hpp
1#ifndef UTIL_BASE64_HPP
2#define UTIL_BASE64_HPP
3
4/*
5 * The code to decode the base64 in compilation time is powered by
6 * https://stackoverflow.com/a/59604914 It's used to decode the base64 string in
7 * compilation time and improve the efficiency. Actually it's dirty, but we just
8 * treat as a utility and won't maintain it, so just make sure it can work.
9 */
10#include <string_view>
11
12static constexpr size_t DecodeBase64Length(const char *s) {
13 size_t len = std::char_traits<char>::length(s);
14 if (s[len - 2] == '=')
15 return (len / 4) * 3 - 2;
16 else if (s[len - 1] == '=')
17 return (len / 4) * 3 - 1;
18 else
19 return (len / 4) * 3;
20}
21
22static constexpr std::array<int, 256> PrepareBase64DecodeTable() {
23 std::array<int, 256> T{0};
24 // breaks constexpr: T.fill(-1) or missing initialization
25 for (int i = 0; i < 256; i++)
26 T[i] = -1;
27 for (int i = 0; i < 64; i++)
28 T["ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
29 [i]] = i;
30 return T;
31}
32
33template <int N>
34static constexpr std::array<std::byte, N>
35DecodeBase64(std::string_view b64Str) {
36 constexpr auto T = PrepareBase64DecodeTable();
37 std::array<std::byte, N> out = {std::byte(0)};
38 int valb = -8;
39 for (size_t i = 0, val = 0, posOut = 0;
40 i < b64Str.length() && T[b64Str[i]] != -1; i++) {
41 val = (val << 6) + T[b64Str[i]];
42 valb += 6;
43 if (valb >= 0) {
44 out[posOut] = std::byte((val >> valb) & 0xFF);
45 posOut += 1;
46 valb -= 8;
47 }
48 }
49 return out;
50}
51
52#endif