@@ -215,17 +215,34 @@ void Dumper::appendUInt(uint64_t v) {
215215
216216void Dumper::appendDouble (double v) {
217217 char temp[24 ];
218- int len = fpconv_dtoa (v, &temp[0 ]);
219- _sink->append (&temp[0 ], static_cast <ValueLength>(len));
220- if (fabs (v) < ldexpl (1.0 , 53 )) {
221- return ;
222- }
223- for (size_t i = 0 ; i < len; ++i) {
224- if (temp[i] == ' .' || temp[i] == ' e' || temp[i] == ' E' ) {
225- return ;
218+ double a = fabs (v);
219+ if (a >= ldexpl (1.0 , 53 ) && a < ldexpl (1.0 , 64 )) {
220+ // This is a special case which we want to handle separately, because
221+ // of two reasons:
222+ // (1) The function fpconv_dtoa below only guarantees to write a
223+ // decimal representation which gives the same double value when
224+ // parsed back into a double. It can write a wrong integer.
225+ // Therefore we want to use the integer code in this case.
226+ // (2) The function fpconv_dtoa will write a normal integer
227+ // representation in this case without a decimal point. If we
228+ // parse this back to vpack later, we end up in a different
229+ // representation (uint64_t or int64_t), so we want to append
230+ // ".0" to the string in this case.
231+ // Note that this automatically excludes all infinities and NaNs,
232+ // which will be handled in the function fpconv_dtoa below.
233+ uint64_t u;
234+ if (v < 0 ) {
235+ u = static_cast <uint64_t >(-v);
236+ _sink->append (" -" , 1 );
237+ } else {
238+ u = static_cast <uint64_t >(v);
226239 }
240+ appendUInt (u);
241+ _sink->append (" .0" , 2 );
242+ return ;
227243 }
228- _sink->append (" .0" , 2 );
244+ int len = fpconv_dtoa (v, &temp[0 ]);
245+ _sink->append (&temp[0 ], static_cast <ValueLength>(len));
229246}
230247
231248void Dumper::dumpUnicodeCharacter (uint16_t value) {
0 commit comments