Roundtrip with subnormal float fails to parse
Take a subnormal double such as 3.2114e-312.
jsoncpp has no trouble converting this to a string but then on the other side the used istream sets a failbit.
Which is interpreted as an error (rightly so I'd say) but that leads to a failed parse.
See: https://github.com/open-source-parsers/jsoncpp/blob/8190e061bc2d95da37479a638aa2c9e483e58ec6/src/lib_json/json_reader.cpp#L604
This seems to be OK according to c++-standard but is not exactly practical to use. See also https://stackoverflow.com/questions/48086830/stdstod-throws-out-of-range-error-for-a-string-that-should-be-valid/48087390#48087390 (sorry but I dont want to go search the standards myself).
It's easy to avoid this problem by adding the below here:
//Avoid subnormal representation as istream fails on it, thus making roundtrip impossible https://stackoverflow.com/a/48087390
if(abs(value) < std::numeric_limits<double>::min())
value = abs(value) > (std::numeric_limits<double>::min()/2) ? std::numeric_limits<double>::min() * !signbit(value): 0;
This way the double is forced to be 0 if smaller than or equal to half of the "minimal double" or just that, the minimal double.
And roundtrips are now possible again.
Edit:
This problem occurs for sure on macos with clang. With msvc there seems to be no problem with this and gcc is also be fine. So some kind of ifdef for CLANG around it would make sense.
If wanted I can make a PR for this.
This sounds like it would be a user-configured option for CharReader, so that it will tolerate parsing subnormals.
Json doesn't specify a particular precision or float representation.
std::istream behavior on extraction of subnormals is implementation-defined.
See here.
From jsoncpp's PoV, we have no idea who will be parsing the json we emit. The formatter isn't the parser, and the formatter is trying to represent the Value as accurately as possible by default, which is why we emit 17 places of precision by default, rather than 15. Deviating from this would have to be opt-in.
So rounding of subnormals may also be a user-configured option for CharWriter, not a default?
Yeah a configuration could also be a good way to handle this.
I also just wish that the libc++ on macos would not emit any error on parsing it...
However for our use-case we do know we are also the parser so Ive just baked this solution in there as a workaround.