Add mechanizm for caching local and peer addresses in AsyncSSLSocket.
[folly.git] / folly / dynamic-inl.h
index 6e2fd62a290705d5d0e7f7902e2512a9e1bf8005..73ab5d37184e535c9b0e7e60b41b0d3508420c12 100644 (file)
@@ -282,6 +282,11 @@ inline dynamic::dynamic(fbstring&& s)
   new (&u_.string) fbstring(std::move(s));
 }
 
+inline dynamic& dynamic::operator=(std::initializer_list<dynamic> il) {
+  (*this) = dynamic(il);
+  return *this;
+}
+
 inline dynamic::dynamic(std::initializer_list<dynamic> il)
   : type_(ARRAY)
 {
@@ -512,6 +517,41 @@ template<class K, class V> inline void dynamic::insert(K&& key, V&& val) {
   rv.first->second = std::forward<V>(val);
 }
 
+inline void dynamic::update(const dynamic& mergeObj) {
+  if (!isObject() || !mergeObj.isObject()) {
+    throw TypeError("object", type(), mergeObj.type());
+  }
+
+  for (const auto& pair : mergeObj.items()) {
+    (*this)[pair.first] = pair.second;
+  }
+}
+
+inline void dynamic::update_missing(const dynamic& mergeObj1) {
+  if (!isObject() || !mergeObj1.isObject()) {
+    throw TypeError("object", type(), mergeObj1.type());
+  }
+
+  // Only add if not already there
+  for (const auto& pair : mergeObj1.items()) {
+    if ((*this).find(pair.first) == (*this).items().end()) {
+      (*this)[pair.first] = pair.second;
+    }
+  }
+}
+
+inline dynamic dynamic::merge(
+    const dynamic& mergeObj1,
+    const dynamic& mergeObj2) {
+
+  // No checks on type needed here because they are done in update_missing
+  // Note that we do update_missing here instead of update() because
+  // it will prevent the extra writes that would occur with update()
+  auto ret = mergeObj2;
+  ret.update_missing(mergeObj1);
+  return ret;
+}
+
 inline std::size_t dynamic::erase(dynamic const& key) {
   auto& obj = get<ObjectImpl>();
   return obj.erase(key);
@@ -577,24 +617,22 @@ inline void dynamic::pop_back() {
 
 //////////////////////////////////////////////////////////////////////
 
-template<class T> struct dynamic::TypeInfo {
-  static char const name[];
-  static Type const type;
-};
-
-#define FB_DEC_TYPE(T)                                      \
-  template<> char const dynamic::TypeInfo<T>::name[];       \
-  template<> dynamic::Type const dynamic::TypeInfo<T>::type
+#define FOLLY_DYNAMIC_DEC_TYPEINFO(T, str, val) \
+  template <> struct dynamic::TypeInfo<T> { \
+    static constexpr const char* name = str; \
+    static constexpr dynamic::Type type = val; \
+  }; \
+  //
 
-FB_DEC_TYPE(void*);
-FB_DEC_TYPE(bool);
-FB_DEC_TYPE(fbstring);
-FB_DEC_TYPE(dynamic::Array);
-FB_DEC_TYPE(double);
-FB_DEC_TYPE(int64_t);
-FB_DEC_TYPE(dynamic::ObjectImpl);
+FOLLY_DYNAMIC_DEC_TYPEINFO(void*,               "null",    dynamic::NULLT)
+FOLLY_DYNAMIC_DEC_TYPEINFO(bool,                "boolean", dynamic::BOOL)
+FOLLY_DYNAMIC_DEC_TYPEINFO(fbstring,            "string",  dynamic::STRING)
+FOLLY_DYNAMIC_DEC_TYPEINFO(dynamic::Array,      "array",   dynamic::ARRAY)
+FOLLY_DYNAMIC_DEC_TYPEINFO(double,              "double",  dynamic::DOUBLE)
+FOLLY_DYNAMIC_DEC_TYPEINFO(int64_t,             "int64",   dynamic::INT64)
+FOLLY_DYNAMIC_DEC_TYPEINFO(dynamic::ObjectImpl, "object",  dynamic::OBJECT)
 
-#undef FB_DEC_TYPE
+#undef FOLLY_DYNAMIC_DEC_TYPEINFO
 
 template<class T>
 T dynamic::asImpl() const {
@@ -690,6 +728,14 @@ struct dynamic::PrintImpl {
     out << t;
   }
 };
+// Otherwise, null, being (void*)0, would print as 0.
+template <>
+struct dynamic::PrintImpl<void*> {
+  static void print(dynamic const& d, std::ostream& out, void* const& nul) {
+    DCHECK_EQ((void*)0, nul);
+    out << "null";
+  }
+};
 template<>
 struct dynamic::PrintImpl<dynamic::ObjectImpl> {
   static void print(dynamic const& d,