summaryrefslogtreecommitdiff
path: root/src/print.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/print.c')
-rw-r--r--src/print.c112
1 files changed, 112 insertions, 0 deletions
diff --git a/src/print.c b/src/print.c
new file mode 100644
index 0000000..4b5c72c
--- /dev/null
+++ b/src/print.c
@@ -0,0 +1,112 @@
+#include <stdarg.h>
+#include <stdio.h>
+#include <json.h>
+
+static bool append_printf(char **dest, size_t *size, size_t *index, const char *fmt, ...) {
+ va_list ap;
+ int len;
+
+ va_start(ap, fmt);
+ len = vsnprintf(*dest + *index, *size - *index, fmt, ap);
+ va_end(ap);
+
+ if (*index + len >= *size) {
+ *size = *size * 2 > *size + len + 1 ? *size * 2 : *size + len + 1;
+ *dest = realloc(*dest, *size);
+
+ va_start(ap, fmt);
+ len = vsnprintf(*dest + *index, *size - *index, fmt, ap);
+ va_end(ap);
+ }
+
+ // TODO: Fix this ugly cast
+ if (len < 0 || len >= (ssize_t)*size) {
+ free(*dest);
+ *dest = "";
+ return false;
+ }
+
+ *index += len;
+
+ return true;
+}
+
+void print_item(struct json *json, char **str, size_t *size, size_t *index) {
+ switch (json->type) {
+ case JSON_OBJECT:
+ append_printf(str, size, index, "{");
+ for (struct json *j = json->children->items[0]; j; j = j->next) {
+ append_printf(str, size, index, "\"%s\":", j->key ? j->key : "(null)");
+ print_item(j, str, size, index);
+ if (j->next)
+ append_printf(str, size, index, ",");
+ }
+ append_printf(str, size, index, "}");
+ break;
+ case JSON_ARRAY:
+ append_printf(str, size, index, "[");
+ for (size_t i = 0; i < json->children->nitems; i++) {
+ struct json *j = json->children->items[i];
+ print_item(j, str, size, index);
+ if (i != json->children->nitems - 1)
+ append_printf(str, size, index, ",");
+ }
+ append_printf(str, size, index, "]");
+ break;
+ case JSON_NUMBER:
+ append_printf(str, size, index, "%lf", json->num);
+ break;
+ case JSON_TRUE:
+ append_printf(str, size, index, "true");
+ break;
+ case JSON_FALSE:
+ append_printf(str, size, index, "false");
+ break;
+ case JSON_NULL:
+ append_printf(str, size, index, "null");
+ break;
+ case JSON_STRING:
+ append_printf(str, size, index, "\"");
+ for (char *ptr = json->string; *ptr != '\0'; ptr++) {
+ switch (*ptr) {
+ case '\\':
+ append_printf(str, size, index, "%s", "\\\\");
+ break;
+ case '\"':
+ append_printf(str, size, index, "%s", "\\\"");
+ break;
+ case '\n':
+ append_printf(str, size, index, "%s", "\\n");
+ break;
+ case '\f':
+ append_printf(str, size, index, "%s", "\\f");
+ break;
+ case '\b':
+ append_printf(str, size, index, "%s", "\\b");
+ break;
+ case '\r':
+ append_printf(str, size, index, "%s", "\\r");
+ break;
+ case '\t':
+ append_printf(str, size, index, "%s", "\\t");
+ break;
+ default:
+ append_printf(str, size, index, "%c", *ptr);
+ break;
+ }
+ }
+ append_printf(str, size, index, "\"");
+ break;
+ case JSON_INVALID:
+ break;
+ }
+}
+
+char *json_print(struct json *json) {
+ size_t size = 1024;
+ size_t index = 0;
+ char *str = calloc(size, sizeof(char));
+ print_item(json, &str, &size, &index);
+ return str;
+}
+