#ifndef CELL_H #define CELL_H #include "quickjs.h" #include "blob.h" #ifdef __cplusplus extern "C" { #endif // blob fns JSValue js_blob_use(JSContext *js); JSValue js_new_blob_stoned_copy(JSContext *js, void *data, size_t bytes); void *js_get_blob_data(JSContext *js, size_t *size, JSValue v); // bytes void *js_get_blob_data_bits(JSContext *js, size_t *bits, JSValue v); // bits int js_is_blob(JSContext *js, JSValue v); double cell_random(); uint64_t cell_random_fit(); int JS_ArrayLength(JSContext *js, JSValue a); int js2bool(JSContext *js, JSValue v); JSValue bool2js(JSContext *js, int b); double js2number(JSContext *js, JSValue v); JSValue number2js(JSContext *js, double g); JSValue wota2value(JSContext *js, void *v); void *value2wota(JSContext *js, JSValue v, JSValue replacer, size_t *bytes); #define CELL_HOOK_ENTER 1 #define CELL_HOOK_EXIT 2 typedef void (*cell_hook)(const char *name, int type); void cell_trace_sethook(cell_hook); // Macros to help with creating scripts #define MIST_CFUNC_DEF(name, length, func1, props) { name, props, JS_DEF_CFUNC, 0, .u = { .func = { length, JS_CFUNC_generic, { .generic = func1 } } } } #define MIST_FUNC_DEF(TYPE, FN, LEN) MIST_CFUNC_DEF(#FN, LEN, js_##TYPE##_##FN, 0) #define PROTO_FUNC_DEF(TYPE, FN, LEN) MIST_CFUNC_DEF(#FN, LEN, js_##TYPE##_##FN, 0) #define JS_SETSIG JSContext *js, JSValue self, JSValue val #define JSC_CCALL(NAME, ...) static JSValue js_##NAME (JSContext *js, JSValue self, int argc, JSValue *argv) { \ JSValue ret = JS_NULL; \ __VA_ARGS__ ;\ return ret; \ } #define JSC_CCALL_EXTERN(NAME, ...) JSValue js_##NAME (JSContext *js, JSValue self, int argc, JSValue *argv) { \ JSValue ret = JS_NULL; \ __VA_ARGS__ ;\ return ret; \ } #define JSC_SCALL(NAME, ...) JSC_CCALL(NAME, \ const char *str = JS_ToCString(js,argv[0]); \ __VA_ARGS__ ;\ JS_FreeCString(js,str); \ ) #define JSC_SSCALL(NAME, ...) JSC_CCALL(NAME, \ const char *str = NULL; \ const char *str2 = NULL; \ if (!JS_IsNull(argv[0])) str = JS_ToCString(js,argv[0]); \ if (!JS_IsNull(argv[1])) str2 = JS_ToCString(js,argv[1]); \ __VA_ARGS__ ; \ JS_FreeCString(js,str2); \ JS_FreeCString(js,str); \ ) \ #define QJSCLASS(TYPE, ...)\ JSClassID js_##TYPE##_id;\ static void js_##TYPE##_finalizer(JSRuntime *rt, JSValue val){\ JSContext *js = JS_GetContext(rt);\ TYPE *n = JS_GetOpaque2(js, val, js_##TYPE##_id); \ TYPE##_free(rt,n);}\ static JSClassDef js_##TYPE##_class = {\ .class_name = #TYPE,\ .finalizer = js_##TYPE##_finalizer,\ };\ TYPE *js2##TYPE (JSContext *js, JSValue val) { \ if (JS_GetClassID(val) != js_##TYPE##_id) return NULL; \ return JS_GetOpaque(val,js_##TYPE##_id); \ }\ JSValue TYPE##2js(JSContext *js, TYPE *n) { \ JSValue j = JS_NewObjectClass(js,js_##TYPE##_id);\ JS_SetOpaque(j,n);\ __VA_ARGS__ \ return j; }\ \ #define QJSCLASSMARK(TYPE, ...)\ static void js_##TYPE##_finalizer(JSRuntime *rt, JSValue val){\ TYPE *n = JS_GetOpaque(val, js_##TYPE##_id);\ TYPE##_free(rt,n);}\ static JSClassDef js_##TYPE##_class = {\ .class_name = #TYPE,\ .finalizer = js_##TYPE##_finalizer,\ .gc_mark = js_##TYPE##_mark,\ };\ TYPE *js2##TYPE (JSContext *js, JSValue val) { \ if (JS_GetClassID(val) != js_##TYPE##_id) return NULL; \ return JS_GetOpaque(val,js_##TYPE##_id); \ }\ JSValue TYPE##2js(JSContext *js, TYPE *n) { \ JSValue j = JS_NewObjectClass(js,js_##TYPE##_id);\ JS_SetOpaque(j,n);\ __VA_ARGS__ \ return j; }\ \ #define QJSCLASSMARK_EXTERN(TYPE, ...)\ static void js_##TYPE##_finalizer(JSRuntime *rt, JSValue val){\ TYPE *n = JS_GetOpaque(val, js_##TYPE##_id);\ TYPE##_free(rt,n);}\ static JSClassDef js_##TYPE##_class = {\ .class_name = #TYPE,\ .finalizer = js_##TYPE##_finalizer,\ .gc_mark = js_##TYPE##_mark,\ };\ extern JSClassID js_##TYPE##_id;\ TYPE *js2##TYPE (JSContext *js, JSValue val) { \ if (JS_GetClassID(val) != js_##TYPE##_id) return NULL; \ return JS_GetOpaque(val,js_##TYPE##_id); \ }\ JSValue TYPE##2js(JSContext *js, TYPE *n) { \ JSValue j = JS_NewObjectClass(js,js_##TYPE##_id);\ JS_SetOpaque(j,n);\ __VA_ARGS__ \ return j; }\ \ /* Defines a class and uses its function list as its prototype */ #define QJSCLASSPREP_FUNCS(TYPE) \ QJSCLASSPREP_NO_FUNCS(TYPE) \ JS_SetPropertyFunctionList(js, TYPE##_proto, js_##TYPE##_funcs, countof(js_##TYPE##_funcs)); \ #define QJSCLASSPREP_NO_FUNCS(TYPE) \ JS_NewClassID(&js_##TYPE##_id);\ JS_NewClass(JS_GetRuntime(js), js_##TYPE##_id, &js_##TYPE##_class);\ JSValue TYPE##_proto = JS_NewObject(js); \ JS_SetClassProto(js, js_##TYPE##_id, TYPE##_proto); \ #define QJSCLASSPREP_FUNCS_CTOR(TYPE, CTOR_ARGC) \ ({ \ QJSCLASSPREP_FUNCS(TYPE); \ JSValue TYPE##_ctor = JS_NewCFunction2(js, js_##TYPE##_constructor, #TYPE, CTOR_ARGC, JS_CFUNC_generic, 0); \ TYPE##_ctor; \ }) #define countof(x) (sizeof(x)/sizeof((x)[0])) // Common macros for property access #define JS_GETPROP(JS, TARGET, VALUE, PROP, TYPE) {\ JSValue __##PROP##__v = JS_GetPropertyStr(JS,VALUE,#PROP); \ TARGET = js2##TYPE(JS, __##PROP##__v); \ JS_FreeValue(JS,__##PROP##__v); }\ #define JS_GETATOM(JS, TARGET, VALUE, ATOM, TYPE) {\ JSValue __##PROP##__v = JS_GetPropertyStr(JS,VALUE,#ATOM); \ TARGET = js2##TYPE(JS, __##PROP##__v); \ JS_FreeValue(JS,__##PROP##__v); }\ // X-macro enum definition system for string<->enum conversion #define ENUM_MAPPING_TABLE(ENUM) \ static const struct { int value; const char *name; } ENUM##_mapping[] #define JS2ENUM(NAME) \ int js2##NAME(JSContext *js, JSValue v) { \ if (JS_IsNull(v)) return 0; \ const char *str = JS_ToCString(js, v); \ if (!str) return 0; \ for(int i = 0; i < sizeof(NAME##_mapping)/sizeof(NAME##_mapping[0]); i++) \ if(!strcmp(NAME##_mapping[i].name, str)) { \ JS_FreeCString(js, str); \ return NAME##_mapping[i].value; \ } \ JS_FreeCString(js, str); \ return 0; \ } \ JSValue NAME##2js(JSContext *js, int enumval) { \ for(int i = 0; i < sizeof(NAME##_mapping)/sizeof(NAME##_mapping[0]); i++) \ if(NAME##_mapping[i].value == enumval) \ return JS_NewString(js, NAME##_mapping[i].name); \ return JS_NULL; \ } #define CELL_USE_INIT(c) \ JSValue CELL_USE_NAME(JSContext *js) { do { c ; } while(0); } #define CELL_USE_FUNCS(FUNCS) \ JSValue CELL_USE_NAME(JSContext *js) { \ JSValue mod = JS_NewObject(js); \ JS_SetPropertyFunctionList(js, mod, FUNCS, countof(FUNCS)); \ return mod; } #ifdef __cplusplus } #endif #endif