src/json.c

changeset 1078
ffa8bb4e9288
parent 1077
911a154dd469
child 1079
4e1872151fb6
--- a/src/json.c	Thu Jan 02 19:07:56 2025 +0100
+++ b/src/json.c	Thu Jan 02 20:58:32 2025 +0100
@@ -944,6 +944,36 @@
     };
 }
 
+static int cx_json_writer_indent(
+    void *target,
+    cx_write_func wfunc,
+    const CxJsonWriter *settings,
+    unsigned int depth
+) {
+    if (depth == 0) return 0;
+
+    // determine the width and characters to use
+    const char* indent; // for 32 prepared chars
+    size_t width = depth;
+    if (settings->indent_space) {
+        if (settings->indent == 0) return 0;
+        width *= settings->indent;
+        indent = "                                ";
+    } else {
+        indent = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
+    }
+
+    // calculate the number of write calls and write
+    size_t full = width / 32;
+    size_t remaining = width % 32;
+    for (size_t i = 0; i < full; i++) {
+        if (32 != wfunc(indent, 1, 32, target)) return 1;
+    }
+    if (remaining != wfunc(indent, 1, remaining, target)) return 1;
+
+    return 0;
+}
+
 
 int cx_json_write_rec(
     void *target,
@@ -952,9 +982,8 @@
     const CxJsonWriter *settings,
     unsigned int depth
 ) {
-    // TODO: implement indentation
-
     // keep track of written items
+    // the idea is to reduce the number of jumps for error checking
     size_t actual = 0, expected = 0;
 
     // small buffer for number to string conversions
@@ -971,8 +1000,14 @@
                 actual += wfunc(begin_obj, 1, 1, target);
                 expected++;
             }
+            depth++;
             CxIterator iter = cxJsonObjIter(value);
             cx_foreach(CxJsonObjValue*, member, iter) {
+                // possible indentation
+                if (settings->pretty) {
+                    if (cx_json_writer_indent(target, wfunc, settings, depth)) return 1;
+                }
+
                 // the name
                 actual += wfunc("\"", 1, 1, target);
                 // TODO: escape the string
@@ -989,13 +1024,7 @@
                 }
 
                 // the value
-                if (0 == cx_json_write_rec(
-                        target, member->value,
-                        wfunc, settings, depth + 1)
-                ) {
-                    actual++; // count the nested values as one item
-                }
-                expected++;
+                if (cx_json_write_rec(target, member->value, wfunc, settings, depth)) return 1;
 
                 // end of object-value
                 if (iter.index < iter.elem_count - 1) {
@@ -1014,6 +1043,10 @@
                     }
                 }
             }
+            depth--;
+            if (settings->pretty) {
+                if (cx_json_writer_indent(target, wfunc, settings, depth)) return 1;
+            }
             actual += wfunc("}", 1, 1, target);
             expected++;
             break;
@@ -1024,14 +1057,10 @@
             expected++;
             CxIterator iter = cxJsonArrIter(value);
             cx_foreach(CxJsonValue*, element, iter) {
-                // TODO: pretty printing obj elements vs. primitives
-                if (0 == cx_json_write_rec(
+                if (cx_json_write_rec(
                         target, element,
-                        wfunc, settings, depth + 1)
-                ) {
-                    actual++; // count the nested values as one item
-                }
-                expected++;
+                        wfunc, settings, depth)
+                ) return 1;
 
                 if (iter.index < iter.elem_count - 1) {
                     const char *arr_value_sep = ", ";

mercurial