fix blob; throw on non stone reads; update blob test

This commit is contained in:
2025-06-02 13:23:05 -05:00
parent e689679aac
commit 2fdf74f6ee
5 changed files with 67 additions and 27 deletions

View File

@@ -50,28 +50,32 @@ static JSValue js_blob_constructor(JSContext *ctx, JSValueConst new_target,
int is_one = JS_ToBool(ctx, argv[1]);
bd = blob_new_with_fill((size_t)length_bits, is_one);
} else if (JS_IsFunction(ctx, argv[1])) {
// Random function provided - call it for each bit
/* Random function provided call it for each bit */
size_t bytes = (length_bits + 7) / 8;
bd = blob_new((size_t)length_bits);
if (bd) {
bd->length = length_bits;
/* Ensure the backing storage starts out zeroed */
memset(bd->data, 0, bytes);
for (size_t i = 0; i < length_bits; i++) {
JSValue randval = JS_Call(ctx, argv[1], JS_UNDEFINED, 0, NULL);
if (JS_IsException(randval)) {
blob_destroy(bd);
return JS_EXCEPTION;
}
int64_t fitval;
JS_ToInt64(ctx, &fitval, randval);
int32_t fitval;
JS_ToInt32(ctx, &fitval, randval);
JS_FreeValue(ctx, randval);
// Set bit based on random value
/* Compute which byte and which bit within that byte to set/clear */
size_t byte_idx = i / 8;
size_t bit_idx = i % 8;
if (fitval & 1) {
bd->data[byte_idx] |= (1 << bit_idx);
} else {
bd->data[byte_idx] &= ~(1 << bit_idx);
}
size_t bit_idx = i % 8;
if (fitval & 1)
bd->data[byte_idx] |= (uint8_t)(1 << bit_idx);
else
bd->data[byte_idx] &= (uint8_t)~(1 << bit_idx);
}
}
} else {
@@ -232,14 +236,14 @@ static JSValue js_blob_read_logical(JSContext *ctx, JSValueConst this_val,
}
int64_t pos;
if (JS_ToInt64(ctx, &pos, argv[0]) < 0) {
return JS_EXCEPTION;
return JS_ThrowInternalError(ctx, "must provide a positive bit");
}
if (pos < 0) {
return JS_NULL; // out of range
return JS_ThrowRangeError(ctx, "read_logical: position must be non-negative");
}
int bit_val;
if (blob_read_bit(bd, (size_t)pos, &bit_val) < 0) {
return JS_NULL; // not stone or out of range
return JS_ThrowTypeError(ctx, "read_logical: blob must be stone");
}
return JS_NewBool(ctx, bit_val);
}
@@ -284,22 +288,21 @@ static JSValue js_blob_read_number(JSContext *ctx, JSValueConst this_val,
}
blob *bd = js2blob(ctx, this_val);
if (!bd) {
return JS_ThrowTypeError(ctx, "read_dec64: not called on a blob");
return JS_ThrowTypeError(ctx, "read_number: not called on a blob");
}
if (!bd->is_stone) {
return JS_ThrowTypeError(ctx, "read_dec64: blob must be stone");
return JS_ThrowTypeError(ctx, "read_number: blob must be stone");
}
double from;
if (JS_ToFloat64(ctx, &from, argv[0]) < 0) return JS_EXCEPTION;
if (from < 0) return JS_ThrowRangeError(ctx, "read_dec64: out of range");
if (from < 0) return JS_ThrowRangeError(ctx, "read_number: position must be non-negative");
double d;
printf("reading blob from %g\n", from);
if (blob_read_dec64(bd, from, &d) < 0) {
return JS_ThrowRangeError(ctx, "read_dec64: out of range");
return JS_ThrowRangeError(ctx, "read_number: out of range");
}
return JS_NewFloat64(ctx, d);