From dde71d6c02d64d0779ae7a9bfac1a51b80f0bf37 Mon Sep 17 00:00:00 2001 From: John Alanbrook Date: Wed, 17 Jan 2024 01:04:52 +0000 Subject: [PATCH] nota array and object serialization --- source/engine/jsffi.c | 138 ++++++++++++++++++++++++++-------------- source/engine/nota.c | 145 +++++++++++++++++++++++++----------------- source/engine/nota.h | 29 +++++---- 3 files changed, 197 insertions(+), 115 deletions(-) diff --git a/source/engine/jsffi.c b/source/engine/jsffi.c index 53595b9..9b69f1d 100644 --- a/source/engine/jsffi.c +++ b/source/engine/jsffi.c @@ -162,19 +162,9 @@ JSValue js_getpropidx(JSValue v, uint32_t i) static inline cpBody *js2body(JSValue v) { return js2gameobject(v)->body; } -uint64_t js2uint64(JSValue v) -{ - int64_t i; - JS_ToInt64(js, &i, v); - uint64_t n = i; - return n; -} +uint64_t js2uint64(JSValue v) { return JS_VALUE_GET_INT(v); } -int js2int(JSValue v) { - int32_t i; - JS_ToInt32(js, &i, v); - return i; -} +int js2int(JSValue v) { return JS_VALUE_GET_INT(v); } JSValue int2js(int i) { return JS_NewInt64(js, i); } @@ -191,6 +181,7 @@ JSValue strarr2js(char **c) } double js2number(JSValue v) { + return JS_VALUE_GET_FLOAT64(v); double g; JS_ToFloat64(js, &g, v); return g; @@ -233,6 +224,87 @@ int js_arrlen(JSValue v) { return len; } +char *js_nota_decode(JSValue *tmp, char *nota) +{ + int type = nota_type(nota); + JSValue ret; + JSValue ret2; + long long n; + double d; + int b; + + char *str = NULL; + switch(type) { + case NOTA_BLOB: + break; + case NOTA_TEXT: + nota = nota_read_text(str, nota); + *tmp = str2js(str); + return nota; + case NOTA_ARR: + nota = nota_read_array(&n, nota); + ret = JS_NewArray(js); + for (int i = 0; i < n; i++) { + nota = js_nota_decode(&ret2, nota); + JS_SetPropertyInt64(js, ret, i, ret2); + } + break; + case NOTA_REC: + break; + case NOTA_FLOAT: + nota = nota_read_float(&d, nota); + *tmp = number2js(d); + return nota; + case NOTA_INT: + nota = nota_read_int(&n, nota); + *tmp = int2js(n); + return nota; + case NOTA_SYM: + nota = nota_read_bool(&b, nota); + *tmp = bool2js(b); + return nota; + } +} + +char *js_nota_encode(JSValue v, char *nota) +{ + int tag = JS_VALUE_GET_TAG(v); + char *str; + JSPropertyEnum *ptab; + uint32_t plen; + int n; + JSValue val; + + switch(tag) { + case JS_TAG_FLOAT64: + return nota_write_float(JS_VALUE_GET_FLOAT64(v), nota); + case JS_TAG_INT: + return nota_write_int(JS_VALUE_GET_INT(v), nota); + case JS_TAG_STRING: + return nota_write_text(JS_VALUE_GET_PTR(v), nota); + case JS_TAG_BOOL: + return nota_write_bool(JS_VALUE_GET_BOOL(v), nota); + case JS_TAG_OBJECT: + if (JS_IsArray(js, v)) { + int n = js_arrlen(v); + nota = nota_write_array(n, nota); + for (int i = 0; i < js_arrlen(v); i++) + nota = js_nota_encode(js_arridx(v, i), nota); + return nota; + } + + n = JS_GetOwnPropertyNames(js, &ptab, &plen, v, JS_GPN_ENUM_ONLY | JS_GPN_STRING_MASK); + nota = nota_write_record(plen, nota); + for (int i = 0; i < plen; i++) { + /* todo: slower than atomtocstring */ + val = JS_AtomToString(js, ptab[i].atom); + nota = nota_write_text(JS_VALUE_GET_PTR(v), nota); + nota = js_nota_encode(JS_GetProperty(js, v, ptab[i].atom), nota); + } + return nota; + } +} + struct rgba js2color(JSValue v) { JSValue c[4]; for (int i = 0; i < 4; i++) @@ -1935,25 +2007,14 @@ JSValue duk_profile(JSContext *js, JSValueConst this, int argc, JSValueConst *ar JSValue nota_encode(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) { - printf("nota encode\n"); if (argc < 1) return JS_UNDEFINED; JSValue obj = argv[0]; - char nota[1024]; + char nota[100000]; + char *e = js_nota_encode(obj, nota); + *e = 0; - if (JS_IsNumber(obj)) { - double n; - JS_ToFloat64(js, &n, obj); - nota_write_float(n, nota); - } else if (JS_IsString(obj)) { - char *str = js2str(obj); - nota_write_text(str, nota); - } else if (JS_IsBool(obj)) { - int b = js2bool(obj); - nota_write_bool(b, nota); - } - - return str2js(nota); + return JS_NewStringLen(js, nota, e-nota); } JSValue nota_decode(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) @@ -1961,25 +2022,9 @@ JSValue nota_decode(JSContext *js, JSValueConst this, int argc, JSValueConst *ar if (argc < 1) return JS_UNDEFINED; char *nota = js2str(argv[0]); - int type = nota_type(nota); - long long n; - - switch(type) { - case NOTA_BLOB: - break; - case NOTA_TEXT: - return str2js(nota_read_text(nota)); - case NOTA_INT: - printf("type int\n"); - nota_read_num(nota, &n); - printf("num is %lld\n", n); - return int2js(n); - case NOTA_SYM: - return bool2js(nota_read_bool(nota)); - default: - return number2js(nota_read_float(nota)); - } - return JS_UNDEFINED; + JSValue ret; + js_nota_decode(&ret, nota); + return ret; } static const JSCFunctionListEntry nota_funcs[] = { @@ -1987,7 +2032,6 @@ static const JSCFunctionListEntry nota_funcs[] = { JS_CFUNC_DEF("decode", 1, nota_decode) }; - #define DUK_FUNC(NAME, ARGS) JS_SetPropertyStr(js, globalThis, #NAME, JS_NewCFunction(js, duk_##NAME, #NAME, ARGS)); void ffi_load() { diff --git a/source/engine/nota.c b/source/engine/nota.c index 07e1b36..d2ae8cc 100644 --- a/source/engine/nota.c +++ b/source/engine/nota.c @@ -23,6 +23,14 @@ int nota_type(char *nota) { return *nota & NOTA_TYPE; } +char *nota_skip(char *nota) +{ + while (CONTINUE(*nota)) + nota++; + + return nota+1; +} + int nota_bits(long long n, int sb) { int bits; @@ -64,11 +72,16 @@ char *nota_continue_num(long long n, char *nota, int sb) void print_nota_hex(char *nota) { - long long chars = 0; - if (!((*nota>>4 & 0x07) ^ NOTA_TEXT>>4)) { - nota_read_num(nota, &chars); - printf("print with %d points\n", chars); + while (*nota) { + printf("%02X ", (unsigned char)(*nota)); + nota++; } + printf("\n"); + + return; + long long chars = 0; + if (!((*nota>>4 & 0x07) ^ NOTA_TEXT>>4)) + nota_read_num(&chars, nota); if ((*nota>>5) == 2 || (*nota>>5) == 6) chars = 1; @@ -82,9 +95,8 @@ void print_nota_hex(char *nota) printf("\n"); } -void nota_write_int(long long n, char *nota) +char *nota_write_int(long long n, char *nota) { - printf("number %lld\n", n); char sign = 0; if (n < 0) { @@ -94,13 +106,14 @@ void nota_write_int(long long n, char *nota) nota[0] = NOTA_INT | sign; - nota = nota_continue_num(n, nota, 3); - *nota = 0; - print_nota_hex(nota); + return nota_continue_num(n, nota, 3); } -char *nota_read_num(char *nota, long long *n) +char *nota_read_num(long long *n, char *nota) { + if (!n) + return nota_skip(nota); + *n = 0; *n |= (*nota) & NOTA_HEAD_DATA; @@ -114,12 +127,10 @@ char *nota_read_num(char *nota, long long *n) #define xstr(s) str(s) #define str(s) #s -void nota_write_float(double n, char *nota) +char *nota_write_float(double n, char *nota) { - if (n == 0) { - nota_write_int(0, nota); - return; - } + if (n == 0) + return nota_write_int(0, nota); int sign = n < 0 ? ~0 : 0; if (sign) n *= -1; @@ -140,11 +151,8 @@ void nota_write_float(double n, char *nota) ns[1] = ns[0]; long long sig = atoll(ns+1); - if (e == 0) { - if (sign) sig*=-1; - nota_write_int(sig, nota); - return; - } + if (e == 0) + return nota_write_int(sig * (sign ? -1 : 1), nota); int expsign = e < 0 ? ~0 : 0; if (expsign) e *= -1; @@ -155,26 +163,24 @@ void nota_write_float(double n, char *nota) char *c = nota_continue_num(e, nota, 3); - nota_continue_num(sig, c, 7); - - printf("float number %g\n", n* (sign ? -1 : 1)); - printf("aka %d x 10^%d\n", sig, e); - print_nota_hex(nota); + return nota_continue_num(sig, c, 7); } -double nota_read_float(char *nota) +char *nota_read_float(double *d, char *nota) { - printf("reading ...\n"); print_nota_hex(nota); long long sig = 0; long long e = 0; char *c = nota; e = (*c) & NOTA_INT_DATA; /* first three bits */ + while (CONTINUE(*c)) { e = (e<<7) | (*c) & NOTA_DATA; c++; } + + c++; sig = (*c) & NOTA_DATA; while (CONTINUE(*c)) { @@ -185,38 +191,60 @@ double nota_read_float(char *nota) if (NOTA_SIG_SIGN(*nota)) sig *= -1; if (NOTA_EXP_SIGN(*nota)) e *= -1; - printf("got %lld x 10^%lld\n", sig, exp); - - return (double)sig * pow(10.0, e); + *d = (double)sig * pow(10.0, e); + return nota; } -long long nota_read_int(char *nota) +char *nota_read_int(long long *n, char *nota) { - long long n = 0; - char *c = nota; - n |= (*c) & NOTA_INT_DATA; /* first three bits */ - while (CONTINUE(*(c++))) - n = (n<<7) | (*c) & NOTA_DATA; + if (!n) + return nota_skip(nota); - if (NOTA_INT_SIGN(*nota)) n *= -1; - return n; + char *c = nota; + *n |= (*c) & NOTA_INT_DATA; /* first three bits */ + while (CONTINUE(*(c++))) + *n = (*n<<7) | (*c) & NOTA_DATA; + + if (NOTA_INT_SIGN(*nota)) *n *= -1; + + return c+1; } /* n is the number of bits */ -void nota_write_blob(unsigned long long n, char *nota) +char *nota_write_blob(unsigned long long n, char *nota) { - printf("blob %lld\n", n); nota[0] = NOTA_BLOB; - nota_continue_num(n, nota, 4); - print_nota_hex(nota); + return nota_continue_num(n, nota, 4); } -void nota_write_array(unsigned long long n, char *nota) +char *nota_write_array(unsigned long long n, char *nota) { - printf("array %lld\n", n); nota[0] = NOTA_ARR; - nota_continue_num(n, nota, 4); - print_nota_hex(nota); + return nota_continue_num(n, nota, 4); +} + +char *nota_read_array(long long *len, char *nota) +{ + if (!len) return nota; + return nota_read_num(len, nota); +} + +char *nota_read_record(long long *len, char *nota) +{ + if (!len) return nota; + return nota_read_num(len, nota); +} + +char *nota_read_blob(long long *len, char *nota) +{ + if (!len) return nota; + return nota_read_num(len, nota); +} + +char *nota_write_record(unsigned long long n, char *nota) +{ + nota[0] = NOTA_REC; + return nota_continue_num(n, nota, 4); } /* kim is 7, 14, then 21 */ @@ -325,33 +353,36 @@ void kim_to_utf8(char *kim, char *utf, int runes) *utf = 0; } -char *nota_read_text(char *nota) +char *nota_read_text(char *text, char *nota) { long long chars; - nota = nota_read_num(nota, &chars); - printf("reading %d runes\n", chars); + nota = nota_read_num(&chars, nota); char utf[chars*4]; kim_to_utf8(nota, utf, chars); - return strdup(utf); + text = strdup(utf); + return nota; } -void nota_write_bool(int b, char *nota) +char *nota_write_bool(int b, char *nota) { *nota = NOTA_SYM | (b ? NOTA_TRUE : NOTA_FALSE); + nota++; + return nota; } -int nota_read_bool(char *nota) +char *nota_read_bool(int *b, char *nota) { - return *nota & 0x0f; + if (b) *b = (*nota) & 0x0f; + return nota+1; } -void nota_write_text(char *s, char *nota) +char *nota_write_text(char *s, char *nota) { char *start = nota; nota[0] = NOTA_TEXT; - long n = utf8_count(s); - printf("text %s with %d points\n", s, n); + long long n = utf8_count(s); nota = nota_continue_num(n,nota,4); utf8_to_kim(s, nota); - print_nota_hex(start); + return nota+n; } + diff --git a/source/engine/nota.h b/source/engine/nota.h index ae3c2c4..a684988 100644 --- a/source/engine/nota.h +++ b/source/engine/nota.h @@ -10,16 +10,23 @@ #define NOTA_SYM 0x70 int nota_type(char *nota); -void nota_write_int(long long n, char *nota); -long long nota_read_int(char *nota); -char *nota_read_num(char *nota, long long *n); -void nota_write_float(double n, char *nota); -double nota_read_float(char *nota); -void nota_write_bool(int b, char *nota); -int nota_read_bool(char *nota); -void nota_write_blob(unsigned long long n, char *nota); -void nota_write_array(unsigned long long n, char *nota); -void nota_write_text(char *s, char *nota); -char *nota_read_text(char *nota); + +char *nota_read_blob(long long *len, char *nota); +char *nota_read_text(char *text, char *nota); +char *nota_read_array(long long *len, char *nota); +char *nota_read_record(long long *len, char *nota); +char *nota_read_float(double *d, char *nota); +char *nota_read_int(long long *l, char *nota); +char *nota_read_bool(int *b, char *nota); + +char *nota_read_num(long long *n, char *nota); + +char *nota_write_blob(unsigned long long n, char *nota); +char *nota_write_text(char *s, char *nota); +char *nota_write_array(unsigned long long n, char *nota); +char *nota_write_record(unsigned long long n, char *nota); +char *nota_write_float(double n, char *nota); +char *nota_write_int(long long n, char *nota); +char *nota_write_bool(int b, char *nota); #endif