X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=folly%2FDynamicConverter.h;h=d64dcc2827bcada3ba2ba986a311d53364de605e;hb=0703c0070b211897f6515656f2e80884ec52b8ee;hp=275d6d936e60a46ab3d9cff51ecdb5b67d881395;hpb=5b67454fe0be0482000e6fb53c73d2c84bb7dab6;p=folly.git diff --git a/folly/DynamicConverter.h b/folly/DynamicConverter.h index 275d6d93..d64dcc28 100644 --- a/folly/DynamicConverter.h +++ b/folly/DynamicConverter.h @@ -1,5 +1,5 @@ /* - * Copyright 2012 Facebook, Inc. + * Copyright 2014 Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,9 +19,10 @@ #ifndef DYNAMIC_CONVERTER_H #define DYNAMIC_CONVERTER_H -#include "folly/dynamic.h" +#include namespace folly { template T convertTo(const dynamic&); + template dynamic toDynamic(const T&); } /** @@ -37,9 +38,10 @@ namespace folly { #include +#include #include #include -#include "folly/Likely.h" +#include namespace folly { @@ -49,28 +51,21 @@ namespace folly { namespace dynamicconverter_detail { BOOST_MPL_HAS_XXX_TRAIT_DEF(value_type); -BOOST_MPL_HAS_XXX_TRAIT_DEF(key_type); -BOOST_MPL_HAS_XXX_TRAIT_DEF(mapped_type); BOOST_MPL_HAS_XXX_TRAIT_DEF(iterator); - -template struct map_container_has_correct_types - : std::is_same::type, - typename T::mapped_type>, - typename T::value_type> {}; +BOOST_MPL_HAS_XXX_TRAIT_DEF(mapped_type); template struct class_is_container { - struct dummy {}; + typedef std::reverse_iterator some_iterator; enum { value = has_value_type::value && has_iterator::value && - std::is_constructible::value }; + std::is_constructible::value }; +}; + +template struct class_is_range { + enum { value = has_value_type::value && + has_iterator::value }; }; -template struct container_is_map - : std::conditional< - has_key_type::value && has_mapped_type::value, - map_container_has_correct_types, - std::false_type - >::type {}; template struct is_container : std::conditional< @@ -79,13 +74,19 @@ template struct is_container std::false_type >::type {}; -template struct is_map_container +template struct is_range : std::conditional< - is_container::value, - container_is_map, + std::is_class::value, + class_is_range, std::false_type >::type {}; +template struct is_map + : std::integral_constant< + bool, + is_range::value && has_mapped_type::value + > {}; + } // namespace dynamicconverter_detail /////////////////////////////////////////////////////////////////////////////// @@ -105,16 +106,33 @@ template struct is_map_container namespace dynamicconverter_detail { -template -inline void -derefToCache(std::pair* mem, const dynamic::const_item_iterator& it) { - new (mem) std::pair(convertTo(it->first), convertTo(it->second)); -} +template +struct Dereferencer { + static inline void + derefToCache(T* mem, const dynamic::const_item_iterator& it) { + throw TypeError("array", dynamic::Type::OBJECT); + } -template -inline void derefToCache(T* mem, const dynamic::const_iterator& it) { - new (mem) T(convertTo(*it)); -} + static inline void derefToCache(T* mem, const dynamic::const_iterator& it) { + new (mem) T(convertTo(*it)); + } +}; + +template +struct Dereferencer> { + static inline void + derefToCache(std::pair* mem, const dynamic::const_item_iterator& it) { + new (mem) std::pair( + convertTo(it->first), convertTo(it->second) + ); + } + + // Intentional duplication of the code in Dereferencer + template + static inline void derefToCache(T* mem, const dynamic::const_iterator& it) { + new (mem) T(convertTo(*it)); + } +}; template class Transformer : public boost::iterator_adaptor< @@ -137,7 +155,7 @@ class Transformer : public boost::iterator_adaptor< ttype& dereference() const { if (LIKELY(!valid_)) { cache_.~ttype(); - derefToCache(&cache_, this->base_reference()); + Dereferencer::derefToCache(&cache_, this->base_reference()); valid_ = true; } return cache_; @@ -160,13 +178,14 @@ conversionIterator(const It& it) { /////////////////////////////////////////////////////////////////////////////// // DynamicConverter specializations -template struct DynamicConverter; - /** * Each specialization of DynamicConverter has the function - * 'static T convert(const dynamic& d);' + * 'static T convert(const dynamic&);' */ +// default - intentionally unimplemented +template struct DynamicConverter; + // boolean template <> struct DynamicConverter { @@ -181,7 +200,7 @@ struct DynamicConverter::value && !std::is_same::value>::type> { static T convert(const dynamic& d) { - return static_cast(d.asInt()); + return folly::to(d.asInt()); } }; @@ -190,7 +209,7 @@ template struct DynamicConverter::value>::type> { static T convert(const dynamic& d) { - return static_cast(d.asDouble()); + return folly::to(d.asDouble()); } }; @@ -225,50 +244,94 @@ struct DynamicConverter> { } }; -// map containers +// containers template struct DynamicConverter::value>::type> { + dynamicconverter_detail::is_container::value>::type> { static C convert(const dynamic& d) { - if (LIKELY(d.isObject())) { + if (d.isArray()) { + return C(dynamicconverter_detail::conversionIterator(d.begin()), + dynamicconverter_detail::conversionIterator(d.end())); + } else if (d.isObject()) { return C(dynamicconverter_detail::conversionIterator (d.items().begin()), dynamicconverter_detail::conversionIterator (d.items().end())); - } else if (d.isArray()) { - return C(dynamicconverter_detail::conversionIterator(d.begin()), - dynamicconverter_detail::conversionIterator(d.end())); } else { throw TypeError("object or array", d.type()); } } }; -// non-map containers -template -struct DynamicConverter::value && - !dynamicconverter_detail::is_map_container::value - >::type - > { - static C convert(const dynamic& d) { - if (LIKELY(d.isArray())) { - return C(dynamicconverter_detail::conversionIterator(d.begin()), - dynamicconverter_detail::conversionIterator(d.end())); - } else { - throw TypeError("array", d.type()); +/////////////////////////////////////////////////////////////////////////////// +// DynamicConstructor specializations + +/** + * Each specialization of DynamicConstructor has the function + * 'static dynamic construct(const C&);' + */ + +// default +template +struct DynamicConstructor { + static dynamic construct(const C& x) { + return dynamic(x); + } +}; + +// maps +template +struct DynamicConstructor::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; + } +}; + +// other ranges +template +struct DynamicConstructor::value && + !std::is_constructible::value && + dynamicconverter_detail::is_range::value>::type> { + static dynamic construct(const C& x) { + dynamic d = {}; + for (auto& item : x) { + d.push_back(toDynamic(item)); } + return d; + } +}; + +// pair +template +struct DynamicConstructor, void> { + static dynamic construct(const std::pair& x) { + dynamic d = {}; + d.push_back(toDynamic(x.first)); + d.push_back(toDynamic(x.second)); + return d; } }; /////////////////////////////////////////////////////////////////////////////// -// convertTo implementation +// implementation template T convertTo(const dynamic& d) { - return DynamicConverter::convert(d); + return DynamicConverter::type>::convert(d); +} + +template +dynamic toDynamic(const T& x) { + return DynamicConstructor::type>::construct(x); } } // namespace folly