0
0
mirror of https://github.com/tursodatabase/libsql.git synced 2025-03-08 23:41:50 +00:00
Glauber Costa d3a156caf5 bundle SQLean extensions
A common complain with libSQL is how to run extensions. The main
mechanism, with a .so, has a lot of issues around how those .so are
distributed.

The most common extensions are the ones in the sqlean package. We can
improve this experience by bundling them in our sqlite build.

Not all SQLean extensions are kosher: some of them, like fileio, use
the vfs. Others, are deemed too complex.

The extensions included here are a subset that we deem important enough,
and low risk enough, to just be a part of the main bundle.
2025-01-16 22:25:16 -05:00

83 lines
2.4 KiB
C

// Copyright (c) 2023 Anton Zhiyanov, MIT License
// https://github.com/nalgeon/sqlean
// Base32 encoding/decoding (RFC 4648)
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
static const char base32_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
uint8_t* base32_encode(const uint8_t* src, size_t len, size_t* out_len) {
*out_len = ((len + 4) / 5) * 8;
uint8_t* encoded = malloc(*out_len + 1);
if (encoded == NULL) {
*out_len = 0;
return NULL;
}
for (size_t i = 0, j = 0; i < len;) {
uint32_t octet0 = i < len ? src[i++] : 0;
uint32_t octet1 = i < len ? src[i++] : 0;
uint32_t octet2 = i < len ? src[i++] : 0;
uint32_t octet3 = i < len ? src[i++] : 0;
uint32_t octet4 = i < len ? src[i++] : 0;
encoded[j++] = base32_chars[octet0 >> 3];
encoded[j++] = base32_chars[((octet0 & 0x07) << 2) | (octet1 >> 6)];
encoded[j++] = base32_chars[(octet1 >> 1) & 0x1F];
encoded[j++] = base32_chars[((octet1 & 0x01) << 4) | (octet2 >> 4)];
encoded[j++] = base32_chars[((octet2 & 0x0F) << 1) | (octet3 >> 7)];
encoded[j++] = base32_chars[(octet3 >> 2) & 0x1F];
encoded[j++] = base32_chars[((octet3 & 0x03) << 3) | (octet4 >> 5)];
encoded[j++] = base32_chars[octet4 & 0x1F];
}
if (len % 5 != 0) {
size_t padding = 7 - (len % 5) * 8 / 5;
for (size_t i = 0; i < padding; i++) {
encoded[*out_len - padding + i] = '=';
}
}
encoded[*out_len] = '\0';
return encoded;
}
uint8_t* base32_decode(const uint8_t* src, size_t len, size_t* out_len) {
while (len > 0 && src[len - 1] == '=') {
len--;
}
*out_len = len * 5 / 8;
uint8_t* decoded = malloc(*out_len);
if (decoded == NULL) {
*out_len = 0;
return NULL;
}
size_t bits = 0, value = 0, count = 0;
for (size_t i = 0; i < len; i++) {
uint8_t c = src[i];
if (c >= 'A' && c <= 'Z') {
c -= 'A';
} else if (c >= '2' && c <= '7') {
c -= '2' - 26;
} else {
continue;
}
value = (value << 5) | c;
bits += 5;
if (bits >= 8) {
decoded[count++] = (uint8_t)(value >> (bits - 8));
bits -= 8;
}
}
if (bits >= 5 || (value & ((1 << bits) - 1)) != 0) {
free(decoded);
return NULL;
}
*out_len = count;
return decoded;
}