qualify std::move in StringKeyedTest
[folly.git] / folly / json.cpp
index d4f0771d98a7d75c6138e0836462e3244ac100f4..4c856598e123bc61a1a8ea8760fdf69ddbf14fdc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2015 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -256,6 +256,26 @@ private:
   serialization_opts const& opts_;
 };
 
+  //////////////////////////////////////////////////////////////////////
+
+  struct ParseError : std::runtime_error {
+    explicit ParseError(int line)
+      : std::runtime_error(to<std::string>("json parse error on line ", line))
+    {}
+
+    explicit ParseError(int line, std::string const& context,
+        std::string const& expected)
+      : std::runtime_error(to<std::string>("json parse error on line ", line,
+          !context.empty() ? to<std::string>(" near `", context, '\'')
+                          : "",
+          ": ", expected))
+    {}
+
+    explicit ParseError(std::string const& msg)
+      : std::runtime_error("json parse error: " + msg)
+    {}
+  };
+
 // Wraps our input buffer with some helper functions.
 struct Input {
   explicit Input(StringPiece range, json::serialization_opts const* opts)
@@ -462,10 +482,23 @@ dynamic parseNumber(Input& in) {
   }
 
   auto const wasE = *in == 'e' || *in == 'E';
+
+  constexpr const char* maxInt = "9223372036854775807";
+  constexpr const char* minInt = "9223372036854775808";
+  constexpr auto maxIntLen = __builtin_strlen(maxInt);
+
   if (*in != '.' && !wasE) {
-    auto val = to<int64_t>(integral);
-    in.skipWhitespace();
-    return val;
+    if (LIKELY(!in.getOpts().double_fallback || integral.size() < maxIntLen) ||
+         (integral.size() == maxIntLen &&
+           (integral <= maxInt || (integral == minInt && negative)))) {
+      auto val = to<int64_t>(integral);
+      in.skipWhitespace();
+      return val;
+    } else {
+      auto val = to<double>(integral);
+      in.skipWhitespace();
+      return val;
+    }
   }
 
   auto end = !wasE ? (++in, in.skipDigits().end()) : in.begin();