ref: c5dfca354a35575443084622a74de02ef3e6ea8e
author: sirjofri <sirjofri@sirjofri.de>
date: Sat Mar 7 18:27:14 EST 2026
adds files
--- /dev/null
+++ b/mkfile
@@ -1,0 +1,7 @@
+</$objtype/mkfile
+
+LIB=rjson.a$O
+OFILES= \
+ rjson.$O\
+
+</sys/src/cmd/mklib
\ No newline at end of file
--- /dev/null
+++ b/rjson.c
@@ -1,0 +1,144 @@
+#include <u.h>
+#include <libc.h>
+#include <json.h>
+#include "rjson.h"
+
+int
+rjsontostruct(JSON *json, Rjson *rjson, void *target)
+{+ Rjson *rj;
+ JSON *j;
+ char **s;
+ double *n;
+ int *b;
+ char *o;
+
+ if (!json) {+ werrstr("invalid json");+ return 0;
+ }
+
+ if (!target) {+ werrstr("invalid target struct");+ return 0;
+ }
+
+ if (!rjson) {+ werrstr("invalid rjson");+ return 0;
+ }
+
+ for (rj = rjson; rj->name; rj++) {+ j = jsonbyname(json, rj->name);
+ if (!j)
+ continue;
+ if (j->t != rj->type) {+ werrstr("inconsistent type: %s is not %d\n", rj->name, rj->type);+ return 0;
+ }
+ switch (j->t) {+ case JSONNull:
+ /* skip null */
+ break;
+ case JSONBool:
+ b = (int*)((char*)target + rj->addr);
+ *b = !!j->n;
+ break;
+ case JSONNumber:
+ n = (double*)((char*)target + rj->addr);
+ *n = j->n;
+ break;
+ case JSONString:
+ s = (char**)((char*)target + rj->addr);
+ *s = strdup(j->s);
+ break;
+ case JSONArray: // TODO
+ break;
+ case JSONObject:
+ if (!rj->sub) {+ werrstr("object %s without valid rjson", rj->name);+ return 0;
+ }
+ o = (char*)target + rj->addr;
+ return rjsontostruct(j, rj->sub, o);
+ break;
+ }
+ }
+ return 1;
+}
+
+static void
+jappend(JSON *json, char *name, JSON *jn)
+{+ JSONEl *jel;
+
+ if (!json->first) {+ jel = json->first = mallocz(sizeof(JSONEl), 1);
+ } else {+ for (jel = json->first; jel->next; jel = jel->next)
+ ;
+ jel->next = mallocz(sizeof(JSONEl), 1);
+ jel = jel->next;
+ }
+ assert(jel);
+ jel->name = strdup(name);
+ jel->val = jn;
+}
+
+JSON*
+rstructtojson(void *src, Rjson *rjson)
+{+ JSON *json, *j;
+ Rjson *rj;
+ int *i;
+ double *n;
+ char **s;
+ char *o;
+
+ if (!src) {+ werrstr("invalid src");+ return nil;
+ }
+ if (!rjson) {+ werrstr("invalid rjson");+ return nil;
+ }
+
+ json = mallocz(sizeof(JSON), 1);
+ assert(json);
+
+ json->t = JSONObject;
+ for (rj = rjson; rj->name; rj++) {+ if (rj->type == JSONNull)
+ continue;
+ if (rj->type == JSONObject) {+ o = (char*)src + rj->addr;
+ j = rstructtojson(o, rj->sub);
+ jappend(json, rj->name, j);
+ continue;
+ }
+ j = mallocz(sizeof(JSON), 1);
+ assert(j);
+ jappend(json, rj->name, j);
+
+ j->t = rj->type;
+ switch (j->t) {+ case JSONBool:
+ i = (int*)((char*)src + rj->addr);
+ j->n = *i;
+ break;
+ case JSONNumber:
+ n = (double*)((char*)src + rj->addr);
+ j->n = *n;
+ break;
+ case JSONString:
+ s = (char**)((char*)src + rj->addr);
+ j->s = strdup(*s);
+ break;
+ case JSONArray: // TODO
+ break;
+ }
+ }
+
+ return json;
+}
--- /dev/null
+++ b/rjson.h
@@ -1,0 +1,17 @@
+#define RJSON_BEGIN(A) Rjson A[] = {+#define RJSON_END() { 0, 0, nil }};+#define RJSON_STRING(A, N) { offsetof(A, N), JSONString, "N", nil },+#define RJSON_NUMBER(A, N) { offsetof(A, N), JSONNumber, "N", nil },+#define RJSON_BOOL(A, N) { offsetof(A, N), JSONBool, "N", nil },+#define RJSON_OBJECT(A, N, S) { offsetof(A, N), JSONObject, "N", S },+
+typedef struct Rjson Rjson;
+struct Rjson {+ int addr;
+ int type;
+ char *name;
+ Rjson *sub;
+};
+
+int rjsontostruct(JSON *json, Rjson*, void*);
+JSON *rstructtojson(void *src, Rjson*);
--- /dev/null
+++ b/test/mkfile
@@ -1,0 +1,6 @@
+</$objtype/mkfile
+
+TEST=t
+LIB=../rjson.a$O
+
+</sys/src/cmd/mktest
--- /dev/null
+++ b/test/t.c
@@ -1,0 +1,88 @@
+#include <u.h>
+#include <libc.h>
+#include "json.h"
+#include "../rjson.h"
+
+typedef struct Sub Sub;
+struct Sub {+ char *xyz;
+};
+
+RJSON_BEGIN(Sub_rjson)
+ RJSON_STRING(Sub,xyz)
+RJSON_END()
+
+typedef struct Test Test;
+struct Test {+ char *one;
+ char *two;
+ double num;
+ int bool;
+ Sub obj;
+};
+
+RJSON_BEGIN(Test_rjson)
+ RJSON_STRING(Test,one)
+ RJSON_STRING(Test,two)
+ RJSON_NUMBER(Test,num)
+ RJSON_BOOL(Test,bool)
+ RJSON_OBJECT(Test,obj,Sub_rjson)
+RJSON_END()
+
+
+char *testjson = ""
+"{\n"+" \"one\": \"eins\",\n"
+" \"two\": \"zwei\",\n"
+" \"num\": 5.540000,\n"
+" \"bool\": true,\n"
+" \"obj\": {\n"+" \"xyz\": \"abc\"\n"
+" }\n"
+"}\n";
+
+void
+main()
+{+ Test t;
+ JSON *j;
+ char *s;
+ int verbose;
+ verbose = !!getenv("verbose");+
+ JSONfmtinstall();
+
+ j = jsonparse(testjson);
+ if (!j)
+ sysfatal("%r");+
+ if (verbose) fprint(2, "=== Testing rjsontostruct\n");
+ if (rjsontostruct(j, Test_rjson, &t)) {+ if (verbose) {+ fprint(2, "parsed: %r\n");
+ fprint(2, " one: %s\n", t.one);
+ fprint(2, " two: %s\n", t.two);
+ fprint(2, " num: %f\n", t.num);
+ fprint(2, " bool: %d\n", t.bool);
+ fprint(2, " obj.xyz: %s\n", t.obj.xyz);
+ }
+ } else {+ fprint(2, "parse failed: %r\n");
+ }
+
+ jsonfree(j);
+
+ if (verbose) fprint(2, "=== Testing rstructtojson\n");
+ j = rstructtojson(&t, Test_rjson);
+ if (!j)
+ sysfatal("err: %r");+ if (verbose)
+ fprint(2, "%J\n", j);
+
+ s = smprint("%J\n", j);+
+ if (strcmp(s, testjson) != 0)
+ exits("test failed");+
+ exits(nil);
+}
--
⑨