浏览代码

Using strto* functions instead of sto*, so that we don't need to catch/rethrow exceptions.
Adding template pound-outs for json::value and json::discard_t to prevent compiler errors

Samuel Jaffe 8 年之前
父节点
当前提交
ff2b56e612
共有 4 个文件被更改,包括 27 次插入30 次删除
  1. 3 3
      json.hpp
  2. 9 0
      json/json_binder_discard.cpp
  3. 1 1
      json/json_direct_scalar_binder.hpp
  4. 14 26
      json_common.hpp

+ 3 - 3
json.hpp

@@ -27,6 +27,9 @@
 namespace json {
   class value;
   
+  template <>
+  void helper::parse_numeric(value & json, char const * & data);
+
   namespace parser {
     void parse(value&, char const*);
   }
@@ -59,9 +62,6 @@ namespace json {
 #define X(type) value(type##_jt val) { data.set<type##_jt>(std::move(val)); }
     JSON_TYPE_LIST
 #undef X
-#define X(type) value(type##_jt && val) { data.set<type##_jt>(std::forward<type##_jt>(val)); }
-    JSON_TYPE_LIST
-#undef X
 #define X(type) value& operator=(type##_jt val) { data.set<type##_jt>(std::move(val)); return *this; }
     JSON_TYPE_LIST
 #undef X

+ 9 - 0
json/json_binder_discard.cpp

@@ -17,6 +17,8 @@ namespace json { namespace {
 } }
 template <>
 void json::helper::parse_numeric<json::discard_t>(json::discard_t &, char const * & data);
+template <>
+json::discard_t json::helper::parse_double_impl<json::discard_t>(const char *begin, const char *&end);
 
 namespace json { namespace {
   void parse_object(discard_t& json, char const*& data);
@@ -66,6 +68,13 @@ namespace json { namespace {
 } }
 
 namespace json {
+  template <>
+  discard_t helper::parse_double_impl<discard_t>(const char *begin, const char *&end) {
+    std::strtod(begin, const_cast<char **>(&end));
+    errno = 0;
+    return discard_t{};
+  }
+  
   template <>
   void helper::parse_numeric<discard_t>(discard_t & d, char const * & data) {
     numeric_token_info info = data;

+ 1 - 1
json/json_direct_scalar_binder.hpp

@@ -56,7 +56,7 @@ namespace json { namespace binder {
     virtual binder_impl<T>* clone() const override { return new direct_binder(*this); }
     
     virtual void parse(T& val, char const*& data, parser::options) const override {
-      json::helper::parse_numeric(val.*ptr, data);
+      json::helper::parse_double(val.*ptr, data);
     }
     
     virtual void write(T const& val, std::ostream & data) const override {

+ 14 - 26
json_common.hpp

@@ -11,6 +11,7 @@
 #include <cstdlib>
 #include <stdexcept>
 #include <string>
+#include <errno.h>
 
 namespace json {
   using string_jt = std::string;
@@ -97,47 +98,34 @@ namespace json { namespace helper {
   }
   
   template <typename T>
-  void parse_double_impl(T & json, char const * begin, char const * end) {
-    json = std::stod(std::string(begin, end));
+  T parse_double_impl(char const * begin, char const * & end) {
+    return std::strtod(begin, const_cast<char**>(&end));
   }
   template <>
-  inline void parse_double_impl<float>(float & json, char const * begin, char const * end) {
-    json = std::stof(std::string(begin, end));
+  inline float parse_double_impl<float>(char const * begin, char const * & end) {
+    return std::strtof(begin, const_cast<char**>(&end));
   }
   template <>
-  inline void parse_double_impl<long double>(long double & json, char const * begin, char const * end) {
-    json = std::stold(std::string(begin, end));
+  inline long double parse_double_impl<long double>(char const * begin, char const * & end) {
+    return std::strtold(begin, const_cast<char**>(&end));
   }
   
   template <typename T>
   void parse_double(T& json, char const * & data) {
     char const * begin = data;
-    if (*data == '-') { ++data; }
-    while (isdigit(*data) || *data == '-') { ++data; }
-    if (*data == '.') { ++data; }
-    else if (begin != data && (*data == 'e' || *data == 'E')) {
-      ++data;
-      if (*data == '-') { ++data; }
-    }
-    while (isdigit(*data)) { ++data; }
-    if ( begin == data ) {
-      throw json::json_numeric_exception{"Expected numeric data"};
-    }
-    try {
-      parse_double_impl(json, begin, data);
-    } catch (std::domain_error const &) {
-      throw json::json_numeric_exception{"Expected a numeric type"};
-    } catch (std::out_of_range const &) {
+    errno = 0;
+    T tmp = parse_double_impl<T>(begin, data);
+    if (errno != 0) {
       throw json::json_numeric_width_exception{"Number is out-of-range for floating-point type"};
+    } else if ( begin == data ) {
+      throw json::json_numeric_exception{"Expected numeric data"};
     }
+    errno = 0;
+    json = std::move(tmp);
   }
   
   template <typename J>
   void parse_numeric(J & json, char const * & data) {
-    if (std::is_floating_point<J>::value) {
-      helper::parse_double(json, data);
-      return;
-    }
     numeric_token_info info = data;
     
     if ( info.is_double || info.parse_numeric() == DOUBLE ) {