X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=folly%2Fdynamic-inl.h;h=dbe36b5d9347314dfe479e9d9415ff5335156213;hb=03ce292a000fb616c12e2aca2a38b7b26e6ef050;hp=a32da925d7385979e89efed09fbf70ab757e18fb;hpb=d458b0a14486b9d80d5644c7b4de60640c891df1;p=folly.git diff --git a/folly/dynamic-inl.h b/folly/dynamic-inl.h index a32da925..dbe36b5d 100644 --- a/folly/dynamic-inl.h +++ b/folly/dynamic-inl.h @@ -1,5 +1,5 @@ /* - * Copyright 2016 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. @@ -92,44 +92,6 @@ namespace detail { template static void destroy(T* t) { t->~T(); } }; - /* - * The enable_if junk here is necessary to avoid ambiguous - * conversions relating to bool and double when you implicitly - * convert an int or long to a dynamic. - */ - template struct ConversionHelper; - template - struct ConversionHelper< - T, - typename std::enable_if< - std::is_integral::value && !std::is_same::value - >::type - > { - typedef int64_t type; - }; - template <> - struct ConversionHelper { - typedef double type; - }; - template - struct ConversionHelper< - T, - typename std::enable_if< - (!std::is_integral::value || std::is_same::value) && - !std::is_same::value && - !std::is_same::value>::type> { - typedef T type; - }; - template - struct ConversionHelper< - T, - typename std::enable_if< - std::is_same::value - >::type - > { - typedef void* type; - }; - /* * Helper for implementing numeric conversions in operators on * numbers. Just promotes to double when one of the arguments is @@ -173,12 +135,7 @@ struct dynamic::ObjectMaker { friend struct dynamic; explicit ObjectMaker() : val_(dynamic::object) {} - explicit ObjectMaker(dynamic const& key, dynamic val) - : val_(dynamic::object) - { - val_.insert(key, std::move(val)); - } - explicit ObjectMaker(dynamic&& key, dynamic val) + explicit ObjectMaker(dynamic key, dynamic val) : val_(dynamic::object) { val_.insert(std::move(key), std::move(val)); @@ -191,15 +148,10 @@ struct dynamic::ObjectMaker { ObjectMaker& operator=(ObjectMaker const&) = delete; ObjectMaker& operator=(ObjectMaker&&) = delete; - // These return rvalue-references instead of lvalue-references to allow - // constructs like this to moved instead of copied: + // This returns an rvalue-reference instead of an lvalue-reference + // to allow constructs like this to moved instead of copied: // dynamic a = dynamic::object("a", "b")("c", "d") - ObjectMaker&& operator()(dynamic const& key, dynamic val) { - val_.insert(key, std::move(val)); - return std::move(*this); - } - - ObjectMaker&& operator()(dynamic&& key, dynamic val) { + ObjectMaker&& operator()(dynamic key, dynamic val) { val_.insert(std::move(key), std::move(val)); return std::move(*this); } @@ -215,33 +167,49 @@ inline dynamic dynamic::array(Args&& ...args) { return dynamic(Array{std::forward(args)...}); } -// This looks like a case for perfect forwarding, but our use of -// std::initializer_list for constructing dynamic arrays makes it less -// functional than doing this manually. - -// TODO(ott, 10300209): When the initializer_list constructor is gone, -// simplify this. inline dynamic::ObjectMaker dynamic::object() { return ObjectMaker(); } -inline dynamic::ObjectMaker dynamic::object(dynamic&& a, dynamic&& b) { +inline dynamic::ObjectMaker dynamic::object(dynamic a, dynamic b) { return ObjectMaker(std::move(a), std::move(b)); } -inline dynamic::ObjectMaker dynamic::object(dynamic const& a, dynamic&& b) { - return ObjectMaker(a, std::move(b)); -} -inline dynamic::ObjectMaker dynamic::object(dynamic&& a, dynamic const& b) { - return ObjectMaker(std::move(a), b); -} -inline dynamic::ObjectMaker -dynamic::object(dynamic const& a, dynamic const& b) { - return ObjectMaker(a, b); -} ////////////////////////////////////////////////////////////////////// +struct dynamic::item_iterator : boost::iterator_adaptor< + dynamic::item_iterator, + dynamic::ObjectImpl::iterator> { + /* implicit */ item_iterator(base_type b) : iterator_adaptor_(b) {} + + using object_type = dynamic::ObjectImpl; + + private: + friend class boost::iterator_core_access; +}; + +struct dynamic::value_iterator : boost::iterator_adaptor< + dynamic::value_iterator, + dynamic::ObjectImpl::iterator, + dynamic> { + /* implicit */ value_iterator(base_type b) : iterator_adaptor_(b) {} + + using object_type = dynamic::ObjectImpl; + + private: + dynamic& dereference() const { + return base_reference()->second; + } + friend class boost::iterator_core_access; +}; + struct dynamic::const_item_iterator : boost::iterator_adaptor { /* implicit */ const_item_iterator(base_type b) : iterator_adaptor_(b) { } + /* implicit */ const_item_iterator(item_iterator i) + : iterator_adaptor_(i.base()) {} + /* implicit */ const_item_iterator(dynamic::ObjectImpl::iterator i) + : iterator_adaptor_(i) {} + + using object_type = dynamic::ObjectImpl const; private: friend class boost::iterator_core_access; @@ -253,6 +221,8 @@ struct dynamic::const_key_iterator dynamic const> { /* implicit */ const_key_iterator(base_type b) : iterator_adaptor_(b) { } + using object_type = dynamic::ObjectImpl const; + private: dynamic const& dereference() const { return base_reference()->first; @@ -265,6 +235,12 @@ struct dynamic::const_value_iterator dynamic::ObjectImpl::const_iterator, dynamic const> { /* implicit */ const_value_iterator(base_type b) : iterator_adaptor_(b) { } + /* implicit */ const_value_iterator(value_iterator i) + : iterator_adaptor_(i.base()) {} + /* implicit */ const_value_iterator(dynamic::ObjectImpl::iterator i) + : iterator_adaptor_(i) {} + + using object_type = dynamic::ObjectImpl const; private: dynamic const& dereference() const { @@ -275,6 +251,10 @@ struct dynamic::const_value_iterator ////////////////////////////////////////////////////////////////////// +inline dynamic::dynamic() : dynamic(nullptr) {} + +inline dynamic::dynamic(std::nullptr_t) : type_(NULLT) {} + inline dynamic::dynamic(void (*)(EmptyArrayTag)) : type_(ARRAY) { @@ -299,13 +279,9 @@ inline dynamic::dynamic(char const* s) new (&u_.string) std::string(s); } -inline dynamic::dynamic(std::string const& s) +inline dynamic::dynamic(std::string s) : type_(STRING) { - new (&u_.string) std::string(s); -} - -inline dynamic::dynamic(std::string&& s) : type_(STRING) { new (&u_.string) std::string(std::move(s)); } @@ -330,14 +306,32 @@ inline dynamic::dynamic(dynamic&& o) noexcept inline dynamic::~dynamic() noexcept { destroy(); } -template +// Integral types except bool convert to int64_t, float types to double. +template +struct dynamic::NumericTypeHelper< + T, typename std::enable_if::value>::type> { + using type = int64_t; +}; +template <> +struct dynamic::NumericTypeHelper { + using type = bool; +}; +template <> +struct dynamic::NumericTypeHelper { + using type = double; +}; +template <> +struct dynamic::NumericTypeHelper { + using type = double; +}; + +template::type */> dynamic::dynamic(T t) { - typedef typename detail::ConversionHelper::type U; - type_ = TypeInfo::type; - new (getAddress()) U(std::move(t)); + type_ = TypeInfo::type; + new (getAddress()) NumericType(NumericType(t)); } -template +template dynamic::dynamic(Iterator first, Iterator last) : type_(ARRAY) { @@ -353,12 +347,20 @@ inline dynamic::const_iterator dynamic::end() const { return get().end(); } +inline dynamic::iterator dynamic::begin() { + return get().begin(); +} +inline dynamic::iterator dynamic::end() { + return get().end(); +} + template struct dynamic::IterableProxy { - typedef It const_iterator; + typedef It iterator; typedef typename It::value_type value_type; + typedef typename It::object_type object_type; - /* implicit */ IterableProxy(const dynamic::ObjectImpl* o) : o_(o) { } + /* implicit */ IterableProxy(object_type* o) : o_(o) {} It begin() const { return o_->begin(); @@ -369,7 +371,7 @@ struct dynamic::IterableProxy { } private: - const dynamic::ObjectImpl* o_; + object_type* o_; }; inline dynamic::IterableProxy dynamic::keys() @@ -387,16 +389,38 @@ inline dynamic::IterableProxy dynamic::items() return &(get()); } +inline dynamic::IterableProxy dynamic::values() { + return &(get()); +} + +inline dynamic::IterableProxy dynamic::items() { + return &(get()); +} + inline bool dynamic::isString() const { - return get_nothrow(); + return get_nothrow() != nullptr; +} +inline bool dynamic::isObject() const { + return get_nothrow() != nullptr; +} +inline bool dynamic::isBool() const { + return get_nothrow() != nullptr; +} +inline bool dynamic::isArray() const { + return get_nothrow() != nullptr; +} +inline bool dynamic::isDouble() const { + return get_nothrow() != nullptr; +} +inline bool dynamic::isInt() const { + return get_nothrow() != nullptr; +} +inline bool dynamic::isNull() const { + return get_nothrow() != nullptr; +} +inline bool dynamic::isNumber() const { + return isInt() || isDouble(); } -inline bool dynamic::isObject() const { return get_nothrow(); } -inline bool dynamic::isBool() const { return get_nothrow(); } -inline bool dynamic::isArray() const { return get_nothrow(); } -inline bool dynamic::isDouble() const { return get_nothrow(); } -inline bool dynamic::isInt() const { return get_nothrow(); } -inline bool dynamic::isNull() const { return get_nothrow(); } -inline bool dynamic::isNumber() const { return isInt() || isDouble(); } inline dynamic::Type dynamic::type() const { return type_; @@ -553,12 +577,15 @@ inline bool dynamic::empty() const { } inline std::size_t dynamic::count(dynamic const& key) const { - return find(key) != items().end(); + return find(key) != items().end() ? 1u : 0u; } inline dynamic::const_item_iterator dynamic::find(dynamic const& key) const { return get().find(key); } +inline dynamic::item_iterator dynamic::find(dynamic const& key) { + return get().find(key); +} template inline void dynamic::insert(K&& key, V&& val) { auto& obj = get(); @@ -606,7 +633,7 @@ inline std::size_t dynamic::erase(dynamic const& key) { return obj.erase(key); } -inline dynamic::const_iterator dynamic::erase(const_iterator it) { +inline dynamic::iterator dynamic::erase(const_iterator it) { auto& arr = get(); // std::vector doesn't have an erase method that works on const iterators, // even though the standard says it should, so this hack converts to a @@ -618,30 +645,31 @@ inline dynamic::const_key_iterator dynamic::erase(const_key_iterator it) { return const_key_iterator(get().erase(it.base())); } -inline dynamic::const_key_iterator dynamic::erase(const_key_iterator first, - const_key_iterator last) { +inline dynamic::const_key_iterator dynamic::erase( + const_key_iterator first, + const_key_iterator last) { return const_key_iterator(get().erase(first.base(), last.base())); } -inline dynamic::const_value_iterator dynamic::erase(const_value_iterator it) { - return const_value_iterator(get().erase(it.base())); +inline dynamic::value_iterator dynamic::erase(const_value_iterator it) { + return value_iterator(get().erase(it.base())); } -inline dynamic::const_value_iterator dynamic::erase(const_value_iterator first, - const_value_iterator last) { - return const_value_iterator(get().erase(first.base(), - last.base())); +inline dynamic::value_iterator dynamic::erase( + const_value_iterator first, + const_value_iterator last) { + return value_iterator(get().erase(first.base(), last.base())); } -inline dynamic::const_item_iterator dynamic::erase(const_item_iterator it) { - return const_item_iterator(get().erase(it.base())); +inline dynamic::item_iterator dynamic::erase(const_item_iterator it) { + return item_iterator(get().erase(it.base())); } -inline dynamic::const_item_iterator dynamic::erase(const_item_iterator first, - const_item_iterator last) { - return const_item_iterator(get().erase(first.base(), - last.base())); +inline dynamic::item_iterator dynamic::erase( + const_item_iterator first, + const_item_iterator last) { + return item_iterator(get().erase(first.base(), last.base())); } inline void dynamic::resize(std::size_t sz, dynamic const& c) { @@ -679,7 +707,7 @@ inline dynamic::dynamic(Array&& r) : type_(ARRAY) { FOLLY_DYNAMIC_DEC_TYPEINFO(void*, "null", dynamic::NULLT) FOLLY_DYNAMIC_DEC_TYPEINFO(bool, "boolean", dynamic::BOOL) -FOLLY_DYNAMIC_DEC_TYPEINFO(std::string, "string", dynamic::STRING) +FOLLY_DYNAMIC_DEC_TYPEINFO(std::string, "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)