aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPetri Lehtinen <petri@digip.org>2009-12-17 23:42:13 +0200
committerPetri Lehtinen <petri@digip.org>2009-12-18 00:05:06 +0200
commitec96cbf01693a90db15a13c3e77f68909036989e (patch)
treed697085af6755c905cf664ff84176ed115e5c96e
parent7c707a73a2251c20afaecc028267b99d0ee60184 (diff)
downloadjansson-ec96cbf01693a90db15a13c3e77f68909036989e.zip
jansson-ec96cbf01693a90db15a13c3e77f68909036989e.tar.gz
jansson-ec96cbf01693a90db15a13c3e77f68909036989e.tar.bz2
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.
-rw-r--r--src/dump.c17
1 files changed, 16 insertions, 1 deletions
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);
}