mesos-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From b...@apache.org
Subject [4/6] git commit: JSON parsing and equality.
Date Tue, 04 Mar 2014 22:06:45 GMT
JSON parsing and equality.

Review: https://reviews.apache.org/r/18700


Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/fd0079f6
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/fd0079f6
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/fd0079f6

Branch: refs/heads/master
Commit: fd0079f6e07e884a3c1b6448a553b3d5cd1f8dce
Parents: fd7de52
Author: Benjamin Hindman <benjamin.hindman@gmail.com>
Authored: Fri Feb 28 22:11:57 2014 -0800
Committer: Benjamin Hindman <benjamin.hindman@gmail.com>
Committed: Tue Mar 4 14:05:54 2014 -0800

----------------------------------------------------------------------
 .../3rdparty/stout/include/stout/json.hpp       | 165 ++++++++++++++++++-
 .../3rdparty/stout/tests/json_tests.cpp         |  31 ++++
 2 files changed, 187 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/fd0079f6/3rdparty/libprocess/3rdparty/stout/include/stout/json.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/include/stout/json.hpp b/3rdparty/libprocess/3rdparty/stout/include/stout/json.hpp
index 778398a..e52be56 100644
--- a/3rdparty/libprocess/3rdparty/stout/include/stout/json.hpp
+++ b/3rdparty/libprocess/3rdparty/stout/include/stout/json.hpp
@@ -14,6 +14,8 @@
 #ifndef __STOUT_JSON__
 #define __STOUT_JSON__
 
+#include <picojson.h>
+
 #include <iomanip>
 #include <iostream>
 #include <limits>
@@ -25,11 +27,11 @@
 #include <boost/utility/enable_if.hpp>
 #include <boost/variant.hpp>
 
+#include <stout/check.hpp>
 #include <stout/foreach.hpp>
+#include <stout/try.hpp>
+#include <stout/unreachable.hpp>
 
-// TODO(jsirois): Implement parsing that constructs JSON objects.
-
-// TODO(bmahler): Evaluate picojson / JSON_Spirit.
 namespace JSON {
 
 // Implementation of the JavaScript Object Notation (JSON) grammar
@@ -116,7 +118,6 @@ struct Null {};
 
 namespace internal {
 
-
 // Only Object and Array require recursive_wrapper, not sure
 // if there is a reason to wrap the others or not.
 // Null needs to be first so that it is the default value.
@@ -148,17 +149,90 @@ struct Value : internal::Variant
   Value(
       const T& value,
       typename boost::enable_if<boost::is_arithmetic<T>, int>::type = 0)
-      : internal::Variant(Number(value)) {}
+    : internal::Variant(Number(value)) {}
 
   // Non-arithmetic types are passed to the default constructor of Variant.
   template <typename T>
   Value(
       const T& value,
       typename boost::disable_if<boost::is_arithmetic<T>, int>::type = 0)
-      : internal::Variant(value) {}
+    : internal::Variant(value) {}
+
+  template <typename T>
+  bool is() const
+  {
+    const T* t = boost::get<T>(this);
+    return t != NULL;
+  }
+
+  template <typename T>
+  const T& as() const
+  {
+    return *CHECK_NOTNULL(boost::get<T>(this));
+  }
 };
 
 
+inline bool operator == (const Value& lhs, const Value& rhs)
+{
+  struct Visitor : boost::static_visitor<bool>
+  {
+    Visitor(const Value& _value)
+      : value(_value) {}
+
+    bool operator () (const Object& object) const
+    {
+      if (value.is<Object>()) {
+        return value.as<Object>().values == object.values;
+      }
+      return false;
+    }
+
+    bool operator () (const String& string) const
+    {
+      if (value.is<String>()) {
+        return value.as<String>().value == string.value;
+      }
+      return false;
+    }
+
+    bool operator () (const Number& number) const
+    {
+      if (value.is<Number>()) {
+        return value.as<Number>().value == number.value;
+      }
+      return false;
+    }
+
+    bool operator () (const Array& array) const
+    {
+      if (value.is<Array>()) {
+        return value.as<Array>().values == array.values;
+      }
+      return false;
+    }
+
+    bool operator () (const Boolean& boolean) const
+    {
+      if (value.is<Boolean>()) {
+        return value.as<Boolean>().value == boolean.value;
+      }
+      return false;
+    }
+
+    bool operator () (const Null&) const
+    {
+      return value.is<Null>();
+    }
+
+  private:
+    const Value& value;
+  };
+
+  return boost::apply_visitor(Visitor(lhs), rhs);
+}
+
+
 // Implementation of rendering JSON objects built above using standard
 // C++ output streams. The visitor pattern is used thanks to to build
 // a "renderer" with boost::static_visitor and two top-level render
@@ -241,7 +315,7 @@ struct Renderer : boost::static_visitor<>
     out << "]";
   }
 
