Fix picojson number representation 67/113467/1
authorJakub Skowron <j.skowron@samsung.com>
Tue, 7 Feb 2017 18:39:54 +0000 (19:39 +0100)
committerJakub Skowron <j.skowron@samsung.com>
Tue, 7 Feb 2017 18:39:54 +0000 (19:39 +0100)
Previous implementation assumed default global locale.
Failed when locale used other decimal point than '.'

Change-Id: I1ffe2847c249cf666e720342e41ed068178cc459
Signed-off-by: Jakub Skowron <j.skowron@samsung.com>
src/common/picojson.h

index 6921b1f12fc08f207afed7124f61cfbe41b810dd..eca7efc9f04c3bbb4207377d6cc94a881b915d4b 100644 (file)
@@ -36,6 +36,8 @@
 #include <cstdlib>
 #include <cstring>
 #include <iostream>
+#include <sstream>
+#include <iomanip>
 #include <iterator>
 #include <map>
 #include <string>
@@ -264,10 +266,14 @@ namespace picojson {
     case null_type:      return "null";
     case boolean_type:   return u_.boolean_ ? "true" : "false";
     case number_type:    {
-      char buf[256];
-      double tmp;
-      SNPRINTF(buf, sizeof(buf), fabs(u_.number_) < (1ULL << 53) && modf(u_.number_, &tmp) == 0 ? "%.f" : "%.17g", u_.number_);
-      return buf;
+      std::stringstream num_str;
+      num_str.imbue( std::locale::classic() );
+      double ignored;
+      if( std::modf(u_.number_, &ignored) != 0 || std::fabs(u_.number_) >= (1ULL << 53) ) {
+        num_str << std::scientific << std::setprecision(16);
+      }
+      num_str << u_.number_;
+      return num_str.str();
     }
     case string_type:    return *u_.string_;
     case array_type:     return "array";
@@ -557,20 +563,23 @@ namespace picojson {
   }
   
   template <typename Iter> inline bool _parse_number(double& out, input<Iter>& in) {
-    std::string num_str;
-    while (1) {
+    std::stringstream num_str;
+    num_str.imbue( std::locale::classic() );
+
+    while (true) {
       int ch = in.getc();
       if (('0' <= ch && ch <= '9') || ch == '+' || ch == '-' || ch == '.'
          || ch == 'e' || ch == 'E') {
-       num_str.push_back(ch);
+       num_str.put(ch);
       } else {
        in.ungetc();
        break;
       }
     }
-    char* endp;
-    out = strtod(num_str.c_str(), &endp);
-    return endp == num_str.c_str() + num_str.size();
+
+    num_str >> out;
+
+    return num_str && num_str.eof();
   }
   
   template <typename Context, typename Iter> inline bool _parse(Context& ctx, input<Iter>& in) {