diff options
Diffstat (limited to 'source/blender/blenlib/BLI_set.hh')
-rw-r--r-- | source/blender/blenlib/BLI_set.hh | 35 |
1 files changed, 34 insertions, 1 deletions
diff --git a/source/blender/blenlib/BLI_set.hh b/source/blender/blenlib/BLI_set.hh index 9684f372db7..06b56c3f8e5 100644 --- a/source/blender/blenlib/BLI_set.hh +++ b/source/blender/blenlib/BLI_set.hh @@ -48,7 +48,7 @@ * - Small buffer optimization is enabled by default, if the key is not too large. * - The methods `add_new` and `remove_contained` should be used instead of `add` and `remove` * whenever appropriate. Assumptions and intention are described better this way. - * - Look-ups can be performed using types other than Key without conversion. For that use the + * - Lookups can be performed using types other than Key without conversion. For that use the * methods ending with `_as`. The template parameters Hash and #IsEqual have to support the other * key type. This can greatly improve performance when the set contains strings. * - The default constructor is cheap, even when a large #InlineBufferCapacity is used. A large @@ -351,6 +351,23 @@ class Set { } /** + * Returns the key in the set that compares equal to the given key. If it does not exist, the key + * is newly added. + */ + const Key &lookup_key_or_add(const Key &key) + { + return this->lookup_key_or_add_as(key); + } + const Key &lookup_key_or_add(Key &&key) + { + return this->lookup_key_or_add_as(std::move(key)); + } + template<typename ForwardKey> const Key &lookup_key_or_add_as(ForwardKey &&key) + { + return this->lookup_key_or_add__impl(std::forward<ForwardKey>(key), hash_(key)); + } + + /** * Deletes the key from the set. Returns true when the key did exist beforehand, otherwise false. * * This is similar to std::unordered_set::erase. @@ -735,6 +752,22 @@ class Set { } template<typename ForwardKey> + const Key &lookup_key_or_add__impl(ForwardKey &&key, const uint64_t hash) + { + SET_SLOT_PROBING_BEGIN (hash, slot) { + if (slot.contains(key, is_equal_, hash)) { + return *slot.key(); + } + if (slot.is_empty()) { + slot.occupy(std::forward<ForwardKey>(key), hash); + occupied_and_removed_slots_++; + return *slot.key(); + } + } + SET_SLOT_PROBING_END(); + } + + template<typename ForwardKey> int64_t count_collisions__impl(const ForwardKey &key, const uint64_t hash) const { int64_t collisions = 0; |