fix blob; throw on non stone reads; update blob test
This commit is contained in:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user