68 lines
2.2 KiB
C
68 lines
2.2 KiB
C
#include "cell.h"
|
|
#include <string.h>
|
|
|
|
/* JSON uses JS_KEY_empty for reviver — define locally from public constants */
|
|
#ifndef JS_KEY_empty
|
|
#define JS_KEY_empty ((JSValue)JS_TAG_STRING_IMM)
|
|
#endif
|
|
|
|
static JSValue js_cell_json_encode (JSContext *ctx, JSValue this_val, int argc, JSValue *argv) {
|
|
if (argc < 1)
|
|
return JS_RaiseDisrupt (ctx, "json.encode requires at least 1 argument");
|
|
|
|
int pretty = argc <= 1 || JS_ToBool (ctx, argv[1]);
|
|
JSValue space = pretty ? JS_NewInt32 (ctx, 2) : JS_NULL;
|
|
JSValue replacer = JS_NULL;
|
|
if (argc > 2 && JS_IsFunction (argv[2]))
|
|
replacer = argv[2];
|
|
else if (argc > 3 && JS_IsArray (argv[3]))
|
|
replacer = argv[3];
|
|
JSValue result = JS_JSONStringify (ctx, argv[0], replacer, space, pretty);
|
|
return result;
|
|
}
|
|
|
|
static JSValue js_cell_json_decode (JSContext *ctx, JSValue this_val, int argc, JSValue *argv) {
|
|
if (argc < 1)
|
|
return JS_RaiseDisrupt (ctx, "json.decode requires at least 1 argument");
|
|
|
|
if (!JS_IsText (argv[0]))
|
|
return JS_RaiseDisrupt (ctx, "couldn't parse text: not a string");
|
|
|
|
const char *str = JS_ToCString (ctx, argv[0]);
|
|
if (!str) return JS_EXCEPTION;
|
|
|
|
size_t len = strlen (str);
|
|
JSValue result = JS_ParseJSON (ctx, str, len, "<json>");
|
|
JS_FreeCString (ctx, str);
|
|
|
|
/* Apply reviver if provided */
|
|
if (argc > 1 && JS_IsFunction (argv[1]) && !JS_IsException (result)) {
|
|
/* Create wrapper object to pass to reviver */
|
|
JSValue wrapper = JS_NewObject (ctx);
|
|
JS_SetPropertyStr (ctx, wrapper, "", result);
|
|
|
|
JSValue holder = wrapper;
|
|
JSValue key = JS_KEY_empty;
|
|
JSValue args[2] = { key, JS_GetProperty (ctx, holder, key) };
|
|
JSValue final = JS_Call (ctx, argv[1], holder, 2, args);
|
|
result = final;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static const JSCFunctionListEntry js_cell_json_funcs[] = {
|
|
JS_CFUNC_DEF ("encode", 4, js_cell_json_encode),
|
|
JS_CFUNC_DEF ("decode", 2, js_cell_json_decode),
|
|
};
|
|
|
|
JSValue js_core_json_use (JSContext *ctx) {
|
|
JSGCRef obj_ref;
|
|
JS_PushGCRef (ctx, &obj_ref);
|
|
obj_ref.val = JS_NewObject (ctx);
|
|
JS_SetPropertyFunctionList (ctx, obj_ref.val, js_cell_json_funcs, countof (js_cell_json_funcs));
|
|
JSValue result = obj_ref.val;
|
|
JS_PopGCRef (ctx, &obj_ref);
|
|
return result;
|
|
}
|