#include "folly/dynamic.h"
namespace folly {
template <typename T> T convertTo(const dynamic&);
+ template <typename T> dynamic toDynamic(const T&);
}
/**
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;
std::is_constructible<T, some_iterator, some_iterator>::value };
};
+template <typename T> struct class_is_range {
+ enum { value = has_value_type<T>::value &&
+ has_iterator<T>::value };
+};
+
+
template <typename T> struct is_container
: std::conditional<
std::is_class<T>::value,
std::false_type
>::type {};
+template <typename T> struct is_range
+ : std::conditional<
+ std::is_class<T>::value,
+ class_is_range<T>,
+ std::false_type
+ >::type {};
+
+template <typename T> struct is_associative_container
+ : std::integral_constant<
+ bool,
+ is_range<T>::value && has_mapped_type<T>::value
+ > {};
+
} // namespace dynamicconverter_detail
///////////////////////////////////////////////////////////////////////////////
throw TypeError("object or array", d.type());
}
}
+
+};
+
+template <typename C, typename Enable = void>
+struct DynamicConstructor {
+ static dynamic construct(const C& x) {
+ return dynamic(x);
+ }
+};
+
+template<typename C>
+struct DynamicConstructor<C,
+ typename std::enable_if<
+ dynamicconverter_detail::is_associative_container<C>::value>::type> {
+ static dynamic construct(const C& x) {
+ dynamic d = dynamic::object;
+ for (auto& pair : x) {
+ d.insert(toDynamic(pair.first), toDynamic(pair.second));
+ }
+ return d;
+ }
+};
+
+template<typename C>
+struct DynamicConstructor<C,
+ typename std::enable_if<
+ !dynamicconverter_detail::is_associative_container<C>::value &&
+ !std::is_constructible<StringPiece, const C&>::value &&
+ dynamicconverter_detail::is_range<C>::value>::type> {
+ static dynamic construct(const C& x) {
+ dynamic d = {};
+ for (auto& item : x) {
+ d.push_back(toDynamic(item));
+ }
+ return d;
+ }
+};
+
+template<typename A, typename B>
+struct DynamicConstructor<std::pair<A, B>, void> {
+ static dynamic construct(const std::pair<A, B>& x) {
+ dynamic d = {};
+ d.push_back(toDynamic(x.first));
+ d.push_back(toDynamic(x.second));
+ return d;
+ }
};
///////////////////////////////////////////////////////////////////////////////
return DynamicConverter<typename std::remove_cv<T>::type>::convert(d);
}
+template<typename T>
+dynamic toDynamic(const T& x) {
+ return DynamicConstructor<typename std::remove_cv<T>::type>::construct(x);
+}
+
} // namespace folly
#endif // DYNAMIC_CONVERTER_H
#include "folly/DynamicConverter.h"
#include <algorithm>
-#include <gtest/gtest.h>
#include <gflags/gflags.h>
+#include <gtest/gtest.h>
+#include <map>
+#include <vector>
+
#include "folly/Benchmark.h"
using namespace folly;
explicit Token(int kind, const fbstring& lexeme)
: kind_(kind), lexeme_(lexeme) {}
};
+
namespace folly {
template <> struct DynamicConverter<Token> {
static Token convert(const dynamic& d) {
}
};
}
+
TEST(DynamicConverter, example) {
dynamic d1 = dynamic::object("KIND", 2)("LEXEME", "a token");
auto i1 = convertTo<Token>(d1);
EXPECT_EQ(i1.lexeme_, "a token");
}
+TEST(DynamicConverter, construct) {
+ using std::vector;
+ using std::map;
+ using std::pair;
+ using std::string;
+ {
+ vector<int> c { 1, 2, 3 };
+ dynamic d = { 1, 2, 3 };
+ EXPECT_EQ(d, toDynamic(c));
+ }
+
+ {
+ map<int, int> c { { 2, 4 }, { 3, 9 } };
+ dynamic d = dynamic::object(2, 4)(3, 9);
+ EXPECT_EQ(d, toDynamic(c));
+ }
+
+ {
+ map<string, string> c { { "a", "b" } };
+ dynamic d = dynamic::object("a", "b");
+ EXPECT_EQ(d, toDynamic(c));
+ }
+
+ {
+ map<string, pair<string, int>> c { { "a", { "b", 3 } } };
+ dynamic d = dynamic::object("a", dynamic { "b", 3 });
+ EXPECT_EQ(d, toDynamic(c));
+ }
+
+ {
+ map<string, pair<string, int>> c { { "a", { "b", 3 } } };
+ dynamic d = dynamic::object("a", dynamic { "b", 3 });
+ EXPECT_EQ(d, toDynamic(c));
+ }
+
+ {
+ vector<int> vi { 2, 3, 4, 5 };
+ auto c = std::make_pair(makeRange(vi.begin(), vi.begin() + 3),
+ makeRange(vi.begin() + 1, vi.begin() + 4));
+ dynamic d = { { 2, 3, 4 }, { 3, 4, 5 } };
+ EXPECT_EQ(d, toDynamic(c));
+ }
+}
+
int main(int argc, char ** argv) {
testing::InitGoogleTest(&argc, argv);
google::ParseCommandLineFlags(&argc, &argv, true);