From: Petri Lehtinen Date: Tue, 12 May 2009 18:34:14 +0000 (+0300) Subject: Implement dumping to file X-Git-Tag: 1.0_branch~305 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=9ea51b28550555484583713261e45df13026fba8;p=profile%2Fivi%2Fjansson.git Implement dumping to file --- diff --git a/src/dump.c b/src/dump.c index 4af0958..3a88d63 100644 --- a/src/dump.c +++ b/src/dump.c @@ -1,46 +1,186 @@ +#define _GNU_SOURCE +#include +#include +#include + #include -char *json_dumps(const json_t *json, uint32_t flags) +typedef int (*dump_func)(const char *buffer, int size, void *data); + +static int dump_to_file(const char *buffer, int size, void *data) +{ + FILE *dest = (FILE *)data; + if(fwrite(buffer, size, 1, dest) != 1) + return -1; + return 0; +} + +static int dump_indent(uint32_t flags, int depth, dump_func dump, void *data) +{ + if(JSON_INDENT(flags) > 0) + { + char *ws_buffer; + int ws_count = JSON_INDENT(flags) * depth; + + if(dump("\n", 1, data)) + return -1; + + if(ws_count == 0) + return 0; + + ws_buffer = alloca(ws_count); + memset(ws_buffer, ' ', ws_count); + return dump(ws_buffer, ws_count, data); + } + else + return dump(" ", 1, data); +} + +static int dump_string(const char *str, dump_func dump, void *data) { - (void)flags; + const char *end; + + if(dump("\"", 1, data)) + return -1; + + end = str; + while(*end) + { + while(*end && *end != '\\' && *end != '"') + end++; + + if(end != str) + if(dump(str, end - str, data)) + return -1; + if(*end == '\\') + { + if(dump("\\\\", 2, data)) + return -1; + end++; + } + else if(*end == '"') + { + if(dump("\\\"", 2, data)) + return -1; + end++; + } + str = end; + } + + return dump("\"", 1, data); +} + +static int do_dump(const json_t *json, uint32_t flags, int depth, + dump_func dump, void *data) +{ switch(json_typeof(json)) { case JSON_NULL: - printf("null"); - break; + return dump("null", 4, data); case JSON_TRUE: - printf("true"); - break; + return dump("true", 4, data); case JSON_FALSE: - printf("false"); - break; + return dump("false", 5, data); case JSON_NUMBER: - printf("%f", json_number_value(json)); - break; + { + char *buffer; + int size, ret; + + size = asprintf(&buffer, "%.17f", json_number_value(json)); + if(size == -1) + return -1; + + ret = dump(buffer, size, data); + free(buffer); + return ret; + } case JSON_STRING: - printf("%s", json_string_value(json)); - break; + return dump_string(json_string_value(json), dump, data); + + case JSON_ARRAY: + { + int i; + int n = json_array_size(json); + + if(dump("[", 1, data)) + return -1; + if(n == 0) + dump("]", 1, data); + if(dump_indent(flags, depth + 1, dump, data)) + return -1; - case JSON_ARRAY: { - int i, n = json_array_size(json); - printf("["); for(i = 0; i < n; ++i) { - json_dumps(json_array_get(json, i), 0); + if(do_dump(json_array_get(json, i), flags, depth + 1, + dump, data)) + return -1; + if(i < n - 1) - printf(", "); + { + if(dump(",", 1, data) || + dump_indent(flags, depth + 1, dump, data)) + return -1; + } + else + { + if(dump_indent(flags, depth, dump, data)) + return -1; + } } - printf("]"); - break; + return dump("]", 1, data); + } + + case JSON_OBJECT: + { + void *iter = json_object_iter((json_t *)json); + + if(dump("{", 1, data)) + return -1; + if(!iter) + return dump("}", 1, data); + if(dump_indent(flags, depth + 1, dump, data)) + return -1; + + while(iter) + { + void *next = json_object_iter_next((json_t *)json, iter); + + dump_string(json_object_iter_key(iter), dump, data); + if(dump(": ", 2, data) || + do_dump(json_object_iter_value(iter), flags, depth + 1, + dump, data)) + return -1; + + if(next) + { + if(dump(",", 1, data) || + dump_indent(flags, depth + 1, dump, data)) + return -1; + } + else + { + if(dump_indent(flags, depth, dump, data)) + return -1; + } + + iter = next; + } + return dump("}", 1, data); } default: - printf(""); - break; + /* not reached */ + return -1; } - return NULL; } + +int json_dumpf(const json_t *json, FILE *output, uint32_t flags) +{ + if(do_dump(json, flags, 0, dump_to_file, (void *)output)) + return -1; + return dump_to_file("\n", 1, (void *)output); +}