X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=src%2Fdump.c;h=a862cba286ed5ba87f965f7f5d1503f397512b57;hb=782acfe378b8d6dddb307029ba97688943312340;hp=dc3fcbcb1fed63a0f46010b50c0ed605591bb5ca;hpb=50031440a3b7ab2623e9468bd20e837250250cd9;p=jansson.git diff --git a/src/dump.c b/src/dump.c index dc3fcbc..a862cba 100644 --- a/src/dump.c +++ b/src/dump.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Petri Lehtinen + * Copyright (c) 2009, 2010 Petri Lehtinen * * Jansson is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include "jansson_private.h" @@ -153,6 +153,18 @@ static int dump_string(const char *str, int ascii, dump_func dump, void *data) return dump("\"", 1, data); } +static int object_key_compare_keys(const void *key1, const void *key2) +{ + return strcmp((*(const object_key_t **)key1)->key, + (*(const object_key_t **)key2)->key); +} + +static int object_key_compare_serials(const void *key1, const void *key2) +{ + return (*(const object_key_t **)key1)->serial - + (*(const object_key_t **)key2)->serial; +} + static int do_dump(const json_t *json, unsigned long flags, int depth, dump_func dump, void *data) { @@ -185,10 +197,25 @@ static int do_dump(const json_t *json, unsigned long flags, int depth, char buffer[MAX_REAL_STR_LENGTH]; int size; - size = snprintf(buffer, MAX_REAL_STR_LENGTH, "%0.17f", json_real_value(json)); + size = snprintf(buffer, MAX_REAL_STR_LENGTH, "%.17g", + json_real_value(json)); if(size >= MAX_REAL_STR_LENGTH) return -1; + /* Make sure there's a dot or 'e' in the output. Otherwise + a real is converted to an integer when decoding */ + if(strchr(buffer, '.') == NULL && + strchr(buffer, 'e') == NULL) + { + if(size + 2 >= MAX_REAL_STR_LENGTH) { + /* No space to append ".0" */ + return -1; + } + buffer[size] = '.'; + buffer[size + 1] = '0'; + size += 2; + } + return dump(buffer, size, data); } @@ -269,29 +296,100 @@ static int do_dump(const json_t *json, unsigned long flags, int depth, if(dump_indent(flags, depth + 1, 0, dump, data)) return -1; - while(iter) + if(flags & JSON_SORT_KEYS || flags & JSON_PRESERVE_ORDER) { - void *next = json_object_iter_next((json_t *)json, iter); - - dump_string(json_object_iter_key(iter), ascii, dump, data); - if(dump(separator, separator_length, data) || - do_dump(json_object_iter_value(iter), flags, depth + 1, - dump, data)) + const object_key_t **keys; + unsigned int size; + unsigned int i; + int (*cmp_func)(const void *, const void *); + + size = json_object_size(json); + keys = malloc(size * sizeof(object_key_t *)); + if(!keys) return -1; - if(next) + i = 0; + while(iter) { - if(dump(",", 1, data) || - dump_indent(flags, depth + 1, 1, dump, data)) - return -1; + keys[i] = jsonp_object_iter_fullkey(iter); + iter = json_object_iter_next((json_t *)json, iter); + i++; } + assert(i == size); + + if(flags & JSON_SORT_KEYS) + cmp_func = object_key_compare_keys; else + cmp_func = object_key_compare_serials; + + qsort(keys, size, sizeof(object_key_t *), cmp_func); + + for(i = 0; i < size; i++) { - if(dump_indent(flags, depth, 0, dump, data)) + const char *key; + json_t *value; + + key = keys[i]->key; + value = json_object_get(json, key); + assert(value); + + dump_string(key, ascii, dump, data); + if(dump(separator, separator_length, data) || + do_dump(value, flags, depth + 1, dump, data)) + { + free(keys); return -1; + } + + if(i < size - 1) + { + if(dump(",", 1, data) || + dump_indent(flags, depth + 1, 1, dump, data)) + { + free(keys); + return -1; + } + } + else + { + if(dump_indent(flags, depth, 0, dump, data)) + { + free(keys); + return -1; + } + } } - iter = next; + free(keys); + } + else + { + /* Don't sort keys */ + + while(iter) + { + void *next = json_object_iter_next((json_t *)json, iter); + + dump_string(json_object_iter_key(iter), ascii, dump, data); + if(dump(separator, separator_length, 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, 1, dump, data)) + return -1; + } + else + { + if(dump_indent(flags, depth, 0, dump, data)) + return -1; + } + + iter = next; + } } object->visited = 0;