70 #include <unordered_map>
104 typename Hash = DefaultHash<Key>,
109 typename IsEqual = DefaultEquality,
132 int64_t occupied_and_removed_slots_;
153 #define LOAD_FACTOR 1, 2
154 LoadFactor max_load_factor_ = LoadFactor(
LOAD_FACTOR);
166 #define MAP_SLOT_PROBING_BEGIN(HASH, R_SLOT) \
167 SLOT_PROBING_BEGIN (ProbingStrategy, HASH, slot_mask_, SLOT_INDEX) \
168 auto &R_SLOT = slots_[SLOT_INDEX];
169 #define MAP_SLOT_PROBING_END() SLOT_PROBING_END()
177 Map(Allocator allocator = {}) noexcept
179 occupied_and_removed_slots_(0),
196 Map(
Map &&other) noexcept(std::is_nothrow_move_constructible_v<SlotArray>)
199 if constexpr (std::is_nothrow_move_constructible_v<SlotArray>) {
200 slots_ = std::move(other.slots_);
204 slots_ = std::move(other.slots_);
207 other.noexcept_reset();
211 removed_slots_ = other.removed_slots_;
212 occupied_and_removed_slots_ = other.occupied_and_removed_slots_;
213 usable_slots_ = other.usable_slots_;
214 slot_mask_ = other.slot_mask_;
215 hash_ = std::move(other.hash_);
216 is_equal_ = std::move(other.is_equal_);
217 other.noexcept_reset();
248 this->
add_new_as(std::move(key), std::move(value));
250 template<
typename ForwardKey,
typename ForwardValue>
254 std::forward<ForwardKey>(key), std::forward<ForwardValue>(value), hash_(key));
264 bool add(
const Key &key,
const Value &value)
266 return this->
add_as(key, value);
270 return this->
add_as(key, std::move(value));
274 return this->
add_as(std::move(key), value);
278 return this->
add_as(std::move(key), std::move(value));
280 template<
typename ForwardKey,
typename ForwardValue>
281 bool add_as(ForwardKey &&key, ForwardValue &&value)
283 return this->add__impl(
284 std::forward<ForwardKey>(key), std::forward<ForwardValue>(value), hash_(key));
310 template<
typename ForwardKey,
typename ForwardValue>
313 return this->add_overwrite__impl(
314 std::forward<ForwardKey>(key), std::forward<ForwardValue>(value), hash_(key));
326 template<
typename ForwardKey>
bool contains_as(
const ForwardKey &key)
const
328 return this->lookup_slot_ptr(key, hash_(key)) !=
nullptr;
341 template<
typename ForwardKey>
bool remove_as(
const ForwardKey &key)
343 Slot *slot = this->lookup_slot_ptr(key, hash_(key));
344 if (slot ==
nullptr) {
362 Slot &slot = this->lookup_slot(key, hash_(key));
377 Slot &slot = this->lookup_slot(key, hash_(key));
378 Value value = std::move(*slot.value());
392 template<
typename ForwardKey> std::optional<Value>
pop_try_as(
const ForwardKey &key)
394 Slot *slot = this->lookup_slot_ptr(key, hash_(key));
395 if (slot ==
nullptr) {
398 std::optional<Value> value = std::move(*slot->value());
416 template<
typename ForwardKey,
typename ForwardValue>
419 Slot *slot = this->lookup_slot_ptr(key, hash_(key));
420 if (slot ==
nullptr) {
421 return std::forward<ForwardValue>(default_value);
423 Value value = std::move(*slot->value());
449 template<
typename CreateValueF,
typename ModifyValueF>
451 const CreateValueF &create_value,
452 const ModifyValueF &modify_value) -> decltype(create_value(
nullptr))
456 template<
typename CreateValueF,
typename ModifyValueF>
457 auto add_or_modify(
Key &&key,
const CreateValueF &create_value,
const ModifyValueF &modify_value)
458 -> decltype(create_value(
nullptr))
462 template<
typename ForwardKey,
typename CreateValueF,
typename ModifyValueF>
464 const CreateValueF &create_value,
465 const ModifyValueF &modify_value) -> decltype(create_value(
nullptr))
467 return this->add_or_modify__impl(
468 std::forward<ForwardKey>(key), create_value, modify_value, hash_(key));
487 const Slot *slot = this->lookup_slot_ptr(key, hash_(key));
488 return (slot !=
nullptr) ? slot->value() :
nullptr;
507 template<
typename ForwardKey>
const Value &
lookup_as(
const ForwardKey &key)
const
528 template<
typename ForwardKey,
typename ForwardValue>
532 if (
ptr !=
nullptr) {
536 return std::forward<ForwardValue>(default_value);
560 template<
typename ForwardKey,
typename ForwardValue>
563 return this->lookup_or_add__impl(
564 std::forward<ForwardKey>(key), std::forward<ForwardValue>(value), hash_(key));
574 template<
typename CreateValueF>
579 template<
typename CreateValueF>
584 template<
typename ForwardKey,
typename CreateValueF>
587 return this->lookup_or_add_cb__impl(std::forward<ForwardKey>(key), create_value, hash_(key));
615 const Slot &slot = slots_[i];
616 if (slot.is_occupied()) {
617 const Key &key = *slot.key();
618 const Value &value = *slot.value();
655 return copied_iterator;
673 if (
slots_[i].is_occupied()) {
771 return {*slot.key(), *slot.value()};
789 return {*slot.key(), *slot.value()};
799 return KeyIterator(slots_.data(), slots_.size(), 0);
856 return occupied_and_removed_slots_ - removed_slots_;
866 return occupied_and_removed_slots_ == removed_slots_;
874 return slots_.size();
882 return removed_slots_;
899 return static_cast<int64_t>(
sizeof(Slot) * slots_.size());
908 if (usable_slots_ < n) {
909 this->realloc_and_reinsert(n);
918 this->noexcept_reset();
927 return this->count_collisions__impl(key, hash_(key));
933 int64_t total_slots, usable_slots;
934 max_load_factor_.compute_total_and_usable_slots(
942 if (this->
size() == 0) {
944 slots_.reinitialize(total_slots);
947 this->noexcept_reset();
951 occupied_and_removed_slots_ = 0;
952 usable_slots_ = usable_slots;
953 slot_mask_ = new_slot_mask;
957 SlotArray new_slots(total_slots);
960 for (Slot &slot : slots_) {
961 if (slot.is_occupied()) {
962 this->add_after_grow(slot, new_slots, new_slot_mask);
966 slots_ = std::move(new_slots);
969 this->noexcept_reset();
973 occupied_and_removed_slots_ -= removed_slots_;
974 usable_slots_ = usable_slots;
976 slot_mask_ = new_slot_mask;
979 void add_after_grow(Slot &old_slot, SlotArray &new_slots,
uint64_t new_slot_mask)
983 Slot &slot = new_slots[slot_index];
984 if (slot.is_empty()) {
985 slot.occupy(std::move(*old_slot.key()), std::move(*old_slot.value()),
hash);
992 void noexcept_reset() noexcept
994 Allocator allocator = slots_.allocator();
996 new (
this)
Map(NoExceptConstructor(), allocator);
999 template<
typename ForwardKey,
typename ForwardValue>
1000 void add_new__impl(ForwardKey &&key, ForwardValue &&value,
uint64_t hash)
1004 this->ensure_can_add();
1007 if (slot.is_empty()) {
1008 slot.occupy(std::forward<ForwardKey>(key), std::forward<ForwardValue>(value),
hash);
1009 occupied_and_removed_slots_++;
1016 template<
typename ForwardKey,
typename ForwardValue>
1017 bool add__impl(ForwardKey &&key, ForwardValue &&value,
uint64_t hash)
1019 this->ensure_can_add();
1022 if (slot.is_empty()) {
1023 slot.occupy(std::forward<ForwardKey>(key), std::forward<ForwardValue>(value),
hash);
1024 occupied_and_removed_slots_++;
1027 if (slot.contains(key, is_equal_,
hash)) {
1034 template<
typename ForwardKey,
typename CreateValueF,
typename ModifyValueF>
1035 auto add_or_modify__impl(ForwardKey &&key,
1036 const CreateValueF &create_value,
1037 const ModifyValueF &modify_value,
1040 using CreateReturnT = decltype(create_value(
nullptr));
1041 using ModifyReturnT = decltype(modify_value(
nullptr));
1043 "Both callbacks should return the same type.");
1045 this->ensure_can_add();
1048 if (slot.is_empty()) {
1049 Value *value_ptr = slot.value();
1050 if constexpr (std::is_void_v<CreateReturnT>) {
1051 create_value(value_ptr);
1052 slot.occupy_no_value(std::forward<ForwardKey>(key),
hash);
1053 occupied_and_removed_slots_++;
1057 auto &&return_value = create_value(value_ptr);
1058 slot.occupy_no_value(std::forward<ForwardKey>(key),
hash);
1059 occupied_and_removed_slots_++;
1060 return return_value;
1063 if (slot.contains(key, is_equal_,
hash)) {
1064 Value *value_ptr = slot.value();
1065 return modify_value(value_ptr);
1071 template<
typename ForwardKey,
typename CreateValueF>
1072 Value &lookup_or_add_cb__impl(ForwardKey &&key,
const CreateValueF &create_value,
uint64_t hash)
1074 this->ensure_can_add();
1077 if (slot.is_empty()) {
1078 slot.occupy(std::forward<ForwardKey>(key), create_value(),
hash);
1079 occupied_and_removed_slots_++;
1080 return *slot.value();
1082 if (slot.contains(key, is_equal_,
hash)) {
1083 return *slot.value();
1089 template<
typename ForwardKey,
typename ForwardValue>
1090 Value &lookup_or_add__impl(ForwardKey &&key, ForwardValue &&value,
uint64_t hash)
1092 this->ensure_can_add();
1095 if (slot.is_empty()) {
1096 slot.occupy(std::forward<ForwardKey>(key), std::forward<ForwardValue>(value),
hash);
1097 occupied_and_removed_slots_++;
1098 return *slot.value();
1100 if (slot.contains(key, is_equal_,
hash)) {
1101 return *slot.value();
1107 template<
typename ForwardKey,
typename ForwardValue>
1108 bool add_overwrite__impl(ForwardKey &&key, ForwardValue &&value,
uint64_t hash)
1111 new (
static_cast<void *
>(
ptr))
Value(std::forward<ForwardValue>(value));
1114 auto modify_func = [&](
Value *
ptr) {
1115 *
ptr = std::forward<ForwardValue>(value);
1118 return this->add_or_modify__impl(
1122 template<
typename ForwardKey>
1123 const Slot &lookup_slot(
const ForwardKey &key,
const uint64_t hash)
const
1127 if (slot.contains(key, is_equal_,
hash)) {
1134 template<
typename ForwardKey> Slot &lookup_slot(
const ForwardKey &key,
const uint64_t hash)
1136 return const_cast<Slot &
>(
const_cast<const Map *
>(
this)->lookup_slot(key,
hash));
1139 template<
typename ForwardKey>
1140 const Slot *lookup_slot_ptr(
const ForwardKey &key,
const uint64_t hash)
const
1143 if (slot.contains(key, is_equal_,
hash)) {
1146 if (slot.is_empty()) {
1153 template<
typename ForwardKey> Slot *lookup_slot_ptr(
const ForwardKey &key,
const uint64_t hash)
1155 return const_cast<Slot *
>(
const_cast<const Map *
>(
this)->lookup_slot_ptr(key,
hash));
1158 template<
typename ForwardKey>
1164 if (slot.contains(key, is_equal_,
hash)) {
1167 if (slot.is_empty()) {
1175 void ensure_can_add()
1177 if (occupied_and_removed_slots_ >= usable_slots_) {
1178 this->realloc_and_reinsert(this->
size() + 1);
1179 BLI_assert(occupied_and_removed_slots_ < usable_slots_);
1188 template<
typename Key,
1193 typename Hash = DefaultHash<Key>,
1194 typename IsEqual = DefaultEquality,
1205 using MapType = std::unordered_map<Key, Value, blender::DefaultHash<Key>>;
1211 return static_cast<int64_t>(map_.size());
1216 return map_.empty();
1224 template<
typename ForwardKey,
typename ForwardValue>
1225 void add_new(ForwardKey &&key, ForwardValue &&value)
1227 map_.insert({std::forward<ForwardKey>(key), std::forward<ForwardValue>(value)});
1230 template<
typename ForwardKey,
typename ForwardValue>
1231 bool add(ForwardKey &&key, ForwardValue &&value)
1233 return map_.insert({std::forward<ForwardKey>(key), std::forward<ForwardValue>(value)}).second;
1238 return map_.find(key) != map_.end();
1243 return (
bool)map_.erase(key);
1248 return map_.find(key)->second;
1253 return map_.find(key)->second;
#define BLI_STATIC_ASSERT(a, msg)
#define MAP_SLOT_PROBING_END()
#define MAP_SLOT_PROBING_BEGIN(HASH, R_SLOT)
#define SLOT_PROBING_BEGIN(PROBING_STRATEGY, HASH, MASK, R_SLOT_INDEX)
#define SLOT_PROBING_END()
Group RGB to Bright Vector Camera Vector Combine Material Light Line Style Layer Add Ambient Diffuse Glossy Refraction Transparent Toon Principled Hair Volume Principled Light Particle Volume Image Sky Noise Wave Voronoi Brick Texture Vector Combine Vertex Separate Vector White Value
static PyObject * create_func(PyObject *, PyObject *args)
static int64_t inline_buffer_capacity()
void print(StringRef name="")
static constexpr int64_t compute_total_slots(int64_t min_usable_slots, uint8_t numerator, uint8_t denominator)
ItemIterator(const Slot *slots, int64_t total_slots, int64_t current_slot)
KeyIterator(const Slot *slots, int64_t total_slots, int64_t current_slot)
const Key & operator*() const
MutableItem operator*() const
MutableItemIterator(const Slot *slots, int64_t total_slots, int64_t current_slot)
MutableValueIterator(const Slot *slots, int64_t total_slots, int64_t current_slot)
const Value & operator*() const
ValueIterator(const Slot *slots, int64_t total_slots, int64_t current_slot)
MutableItemIterator items()
Value pop_default_as(const ForwardKey &key, ForwardValue &&default_value)
Map & operator=(Map &&other)
Value pop_as(const ForwardKey &key)
bool add_overwrite(Key &&key, Value &&value)
Value & lookup_or_add_default_as(ForwardKey &&key)
int64_t size_in_bytes() const
Value pop(const Key &key)
void add_new(const Key &key, Value &&value)
void add_new(Key &&key, const Value &value)
int64_t removed_amount() const
Map(NoExceptConstructor, Allocator allocator={}) noexcept
Value & lookup_as(const ForwardKey &key)
Map & operator=(const Map &other)
bool remove_as(const ForwardKey &key)
bool add_overwrite(const Key &key, const Value &value)
std::optional< Value > pop_try_as(const ForwardKey &key)
void add_new_as(ForwardKey &&key, ForwardValue &&value)
Value & lookup_or_add_cb(Key &&key, const CreateValueF &create_value)
bool add(const Key &key, const Value &value)
int64_t size_per_element() const
Value & lookup_or_add(Key &&key, const Value &value)
void remove_contained_as(const ForwardKey &key)
void print_stats(StringRef name="") const
Value lookup_default(const Key &key, const Value &default_value) const
Value & lookup_or_add(Key &&key, Value &&value)
bool add_overwrite(Key &&key, const Value &value)
int64_t count_collisions(const Key &key) const
ValueIterator values() const
MutableValueIterator values()
Value & lookup_or_add_default(Key &&key)
const Value * lookup_ptr_as(const ForwardKey &key) const
const Value & lookup(const Key &key) const
Value * lookup_ptr_as(const ForwardKey &key)
Value & lookup_or_add_cb(const Key &key, const CreateValueF &create_value)
Value & lookup_or_add_cb_as(ForwardKey &&key, const CreateValueF &create_value)
void foreach_item(const FuncT &func) const
void remove_contained(const Key &key)
Map(const Map &other)=default
Map(Allocator allocator={}) noexcept
Value & lookup_or_add_default(const Key &key)
auto add_or_modify_as(ForwardKey &&key, const CreateValueF &create_value, const ModifyValueF &modify_value) -> decltype(create_value(nullptr))
void add_new(Key &&key, Value &&value)
void add_new(const Key &key, const Value &value)
bool add(Key &&key, Value &&value)
Map(Map &&other) noexcept(std::is_nothrow_move_constructible_v< SlotArray >)
Value & lookup_or_add(const Key &key, const Value &value)
bool add_as(ForwardKey &&key, ForwardValue &&value)
bool remove(const Key &key)
bool contains_as(const ForwardKey &key) const
ItemIterator items() const
const Value & lookup_as(const ForwardKey &key) const
bool add(const Key &key, Value &&value)
Value & lookup_or_add(const Key &key, Value &&value)
auto add_or_modify(Key &&key, const CreateValueF &create_value, const ModifyValueF &modify_value) -> decltype(create_value(nullptr))
Value & lookup(const Key &key)
Value lookup_default_as(const ForwardKey &key, ForwardValue &&default_value) const
bool contains(const Key &key) const
Value pop_default(const Key &key, Value &&default_value)
bool add(Key &&key, const Value &value)
bool add_overwrite(const Key &key, Value &&value)
Value * lookup_ptr(const Key &key)
const Value * lookup_ptr(const Key &key) const
auto add_or_modify(const Key &key, const CreateValueF &create_value, const ModifyValueF &modify_value) -> decltype(create_value(nullptr))
bool add_overwrite_as(ForwardKey &&key, ForwardValue &&value)
Value & lookup_or_add_as(ForwardKey &&key, ForwardValue &&value)
Value pop_default(const Key &key, const Value &default_value)
std::optional< Value > pop_try(const Key &key)
const Value & lookup(const Key &key) const
void add_new(ForwardKey &&key, ForwardValue &&value)
bool add(ForwardKey &&key, ForwardValue &&value)
bool contains(const Key &key) const
void print_stats(StringRef UNUSED(name)="") const
bool remove(const Key &key)
Value & lookup(const Key &key)
Container & move_assign_container(Container &dst, Container &&src) noexcept(std::is_nothrow_move_constructible_v< Container >)
Container & copy_assign_container(Container &dst, const Container &src)
PythonProbingStrategy<> DefaultProbingStrategy
constexpr int64_t default_inline_buffer_capacity(size_t element_size)
unsigned __int64 uint64_t
SimpleMapSlot< Key, Value > type
friend bool operator==(const BaseIterator &a, const BaseIterator &b)
BaseIterator & operator++()
BaseIterator(const Slot *slots, int64_t total_slots, int64_t current_slot)
std::forward_iterator_tag iterator_category
std::ptrdiff_t difference_type
friend bool operator!=(const BaseIterator &a, const BaseIterator &b)
BaseIterator operator++(int) const
SubIterator begin() const
Slot & current_slot() const