-
Notifications
You must be signed in to change notification settings - Fork 34
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Misc fixes #173
Misc fixes #173
Conversation
types.c
Outdated
ucv_stringbuf_printf(pb, "%.14g", d); | ||
else { | ||
size_t len = ucv_stringbuf_printf(pb, "%.14g", d); | ||
if (json && !strchr(pb->buf + pb->bpos - len, '.')) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, this feels slightly unelegant. What about this:
...
else if (json && trunc(d) == d)
ucv_stringbuf_printf(pb, "%.1f", d);
else
ucv_stringbuf_printf(pb, "%.14g", d);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought about doing it this way too, but I read in a few places that this can be prone to corner cases caused by weird floating point rounding issue. I think checking the output of sprintf is more reliable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can be prone to corner cases caused by weird floating point rounding issue
Hm, can you provide some links for this? My research so far seems to indicate that trunc(x) == x
is indeed the way to go, but maybe I overlooked something.
The problem with the "scan backwards for a decimal point and append .0
if none found" approach is that it will fail if the %g
format decides to yield an exponent form, e.g. we don't want to turn 1e100
into 1e100.0
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I can't find the original link anymore. I took a look at this from another angle and checked how existing JSON libraries are handling this issue. I looked at json-c, jansson and yajl, and they all use the scan-for-decimal-point approach. The code is rather different in each one, so I don't believe it was copied/cargo-culted between implementations. Would you accept my patch if I keep the approach, but fix the exponent form case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I pushed a fix based on your suggestion and including a testcase covering this corner case. Could you rebase this PR against master so that I can merge the remainder?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
The `%g` printf format used for serializing double values into strings will not include any decimal place if the value happens to be integral, leading to an unwanted double to integer conversion when serializing and subsequently deserializing an integral double value as JSON. Solve this issue by checking the serialized string result for a decimal point or exponential notation and appending `.0` if neither is found. Ref: #173 Suggested-by: Felix Fietkau <nbd@nbd.name> Signed-off-by: Jo-Philipp Wich <jo@mein.io>
… macOS Signed-off-by: Felix Fietkau <nbd@nbd.name>
Accept char * const *, cast internally. Fixes a compile error Signed-off-by: Felix Fietkau <nbd@nbd.name>
Merged, thanks for your patience :) |
Two compile error fixes for macOS, and a fix for preserving the double type when generating JSON.