Files
cell/source/qjs_nota.c

201 lines
5.3 KiB
C
Executable File

#include "quickjs.h"
#define KIM_IMPLEMENTATION
#define NOTA_IMPLEMENTATION
#include "nota.h"
JSValue number;
char *js_do_nota_decode(JSContext *js, JSValue *tmp, char *nota)
{
int type = nota_type(nota);
JSValue ret2;
long long n;
double d;
int b;
char *str;
uint8_t *blob;
switch(type) {
case NOTA_BLOB:
nota = nota_read_blob(&n, &blob, nota);
*tmp = JS_NewArrayBufferCopy(js, blob, n);
free(blob);
break;
case NOTA_TEXT:
nota = nota_read_text(&str, nota);
*tmp = JS_NewString(js, str);
/* TODO: Avoid malloc and free here */
free(str);
break;
case NOTA_ARR:
nota = nota_read_array(&n, nota);
*tmp = JS_NewArray(js);
for (int i = 0; i < n; i++) {
nota = js_do_nota_decode(js, &ret2, nota);
JS_SetPropertyInt64(js, *tmp, i, ret2);
}
break;
case NOTA_REC:
nota = nota_read_record(&n, nota);
*tmp = JS_NewObject(js);
for (int i = 0; i < n; i++) {
nota = nota_read_text(&str, nota);
nota = js_do_nota_decode(js, &ret2, nota);
JS_SetPropertyStr(js, *tmp, str, ret2);
free(str);
}
break;
case NOTA_INT:
nota = nota_read_int(&n, nota);
*tmp = JS_NewInt64(js,n);
break;
case NOTA_SYM:
nota = nota_read_sym(&b, nota);
switch(b) {
case NOTA_NULL:
*tmp = JS_UNDEFINED;
break;
case NOTA_FALSE:
*tmp = JS_NewBool(js,0);
break;
case NOTA_TRUE:
*tmp = JS_NewBool(js,1);
break;
}
break;
default:
case NOTA_FLOAT:
nota = nota_read_float(&d, nota);
*tmp = JS_NewFloat64(js,d);
break;
}
return nota;
}
// Writers the JSValue v into the buffer of char *nota, returning a pointer to the next byte in nota to be written
char *js_do_nota_encode(JSContext *js, JSValue v, char *nota)
{
int tag = JS_VALUE_GET_TAG(v);
const char *str = NULL;
JSPropertyEnum *ptab;
uint32_t plen;
double nval;
JSValue val;
void *blob;
size_t bloblen;
switch(tag) {
case JS_TAG_FLOAT64:
case JS_TAG_INT:
case JS_TAG_BIG_DECIMAL:
case JS_TAG_BIG_INT:
case JS_TAG_BIG_FLOAT:
JS_ToFloat64(js, &nval, v);
return nota_write_number(nval, nota);
/* str = JS_ToCString(js,v);
nota = nota_write_decimal_str(str, nota);
JS_FreeCString(js,str);
return nota;
*/
case JS_TAG_STRING:
str = JS_ToCString(js, v);
nota = nota_write_text(str, nota);
JS_FreeCString(js, str);
return nota;
case JS_TAG_BOOL:
if (JS_VALUE_GET_BOOL(v)) return nota_write_sym(NOTA_TRUE, nota);
else
return nota_write_sym(NOTA_FALSE, nota);
case JS_TAG_UNDEFINED:
case JS_TAG_NULL:
return nota_write_sym(NOTA_NULL, nota);
case JS_TAG_OBJECT:
blob = JS_GetArrayBuffer(js,&bloblen, v);
if (blob)
return nota_write_blob(bloblen*8, blob, nota);
if (JS_IsArray(js, v)) {
int n;
JS_ToInt32(js, &n, JS_GetPropertyStr(js, v, "length"));
nota = nota_write_array(n, nota);
for (int i = 0; i < n; i++)
nota = js_do_nota_encode(js, JS_GetPropertyUint32(js, v, i), nota);
return nota;
}
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++) {
val = JS_GetProperty(js,v,ptab[i].atom);
str = JS_AtomToCString(js, ptab[i].atom);
JS_FreeAtom(js, ptab[i].atom);
nota = nota_write_text(str, nota);
JS_FreeCString(js, str);
nota = js_do_nota_encode(js, val, nota);
JS_FreeValue(js,val);
}
js_free(js, ptab);
return nota;
default:
return nota;
}
return nota;
}
JSValue js_nota_encode(JSContext *js, JSValue self, int argc, JSValue *argv)
{
if (argc < 1)
JS_ThrowInternalError(js, "Expected at least one argument to encode.");
JSValue obj = argv[0];
char nota[1024*1024];
char *e = js_do_nota_encode(js, obj, nota);
return JS_NewArrayBufferCopy(js, (unsigned char*)nota, e-nota);
}
JSValue js_nota_decode(JSContext *js, JSValue self, int argc, JSValue *argv)
{
if (argc < 1) return JS_UNDEFINED;
size_t len;
unsigned char *nota = JS_GetArrayBuffer(js, &len, argv[0]);
JSValue ret;
js_do_nota_decode(js, &ret, (char*)nota);
return ret;
}
static const JSCFunctionListEntry js_nota_funcs[] = {
JS_CFUNC_DEF("encode", 1, js_nota_encode),
JS_CFUNC_DEF("decode", 1, js_nota_decode),
};
static int js_nota_init(JSContext *ctx, JSModuleDef *m) {
JS_SetModuleExportList(ctx, m, js_nota_funcs, sizeof(js_nota_funcs)/sizeof(JSCFunctionListEntry));
return 0;
}
JSValue js_nota_use(JSContext *js)
{
JSValue export = JS_NewObject(js);
JS_SetPropertyFunctionList(js, export, js_nota_funcs, sizeof(js_nota_funcs)/sizeof(JSCFunctionListEntry));
number = JS_GetPropertyStr(js, JS_GetGlobalObject(js), "Number");
return export;
}
#ifdef JS_SHARED_LIBRARY
#define JS_INIT_MODULE js_init_module
#else
#define JS_INIT_MODULE js_init_module_nota
#endif
JSModuleDef *JS_INIT_MODULE(JSContext *ctx, const char *module_name) {
JSModuleDef *m = JS_NewCModule(ctx, module_name, js_nota_init);
if (!m) return NULL;
JS_AddModuleExportList(ctx, m, js_nota_funcs, sizeof(js_nota_funcs)/sizeof(JSCFunctionListEntry));
return m;
}