-  void operator() (const Boolean& boolean) const
+  void operator () (const Boolean& boolean) const
   {
     out << (boolean.value ? "true" : "false");
   }
@@ -262,12 +336,85 @@ inline void render(std::ostream& out, const Value& value)
 }
 
 
-inline std::ostream& operator<<(std::ostream& out, const JSON::Value& value)
+inline std::ostream& operator << (std::ostream& out, const Value& value)
 {
-  JSON::render(out, value);
+  render(out, value);
   return out;
 }
 
+
+namespace internal {
+
+inline Value convert(const picojson::value& value)
+{
+  if (value.is<picojson::null>()) {
+    return Null();
+  } else if (value.is<bool>()) {
+    return Boolean(value.get<bool>());
+  } else if (value.is<picojson::value::object>()) {
+    Object object;
+    foreachpair (const std::string& name,
+                 const picojson::value& value,
+                 value.get<picojson::value::object>()) {
+      object.values[name] = convert(value);
+    }
+    return object;
+  } else if (value.is<picojson::value::array>()) {
+    Array array;
+    foreach (const picojson::value& value,
+             value.get<picojson::value::array>()) {
+      array.values.push_back(convert(value));
+    }
+    return array;
+  } else if (value.is<double>()) {
+    return Number(value.get<double>());
+  } else if (value.is<std::string>()) {
+    return String(value.get<std::string>());
+  }
+  return Null();
+}
+
+} // namespace internal {
+
+
+inline Try<Value> parse(const std::string& s)
+{
+  picojson::value value;
+  std::string error;
+
+  picojson::parse(value, s.c_str(), s.c_str() + s.size(), &error);
+
+  if (!error.empty()) {
+    return Error(error);
+  }
+
+  return internal::convert(value);
+}
+
+
+template <typename T>
+Try<T> parse(const std::string& s)
+{
+  Try<Value> value = parse(s);
+
+  if (value.isError()) {
+    return Error(value.error());
+  }
+
+  if (!value.get().is<T>()) {
+    return Error("Unexpected JSON type parsed");
+  }
+
+  return value.get().as<T>();
+}
+
+
+template <>
+inline Try<Value> parse(const std::string& s)
+{
+  return parse(s);
+}
+
 } // namespace JSON {
 
 #endif // __STOUT_JSON__

http://git-wip-us.apache.org/repos/asf/mesos/blob/fd0079f6/3rdparty/libprocess/3rdparty/stout/tests/json_tests.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/tests/json_tests.cpp b/3rdparty/libprocess/3rdparty/stout/tests/json_tests.cpp
index 5b7cbb9..ee82d15 100644
--- a/3rdparty/libprocess/3rdparty/stout/tests/json_tests.cpp
+++ b/3rdparty/libprocess/3rdparty/stout/tests/json_tests.cpp
@@ -8,8 +8,10 @@
 
 #include <string>
 
+#include <stout/gtest.hpp>
 #include <stout/json.hpp>
 #include <stout/stringify.hpp>
+#include <stout/strings.hpp>
 
 using std::string;
 
@@ -144,3 +146,32 @@ TEST(JsonTest, NumericAssignment)
   EXPECT_EQ(get<JSON::Number>(v).value, 7.0);
   EXPECT_EQ(d.value, 7.0);
 }
+
+
+TEST(JsonTest, parse)
+{
+  JSON::Object object;
+
+  object.values["strings"] = "string";
+  object.values["integer1"] = 1;
+  object.values["integer2"] = -1;
+  object.values["double1"] = 1;
+  object.values["double2"] = -1;
+  object.values["double3"] = -1.42;
+
+  JSON::Object nested;
+  nested.values["string"] = "string";
+
+  EXPECT_SOME_EQ(nested, JSON::parse<JSON::Object>(stringify(nested)));
+
+  object.values["nested"] = nested;
+
+  JSON::Array array;
+  array.values.push_back(nested);
+
+  EXPECT_SOME_EQ(array, JSON::parse<JSON::Array>(stringify(array)));
+
+  object.values["array"] = array;
+
+  EXPECT_SOME_EQ(object, JSON::parse(stringify(object)));
+}


Mime
View raw message