2023-06-20 04:33:09 +00:00
|
|
|
#include "StarEncode.hpp"
|
|
|
|
|
|
|
|
namespace Star {
|
|
|
|
|
|
|
|
size_t hexEncode(char const* data, size_t len, char* output, size_t outLen) {
|
|
|
|
static char const hex[] = "0123456789abcdef";
|
|
|
|
|
|
|
|
len = std::min(len, outLen / 2);
|
|
|
|
for (size_t i = 0; i < len; ++i) {
|
|
|
|
output[i * 2] = hex[(data[i] & 0xf0) >> 4];
|
|
|
|
output[i * 2 + 1] = hex[(data[i] & 0x0f)];
|
|
|
|
}
|
|
|
|
|
|
|
|
return len * 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t hexDecode(char const* src, size_t len, char* output, size_t outLen) {
|
|
|
|
for (size_t i = 0; i < len / 2; ++i) {
|
|
|
|
if (i >= outLen)
|
|
|
|
return i;
|
|
|
|
|
|
|
|
uint8_t b1 = 0;
|
|
|
|
char c1 = src[i * 2];
|
|
|
|
if (c1 >= '0' && c1 <= '9')
|
|
|
|
b1 = c1 - '0';
|
|
|
|
else if (c1 >= 'A' && c1 <= 'F')
|
|
|
|
b1 = c1 - 'A' + 10;
|
|
|
|
else if (c1 >= 'a' && c1 <= 'f')
|
|
|
|
b1 = c1 - 'a' + 10;
|
|
|
|
|
|
|
|
uint8_t b2 = 0;
|
|
|
|
char c2 = src[i * 2 + 1];
|
|
|
|
if (c2 >= '0' && c2 <= '9')
|
|
|
|
b2 = c2 - '0';
|
|
|
|
else if (c2 >= 'A' && c2 <= 'F')
|
|
|
|
b2 = c2 - 'A' + 10;
|
|
|
|
else if (c2 >= 'a' && c2 <= 'f')
|
|
|
|
b2 = c2 - 'a' + 10;
|
|
|
|
|
|
|
|
*output++ = (b1 << 4) | b2;
|
|
|
|
}
|
|
|
|
|
|
|
|
return len / 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t nibbleDecode(char const* src, size_t len, char* output, size_t outLen) {
|
|
|
|
for (size_t i = 0; i < len; ++i) {
|
|
|
|
if (i >= outLen)
|
|
|
|
return i;
|
|
|
|
|
|
|
|
uint8_t b = 0;
|
|
|
|
char c = src[i];
|
|
|
|
if (c >= '0' && c <= '9')
|
|
|
|
b = c - '0';
|
|
|
|
else if (c >= 'A' && c <= 'F')
|
|
|
|
b = c - 'A' + 10;
|
|
|
|
else if (c >= 'a' && c <= 'f')
|
|
|
|
b = c - 'a' + 10;
|
|
|
|
|
|
|
|
*output++ = b;
|
|
|
|
}
|
|
|
|
|
|
|
|
return len;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const std::string base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
|
|
|
|
|
|
size_t base64Encode(char const* data, size_t len, char* output, size_t outLen) {
|
|
|
|
if (outLen == 0)
|
|
|
|
return 0;
|
|
|
|
size_t written = 0;
|
|
|
|
|
|
|
|
unsigned char ca3[3] = {0, 0, 0};
|
|
|
|
unsigned char ca4[4] = {0, 0, 0, 0};
|
|
|
|
const unsigned char* inPtr = (const unsigned char*)data;
|
|
|
|
int i = 0, j = 0, in_len = len;
|
|
|
|
|
|
|
|
while (in_len--) {
|
|
|
|
ca3[i++] = *(inPtr++);
|
|
|
|
if (i == 3) {
|
|
|
|
ca4[0] = (ca3[0] & 0xfc) >> 2;
|
|
|
|
ca4[1] = ((ca3[0] & 0x03) << 4) + ((ca3[1] & 0xf0) >> 4);
|
|
|
|
ca4[2] = ((ca3[1] & 0x0f) << 2) + ((ca3[2] & 0xc0) >> 6);
|
|
|
|
ca4[3] = ca3[2] & 0x3f;
|
|
|
|
for (i = 0; (i < 4); i++) {
|
|
|
|
--outLen;
|
|
|
|
*output = base64_chars[ca4[i]];
|
|
|
|
++output;
|
|
|
|
++written;
|
|
|
|
|
|
|
|
if (outLen == 0)
|
|
|
|
return written;
|
|
|
|
}
|
|
|
|
i = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (i) {
|
|
|
|
for (j = i; j < 3; j++)
|
|
|
|
ca3[j] = '\0';
|
|
|
|
ca4[0] = (ca3[0] & 0xfc) >> 2;
|
|
|
|
ca4[1] = ((ca3[0] & 0x03) << 4) + ((ca3[1] & 0xf0) >> 4);
|
|
|
|
ca4[2] = ((ca3[1] & 0x0f) << 2) + ((ca3[2] & 0xc0) >> 6);
|
|
|
|
ca4[3] = ca3[2] & 0x3f;
|
|
|
|
for (j = 0; (j < i + 1); j++) {
|
|
|
|
--outLen;
|
|
|
|
*output = base64_chars[ca4[j]];
|
|
|
|
++output;
|
|
|
|
++written;
|
|
|
|
|
|
|
|
if (outLen == 0)
|
|
|
|
return written;
|
|
|
|
}
|
|
|
|
while ((i++ < 3)) {
|
|
|
|
--outLen;
|
|
|
|
*output = '=';
|
|
|
|
++output;
|
|
|
|
++written;
|
|
|
|
|
|
|
|
if (outLen == 0)
|
|
|
|
return written;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return written;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool is_base64(unsigned char c) {
|
|
|
|
return (isalnum(c) || (c == '+') || (c == '/'));
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t base64Decode(char const* src, size_t len, char* output, size_t outLen) {
|
|
|
|
if (outLen == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
size_t written = 0;
|
|
|
|
|
|
|
|
int i = 0, j = 0, in_ = 0, in_len = len;
|
|
|
|
unsigned char ca4[4], ca3[3];
|
|
|
|
|
|
|
|
while (in_len-- && (src[in_] != '=') && is_base64(src[in_])) {
|
|
|
|
ca4[i++] = src[in_++];
|
|
|
|
if (i == 4) {
|
|
|
|
for (i = 0; i < 4; i++)
|
|
|
|
ca4[i] = base64_chars.find(ca4[i]);
|
|
|
|
ca3[0] = (ca4[0] << 2) + ((ca4[1] & 0x30) >> 4);
|
|
|
|
ca3[1] = ((ca4[1] & 0xf) << 4) + ((ca4[2] & 0x3c) >> 2);
|
|
|
|
ca3[2] = ((ca4[2] & 0x3) << 6) + ca4[3];
|
|
|
|
for (i = 0; (i < 3); i++) {
|
|
|
|
--outLen;
|
|
|
|
*output = ca3[i];
|
|
|
|
++output;
|
|
|
|
++written;
|
|
|
|
|
|
|
|
if (outLen == 0)
|
|
|
|
return written;
|
|
|
|
}
|
|
|
|
i = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (i) {
|
|
|
|
for (j = i; j < 4; j++)
|
|
|
|
ca4[j] = 0;
|
|
|
|
for (j = 0; j < 4; j++)
|
|
|
|
ca4[j] = base64_chars.find(ca4[j]);
|
|
|
|
ca3[0] = (ca4[0] << 2) + ((ca4[1] & 0x30) >> 4);
|
|
|
|
ca3[1] = ((ca4[1] & 0xf) << 4) + ((ca4[2] & 0x3c) >> 2);
|
|
|
|
ca3[2] = ((ca4[2] & 0x3) << 6) + ca4[3];
|
|
|
|
for (j = 0; (j < i - 1); j++) {
|
|
|
|
--outLen;
|
|
|
|
*output = ca3[j];
|
|
|
|
++output;
|
|
|
|
++written;
|
|
|
|
|
|
|
|
if (outLen == 0)
|
|
|
|
return written;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return written;
|
|
|
|
}
|
|
|
|
|
|
|
|
String hexEncode(char const* data, size_t len) {
|
|
|
|
std::string res(len * 2, '\0');
|
|
|
|
size_t encoded = hexEncode(data, len, &res[0], res.size());
|
|
|
|
_unused(encoded);
|
|
|
|
starAssert(encoded == res.size());
|
2023-06-26 18:48:27 +00:00
|
|
|
return res;
|
2023-06-20 04:33:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
String base64Encode(char const* data, size_t len) {
|
|
|
|
std::string res(len * 4 / 3 + 3, '\0');
|
|
|
|
size_t encoded = base64Encode(data, len, &res[0], res.size());
|
|
|
|
_unused(encoded);
|
|
|
|
starAssert(encoded <= res.size());
|
|
|
|
res.resize(encoded);
|
2023-06-26 18:48:27 +00:00
|
|
|
return res;
|
2023-06-20 04:33:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
String hexEncode(ByteArray const& data) {
|
|
|
|
return hexEncode(data.ptr(), data.size());
|
|
|
|
}
|
|
|
|
|
|
|
|
ByteArray hexDecode(String const& encodedData) {
|
|
|
|
ByteArray res(encodedData.size() / 2, 0);
|
2024-03-09 00:09:04 +00:00
|
|
|
size_t decoded = hexDecode(encodedData.utf8Ptr(), encodedData.utf8Size(), res.ptr(), res.size());
|
2023-06-20 04:33:09 +00:00
|
|
|
_unused(decoded);
|
|
|
|
starAssert(decoded == res.size());
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
String base64Encode(ByteArray const& data) {
|
|
|
|
return base64Encode(data.ptr(), data.size());
|
|
|
|
}
|
|
|
|
|
|
|
|
ByteArray base64Decode(String const& encodedData) {
|
|
|
|
ByteArray res(encodedData.size() * 3 / 4, 0);
|
2024-03-09 00:09:04 +00:00
|
|
|
size_t decoded = base64Decode(encodedData.utf8Ptr(), encodedData.utf8Size(), res.ptr(), res.size());
|
2023-06-20 04:33:09 +00:00
|
|
|
_unused(decoded);
|
|
|
|
starAssert(decoded <= res.size());
|
|
|
|
res.resize(decoded);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|