TEC
A lightweight C++ library enabling safe, efficient execution in multithreaded and concurrent systems.
Loading...
Searching...
No Matches
tec_base64.hpp
Go to the documentation of this file.
1// Time-stamp: <Last changed 2026-02-20 15:52:46 by magnolia>
2/*----------------------------------------------------------------------
3------------------------------------------------------------------------
4Copyright (c) 2020-2026 The Emacs Cat (https://github.com/olddeuteronomy/tec).
5
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
9
10 http://www.apache.org/licenses/LICENSE-2.0
11
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
17------------------------------------------------------------------------
18----------------------------------------------------------------------*/
19
27#pragma once
28
29#include <string>
30#include <string_view>
31#include <vector>
32#include <array>
33#include <cstdint>
34
35
36namespace tec {
37
38namespace base64 {
39
40inline constexpr std::string_view chars =
41 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
42
46static constexpr std::array<int, 256> build_decode_table() {
47 std::array<int, 256> table{};
48 for (size_t i = 0; i < 256; ++i) {
49 table[i] = -1;
50 }
51 for (size_t i = 0; i < chars.size(); ++i) {
52 table[static_cast<uint8_t>(chars[i])] = static_cast<int>(i);
53 }
54 return table;
55}
56
57static constexpr auto decode_table = build_decode_table();
58
59
63inline bool is_valid(std::string_view data) {
64 if (data.empty() || data.size() % 4 != 0) return false;
65
66 size_t size = data.size();
67 size_t padding = 0;
68
69 for (size_t i = 0; i < size; ++i) {
70 unsigned char c = static_cast<uint8_t>(data[i]);
71
72 if (c == '=') {
73 padding++;
74 // Check if '=' is at the end and total padding <= 2
75 if (i < size - 2 || (i == size - 2 && data[size - 1] != '='))
76 return false;
77 if (padding > 2)
78 return false;
79 continue;
80 }
81
82 // No characters allowed after padding started
83 if (padding > 0)
84 return false;
85
86 // Check against lookup table
87 if (decode_table[c] == -1)
88 return false;
89 }
90 return true;
91}
92
93
97inline std::string encode(std::string_view data) {
98 std::string out;
99 int val = 0;
100 int valb = -6;
101 out.reserve(((data.size() + 2) / 3) * 4);
102 for (unsigned char c : data) {
103 val = (val << 8) + c;
104 valb += 8;
105 while (valb >= 0) {
106 out.push_back(chars[(val >> valb) & 0x3F]);
107 valb -= 6;
108 }
109 }
110 if (valb > -6)
111 out.push_back(chars[((val << 8) >> (valb + 8)) & 0x3F]);
112 while (out.size() % 4)
113 out.push_back('=');
114 return out;
115}
116
117
121inline std::vector<uint8_t> decode(std::string_view data) {
122 std::vector<uint8_t> out;
123 out.reserve((data.size() / 4) * 3);
124 int val = 0;
125 int valb = -8;
126 for (char c : data) {
127 if (c == '=')
128 break;
129 int v = decode_table[static_cast<uint8_t>(c)];
130 if (v == -1)
131 continue; // Skip newlines.
132 val = (val << 6) + v;
133 valb += 6;
134 if (valb >= 0) {
135 out.push_back(static_cast<uint8_t>((val >> valb) & 0xFF));
136 valb -= 8;
137 }
138 }
139 return out;
140}
141
142} // namespace base64
143
144} // namespace tec
std::vector< uint8_t > decode(std::string_view data)
Definition tec_base64.hpp:121
std::string encode(std::string_view data)
Definition tec_base64.hpp:97
bool is_valid(std::string_view data)
Definition tec_base64.hpp:63