Future<Unit> global fixup
[folly.git] / folly / json.cpp
index f51b038b4f186891b6be8614bbc467eeded69a68..fe06001cfee9c75ac7a7c199d49b06840c9568b6 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)
@@ -705,18 +725,21 @@ fbstring stripComments(StringPiece jsonC) {
           state = State::LineComment;
           ++i;
           continue;
-        } else if (s.startsWith("\"")) {
+        } else if (s[0] == '\"') {
           state = State::InString;
         }
         result.push_back(s[0]);
         break;
       case State::InString:
-        if (s.startsWith("\\\"")) {
+        if (s[0] == '\\') {
+          if (UNLIKELY(s.size() == 1)) {
+            throw std::logic_error("Invalid JSONC: string is not terminated");
+          }
           result.push_back(s[0]);
           result.push_back(s[1]);
           ++i;
           continue;
-        } else if (s.startsWith("\"")) {
+        } else if (s[0] == '\"') {
           state = State::None;
         }
         result.push_back(s[0]);
@@ -728,7 +751,7 @@ fbstring stripComments(StringPiece jsonC) {
         }
         break;
       case State::LineComment:
-        if (s.startsWith("\n")) {
+        if (s[0] == '\n') {
           // skip the line break. It doesn't matter.
           state = State::None;
         }