95 lines
2.5 KiB
C
95 lines
2.5 KiB
C
#include "qjs_text.h"
|
|
#include "qjs_blob.h"
|
|
#include "blob.h"
|
|
#include "jsffi.h"
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
|
|
JSC_CCALL(text_blob_to_hex,
|
|
size_t blob_len;
|
|
void *blob_data = js_get_blob_data(js, &blob_len, argv[0]);
|
|
if (!blob_data) return JS_ThrowTypeError(js, "Expected stone blob");
|
|
|
|
uint8_t *bytes = (uint8_t *)blob_data;
|
|
|
|
// Hex encoding: each byte becomes 2 hex characters
|
|
size_t hex_len = blob_len * 2;
|
|
char *hex_str = malloc(hex_len + 1);
|
|
|
|
static const char hex_digits[] = "0123456789ABCDEF";
|
|
|
|
for (size_t i = 0; i < blob_len; i++) {
|
|
hex_str[i * 2] = hex_digits[(bytes[i] >> 4) & 0xF];
|
|
hex_str[i * 2 + 1] = hex_digits[bytes[i] & 0xF];
|
|
}
|
|
|
|
hex_str[hex_len] = '\0';
|
|
ret = JS_NewString(js, hex_str);
|
|
free(hex_str);
|
|
)
|
|
|
|
JSC_CCALL(text_blob_to_base32,
|
|
size_t blob_len;
|
|
void *blob_data = js_get_blob_data(js, &blob_len, argv[0]);
|
|
if (!blob_data) return JS_ThrowTypeError(js, "Expected stone blob");
|
|
|
|
uint8_t *bytes = (uint8_t *)blob_data;
|
|
|
|
static const char b32_digits[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
|
|
|
|
// Calculate output length: each 5 bytes becomes 8 base32 chars
|
|
size_t groups = (blob_len + 4) / 5;
|
|
size_t b32_len = groups * 8;
|
|
char *b32_str = malloc(b32_len + 1);
|
|
|
|
size_t in_idx = 0;
|
|
size_t out_idx = 0;
|
|
|
|
while (in_idx < blob_len) {
|
|
// Process 5 bytes (40 bits) at a time to produce 8 base32 chars
|
|
uint64_t buf = 0;
|
|
int bytes_read = 0;
|
|
|
|
// Read up to 5 bytes into buffer
|
|
for (int i = 0; i < 5 && in_idx < blob_len; i++) {
|
|
buf = (buf << 8) | bytes[in_idx++];
|
|
bytes_read++;
|
|
}
|
|
|
|
// Pad with zeros if we read fewer than 5 bytes
|
|
buf = buf << (8 * (5 - bytes_read));
|
|
|
|
// Extract 8 groups of 5 bits from the 40-bit buffer
|
|
for (int i = 7; i >= 0; i--) {
|
|
b32_str[out_idx + i] = b32_digits[buf & 0x1F];
|
|
buf >>= 5;
|
|
}
|
|
out_idx += 8;
|
|
}
|
|
|
|
// Replace trailing chars with padding if needed
|
|
int padding = (5 - (blob_len % 5)) % 5;
|
|
if (padding > 0) {
|
|
static const int pad_chars[] = {0, 6, 4, 3, 1};
|
|
for (int i = 0; i < pad_chars[padding]; i++) {
|
|
b32_str[b32_len - 1 - i] = '=';
|
|
}
|
|
}
|
|
|
|
b32_str[b32_len] = '\0';
|
|
ret = JS_NewString(js, b32_str);
|
|
free(b32_str);
|
|
)
|
|
|
|
static const JSCFunctionListEntry js_text_funcs[] = {
|
|
MIST_FUNC_DEF(text, blob_to_hex, 1),
|
|
MIST_FUNC_DEF(text, blob_to_base32, 1),
|
|
};
|
|
|
|
JSValue js_text_use(JSContext *js)
|
|
{
|
|
JSValue mod = JS_NewObject(js);
|
|
JS_SetPropertyFunctionList(js, mod, js_text_funcs, countof(js_text_funcs));
|
|
return mod;
|
|
}
|