blob
This commit is contained in:
5
build.cm
5
build.cm
@@ -73,7 +73,8 @@ Build.detect_host_target = function() {
|
||||
// ============================================================================
|
||||
|
||||
function content_hash(str) {
|
||||
return text(crypto.blake2(new blob(str)), 'h')
|
||||
var bb = stone(new blob(str))
|
||||
return text(crypto.blake2(bb, 32), 'h')
|
||||
}
|
||||
|
||||
function get_build_dir() {
|
||||
@@ -379,7 +380,7 @@ Build.build_all_dynamic = function(target, buildtype = 'release') {
|
||||
var lib = Build.build_dynamic('core', target, buildtype)
|
||||
results.push({ package: 'core', library: lib })
|
||||
} catch (e) {
|
||||
log.error('Failed to build core: ' + e)
|
||||
log.error('Failed to build core: ' + text(e))
|
||||
results.push({ package: 'core', error: e })
|
||||
}
|
||||
}
|
||||
|
||||
111
source/blob.h
111
source/blob.h
@@ -138,72 +138,81 @@ void bitcpy(unsigned char *dst, size_t dst_bit_offset,
|
||||
}
|
||||
}
|
||||
|
||||
// Fast bit-copy for arbitrary bit ranges (inclusive) from src → dest
|
||||
void copy_bits_fast(const void *src, void *dest,
|
||||
size_t n, /* start bit in src (inclusive) */
|
||||
size_t m, /* end bit in src (inclusive) */
|
||||
size_t x) /* start bit in dest */
|
||||
static inline uint16_t load16_window(const uint8_t *s, size_t i, size_t last_byte)
|
||||
{
|
||||
const uint8_t *s = (const uint8_t*)src;
|
||||
uint8_t *d = (uint8_t*)dest;
|
||||
uint16_t lo = s[i];
|
||||
uint16_t hi = 0;
|
||||
if (i + 1 <= last_byte) hi = (uint16_t)s[i + 1] << 8;
|
||||
return lo | hi;
|
||||
}
|
||||
|
||||
size_t total_bits = m - n + 1;
|
||||
void copy_bits_fast(const void *src, void *dest, size_t n, size_t m, size_t x)
|
||||
{
|
||||
if (m < n) return;
|
||||
|
||||
size_t src_bit = n;
|
||||
size_t dst_bit = x;
|
||||
const uint8_t *s = (const uint8_t *)src;
|
||||
uint8_t *d = (uint8_t *)dest;
|
||||
|
||||
size_t total_bits = m - n + 1;
|
||||
size_t src_bit = n;
|
||||
size_t dst_bit = x;
|
||||
size_t src_byte = src_bit >> 3;
|
||||
size_t dst_byte = dst_bit >> 3;
|
||||
int src_off = src_bit & 7;
|
||||
int dst_off = dst_bit & 7;
|
||||
int src_off = src_bit & 7;
|
||||
int dst_off = dst_bit & 7;
|
||||
|
||||
// 1) Leading partial byte to align dest
|
||||
size_t last_src_byte = m >> 3;
|
||||
|
||||
/* Fast path: whole bytes, aligned */
|
||||
if (src_off == 0 && dst_off == 0 && (total_bits & 7) == 0) {
|
||||
memcpy(d + dst_byte, s + src_byte, total_bits >> 3);
|
||||
return;
|
||||
}
|
||||
|
||||
/* 1) Leading partial byte to align dest */
|
||||
if (dst_off != 0) {
|
||||
size_t chunk = 8 - dst_off;
|
||||
if (chunk > total_bits) chunk = total_bits;
|
||||
|
||||
uint8_t dst_mask = (((1u << chunk) - 1u) << dst_off);
|
||||
uint16_t wb = (uint16_t)s[src_byte] | ((uint16_t)s[src_byte + 1] << 8);
|
||||
uint8_t dst_mask = (uint8_t)(((1u << chunk) - 1u) << dst_off);
|
||||
uint16_t wb = load16_window(s, src_byte, last_src_byte);
|
||||
uint8_t bits = (uint8_t)((wb >> src_off) & ((1u << chunk) - 1u));
|
||||
bits <<= dst_off;
|
||||
d[dst_byte] = (d[dst_byte] & ~dst_mask) | (bits & dst_mask);
|
||||
d[dst_byte] = (d[dst_byte] & (uint8_t)~dst_mask) | (bits & dst_mask);
|
||||
|
||||
total_bits -= chunk;
|
||||
src_bit += chunk;
|
||||
dst_bit += chunk;
|
||||
src_byte = src_bit >> 3;
|
||||
dst_byte = dst_bit >> 3;
|
||||
src_off = src_bit & 7;
|
||||
dst_off = dst_bit & 7; // now zero
|
||||
src_bit += chunk;
|
||||
dst_bit += chunk;
|
||||
src_byte = src_bit >> 3;
|
||||
dst_byte = dst_bit >> 3;
|
||||
src_off = src_bit & 7;
|
||||
dst_off = dst_bit & 7;
|
||||
}
|
||||
|
||||
// 2) Copy full bytes
|
||||
/* 2) Copy full bytes */
|
||||
if (total_bits >= 8) {
|
||||
size_t num_bytes = total_bits >> 3;
|
||||
|
||||
if (src_off == 0) {
|
||||
size_t num_bytes = total_bits >> 3;
|
||||
memcpy(&d[dst_byte], &s[src_byte], num_bytes);
|
||||
total_bits -= num_bytes << 3;
|
||||
src_byte += num_bytes;
|
||||
dst_byte += num_bytes;
|
||||
memcpy(d + dst_byte, s + src_byte, num_bytes);
|
||||
} else {
|
||||
size_t num_bytes = total_bits >> 3;
|
||||
for (size_t i = 0; i < num_bytes; i++) {
|
||||
uint16_t wb = (uint16_t)s[src_byte + i] |
|
||||
((uint16_t)s[src_byte + i + 1] << 8);
|
||||
uint16_t wb = load16_window(s, src_byte + i, last_src_byte);
|
||||
d[dst_byte + i] = (uint8_t)((wb >> src_off) & 0xFFu);
|
||||
}
|
||||
total_bits -= num_bytes << 3;
|
||||
src_byte += num_bytes;
|
||||
dst_byte += num_bytes;
|
||||
}
|
||||
|
||||
total_bits -= num_bytes << 3;
|
||||
src_byte += num_bytes;
|
||||
dst_byte += num_bytes;
|
||||
}
|
||||
|
||||
// 3) Trailing bits (< 8)
|
||||
/* 3) Trailing bits (< 8), dest is byte-aligned here */
|
||||
if (total_bits > 0) {
|
||||
uint8_t dst_mask = (1u << total_bits) - 1u;
|
||||
uint16_t wb = (uint16_t)s[src_byte] | ((uint16_t)s[src_byte + 1] << 8);
|
||||
uint8_t dst_mask = (uint8_t)((1u << total_bits) - 1u);
|
||||
uint16_t wb = load16_window(s, src_byte, last_src_byte);
|
||||
uint8_t bits = (uint8_t)((wb >> src_off) & dst_mask);
|
||||
d[dst_byte] = (d[dst_byte] & ~dst_mask) | (bits & dst_mask);
|
||||
d[dst_byte] = (d[dst_byte] & (uint8_t)~dst_mask) | (bits & dst_mask);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -378,16 +387,30 @@ int blob_write_text(blob *b, const char *text) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int blob_write_bytes(blob *b, const void *data, size_t len_bytes) {
|
||||
int blob_write_bytes(blob *b, const void *data, size_t len_bytes)
|
||||
{
|
||||
if (!b || b->is_stone) return -1;
|
||||
if (len_bytes == 0) return 0;
|
||||
size_t bits = len_bytes * 8;
|
||||
if (blob_ensure_capacity(b, bits) < 0) return -1;
|
||||
copy_bits_fast(data, b->data, 0, bits - 1, b->length);
|
||||
b->length += bits;
|
||||
if (!len_bytes) return 0;
|
||||
|
||||
size_t bit_len = len_bytes << 3;
|
||||
size_t bit_off = b->length;
|
||||
size_t new_len = bit_off + bit_len;
|
||||
if (new_len < bit_off) return -1;
|
||||
|
||||
if (blob_ensure_capacity(b, new_len) < 0) return -1;
|
||||
|
||||
if ((bit_off & 7) == 0) {
|
||||
uint8_t *dst = (uint8_t *)b->data + (bit_off >> 3);
|
||||
memcpy(dst, data, len_bytes);
|
||||
} else {
|
||||
copy_bits_fast(data, b->data, 0, bit_len - 1, bit_off);
|
||||
}
|
||||
|
||||
b->length = new_len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int blob_read_bit(const blob *b, size_t pos, int *out_bit) {
|
||||
if (!b || !b->is_stone || !out_bit) return -1;
|
||||
if (pos >= b->length) return -1;
|
||||
|
||||
@@ -39674,26 +39674,32 @@ static JSValue js_blob_w16(JSContext *ctx, JSValueConst this_val,
|
||||
}
|
||||
|
||||
/* blob.wf(value) - write float */
|
||||
static JSValue js_blob_wf(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
static JSValue js_blob_wf(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
||||
{
|
||||
if (argc < 1)
|
||||
return JS_ThrowTypeError(ctx, "wf(value) requires 1 argument");
|
||||
if (argc < 1) return JS_ThrowTypeError(ctx, "wf(value) requires 1 argument");
|
||||
|
||||
blob *bd = js_get_blob(ctx, this_val);
|
||||
if (!bd)
|
||||
return JS_ThrowTypeError(ctx, "wf: not called on a blob");
|
||||
if (!bd) return JS_ThrowTypeError(ctx, "wf: not called on a blob");
|
||||
|
||||
double d;
|
||||
if (JS_ToFloat64(ctx, &d, argv[0]) < 0) return JS_EXCEPTION;
|
||||
float f;
|
||||
int tag = JS_VALUE_GET_TAG(argv[0]);
|
||||
if (tag == JS_TAG_INT) {
|
||||
f = (float)JS_VALUE_GET_INT(argv[0]);
|
||||
} else if (tag == JS_TAG_FLOAT64) {
|
||||
f = (float)JS_VALUE_GET_FLOAT64(argv[0]);
|
||||
} else {
|
||||
double d;
|
||||
if (JS_ToFloat64(ctx, &d, argv[0]) < 0) return JS_EXCEPTION;
|
||||
f = (float)d;
|
||||
}
|
||||
|
||||
float f = (float)d;
|
||||
if (blob_write_bytes(bd, &f, sizeof(float)) < 0)
|
||||
if (blob_write_bytes(bd, &f, sizeof(f)) < 0)
|
||||
return JS_ThrowTypeError(ctx, "wf: cannot write");
|
||||
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
|
||||
/* blob.read_logical(from) */
|
||||
static JSValue js_blob_read_logical(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
|
||||
Reference in New Issue
Block a user