/*
- * Copyright (c) 2009 Petri Lehtinen <petri@digip.org>
+ * Copyright (c) 2009, 2010 Petri Lehtinen <petri@digip.org>
*
* Jansson is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <stdint.h>
+#include <assert.h>
#include <jansson.h>
#include "jansson_private.h"
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)
{
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);
}
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;