--- 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 = ", ";