aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/lib/json.c
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-05-03 17:29:12 +0900
committernsfisis <nsfisis@gmail.com>2026-05-03 18:42:58 +0900
commit3654ce578e6fff53950874adf7e0e4ae0a6eb956 (patch)
tree5b6c04273de38dba70b7c25e55da144f5f7c37da /src/lib/json.c
parent1b406b13b03055d2b2d08e8279a4a80c41ca7c20 (diff)
downloadducc-3654ce578e6fff53950874adf7e0e4ae0a6eb956.tar.gz
ducc-3654ce578e6fff53950874adf7e0e4ae0a6eb956.tar.zst
ducc-3654ce578e6fff53950874adf7e0e4ae0a6eb956.zip
refactor: organize directory structureHEADmain
Diffstat (limited to 'src/lib/json.c')
-rw-r--r--src/lib/json.c112
1 files changed, 112 insertions, 0 deletions
diff --git a/src/lib/json.c b/src/lib/json.c
new file mode 100644
index 0000000..0384516
--- /dev/null
+++ b/src/lib/json.c
@@ -0,0 +1,112 @@
+#include "json.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include "common.h"
+
+struct JsonBuilder {
+ StrBuilder buf;
+ // not supported by ducc for now
+ // bool has_output_element[256];
+ bool* has_output_element;
+ int depth;
+};
+
+JsonBuilder* jsonbuilder_new() {
+ JsonBuilder* b = calloc(1, sizeof(JsonBuilder));
+ strbuilder_init(&b->buf);
+ b->has_output_element = calloc(256, sizeof(bool));
+ return b;
+}
+
+const char* jsonbuilder_get_output(JsonBuilder* b) {
+ return b->buf.buf;
+}
+
+static void emit_comma_if_needed(JsonBuilder* b) {
+ if (b->has_output_element[b->depth - 1]) {
+ strbuilder_append_char(&b->buf, ',');
+ }
+}
+
+void jsonbuilder_object_start(JsonBuilder* b) {
+ strbuilder_append_char(&b->buf, '{');
+ b->has_output_element[b->depth++] = false;
+}
+
+void jsonbuilder_object_end(JsonBuilder* b) {
+ b->depth--;
+ strbuilder_append_char(&b->buf, '}');
+}
+
+void jsonbuilder_object_member_start(JsonBuilder* b, const char* key) {
+ emit_comma_if_needed(b);
+ jsonbuilder_string(b, key);
+ strbuilder_append_char(&b->buf, ':');
+}
+
+void jsonbuilder_object_member_end(JsonBuilder* b) {
+ b->has_output_element[b->depth - 1] = true;
+}
+
+void jsonbuilder_array_start(JsonBuilder* b) {
+ strbuilder_append_char(&b->buf, '[');
+ b->has_output_element[b->depth++] = false;
+}
+
+void jsonbuilder_array_end(JsonBuilder* b) {
+ b->depth--;
+ strbuilder_append_char(&b->buf, ']');
+}
+
+void jsonbuilder_array_element_start(JsonBuilder* b) {
+ emit_comma_if_needed(b);
+}
+
+void jsonbuilder_array_element_end(JsonBuilder* b) {
+ b->has_output_element[b->depth - 1] = true;
+}
+
+void jsonbuilder_null(JsonBuilder* b) {
+ strbuilder_append_string(&b->buf, "null");
+}
+
+void jsonbuilder_boolean(JsonBuilder* b, bool value) {
+ strbuilder_append_string(&b->buf, value ? "true" : "false");
+}
+
+void jsonbuilder_integer(JsonBuilder* b, int value) {
+ char buf[32];
+ sprintf(buf, "%d", value);
+ strbuilder_append_string(&b->buf, buf);
+}
+
+void jsonbuilder_string(JsonBuilder* b, const char* value) {
+ if (!value) {
+ jsonbuilder_null(b);
+ return;
+ }
+
+ strbuilder_append_char(&b->buf, '"');
+
+ for (const char* p = value; *p; p++) {
+ if (*p == '"') {
+ strbuilder_append_string(&b->buf, "\\\"");
+ } else if (*p == '\\') {
+ strbuilder_append_string(&b->buf, "\\\\");
+ } else if (*p == '\b') {
+ strbuilder_append_string(&b->buf, "\\b");
+ } else if (*p == '\f') {
+ strbuilder_append_string(&b->buf, "\\f");
+ } else if (*p == '\n') {
+ strbuilder_append_string(&b->buf, "\\n");
+ } else if (*p == '\r') {
+ strbuilder_append_string(&b->buf, "\\r");
+ } else if (*p == '\t') {
+ strbuilder_append_string(&b->buf, "\\t");
+ } else {
+ strbuilder_append_char(&b->buf, *p);
+ }
+ }
+
+ strbuilder_append_char(&b->buf, '"');
+}