diff options
author | Kae <80987908+Novaenia@users.noreply.github.com> | 2023-06-20 14:33:09 +1000 |
---|---|---|
committer | Kae <80987908+Novaenia@users.noreply.github.com> | 2023-06-20 14:33:09 +1000 |
commit | 6352e8e3196f78388b6c771073f9e03eaa612673 (patch) | |
tree | e23772f79a7fbc41bc9108951e9e136857484bf4 /source/core/StarEncode.cpp | |
parent | 6741a057e5639280d85d0f88ba26f000baa58f61 (diff) |
everything everywhere
all at once
Diffstat (limited to 'source/core/StarEncode.cpp')
-rw-r--r-- | source/core/StarEncode.cpp | 226 |
1 files changed, 226 insertions, 0 deletions
diff --git a/source/core/StarEncode.cpp b/source/core/StarEncode.cpp new file mode 100644 index 0000000..b3a8b79 --- /dev/null +++ b/source/core/StarEncode.cpp @@ -0,0 +1,226 @@ +#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()); + return move(res); +} + +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); + return move(res); +} + +String hexEncode(ByteArray const& data) { + return hexEncode(data.ptr(), data.size()); +} + +ByteArray hexDecode(String const& encodedData) { + ByteArray res(encodedData.size() / 2, 0); + size_t decoded = hexDecode(encodedData.utf8Ptr(), encodedData.size(), res.ptr(), res.size()); + _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); + size_t decoded = base64Decode(encodedData.utf8Ptr(), encodedData.size(), res.ptr(), res.size()); + _unused(decoded); + starAssert(decoded <= res.size()); + res.resize(decoded); + return res; +} + +} |