Browse Source

Add Base64 encoding/decoding to string.hpp.

tags/v1.1.4
Andrew Belt 4 years ago
parent
commit
ab0b0852df
2 changed files with 99 additions and 0 deletions
  1. +10
    -0
      include/string.hpp
  2. +89
    -0
      src/string.cpp

+ 10
- 0
include/string.hpp View File

@@ -57,6 +57,16 @@ A score of 0 means no match.
The score is arbitrary and is only meaningful for sorting.
*/
float fuzzyScore(const std::string& s, const std::string& query);
/** Converts a byte array to a Base64-encoded string.
https://en.wikipedia.org/wiki/Base64
*/
std::string toBase64(const uint8_t* data, size_t len);
/** Converts a Base64-encoded string to a byte array.
`outLen` is set to the length of the byte array.
If non-NULL, caller must delete[] the result.
*/
uint8_t* fromBase64(const std::string& str, size_t* outLen);


struct CaseInsensitiveCompare {
bool operator()(const std::string& a, const std::string& b) const {


+ 89
- 0
src/string.cpp View File

@@ -154,5 +154,94 @@ float fuzzyScore(const std::string& s, const std::string& query) {
}


std::string toBase64(const uint8_t* data, size_t len) {
static const char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

size_t numBlocks = size_t((len + 2) / 3);
size_t strLen = numBlocks * 4;
std::string str;
str.reserve(strLen);

for (size_t b = 0; b < numBlocks; b++) {
// Encode block
uint32_t block = 0;
int i;
for (i = 0; i < 3 && 3 * b + i < len; i++) {
block |= uint32_t(data[3 * b + i]) << (8 * (2 - i));
}

// Decode block
str += alphabet[(block >> 18) & 0x3f];
str += alphabet[(block >> 12) & 0x3f];
str += (i > 1) ? alphabet[(block >> 6) & 0x3f] : '=';
str += (i > 2) ? alphabet[(block >> 0) & 0x3f] : '=';
}
return str;
}


uint8_t* fromBase64(const std::string& str, size_t* outLen) {
size_t strLen = str.size();
if (strLen % 4 != 0)
return NULL;

size_t numBlocks = strLen / 4;
size_t len = numBlocks * 3;
if (strLen >= 4) {
if (str[strLen - 1] == '=')
len--;
if (str[strLen - 2] == '=')
len--;
}
if (outLen)
*outLen = len;

uint8_t* data = new uint8_t[len];

for (size_t b = 0; b < numBlocks; b++) {
// Encode block
uint32_t block = 0;
size_t i;
for (i = 0; i < 4; i++) {
uint8_t c = str[4 * b + i];
uint8_t d = 0;

if ('A' <= c && c <= 'Z') {
d = c - 'A';
}
else if ('a' <= c && c <= 'z') {
d = c - 'a' + 26;
}
else if ('0' <= c && c <= '9') {
d = c - '0' + 52;
}
else if (c == '+') {
d = 62;
}
else if (c == '/') {
d = 63;
}
else if (c == '=') {
// Padding ends block encoding
break;
}
else {
// Ignore invalid characters, such as whitespace.
continue;
}

block |= uint32_t(d) << (6 * (3 - i));
}

// Decode block
for (size_t k = 0; k < i - 1; k++) {
data[3 * b + k] = (block >> (8 * (2 - k))) & 0xff;
}
}

return data;
}


} // namespace string
} // namespace rack

Loading…
Cancel
Save