Use std::nullptr_t in dynamic
[folly.git] / folly / DynamicConverter.h
index 16c3a0888bf7150e635231a4bddfc140a426193e..9ab4f73ac324b3befc8d2395136ac4e308b08a57 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2015 Facebook, Inc.
+ * Copyright 2017 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -16,8 +16,7 @@
 
 // @author Nicholas Ormrod <njormrod@fb.com>
 
-#ifndef DYNAMIC_CONVERTER_H
-#define DYNAMIC_CONVERTER_H
+#pragma once
 
 #include <folly/dynamic.h>
 namespace folly {
@@ -30,7 +29,9 @@ namespace folly {
  *
  * Example:
  *
- *   dynamic d = { { 1, 2, 3 }, { 4, 5 } }; // a vector of vector of int
+ *   dynamic d = dynamic::array(
+ *       dynamic::array(1, 2, 3),
+ *       dynamic::array(4, 5)); // a vector of vector of int
  *   auto vvi = convertTo<fbvector<fbvector<int>>>(d);
  *
  * See docs/DynamicConverter.md for supported types and customization
@@ -54,13 +55,20 @@ BOOST_MPL_HAS_XXX_TRAIT_DEF(value_type);
 BOOST_MPL_HAS_XXX_TRAIT_DEF(iterator);
 BOOST_MPL_HAS_XXX_TRAIT_DEF(mapped_type);
 
-template <typename T> struct class_is_container {
-  typedef std::reverse_iterator<T*> some_iterator;
+template <typename T> struct iterator_class_is_container {
+  typedef std::reverse_iterator<typename T::iterator> some_iterator;
   enum { value = has_value_type<T>::value &&
-                 has_iterator<T>::value &&
               std::is_constructible<T, some_iterator, some_iterator>::value };
 };
 
+template <typename T>
+using class_is_container = typename
+  std::conditional<
+    has_iterator<T>::value,
+    iterator_class_is_container<T>,
+    std::false_type
+  >::type;
+
 template <typename T> struct class_is_range {
   enum { value = has_value_type<T>::value &&
                  has_iterator<T>::value };
@@ -108,8 +116,8 @@ namespace dynamicconverter_detail {
 
 template<typename T>
 struct Dereferencer {
-  static inline void
-  derefToCache(T* mem, const dynamic::const_item_iterator& it) {
+  static inline void derefToCache(
+      T* /* mem */, const dynamic::const_item_iterator& /* it */) {
     throw TypeError("array", dynamic::Type::OBJECT);
   }
 
@@ -204,6 +212,16 @@ struct DynamicConverter<T,
   }
 };
 
+// enums
+template <typename T>
+struct DynamicConverter<T,
+                        typename std::enable_if<std::is_enum<T>::value>::type> {
+  static T convert(const dynamic& d) {
+    using type = typename std::underlying_type<T>::type;
+    return static_cast<T>(DynamicConverter<type>::convert(d));
+  }
+};
+
 // floating point
 template <typename T>
 struct DynamicConverter<T,
@@ -225,7 +243,7 @@ struct DynamicConverter<folly::fbstring> {
 template <>
 struct DynamicConverter<std::string> {
   static std::string convert(const dynamic& d) {
-    return d.asString().toStdString();
+    return d.asString();
   }
 };
 
@@ -280,11 +298,23 @@ struct DynamicConstructor {
   }
 };
 
+// identity
+template <typename C>
+struct DynamicConstructor<
+    C,
+    typename std::enable_if<std::is_same<C, dynamic>::value>::type> {
+  static dynamic construct(const C& x) {
+    return x;
+  }
+};
+
 // maps
-template<typename C>
-struct DynamicConstructor<C,
+template <typename C>
+struct DynamicConstructor<
+    C,
     typename std::enable_if<
-      dynamicconverter_detail::is_map<C>::value>::type> {
+        !std::is_same<C, dynamic>::value &&
+        dynamicconverter_detail::is_map<C>::value>::type> {
   static dynamic construct(const C& x) {
     dynamic d = dynamic::object;
     for (auto& pair : x) {
@@ -295,14 +325,16 @@ struct DynamicConstructor<C,
 };
 
 // other ranges
-template<typename C>
-struct DynamicConstructor<C,
+template <typename C>
+struct DynamicConstructor<
+    C,
     typename std::enable_if<
-      !dynamicconverter_detail::is_map<C>::value &&
-      !std::is_constructible<StringPiece, const C&>::value &&
-      dynamicconverter_detail::is_range<C>::value>::type> {
+        !std::is_same<C, dynamic>::value &&
+        !dynamicconverter_detail::is_map<C>::value &&
+        !std::is_constructible<StringPiece, const C&>::value &&
+        dynamicconverter_detail::is_range<C>::value>::type> {
   static dynamic construct(const C& x) {
-    dynamic d = {};
+    dynamic d = dynamic::array;
     for (auto& item : x) {
       d.push_back(toDynamic(item));
     }
@@ -314,7 +346,7 @@ struct DynamicConstructor<C,
 template<typename A, typename B>
 struct DynamicConstructor<std::pair<A, B>, void> {
   static dynamic construct(const std::pair<A, B>& x) {
-    dynamic d = {};
+    dynamic d = dynamic::array;
     d.push_back(toDynamic(x.first));
     d.push_back(toDynamic(x.second));
     return d;
@@ -335,5 +367,3 @@ dynamic toDynamic(const T& x) {
 }
 
 } // namespace folly
-
-#endif // DYNAMIC_CONVERTER_H