diff options
Diffstat (limited to 'src/print.c')
| -rw-r--r-- | src/print.c | 112 | 
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; +} + | 
