From ec96cbf01693a90db15a13c3e77f68909036989e Mon Sep 17 00:00:00 2001 From: Petri Lehtinen Date: Thu, 17 Dec 2009 23:42:13 +0200 Subject: [PATCH] Encode reals correctly This patch changes the sprintf format from "%0.17f" to "%.17g", as the f format specifier doesn't print the exponent at all. This caused losing precision in all but the most simple cases. Because the g specifier doesn't print the decimal fraction or exponent if they're not needed, a ".0" has to be appended by hand in these cases. Otherwise the value's type changes from real to integer when decoding again. Thanks to Philip Grandinetti for reporting this issue. --- src/dump.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/dump.c b/src/dump.c index 7dbc9f2..bd12a7b 100644 --- a/src/dump.c +++ b/src/dump.c @@ -145,10 +145,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); }