Commit 41431d75 authored by Xiao Shi's avatar Xiao Shi Committed by Facebook Github Bot

Back out "[folly] use heterogeneous lookup and mutation in folly::dynamic" and...

Back out "[folly] use heterogeneous lookup and mutation in folly::dynamic" and "[folly] use F14NodeMap in folly::dynamic"

Summary:
D8299863 and D8299800

Mostly backing out for xplat autoupdater. The TARGETS / DEFS got scrambled.

Differential Revision: D9139265

fbshipit-source-id: 78b0238370d4de4fdc363d0867dc46de3a572f58
parent 5f195e92
...@@ -23,59 +23,6 @@ ...@@ -23,59 +23,6 @@
#include <folly/Likely.h> #include <folly/Likely.h>
#include <folly/detail/Iterators.h> #include <folly/detail/Iterators.h>
namespace folly {
namespace detail {
struct DynamicHasher {
using is_transparent = void;
size_t operator()(dynamic const& d) const {
return d.hash();
}
template <typename T>
std::enable_if_t<std::is_convertible<T, StringPiece>::value, size_t>
operator()(T const& val) const {
// keep consistent with dynamic::hash() for strings
return Hash()(static_cast<StringPiece>(val));
}
};
struct DynamicKeyEqual {
using is_transparent = void;
bool operator()(const dynamic& lhs, const dynamic& rhs) const {
return std::equal_to<dynamic>()(lhs, rhs);
}
// Dynamic objects contains a map<dynamic, dynamic>. At least one of the
// operands should be a dynamic. Hence, an operator() where both operands are
// convertible to StringPiece is unnecessary.
template <typename A, typename B>
std::enable_if_t<
std::is_convertible<A, StringPiece>::value &&
std::is_convertible<B, StringPiece>::value,
bool>
operator()(A const& lhs, B const& rhs) const = delete;
template <typename A>
std::enable_if_t<std::is_convertible<A, StringPiece>::value, bool> operator()(
A const& lhs,
dynamic const& rhs) const {
return FOLLY_LIKELY(rhs.type() == dynamic::Type::STRING) &&
std::equal_to<StringPiece>()(lhs, rhs.stringPiece());
}
template <typename B>
std::enable_if_t<std::is_convertible<B, StringPiece>::value, bool> operator()(
dynamic const& lhs,
B const& rhs) const {
return FOLLY_LIKELY(lhs.type() == dynamic::Type::STRING) &&
std::equal_to<StringPiece>()(lhs.stringPiece(), rhs);
}
};
} // namespace detail
} // namespace folly
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
namespace std { namespace std {
...@@ -194,17 +141,13 @@ dynamic numericOp(dynamic const& a, dynamic const& b) { ...@@ -194,17 +141,13 @@ dynamic numericOp(dynamic const& a, dynamic const& b) {
/* /*
* We're doing this instead of a simple member typedef to avoid the * We're doing this instead of a simple member typedef to avoid the
* undefined behavior of parameterizing F14NodeMap<> with an * undefined behavior of parameterizing std::unordered_map<> with an
* incomplete type. * incomplete type.
* *
* Note: Later we may add separate order tracking here (a multi-index * Note: Later we may add separate order tracking here (a multi-index
* type of thing.) * type of thing.)
*/ */
struct dynamic::ObjectImpl : F14NodeMap< struct dynamic::ObjectImpl : std::unordered_map<dynamic, dynamic> {};
dynamic,
dynamic,
detail::DynamicHasher,
detail::DynamicKeyEqual> {};
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
...@@ -647,43 +590,21 @@ inline dynamic&& dynamic::operator[](dynamic const& idx) && { ...@@ -647,43 +590,21 @@ inline dynamic&& dynamic::operator[](dynamic const& idx) && {
return std::move((*this)[idx]); return std::move((*this)[idx]);
} }
template <typename K> template <class K, class V> inline dynamic& dynamic::setDefault(K&& k, V&& v) {
inline std::enable_if_t<std::is_convertible<K, StringPiece>::value, dynamic&>
dynamic::operator[](K&& k) & {
auto& obj = get<ObjectImpl>();
auto ret = obj.emplace(std::forward<K>(k), nullptr);
return ret.first->second;
}
template <typename K>
inline std::
enable_if_t<std::is_convertible<K, StringPiece>::value, dynamic const&>
dynamic::operator[](K&& k) const& {
return at(std::forward<K>(k));
}
template <typename K>
inline std::enable_if_t<std::is_convertible<K, StringPiece>::value, dynamic&&>
dynamic::operator[](K&& k) && {
return std::move((*this)[std::forward<K>(k)]);
}
template <class K, class V>
inline dynamic& dynamic::setDefault(K&& k, V&& v) {
auto& obj = get<ObjectImpl>(); auto& obj = get<ObjectImpl>();
return obj.emplace(std::forward<K>(k), std::forward<V>(v)).first->second; return obj.insert(std::make_pair(std::forward<K>(k),
std::forward<V>(v))).first->second;
} }
template <class K> template <class K> inline dynamic& dynamic::setDefault(K&& k, dynamic&& v) {
inline dynamic& dynamic::setDefault(K&& k, dynamic&& v) {
auto& obj = get<ObjectImpl>(); auto& obj = get<ObjectImpl>();
return obj.emplace(std::forward<K>(k), std::move(v)).first->second; return obj.insert(std::make_pair(std::forward<K>(k),
std::move(v))).first->second;
} }
template <class K> template <class K> inline dynamic& dynamic::setDefault(K&& k, const dynamic& v) {
inline dynamic& dynamic::setDefault(K&& k, const dynamic& v) {
auto& obj = get<ObjectImpl>(); auto& obj = get<ObjectImpl>();
return obj.emplace(std::forward<K>(k), v).first->second; return obj.insert(std::make_pair(std::forward<K>(k), v)).first->second;
} }
inline dynamic* dynamic::get_ptr(dynamic const& idx) & { inline dynamic* dynamic::get_ptr(dynamic const& idx) & {
...@@ -703,33 +624,6 @@ inline dynamic&& dynamic::at(dynamic const& idx) && { ...@@ -703,33 +624,6 @@ inline dynamic&& dynamic::at(dynamic const& idx) && {
return std::move(at(idx)); return std::move(at(idx));
} }
template <typename K>
std::enable_if_t<std::is_convertible<K, StringPiece>::value, dynamic const&>
dynamic::at(K const& idx) const& {
auto* pobject = get_nothrow<ObjectImpl>();
if (!pobject) {
throwTypeError_("object/array", type());
}
auto it = pobject->find(idx);
if (it == pobject->end()) {
throw_exception<std::out_of_range>(
sformat("couldn't find key {} in dynamic object", idx));
}
return it->second;
}
template <typename K>
inline std::enable_if_t<std::is_convertible<K, StringPiece>::value, dynamic&>
dynamic::at(K const& idx) & {
return const_cast<dynamic&>(const_cast<dynamic const*>(this)->at(idx));
}
template <typename K>
inline std::enable_if_t<std::is_convertible<K, StringPiece>::value, dynamic&&>
dynamic::at(K const& idx) && {
return std::move(at(idx));
}
inline bool dynamic::empty() const { inline bool dynamic::empty() const {
if (isNull()) { if (isNull()) {
return true; return true;
...@@ -740,11 +634,6 @@ inline bool dynamic::empty() const { ...@@ -740,11 +634,6 @@ inline bool dynamic::empty() const {
inline std::size_t dynamic::count(dynamic const& key) const { inline std::size_t dynamic::count(dynamic const& key) const {
return find(key) != items().end() ? 1u : 0u; return find(key) != items().end() ? 1u : 0u;
} }
template <typename K>
inline std::enable_if_t<std::is_convertible<K, StringPiece>::value, std::size_t>
dynamic::count(K const& key) const {
return find(key) != items().end() ? 1u : 0u;
}
inline dynamic::const_item_iterator dynamic::find(dynamic const& key) const { inline dynamic::const_item_iterator dynamic::find(dynamic const& key) const {
return get<ObjectImpl>().find(key); return get<ObjectImpl>().find(key);
...@@ -753,25 +642,10 @@ inline dynamic::item_iterator dynamic::find(dynamic const& key) { ...@@ -753,25 +642,10 @@ inline dynamic::item_iterator dynamic::find(dynamic const& key) {
return get<ObjectImpl>().find(key); return get<ObjectImpl>().find(key);
} }
template <typename K> template <class K, class V> inline void dynamic::insert(K&& key, V&& val) {
inline std::enable_if_t<
std::is_convertible<K, StringPiece>::value,
dynamic::const_item_iterator>
dynamic::find(K const& key) const {
return get<ObjectImpl>().find(key);
}
template <typename K>
inline std::enable_if_t<
std::is_convertible<K, StringPiece>::value,
dynamic::item_iterator>
dynamic::find(K const& key) {
return get<ObjectImpl>().find(key);
}
template <class K, class V>
inline void dynamic::insert(K&& key, V&& val) {
auto& obj = get<ObjectImpl>(); auto& obj = get<ObjectImpl>();
obj[std::forward<K>(key)] = std::forward<V>(val); auto rv = obj.insert({ std::forward<K>(key), nullptr });
rv.first->second = std::forward<V>(val);
} }
inline void dynamic::update(const dynamic& mergeObj) { inline void dynamic::update(const dynamic& mergeObj) {
...@@ -836,12 +710,6 @@ inline std::size_t dynamic::erase(dynamic const& key) { ...@@ -836,12 +710,6 @@ inline std::size_t dynamic::erase(dynamic const& key) {
auto& obj = get<ObjectImpl>(); auto& obj = get<ObjectImpl>();
return obj.erase(key); return obj.erase(key);
} }
template <typename K>
inline std::enable_if_t<std::is_convertible<K, StringPiece>::value, std::size_t>
dynamic::erase(K&& key) {
auto& obj = get<ObjectImpl>();
return obj.erase(std::forward<K>(key));
}
inline dynamic::iterator dynamic::erase(const_iterator it) { inline dynamic::iterator dynamic::erase(const_iterator it) {
auto& arr = get<Array>(); auto& arr = get<Array>();
...@@ -987,9 +855,8 @@ struct dynamic::GetAddrImpl<std::string> { ...@@ -987,9 +855,8 @@ struct dynamic::GetAddrImpl<std::string> {
} }
}; };
template <> struct dynamic::GetAddrImpl<dynamic::ObjectImpl> { template <> struct dynamic::GetAddrImpl<dynamic::ObjectImpl> {
static_assert( static_assert(sizeof(ObjectImpl) <= sizeof(Data::objectBuffer),
sizeof(ObjectImpl) <= sizeof(Data::objectBuffer), "In your implementation, std::unordered_map<> apparently takes different"
"In your implementation, F14NodeMap<> apparently takes different"
" amount of space depending on its template parameters. This is " " amount of space depending on its template parameters. This is "
"weird. Make objectBuffer bigger if you want to compile dynamic."); "weird. Make objectBuffer bigger if you want to compile dynamic.");
......
...@@ -188,7 +188,7 @@ dynamic& dynamic::operator[](dynamic const& k) & { ...@@ -188,7 +188,7 @@ dynamic& dynamic::operator[](dynamic const& k) & {
return at(k); return at(k);
} }
auto& obj = get<ObjectImpl>(); auto& obj = get<ObjectImpl>();
auto ret = obj.emplace(k, nullptr); auto ret = obj.insert({k, nullptr});
return ret.first->second; return ret.first->second;
} }
...@@ -246,6 +246,11 @@ const dynamic* dynamic::get_ptr(dynamic const& idx) const& { ...@@ -246,6 +246,11 @@ const dynamic* dynamic::get_ptr(dynamic const& idx) const& {
} }
} }
[[noreturn]] static void throwOutOfRangeAtMissingKey(dynamic const& idx) {
auto msg = sformat("couldn't find key {} in dynamic object", idx.asString());
throw_exception<std::out_of_range>(msg);
}
dynamic const& dynamic::at(dynamic const& idx) const& { dynamic const& dynamic::at(dynamic const& idx) const& {
if (auto* parray = get_nothrow<Array>()) { if (auto* parray = get_nothrow<Array>()) {
if (!idx.isInt()) { if (!idx.isInt()) {
...@@ -258,8 +263,7 @@ dynamic const& dynamic::at(dynamic const& idx) const& { ...@@ -258,8 +263,7 @@ dynamic const& dynamic::at(dynamic const& idx) const& {
} else if (auto* pobject = get_nothrow<ObjectImpl>()) { } else if (auto* pobject = get_nothrow<ObjectImpl>()) {
auto it = pobject->find(idx); auto it = pobject->find(idx);
if (it == pobject->end()) { if (it == pobject->end()) {
throw_exception<std::out_of_range>( throwOutOfRangeAtMissingKey(idx);
sformat("couldn't find key {} in dynamic object", idx.asString()));
} }
return it->second; return it->second;
} else { } else {
...@@ -312,7 +316,6 @@ std::size_t dynamic::hash() const { ...@@ -312,7 +316,6 @@ std::size_t dynamic::hash() const {
case BOOL: case BOOL:
return std::hash<bool>()(getBool()); return std::hash<bool>()(getBool());
case STRING: case STRING:
// keep consistent with detail::DynamicHasher
return Hash()(getString()); return Hash()(getString());
} }
assume_unreachable(); assume_unreachable();
......
...@@ -57,6 +57,7 @@ ...@@ -57,6 +57,7 @@
#include <ostream> #include <ostream>
#include <string> #include <string>
#include <type_traits> #include <type_traits>
#include <unordered_map>
#include <utility> #include <utility>
#include <vector> #include <vector>
...@@ -64,7 +65,6 @@ ...@@ -64,7 +65,6 @@
#include <folly/Range.h> #include <folly/Range.h>
#include <folly/Traits.h> #include <folly/Traits.h>
#include <folly/container/F14Map.h>
#include <folly/json_pointer.h> #include <folly/json_pointer.h>
namespace folly { namespace folly {
...@@ -379,25 +379,12 @@ struct dynamic : private boost::operators<dynamic> { ...@@ -379,25 +379,12 @@ struct dynamic : private boost::operators<dynamic> {
const_item_iterator find(dynamic const&) const; const_item_iterator find(dynamic const&) const;
item_iterator find(dynamic const&); item_iterator find(dynamic const&);
template <typename K>
std::enable_if_t<
std::is_convertible<K, StringPiece>::value,
const_item_iterator>
find(K const&) const;
template <typename K>
std::enable_if_t<std::is_convertible<K, StringPiece>::value, item_iterator>
find(K const&);
/* /*
* If this is an object, returns whether it contains a field with * If this is an object, returns whether it contains a field with
* the given name. Otherwise throws TypeError. * the given name. Otherwise throws TypeError.
*/ */
std::size_t count(dynamic const&) const; std::size_t count(dynamic const&) const;
template <typename K>
std::enable_if_t<std::is_convertible<K, StringPiece>::value, std::size_t>
count(K const&) const;
/* /*
* For objects or arrays, provides access to sub-fields by index or * For objects or arrays, provides access to sub-fields by index or
* field name. * field name.
...@@ -410,16 +397,6 @@ struct dynamic : private boost::operators<dynamic> { ...@@ -410,16 +397,6 @@ struct dynamic : private boost::operators<dynamic> {
dynamic& at(dynamic const&) &; dynamic& at(dynamic const&) &;
dynamic&& at(dynamic const&) &&; dynamic&& at(dynamic const&) &&;
template <typename K>
std::enable_if_t<std::is_convertible<K, StringPiece>::value, dynamic const&>
at(K const&) const&;
template <typename K>
std::enable_if_t<std::is_convertible<K, StringPiece>::value, dynamic&> at(
K const&) &;
template <typename K>
std::enable_if_t<std::is_convertible<K, StringPiece>::value, dynamic&&> at(
K const&) &&;
/* /*
* Locate element using JSON pointer, per RFC 6901. Returns nullptr if * Locate element using JSON pointer, per RFC 6901. Returns nullptr if
* element could not be located. Throws if pointer does not match the * element could not be located. Throws if pointer does not match the
...@@ -463,16 +440,6 @@ struct dynamic : private boost::operators<dynamic> { ...@@ -463,16 +440,6 @@ struct dynamic : private boost::operators<dynamic> {
dynamic const& operator[](dynamic const&) const&; dynamic const& operator[](dynamic const&) const&;
dynamic&& operator[](dynamic const&) &&; dynamic&& operator[](dynamic const&) &&;
template <typename K>
std::enable_if_t<std::is_convertible<K, StringPiece>::value, dynamic&>
operator[](K&&) &;
template <typename K>
std::enable_if_t<std::is_convertible<K, StringPiece>::value, dynamic const&>
operator[](K&&) const&;
template <typename K>
std::enable_if_t<std::is_convertible<K, StringPiece>::value, dynamic&&>
operator[](K&&) &&;
/* /*
* Only defined for objects, throws TypeError otherwise. * Only defined for objects, throws TypeError otherwise.
* *
...@@ -510,8 +477,7 @@ struct dynamic : private boost::operators<dynamic> { ...@@ -510,8 +477,7 @@ struct dynamic : private boost::operators<dynamic> {
/* /*
* Inserts the supplied key-value pair to an object, or throws if * Inserts the supplied key-value pair to an object, or throws if
* it's not an object. If the key already exists, insert will overwrite the * it's not an object.
* value, i.e., similar to insert_or_assign.
* *
* Invalidates iterators. * Invalidates iterators.
*/ */
...@@ -553,9 +519,6 @@ struct dynamic : private boost::operators<dynamic> { ...@@ -553,9 +519,6 @@ struct dynamic : private boost::operators<dynamic> {
* Returns the number of elements erased (i.e. 1 or 0). * Returns the number of elements erased (i.e. 1 or 0).
*/ */
std::size_t erase(dynamic const& key); std::size_t erase(dynamic const& key);
template <typename K>
std::enable_if_t<std::is_convertible<K, StringPiece>::value, std::size_t>
erase(K&&);
/* /*
* Erase an element from a dynamic object or array, using an * Erase an element from a dynamic object or array, using an
...@@ -645,14 +608,15 @@ struct dynamic : private boost::operators<dynamic> { ...@@ -645,14 +608,15 @@ struct dynamic : private boost::operators<dynamic> {
/* /*
* Objects are placement new'd here. We have to use a char buffer * Objects are placement new'd here. We have to use a char buffer
* because we don't know the type here (F14NodeMap<> with * because we don't know the type here (std::unordered_map<> with
* dynamic would be parameterizing a std:: template with an * dynamic would be parameterizing a std:: template with an
* incomplete type right now). (Note that in contrast we know it * incomplete type right now). (Note that in contrast we know it
* is ok to do this with fbvector because we own it.) * is ok to do this with fbvector because we own it.)
*/ */
std::aligned_storage< std::aligned_storage<
sizeof(F14NodeMap<int, int>), sizeof(std::unordered_map<int,int>),
alignof(F14NodeMap<int, int>)>::type objectBuffer; alignof(std::unordered_map<int,int>)
>::type objectBuffer;
} u_; } u_;
}; };
......
...@@ -33,31 +33,11 @@ TEST(Dynamic, ObjectBasics) { ...@@ -33,31 +33,11 @@ TEST(Dynamic, ObjectBasics) {
EXPECT_EQ(obj.at("a"), false); EXPECT_EQ(obj.at("a"), false);
EXPECT_EQ(obj.size(), 1); EXPECT_EQ(obj.size(), 1);
obj.insert("a", true); obj.insert("a", true);
dynamic key{"a"};
folly::StringPiece sp{"a"};
std::string s{"a"};
EXPECT_EQ(obj.size(), 1); EXPECT_EQ(obj.size(), 1);
EXPECT_EQ(obj.at("a"), true); EXPECT_EQ(obj.at("a"), true);
EXPECT_EQ(obj.at(sp), true); obj.at("a") = nullptr;
EXPECT_EQ(obj.at(key), true);
obj.at(sp) = nullptr;
EXPECT_EQ(obj.size(), 1); EXPECT_EQ(obj.size(), 1);
EXPECT_TRUE(obj.at(s) == nullptr); EXPECT_TRUE(obj.at("a") == nullptr);
obj["a"] = 12;
EXPECT_EQ(obj[sp], 12);
obj[key] = "foo";
EXPECT_EQ(obj["a"], "foo");
(void)obj["b"];
EXPECT_EQ(obj.size(), 2);
obj.erase("a");
EXPECT_TRUE(obj.find(sp) == obj.items().end());
obj.erase("b");
EXPECT_EQ(obj.size(), 0);
dynamic newObject = dynamic::object; dynamic newObject = dynamic::object;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment