/*
- * Copyright 2013 Facebook, Inc.
+ * Copyright 2016 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
// @author Nicholas Ormrod <njormrod@fb.com>
-#ifndef DYNAMIC_CONVERTER_H
-#define DYNAMIC_CONVERTER_H
+#pragma once
-#include "folly/dynamic.h"
+#include <folly/dynamic.h>
namespace folly {
template <typename T> T convertTo(const dynamic&);
template <typename T> dynamic toDynamic(const T&);
*
* 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
#include <iterator>
#include <boost/iterator/iterator_adaptor.hpp>
#include <boost/mpl/has_xxx.hpp>
-#include "folly/Likely.h"
+#include <folly/Likely.h>
namespace folly {
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 };
std::false_type
>::type {};
-template <typename T> struct is_associative_container
+template <typename T> struct is_map
: std::integral_constant<
bool,
is_range<T>::value && has_mapped_type<T>::value
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);
}
// conversion factory
template <typename T, typename It>
-static inline std::move_iterator<Transformer<T, It>>
+inline std::move_iterator<Transformer<T, It>>
conversionIterator(const It& it) {
return std::make_move_iterator(Transformer<T, It>(it));
}
///////////////////////////////////////////////////////////////////////////////
// DynamicConverter specializations
-template <typename T, typename Enable = void> struct DynamicConverter;
-
/**
* Each specialization of DynamicConverter has the function
- * 'static T convert(const dynamic& d);'
+ * 'static T convert(const dynamic&);'
*/
+// default - intentionally unimplemented
+template <typename T, typename Enable = void> struct DynamicConverter;
+
// boolean
template <>
struct DynamicConverter<bool> {
typename std::enable_if<std::is_integral<T>::value &&
!std::is_same<T, bool>::value>::type> {
static T convert(const dynamic& d) {
- return static_cast<T>(d.asInt());
+ return folly::to<T>(d.asInt());
+ }
+};
+
+// 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));
}
};
struct DynamicConverter<T,
typename std::enable_if<std::is_floating_point<T>::value>::type> {
static T convert(const dynamic& d) {
- return static_cast<T>(d.asDouble());
+ return folly::to<T>(d.asDouble());
}
};
template <>
struct DynamicConverter<std::string> {
static std::string convert(const dynamic& d) {
- return d.asString().toStdString();
+ return d.asString();
}
};
throw TypeError("object or array", d.type());
}
}
-
};
+///////////////////////////////////////////////////////////////////////////////
+// DynamicConstructor specializations
+
+/**
+ * Each specialization of DynamicConstructor has the function
+ * 'static dynamic construct(const C&);'
+ */
+
+// default
template <typename C, typename Enable = void>
struct DynamicConstructor {
static dynamic construct(const C& x) {
}
};
+// maps
template<typename C>
struct DynamicConstructor<C,
typename std::enable_if<
- dynamicconverter_detail::is_associative_container<C>::value>::type> {
+ dynamicconverter_detail::is_map<C>::value>::type> {
static dynamic construct(const C& x) {
dynamic d = dynamic::object;
for (auto& pair : x) {
}
};
+// other ranges
template<typename C>
struct DynamicConstructor<C,
typename std::enable_if<
- !dynamicconverter_detail::is_associative_container<C>::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));
}
}
};
+// pair
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;
};
///////////////////////////////////////////////////////////////////////////////
-// convertTo implementation
+// implementation
template <typename T>
T convertTo(const dynamic& d) {
}
} // namespace folly
-
-#endif // DYNAMIC_CONVERTER_H
-