Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorJacques Lucke <mail@jlucke.com>2019-09-14 17:25:17 +0300
committerJacques Lucke <mail@jlucke.com>2019-09-14 17:25:17 +0300
commit38cc53a168d27b19fb6033a38a043b5076c0aea6 (patch)
treed45fdeb41c60fc2c18420afca2af834b1d56fe21 /source
parentd6057b919dca589be97e3b0be15d6e61b04172ea (diff)
BLI: make Map.add_or_modify more powerful
The function now allows custom return types defined by the callbacks. This can be useful when a user of the data structure has to implement some custom behavior.
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenlib/BLI_map.h60
1 files changed, 42 insertions, 18 deletions
diff --git a/source/blender/blenlib/BLI_map.h b/source/blender/blenlib/BLI_map.h
index 3dc51a79be9..3e934480b94 100644
--- a/source/blender/blenlib/BLI_map.h
+++ b/source/blender/blenlib/BLI_map.h
@@ -151,6 +151,13 @@ template<typename KeyT, typename ValueT, typename Allocator = GuardedAllocator>
new (this->value(offset)) ValueT(std::forward<ForwardValueT>(value));
}
+ template<typename ForwardKeyT> void store_without_value(uint offset, ForwardKeyT &&key)
+ {
+ BLI_assert(m_status[offset] != IS_SET);
+ m_status[offset] = IS_SET;
+ new (this->key(offset)) KeyT(std::forward<ForwardKeyT>(key));
+ }
+
void set_dummy(uint offset)
{
BLI_assert(m_status[offset] == IS_SET);
@@ -280,22 +287,28 @@ template<typename KeyT, typename ValueT, typename Allocator = GuardedAllocator>
}
/**
- * Check if the key exists in the map.
- * If it does exist, call the modify function with a reference to the corresponding value.
- * If it does not exist, call the create function and insert a new key-value-pair.
- * Returns true when a new pair was inserted, otherwise false.
+ * First, checks if the key exists in the map.
+ * If it does exist, call the modify function with a pointer to the corresponding value.
+ * If it does not exist, call the create function with a pointer to where the value should be
+ * created.
+ *
+ * Returns whatever is returned from one of the callback functions. Both callbacks have to return
+ * the same type.
+ *
+ * CreateValueF: Takes a pointer to where the value should be created.
+ * ModifyValueF: Takes a pointer to the value that should be modified.
*/
template<typename CreateValueF, typename ModifyValueF>
- bool add_or_modify(const KeyT &key,
+ auto add_or_modify(const KeyT &key,
const CreateValueF &create_value,
- const ModifyValueF &modify_value)
+ const ModifyValueF &modify_value) -> decltype(create_value(nullptr))
{
return this->add_or_modify__impl(key, create_value, modify_value);
}
template<typename CreateValueF, typename ModifyValueF>
- bool add_or_modify(KeyT &&key,
+ auto add_or_modify(KeyT &&key,
const CreateValueF &create_value,
- const ModifyValueF &modify_value)
+ const ModifyValueF &modify_value) -> decltype(create_value(nullptr))
{
return this->add_or_modify__impl(std::move(key), create_value, modify_value);
}
@@ -611,10 +624,15 @@ template<typename KeyT, typename ValueT, typename Allocator = GuardedAllocator>
template<typename ForwardKeyT, typename ForwardValueT>
bool add_override__impl(ForwardKeyT &&key, ForwardValueT &&value)
{
- return this->add_or_modify(
- std::forward<ForwardKeyT>(key),
- [&]() { return std::forward<ForwardValueT>(value); },
- [&](ValueT &old_value) { old_value = std::forward<ForwardValueT>(value); });
+ return this->add_or_modify(std::forward<ForwardKeyT>(key),
+ [&](ValueT *dst) {
+ new (dst) ValueT(std::forward<ForwardValueT>(value));
+ return true;
+ },
+ [&](ValueT *old_value) {
+ *old_value = std::forward<ForwardValueT>(value);
+ return false;
+ });
}
template<typename ForwardKeyT, typename ForwardValueT>
@@ -652,21 +670,27 @@ template<typename KeyT, typename ValueT, typename Allocator = GuardedAllocator>
}
template<typename ForwardKeyT, typename CreateValueF, typename ModifyValueF>
- bool add_or_modify__impl(ForwardKeyT &&key,
+ auto add_or_modify__impl(ForwardKeyT &&key,
const CreateValueF &create_value,
- const ModifyValueF &modify_value)
+ const ModifyValueF &modify_value) -> decltype(create_value(nullptr))
{
+ using CreateReturnT = decltype(create_value(nullptr));
+ using ModifyReturnT = decltype(modify_value(nullptr));
+ BLI_STATIC_ASSERT((std::is_same<CreateReturnT, ModifyReturnT>::value),
+ "Both callbacks should return the same type.");
+
this->ensure_can_add();
ITER_SLOTS_BEGIN (key, m_array, , item, offset) {
if (item.is_empty(offset)) {
- item.store(offset, std::forward<ForwardKeyT>(key), create_value());
m_array.update__empty_to_set();
- return true;
+ item.store_without_value(offset, std::forward<ForwardKeyT>(key));
+ ValueT *value_ptr = item.value(offset);
+ return create_value(value_ptr);
}
else if (item.has_key(offset, key)) {
- modify_value(*item.value(offset));
- return false;
+ ValueT *value_ptr = item.value(offset);
+ return modify_value(value_ptr);
}
}
ITER_SLOTS_END(offset);