This commit is contained in:
Timerix 2025-09-29 08:19:13 +05:00
parent 7e7bd195a9
commit b3f67a38de
2 changed files with 109 additions and 0 deletions

23
include/tlibc/base64.h Normal file
View File

@ -0,0 +1,23 @@
#pragma once
#include "tlibc/std.h"
/// @param src_size size of data to encode
/// @return number of encoded characters. Is a multiple of 4.
u32 base64_encodedSize(u32 src_size);
/// @param src data to encode
/// @param src_size size of data to encode
/// @param dst buffer of size base64_encodedSize(src_size)
/// @return number of encoded characters. Is a multiple of 4.
u32 base64_encode(const u8* src, u32 src_size, char* dst);
/// @param src data to decode
/// @param src_size size of data to decode. Must be a multiple of 4 for valid base64 data.
/// @return number of decoded characters or 0 on error
u32 base64_decodedSize(const char* src, u32 src_size);
/// @param src data to decode
/// @param src_size size of data to decode. Must be a multiple of 4 for valid base64 data.
/// @param dst buffer of size base64_decodedSize(src, src_size)
/// @return number of decoded characters or 0 on error
u32 base64_decode(const u8* src, u32 src_size, u8* dst);

86
src/base64.c Normal file
View File

@ -0,0 +1,86 @@
#include "tlibc/base64.h"
// based on https://nachtimwald.com/2017/11/18/base64-encode-and-decode-in-c
u32 base64_encodedSize(u32 src_size){
u32 ret = src_size;
if (src_size % 3 != 0)
ret += 3 - (src_size % 3);
ret /= 3;
ret *= 4;
return ret;
}
static const char b64chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
u32 base64_encode(const u8* src, u32 src_size, char* dst){
u32 i = 0, j = 0, v = 0;
for (; i < src_size; i += 3) {
v = src[i];
v = i + 1 < src_size ? v << 8 | src[i + 1] : v << 8;
v = i + 2 < src_size ? v << 8 | src[i + 2] : v << 8;
dst[j++] = b64chars[(v >> 18) & 0x3F];
dst[j++] = b64chars[(v >> 12) & 0x3F];
dst[j++] = i + 1 < src_size ? b64chars[(v >> 6) & 0x3F] : '=';
dst[j++] = i + 2 < src_size ? b64chars[v & 0x3F] : '=';
}
return j;
}
u32 base64_decodedSize(const char* src, u32 src_size){
// incomplete src
if(src_size % 4 != 0)
return 0;
u32 ret = src_size / 4 * 3;
u32 i = src_size;
while(i > 0 && src[--i] == '=') {
ret--;
}
return ret;
}
/*
void base64_generateDecodeTable(){
int inv[80];
memset(inv, -1, sizeof(inv));
for (u32 i = 0; i < 64; i + +) {
inv[b64chars[i] - 43] = i;
}
}
*/
static int b64inverse[] = {
62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58,
59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5,
6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28,
29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
43, 44, 45, 46, 47, 48, 49, 50, 51
};
u32 base64_decode(const u8* src, u32 src_size, u8* dst){
// incomplete src
if(src_size % 4 != 0)
return 0;
u32 i = 0, j = 0, v = 0;
for (; i < src_size; i += 4) {
v = b64inverse[src[i] - 43];
v = (v << 6) | b64inverse[src[i + 1] - 43];
v = src[i + 2]=='=' ? v << 6 : (v << 6) | b64inverse[src[i + 2] - 43];
v = src[i + 3]=='=' ? v << 6 : (v << 6) | b64inverse[src[i + 3] - 43];
dst[j++] = (v >> 16) & 0xFF;
if (src[i + 2] != '='){
dst[j++] = (v >> 8) & 0xFF;
}
if (src[i + 3] != '='){
dst[j++] = v & 0xFF;
}
}
return j;
}