[Bf-blender-cvs] [33dda8463d7] functions: improved lookup or insert functions for map
Jacques Lucke
noreply at git.blender.org
Wed Jul 3 19:14:19 CEST 2019
Commit: 33dda8463d7e9918268b0ef1f4331b03f6536b1c
Author: Jacques Lucke
Date: Wed Jul 3 18:41:16 2019 +0200
Branches: functions
https://developer.blender.org/rB33dda8463d7e9918268b0ef1f4331b03f6536b1c
improved lookup or insert functions for map
===================================================================
M source/blender/blenlib/BLI_small_map.hpp
M tests/gtests/blenlib/BLI_small_map_test.cc
===================================================================
diff --git a/source/blender/blenlib/BLI_small_map.hpp b/source/blender/blenlib/BLI_small_map.hpp
index e8add508606..57b440cb5f2 100644
--- a/source/blender/blenlib/BLI_small_map.hpp
+++ b/source/blender/blenlib/BLI_small_map.hpp
@@ -162,43 +162,55 @@ template<typename K, typename V, uint N = 4> class SmallMap {
}
/**
- * Return the pointer to the value corresponding to the key.
+ * Return a reference to the value corresponding to the key.
* If the key does not exist yet, insert the given key-value-pair first.
*/
- V *lookup_ptr_or_insert(const K &key, V initial_value)
+ V &lookup_ref_or_insert(const K &key, V initial_value)
{
V *ptr = this->lookup_ptr(key);
- if (ptr == nullptr) {
- this->add_new(key, initial_value);
- ptr = &m_entries[m_entries.size() - 1].value;
+ if (ptr != nullptr) {
+ return *ptr;
}
- return ptr;
+ this->add_new(key, initial_value);
+ return m_entries[m_entries.size() - 1].value;
}
/**
* Return a reference to the value corresponding to the key.
- * If the key does not exist yet, the given function will be called
- * with the given parameters, to create the value that will be stored for the key.
+ * If the key does not exist yet, create the value by calling the function, and insert the
+ * key-value pair.
*/
- template<typename... Args>
- V &lookup_ref_or_insert_func(const K &key, V (*create_value)(Args... args), Args &&... args)
+ template<typename CreateValueFunc>
+ V &lookup_ref_or_insert_func(const K &key, const CreateValueFunc &create_value)
{
- V *value = this->lookup_ptr(key);
- if (value != NULL) {
- return *value;
+ V *ptr = this->lookup_ptr(key);
+ if (ptr != nullptr) {
+ return *ptr;
}
- this->add_new(key, create_value(std::forward<Args>(args)...));
- return this->lookup_ref(key);
+
+ this->add_new(key, create_value());
+ return m_entries[m_entries.size() - 1].value;
}
/**
- * Returns a reference to the value corresponding to the key.
- * If the key does not exist yet, the given function will be called
- * with the key as parameter, to create the value that will be stored for the key.
+ * Insert a new value for the given key or modify the existing one.
+ * Return true when a new value was inserted, false otherwise.
*/
- V &lookup_ref_or_insert_key_func(const K &key, V (*create_value)(const K &key))
+ template<typename CreateValueFunc, typename ModifyValueFunc>
+ bool insert_or_modify(const K &key,
+ const CreateValueFunc &create_value,
+ const ModifyValueFunc &modify_value)
{
- return lookup_ref_or_insert_func(key, create_value, key);
+ uint desired_new_index = m_entries.size();
+ uint value_index = m_lookup.add(m_entries.begin(), key, desired_new_index);
+ if (value_index == desired_new_index) {
+ m_entries.append({key, create_value()});
+ return true;
+ }
+ else {
+ modify_value(m_entries[value_index].value);
+ return false;
+ }
}
/**
diff --git a/tests/gtests/blenlib/BLI_small_map_test.cc b/tests/gtests/blenlib/BLI_small_map_test.cc
index 5ab6743cd06..366ce770070 100644
--- a/tests/gtests/blenlib/BLI_small_map_test.cc
+++ b/tests/gtests/blenlib/BLI_small_map_test.cc
@@ -87,14 +87,14 @@ TEST(small_map, PopItemMany)
}
}
-TEST(small_map, LookupPtrOrInsert)
+TEST(small_map, LookupRefOrInsert)
{
IntFloatMap map;
- float *value = map.lookup_ptr_or_insert(3, 5.0f);
- EXPECT_EQ(*value, 5.0f);
- *value += 1;
- value = map.lookup_ptr_or_insert(3, 5.0f);
- EXPECT_EQ(*value, 6.0f);
+ float &value = map.lookup_ref_or_insert(3, 5.0f);
+ EXPECT_EQ(value, 5.0f);
+ value += 1;
+ value = map.lookup_ref_or_insert(3, 5.0f);
+ EXPECT_EQ(value, 6.0f);
}
TEST(small_map, ValueIterator)
@@ -170,73 +170,32 @@ float return_42()
return 42.0f;
}
-TEST(small_map, LookupOrInsertFunc_NoArgs)
+TEST(small_map, LookupOrInsertFunc_SeparateFunction)
{
IntFloatMap map;
EXPECT_EQ(map.lookup_ref_or_insert_func(0, return_42), 42.0f);
EXPECT_EQ(map.lookup(0), 42);
}
-float return_identity(float a)
-{
- return a;
-}
-
-TEST(small_map, LookupOrInsertFunc_SingleArg)
-{
- IntFloatMap map;
- EXPECT_EQ(map.lookup_ref_or_insert_func(1, return_identity, 5.0f), 5.0f);
- EXPECT_EQ(map.lookup(1), 5.0f);
-}
-
-float add_func(float a, float b)
-{
- return a + b;
-}
-
-TEST(small_map, LookupOrInsertFunc_TwoArgs)
-{
- IntFloatMap map;
- EXPECT_EQ(map.lookup_ref_or_insert_func(2, add_func, 4.0f, 6.0f), 10.0f);
- EXPECT_EQ(map.lookup(2), 10.0f);
-}
-
-TEST(small_map, LookupOrInsertFunc_NoReinsert)
+TEST(small_map, LookupOrInsertFunc_Lambdas)
{
IntFloatMap map;
- EXPECT_EQ(map.lookup_ref_or_insert_func(2, return_identity, 4.0f), 4.0f);
- EXPECT_EQ(map.lookup_ref_or_insert_func(2, return_identity, 6.0f), 4.0f);
- EXPECT_EQ(map.lookup_ref_or_insert_func(2, return_identity, 8.0f), 4.0f);
- EXPECT_EQ(map.size(), 1);
-}
+ auto lambda1 = []() { return 11.0f; };
+ EXPECT_EQ(map.lookup_ref_or_insert_func(0, lambda1), 11.0f);
+ auto lambda2 = []() { return 20.0f; };
+ EXPECT_EQ(map.lookup_ref_or_insert_func(1, lambda2), 20.0f);
-float inc_value_and_return_42(int *ptr)
-{
- *ptr += 1;
- return 42.0f;
+ EXPECT_EQ(map.lookup_ref_or_insert_func(0, lambda2), 11.0f);
+ EXPECT_EQ(map.lookup_ref_or_insert_func(1, lambda1), 20.0f);
}
-TEST(small_map, LookupOrInsertFunc_FuncCalledOnce)
+TEST(small_map, InsertOrModify)
{
- int counter = 0;
IntFloatMap map;
- EXPECT_EQ(map.lookup_ref_or_insert_func(0, inc_value_and_return_42, &counter), 42.0f);
- EXPECT_EQ(counter, 1);
- EXPECT_EQ(map.lookup_ref_or_insert_func(0, inc_value_and_return_42, &counter), 42.0f);
- EXPECT_EQ(counter, 1);
-}
-
-float add_10(const int &value)
-{
- return value + 10.0f;
-}
-
-TEST(small_map, LookupOrInsertKeyFunc)
-{
- IntFloatMap map;
- EXPECT_EQ(map.lookup_ref_or_insert_key_func(4, add_10), 14.0f);
- EXPECT_EQ(map.lookup_ref_or_insert_key_func(10, add_10), 20.0f);
-
- EXPECT_EQ(map.lookup(4), 14.0f);
- EXPECT_EQ(map.lookup(10), 20.0f);
+ auto create_func = []() { return 10.0f; };
+ auto modify_func = [](float &value) { value += 5; };
+ EXPECT_TRUE(map.insert_or_modify(1, create_func, modify_func));
+ EXPECT_EQ(map.lookup(1), 10.0f);
+ EXPECT_FALSE(map.insert_or_modify(1, create_func, modify_func));
+ EXPECT_EQ(map.lookup(1), 15.0f);
}
More information about the Bf-blender-cvs
mailing list