34 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
35 "abcdefghijklmnopqrstuvwxyz"
40 return (isalnum(c) || (c ==
'+') || (c ==
'/'));
45 return base64_encode((
const unsigned char*)string_to_encode.c_str(), (
unsigned int)string_to_encode.length());
50 std::string str = encoded_string;
54std::string
base64_encode(
unsigned char const* bytes_to_encode,
unsigned int in_len) {
58 unsigned char char_array_3[3];
59 unsigned char char_array_4[4];
62 char_array_3[i++] = *(bytes_to_encode++);
64 char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
65 char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
66 char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
67 char_array_4[3] = char_array_3[2] & 0x3f;
69 for(i = 0; (i <4) ; i++)
77 for(j = i; j < 3; j++)
78 char_array_3[j] =
'\0';
80 char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
81 char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
82 char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
83 char_array_4[3] = char_array_3[2] & 0x3f;
85 for (j = 0; (j < i + 1); j++)
98 int in_len = (int)encoded_string.size();
102 unsigned char char_array_4[4], char_array_3[3];
105 while (in_len-- && ( encoded_string[in_] !=
'=') &&
is_base64(encoded_string[in_])) {
106 char_array_4[i++] = encoded_string[in_]; in_++;
108 for (i = 0; i <4; i++)
109 char_array_4[i] = (
unsigned char)
base64_chars.find(char_array_4[i]);
111 char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
112 char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
113 char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
115 for (i = 0; (i < 3); i++)
116 ret += char_array_3[i];
122 for (j = i; j <4; j++)
125 for (j = 0; j <4; j++)
126 char_array_4[j] = (
unsigned char)
base64_chars.find(char_array_4[j]);
128 char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
129 char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
130 char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
132 for (j = 0; (j < i - 1); j++) ret += char_array_3[j];
153 struct Vec {
const char* in;
const char* out; };
154 static const Vec vectors[] = {
159 {
"foob",
"Zm9vYg==" },
160 {
"fooba",
"Zm9vYmE=" },
161 {
"foobar",
"Zm9vYmFy" },
163 const int nvec = (int)(
sizeof(vectors) /
sizeof(vectors[0]));
164 for (
int v = 0; v < nvec; v++) {
165 std::string in = vectors[v].in;
167 if (enc != vectors[v].out) {
168 unittest::fail(
"Base64 test: encode(\"%s\") = \"%s\", expected \"%s\"",
169 vectors[v].in, enc.c_str(), vectors[v].out);
177 unittest::fail(
"Base64 test: decode(\"%s\") = \"%s\", expected \"%s\"",
178 vectors[v].out, dec.c_str(), vectors[v].in);
191 uint32 seed = 0x1234abcdU;
192 for (
int trial = 0; trial < 200; trial++) {
193 uint32 len = (seed % 256u);
194 seed = seed * 1664525u + 1013904223u;
197 for (uint32 b = 0; b < len; b++) {
198 blob.push_back((
char)(seed & 0xffu));
199 seed = seed * 1664525u + 1013904223u;
201 std::string enc =
::base64_encode((
const unsigned char*)blob.data(), (
unsigned int)blob.size());
204 unittest::fail(
"Base64 test: random round-trip mismatch at trial %d (len %u): got %u bytes back",
205 trial, (
unsigned int)blob.size(), (
unsigned int)dec.size());
214 for (uint32 len = 0; len <= 32; len++) {
215 std::string blob(len,
'A');
216 std::string enc =
::base64_encode((
const unsigned char*)blob.data(), (
unsigned int)blob.size());
218 size_t expectedLen = len == 0 ? 0 : (((size_t)len + 2) / 3) * 4;
219 if (enc.size() != expectedLen) {
220 unittest::fail(
"Base64 test: encode length for %u bytes = %u, expected %u",
221 len, (
unsigned int)enc.size(), (
unsigned int)expectedLen);
226 unittest::fail(
"Base64 test: length-vector round-trip mismatch at len %u", len);
235 const uint32 payloadSize = 64u * 1024u;
236 std::string payload(payloadSize,
'\0');
237 uint32 seed = 0xdeadbeefU;
238 for (uint32 b = 0; b < payloadSize; b++) {
239 payload[b] = (char)(seed & 0xffu);
240 seed = seed * 1664525u + 1013904223u;
243 const int iterations = 64;
245 std::string enc, dec;
246 for (
int it = 0; it < iterations; it++) {
247 enc =
::base64_encode((
const unsigned char*)payload.data(), (
unsigned int)payload.size());
249 if (dec != payload) {
250 unittest::fail(
"Base64 test: throughput round-trip mismatch at iteration %d", it);
255 if (us < 1.0) us = 1.0;
256 double totalBytes = (double)payloadSize * iterations * 2.0;
257 double mbPerSec = (totalBytes / (1024.0 * 1024.0)) / (us / 1e6);
259 unittest::detail(
"processed %.1f MB in %.0f us", totalBytes / (1024.0 * 1024.0), us);
268 "Base64 encode/decode RFC 4648 vectors, binary round-trip, throughput",
"util");
std::string base64_decode(const char *encoded_string)
Decode Base64 text.
std::string base64_encode(std::string string_to_encode)
Base64-encode a string's bytes.
static bool is_base64(unsigned char c)
static const std::string base64_chars
Base64 encoding/decoding of arbitrary binary data (standard alphabet, '=' padding).
std::string base64_decode(const char *encoded_string)
Decode Base64 text.
std::string base64_encode(std::string string_to_encode)
Base64-encode a string's bytes.
CMSDK time: µs-resolution 64-bit timestamps and the Time Mapping Constant (TMC).
Small, dependency-free unit test harness used by all CMSDK object tests.
static UnitTestRunner & instance()
Access the singleton (created on first use).
void registerTest(const char *name, UnitTestFunc func, const char *description="", const char *category="", bool inDefaultRun=true)
Register a test with the runner.
uint64 GetTimeNow()
Return the current absolute time (µs since year 0) according to the TMC.
void fail(const char *fmt,...)
Set an explanatory reason shown on the FAIL line.
void metric(const char *name, double value, const char *unit="", bool higherIsBetter=true)
Record a performance metric.
void detail(const char *fmt,...)
Verbose-only indented diagnostic line (shown only when verbose=1).
void progress(int percent, const char *action)
Report progress with a short description of the current action.
void Register_Base64_Tests()
bool Base64_UnitTest()
Base64 round-trip unit test.