浏览代码

Fixed a bug with negative number handling.

Samuel Jaffe 9 年之前
父节点
当前提交
b4171bfc66
共有 3 个文件被更改,包括 69 次插入41 次删除
  1. 1 1
      example.json
  2. 32 6
      json_common.cpp
  3. 36 34
      json_common.hpp

+ 1 - 1
example.json

@@ -1,4 +1,4 @@
 {
-  "t":{"a":1,"b":2},
+  "t":{"a":1,"b":-2},
   "d":1.5
 }

+ 32 - 6
json_common.cpp

@@ -19,13 +19,39 @@ namespace json {
       }
     }
     
-    char const * get_numeric_token_end(char const * start) {
-      while (strchr(",]}", *start) == NULL &&
-             !isspace(*start)) {
-        ++start;
+    numeric_token_info::numeric_token_info(char const * start)
+    : val(0)
+    , it(start)
+    , end(start)
+    , is_double(false)
+    , is_negative(*start == '-') {
+      if ( is_negative ) { ++it; ++end; }
+      for (char c = *end;
+           strchr(",]}", c) == NULL && !isspace(c);
+           c = *++end) {
+        is_double |= !isdigit(*end);
+      }
+      
+      if (end == it) {
+        throw malformed_json_exception("Expected any token, got nothing");
       }
-      return start;
     }
+    
+    numeric_state numeric_token_info::parse_numeric() {
+      static uint_jt const threshold = (UINT_JT_MAX / 10);
+      val = 0;
+      for (char c = *it; it != end; c = *++it) {
+        int_jt digit = static_cast<int_jt>(c - '0');
+        if (val > threshold ||
+            ( val == threshold && ((it + 1) < end ||
+              digit > INT_JT_MAX_LAST_DIGIT))) {
+          return DOUBLE;
+        }
+        val = (10 * val) + digit;
+      }
+      return INTEGER;
+    }
+
 
     const char get_next_element(char const*& data) {
       while (isspace(*data)) ++data;
@@ -49,6 +75,6 @@ namespace json {
         }
       }
       throw json::malformed_json_exception("Could not locate end of string");
-    }    
+    }
   }
 }

+ 36 - 34
json_common.hpp

@@ -39,7 +39,24 @@ namespace json {
 namespace json {
   namespace helper {
     const char get_next_element(char const*& data);
-    char const * get_numeric_token_end(char const * start);
+    
+    enum numeric_state {
+      DOUBLE, INTEGER
+    };
+
+    struct numeric_token_info {
+      numeric_token_info(char const * start);
+      numeric_state parse_numeric();
+      
+      uint_jt val;
+
+      char const * it;
+      char const * end;
+      bool is_double;
+      bool is_negative;
+    };
+    
+    numeric_token_info get_numeric_token_info(char const * it);
     
     /**
      * @throws json::malformed_json_exception
@@ -72,42 +89,27 @@ namespace json {
     
     template <typename J>
     void parse_numeric(J & json, char const * & data) {
-      char const * start = data;
-      char const * const end = get_numeric_token_end(start);
-      
-      if (end == start) {
-        throw malformed_json_exception("Expected any token, got nothing");
-      }
+      numeric_token_info info = data;
       
-      bool const negative = *start == '-';
-      if (negative) ++start;
-      
-      uint_jt const threshold = (UINT_JT_MAX / 10);
-      uint_jt val = 0;
-      for (; start != end; ++start) {
-        if (!isdigit(*start)) {
-          helper::parse_double(json, data);
-          return;
-        }
-        int_jt digit = static_cast<int_jt>(*start - '0');
-        if (val >= threshold) {
-          if (val > threshold || (start + 1) < end || digit > INT_JT_MAX_LAST_DIGIT) {
-            helper::parse_double(json, data);
-            return;
+      if ( info.is_double ) {
+        helper::parse_double(json, data);
+      } else if ( info.parse_numeric() == DOUBLE ) {
+        helper::parse_double(json, data);
+      } else {
+        uint_jt const val = info.val;
+        if (info.is_negative) {
+          if (val == INT_JT_OVER) {
+            json = INT_JT_MIN;
+          } else {
+            json = -int_jt(val);
           }
+        } else if (val <= uint_jt(INT_JT_MAX)) {
+          json = int_jt(val);
+        } else {
+          json = val;
         }
-        val = (10 * val) + digit;
+        data = info.it;
       }
-      if (negative && val == INT_JT_OVER) {
-        json = INT_JT_MIN;
-      } else if (negative) {
-        json = -int_jt(val);
-      } else if (val <= uint_jt(INT_JT_MAX)) {
-        json = int_jt(val);
-      } else {
-        json = val;
-      }
-      data = start;
     }
-  }  
+  }
 }