Files
cell/json.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", 1, js_cell_json_encode),
JS_CFUNC_DEF ("decode", 1, 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;
}