mirror of
https://github.com/Karaka-Management/cOMS.git
synced 2026-01-10 19:08:39 +00:00
109 lines
3.2 KiB
C
109 lines
3.2 KiB
C
/**
|
|
* Jingga
|
|
*
|
|
* @copyright Jingga
|
|
* @license OMS License 2.0
|
|
* @version 1.0.0
|
|
* @link https://jingga.app
|
|
*/
|
|
#ifndef COMS_ENCODING_BASE64_H
|
|
#define COMS_ENCODING_BASE64_H
|
|
|
|
#include "../stdlib/Types.h"
|
|
#include "../utils/StringUtils.h"
|
|
#include "Base64Definitions.h"
|
|
|
|
void base64_encode(const byte* data, char* encoded_data, size_t data_length = 0) {
|
|
size_t output_length = 4 * ((data_length + 2) / 3);
|
|
|
|
if (!data_length) {
|
|
// WARNING: This should only happen if the data is a char string
|
|
// Binary data is not allowed since it often has '\0' characters
|
|
data_length = str_length((const char *) data);
|
|
}
|
|
|
|
size_t i = 0;
|
|
size_t j = 0;
|
|
while (i + 3 <= data_length) {
|
|
uint32 triple = ((uint32) data[i] << 16) | ((uint32) data[i + 1] << 8) | data[i + 2];
|
|
|
|
encoded_data[j++] = BASE64_CHARS[(triple >> 3 * 6) & 0x3F];
|
|
encoded_data[j++] = BASE64_CHARS[(triple >> 2 * 6) & 0x3F];
|
|
encoded_data[j++] = BASE64_CHARS[(triple >> 1 * 6) & 0x3F];
|
|
encoded_data[j++] = BASE64_CHARS[(triple >> 0 * 6) & 0x3F];
|
|
|
|
i += 3;
|
|
}
|
|
|
|
if (i < data_length) {
|
|
uint32 triple = ((uint32) data[i] << 16);
|
|
if (i + 1 < data_length) {
|
|
triple |= ((uint32) data[i + 1] << 8);
|
|
}
|
|
|
|
encoded_data[j++] = BASE64_CHARS[(triple >> 18) & 0x3F];
|
|
encoded_data[j++] = BASE64_CHARS[(triple >> 12) & 0x3F];
|
|
encoded_data[j] = (i + 1 < data_length) ? BASE64_CHARS[(triple >> 6) & 0x3F] : '=';
|
|
encoded_data[j + 1] = '=';
|
|
}
|
|
|
|
encoded_data[output_length] = '\0';
|
|
}
|
|
|
|
size_t base64_decode(const char* encoded_data, byte* data, size_t encoded_length = 0) {
|
|
if (!encoded_length) {
|
|
encoded_length = str_length(encoded_data);
|
|
}
|
|
|
|
size_t output_length = encoded_length / 4 * 3;
|
|
int32 padding = 0;
|
|
|
|
if (encoded_data[encoded_length - 1] == '=') {
|
|
--output_length;
|
|
++padding;
|
|
|
|
if (encoded_data[encoded_length - 2] == '=') {
|
|
--output_length;
|
|
++padding;
|
|
}
|
|
}
|
|
|
|
size_t complete_blocks = (encoded_length - padding) / 4;
|
|
size_t i, j;
|
|
|
|
for (i = 0, j = 0; i < complete_blocks * 4; i += 4, j += 3) {
|
|
uint32 sextet_a = BASE64_LOOKUP[(byte) encoded_data[i]];
|
|
uint32 sextet_b = BASE64_LOOKUP[(byte) encoded_data[i + 1]];
|
|
uint32 sextet_c = BASE64_LOOKUP[(byte) encoded_data[i + 2]];
|
|
uint32 sextet_d = BASE64_LOOKUP[(byte) encoded_data[i + 3]];
|
|
|
|
uint32 triple = (sextet_a << 18) | (sextet_b << 12) | (sextet_c << 6) | sextet_d;
|
|
|
|
data[j] = (triple >> 16) & 0xFF;
|
|
data[j + 1] = (triple >> 8) & 0xFF;
|
|
data[j + 2] = triple & 0xFF;
|
|
}
|
|
|
|
if (padding > 0) {
|
|
uint32 sextet_a = BASE64_LOOKUP[(byte) encoded_data[i]];
|
|
uint32 sextet_b = BASE64_LOOKUP[(byte) encoded_data[i + 1]];
|
|
uint32 sextet_c = (padding > 1) ? 0 : BASE64_LOOKUP[(byte) encoded_data[i + 2]];
|
|
|
|
uint32 triple = (sextet_a << 18) | (sextet_b << 12) | (sextet_c << 6);
|
|
|
|
data[j + 1] = (triple >> 16) & 0xFF;
|
|
if (padding == 1) {
|
|
data[j + 2] = (triple >> 8) & 0xFF;
|
|
}
|
|
}
|
|
|
|
return output_length;
|
|
}
|
|
|
|
#if __aarch64__
|
|
#include "Base64SimdArm.h"
|
|
#else
|
|
#include "Base64SimdX86.h"
|
|
#endif
|
|
|
|
#endif |