Ported protobuf's dtoa() function for text format and JSON.
diff --git a/upb/json_encode.c b/upb/json_encode.c
index a63b3c6..64826e3 100644
--- a/upb/json_encode.c
+++ b/upb/json_encode.c
@@ -38,6 +38,7 @@
#include "upb/decode.h"
#include "upb/reflection.h"
+#include "upb/upb_internal.h"
/* Must be last. */
#include "upb/port_def.inc"
@@ -305,7 +306,7 @@
jsonenc_putstr(e, "\"");
}
-static void jsonenc_double(jsonenc* e, const char* fmt, double val) {
+static bool upb_JsonEncode_HandleSpecialDoubles(jsonenc* e, double val) {
if (val == INFINITY) {
jsonenc_putstr(e, "\"Infinity\"");
} else if (val == -INFINITY) {
@@ -313,18 +314,23 @@
} else if (val != val) {
jsonenc_putstr(e, "\"NaN\"");
} else {
- char* p = e->ptr;
- jsonenc_printf(e, fmt, val);
-
- /* printf() is dependent on locales; sadly there is no easy and portable way
- * to avoid this. This little post-processing step will translate 1,2 -> 1.2
- * since JSON needs the latter. Arguably a hack, but it is simple and the
- * alternatives are far more complicated, platform-dependent, and/or larger
- * in code size. */
- for (char* end = e->ptr; p < end; p++) {
- if (*p == ',') *p = '.';
- }
+ return false;
}
+ return true;
+}
+
+static void upb_JsonEncode_Double(jsonenc* e, double val) {
+ if (upb_JsonEncode_HandleSpecialDoubles(e, val)) return;
+ char buf[32];
+ _upb_EncodeRoundTripDouble(val, buf, sizeof(buf));
+ jsonenc_putstr(e, buf);
+}
+
+static void upb_JsonEncode_Float(jsonenc* e, float val) {
+ if (upb_JsonEncode_HandleSpecialDoubles(e, val)) return;
+ char buf[32];
+ _upb_EncodeRoundTripFloat(val, buf, sizeof(buf));
+ jsonenc_putstr(e, buf);
}
static void jsonenc_wrapper(jsonenc* e, const upb_Message* msg,
@@ -517,7 +523,7 @@
jsonenc_putstr(e, "null");
break;
case 2:
- jsonenc_double(e, "%.17g", val.double_val);
+ upb_JsonEncode_Double(e, val.double_val);
break;
case 3:
jsonenc_string(e, val.str_val);
@@ -582,10 +588,10 @@
jsonenc_putstr(e, val.bool_val ? "true" : "false");
break;
case kUpb_CType_Float:
- jsonenc_double(e, "%.9g", val.float_val);
+ upb_JsonEncode_Float(e, val.float_val);
break;
case kUpb_CType_Double:
- jsonenc_double(e, "%.17g", val.double_val);
+ upb_JsonEncode_Double(e, val.double_val);
break;
case kUpb_CType_Int32:
jsonenc_printf(e, "%" PRId32, val.int32_val);