201 lines
5.3 KiB
C
Executable File
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;
|
|
}
|