cOMS/encoding/Base64.h
Dennis Eichhorn dc9f37b726
Some checks failed
CodeQL / Analyze (${{ matrix.language }}) (autobuild, c-cpp) (push) Has been cancelled
Microsoft C++ Code Analysis / Analyze (push) Has been cancelled
update
2025-04-06 10:34:47 +00:00

110 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 (data[encoded_length - 1] == '=') {
--output_length;
++padding;
if (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 sextet_d = 0;
uint32 triple = (sextet_a << 18) | (sextet_b << 12) | (sextet_c << 6) | sextet_d;
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