Cleanup: Deduplicate custom VectorSet identifier hash and equality
Add `CustomIDVectorSet` for this purpose. Based on code from Jacques in #133778. Pull Request: https://projects.blender.org/blender/blender/pulls/133821
This commit is contained in:
@@ -47,39 +47,19 @@ struct ReferenceLifetimesInfo;
|
||||
|
||||
namespace blender::bke {
|
||||
|
||||
struct NodeIDHash {
|
||||
uint64_t operator()(const bNode *node) const
|
||||
{
|
||||
return node->identifier;
|
||||
}
|
||||
uint64_t operator()(const int32_t id) const
|
||||
{
|
||||
return id;
|
||||
}
|
||||
};
|
||||
|
||||
struct NodeIDEquality {
|
||||
bool operator()(const bNode *a, const bNode *b) const
|
||||
{
|
||||
return a->identifier == b->identifier;
|
||||
}
|
||||
bool operator()(const bNode *a, const int32_t b) const
|
||||
{
|
||||
return a->identifier == b;
|
||||
}
|
||||
bool operator()(const int32_t a, const bNode *b) const
|
||||
{
|
||||
return this->operator()(b, a);
|
||||
}
|
||||
};
|
||||
|
||||
enum class FieldSocketState : int8_t {
|
||||
RequiresSingle,
|
||||
CanBeField,
|
||||
IsField,
|
||||
};
|
||||
|
||||
using NodeIDVectorSet = VectorSet<bNode *, DefaultProbingStrategy, NodeIDHash, NodeIDEquality>;
|
||||
struct NodeIDGetter {
|
||||
int32_t operator()(const bNode *value) const
|
||||
{
|
||||
return value->identifier;
|
||||
}
|
||||
};
|
||||
using NodeIDVectorSet = CustomIDVectorSet<bNode *, NodeIDGetter>;
|
||||
|
||||
struct NodeLinkError {
|
||||
std::string tooltip;
|
||||
|
||||
@@ -1620,45 +1620,22 @@ void node_tree_set_type(const bContext *C, bNodeTree *ntree)
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T> struct StructPointerIDNameHash {
|
||||
uint64_t operator()(const T *value) const
|
||||
template<typename T> struct NodeStructIDNameGetter {
|
||||
StringRef operator()(const T *value) const
|
||||
{
|
||||
return get_default_hash(value->idname);
|
||||
}
|
||||
uint64_t operator()(const StringRef name) const
|
||||
{
|
||||
return get_default_hash(name);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T> struct StructPointerNameEqual {
|
||||
bool operator()(const T *a, const T *b) const
|
||||
{
|
||||
return a->idname == b->idname;
|
||||
}
|
||||
bool operator()(const StringRef idname, const T *a) const
|
||||
{
|
||||
return a->idname == idname;
|
||||
return StringRef(value->idname);
|
||||
}
|
||||
};
|
||||
|
||||
static auto &get_node_tree_type_map()
|
||||
{
|
||||
static VectorSet<bNodeTreeType *,
|
||||
DefaultProbingStrategy,
|
||||
StructPointerIDNameHash<bNodeTreeType>,
|
||||
StructPointerNameEqual<bNodeTreeType>>
|
||||
map;
|
||||
static CustomIDVectorSet<bNodeTreeType *, NodeStructIDNameGetter<bNodeTreeType>> map;
|
||||
return map;
|
||||
}
|
||||
|
||||
static auto &get_node_type_map()
|
||||
{
|
||||
static VectorSet<bNodeType *,
|
||||
DefaultProbingStrategy,
|
||||
StructPointerIDNameHash<bNodeType>,
|
||||
StructPointerNameEqual<bNodeType>>
|
||||
map;
|
||||
static CustomIDVectorSet<bNodeType *, NodeStructIDNameGetter<bNodeType>> map;
|
||||
return map;
|
||||
}
|
||||
|
||||
@@ -1670,11 +1647,7 @@ static auto &get_node_type_alias_map()
|
||||
|
||||
static auto &get_socket_type_map()
|
||||
{
|
||||
static VectorSet<bNodeSocketType *,
|
||||
DefaultProbingStrategy,
|
||||
StructPointerIDNameHash<bNodeSocketType>,
|
||||
StructPointerNameEqual<bNodeSocketType>>
|
||||
map;
|
||||
static CustomIDVectorSet<bNodeSocketType *, NodeStructIDNameGetter<bNodeSocketType>> map;
|
||||
return map;
|
||||
}
|
||||
|
||||
|
||||
@@ -926,4 +926,45 @@ template<typename Key,
|
||||
typename Slot = typename DefaultVectorSetSlot<Key>::type>
|
||||
using RawVectorSet = VectorSet<Key, ProbingStrategy, Hash, IsEqual, Slot, RawAllocator>;
|
||||
|
||||
template<typename T, typename GetIDFn> struct CustomIDHash {
|
||||
using CustomIDType = decltype(GetIDFn{}(std::declval<T>()));
|
||||
|
||||
uint64_t operator()(const T &value) const
|
||||
{
|
||||
return get_default_hash(GetIDFn{}(value));
|
||||
}
|
||||
uint64_t operator()(const CustomIDType &value) const
|
||||
{
|
||||
return get_default_hash(value);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename GetIDFn> struct CustomIDEqual {
|
||||
using CustomIDType = decltype(GetIDFn{}(std::declval<T>()));
|
||||
|
||||
bool operator()(const T &a, const T &b) const
|
||||
{
|
||||
return GetIDFn{}(a) == GetIDFn{}(b);
|
||||
}
|
||||
bool operator()(const CustomIDType &a, const T &b) const
|
||||
{
|
||||
return a == GetIDFn{}(b);
|
||||
}
|
||||
bool operator()(const T &a, const CustomIDType &b) const
|
||||
{
|
||||
return GetIDFn{}(a) == b;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Used for a set where the key itself isn't used for the hash or equality but some part of the
|
||||
* key instead. For example the string identifiers of node types.
|
||||
*
|
||||
* #GetIDFn should have an implementation that returns a hashable and equality comparable type,
|
||||
* i.e. `StringRef operator()(const bNode *value) { return value->idname; }`.
|
||||
*/
|
||||
template<typename T, typename GetIDFn>
|
||||
using CustomIDVectorSet =
|
||||
VectorSet<T, DefaultProbingStrategy, CustomIDHash<T, GetIDFn>, CustomIDEqual<T, GetIDFn>>;
|
||||
|
||||
} // namespace blender
|
||||
|
||||
@@ -317,4 +317,26 @@ TEST(vector_set, ExtractVectorEmpty)
|
||||
EXPECT_TRUE(vec.is_empty());
|
||||
}
|
||||
|
||||
TEST(vector_set, CustomIDVectorSet)
|
||||
{
|
||||
struct ThingWithID {
|
||||
int a;
|
||||
std::string b;
|
||||
int c;
|
||||
};
|
||||
struct ThingGetter {
|
||||
StringRef operator()(const ThingWithID &value) const
|
||||
{
|
||||
return value.b;
|
||||
}
|
||||
};
|
||||
CustomIDVectorSet<ThingWithID, ThingGetter> set;
|
||||
set.add_new(ThingWithID{0, "test", 54});
|
||||
EXPECT_TRUE(set.contains_as("test"));
|
||||
set.add_new(ThingWithID{4333, "other", 2});
|
||||
EXPECT_EQ(set.size(), 2);
|
||||
set.add(ThingWithID{3333, "test", 27});
|
||||
EXPECT_EQ(set.size(), 2);
|
||||
}
|
||||
|
||||
} // namespace blender::tests
|
||||
|
||||
@@ -30,35 +30,15 @@
|
||||
|
||||
using blender::StringRef;
|
||||
|
||||
struct GizmoGroupTypePointerHash {
|
||||
uint64_t operator()(const wmGizmoGroupType *value) const
|
||||
{
|
||||
return get_default_hash(StringRef(value->idname));
|
||||
}
|
||||
uint64_t operator()(const StringRef name) const
|
||||
{
|
||||
return get_default_hash(name);
|
||||
}
|
||||
};
|
||||
|
||||
struct GizmoGroupTypePointerNameEqual {
|
||||
bool operator()(const wmGizmoGroupType *a, const wmGizmoGroupType *b) const
|
||||
{
|
||||
return STREQ(a->idname, b->idname);
|
||||
}
|
||||
bool operator()(const StringRef idname, const wmGizmoGroupType *a) const
|
||||
{
|
||||
return a->idname == idname;
|
||||
}
|
||||
};
|
||||
|
||||
static auto &get_gizmo_group_type_map()
|
||||
{
|
||||
static blender::VectorSet<wmGizmoGroupType *,
|
||||
blender::DefaultProbingStrategy,
|
||||
GizmoGroupTypePointerHash,
|
||||
GizmoGroupTypePointerNameEqual>
|
||||
map;
|
||||
struct IDNameGetter {
|
||||
StringRef operator()(const wmGizmoGroupType *value) const
|
||||
{
|
||||
return StringRef(value->idname);
|
||||
}
|
||||
};
|
||||
static blender::CustomIDVectorSet<wmGizmoGroupType *, IDNameGetter> map;
|
||||
return map;
|
||||
}
|
||||
|
||||
|
||||
@@ -39,35 +39,15 @@
|
||||
|
||||
using blender::StringRef;
|
||||
|
||||
struct GizmoTypePointerHash {
|
||||
uint64_t operator()(const wmGizmoType *value) const
|
||||
{
|
||||
return get_default_hash(StringRef(value->idname));
|
||||
}
|
||||
uint64_t operator()(const StringRef name) const
|
||||
{
|
||||
return get_default_hash(name);
|
||||
}
|
||||
};
|
||||
|
||||
struct GizmoTypePointerNameEqual {
|
||||
bool operator()(const wmGizmoType *a, const wmGizmoType *b) const
|
||||
{
|
||||
return STREQ(a->idname, b->idname);
|
||||
}
|
||||
bool operator()(const StringRef idname, const wmGizmoType *a) const
|
||||
{
|
||||
return a->idname == idname;
|
||||
}
|
||||
};
|
||||
|
||||
static auto &get_gizmo_type_map()
|
||||
{
|
||||
static blender::VectorSet<wmGizmoType *,
|
||||
blender::DefaultProbingStrategy,
|
||||
GizmoTypePointerHash,
|
||||
GizmoTypePointerNameEqual>
|
||||
map;
|
||||
struct IDNameGetter {
|
||||
StringRef operator()(const wmGizmoType *value) const
|
||||
{
|
||||
return StringRef(value->idname);
|
||||
}
|
||||
};
|
||||
static blender::CustomIDVectorSet<wmGizmoType *, IDNameGetter> map;
|
||||
return map;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,35 +28,15 @@
|
||||
|
||||
using blender::StringRef;
|
||||
|
||||
struct MenuTypePointerHash {
|
||||
uint64_t operator()(const MenuType *value) const
|
||||
{
|
||||
return get_default_hash(StringRef(value->idname));
|
||||
}
|
||||
uint64_t operator()(const StringRef name) const
|
||||
{
|
||||
return get_default_hash(name);
|
||||
}
|
||||
};
|
||||
|
||||
struct MenuTypePointerNameEqual {
|
||||
bool operator()(const MenuType *a, const MenuType *b) const
|
||||
{
|
||||
return STREQ(a->idname, b->idname);
|
||||
}
|
||||
bool operator()(const StringRef idname, const MenuType *a) const
|
||||
{
|
||||
return a->idname == idname;
|
||||
}
|
||||
};
|
||||
|
||||
static auto &get_menu_type_map()
|
||||
{
|
||||
static blender::VectorSet<MenuType *,
|
||||
blender::DefaultProbingStrategy,
|
||||
MenuTypePointerHash,
|
||||
MenuTypePointerNameEqual>
|
||||
map;
|
||||
struct IDNameGetter {
|
||||
StringRef operator()(const MenuType *value) const
|
||||
{
|
||||
return StringRef(value->idname);
|
||||
}
|
||||
};
|
||||
static blender::CustomIDVectorSet<MenuType *, IDNameGetter> map;
|
||||
return map;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,35 +25,15 @@
|
||||
|
||||
using blender::StringRef;
|
||||
|
||||
struct PanelTypePointerHash {
|
||||
uint64_t operator()(const PanelType *value) const
|
||||
{
|
||||
return get_default_hash(StringRef(value->idname));
|
||||
}
|
||||
uint64_t operator()(const StringRef name) const
|
||||
{
|
||||
return get_default_hash(name);
|
||||
}
|
||||
};
|
||||
|
||||
struct PanelTypePointerNameEqual {
|
||||
bool operator()(const PanelType *a, const PanelType *b) const
|
||||
{
|
||||
return STREQ(a->idname, b->idname);
|
||||
}
|
||||
bool operator()(const StringRef idname, const PanelType *a) const
|
||||
{
|
||||
return a->idname == idname;
|
||||
}
|
||||
};
|
||||
|
||||
static auto &get_panel_type_map()
|
||||
{
|
||||
static blender::VectorSet<PanelType *,
|
||||
blender::DefaultProbingStrategy,
|
||||
PanelTypePointerHash,
|
||||
PanelTypePointerNameEqual>
|
||||
map;
|
||||
struct IDNameGetter {
|
||||
StringRef operator()(const PanelType *value) const
|
||||
{
|
||||
return StringRef(value->idname);
|
||||
}
|
||||
};
|
||||
static blender::CustomIDVectorSet<PanelType *, IDNameGetter> map;
|
||||
return map;
|
||||
}
|
||||
|
||||
|
||||
@@ -32,35 +32,15 @@
|
||||
|
||||
using blender::StringRef;
|
||||
|
||||
struct ListTypePointerHash {
|
||||
uint64_t operator()(const uiListType *value) const
|
||||
{
|
||||
return get_default_hash(StringRef(value->idname));
|
||||
}
|
||||
uint64_t operator()(const StringRef name) const
|
||||
{
|
||||
return get_default_hash(name);
|
||||
}
|
||||
};
|
||||
|
||||
struct ListTypePointerNameEqual {
|
||||
bool operator()(const uiListType *a, const uiListType *b) const
|
||||
{
|
||||
return STREQ(a->idname, b->idname);
|
||||
}
|
||||
bool operator()(const StringRef idname, const uiListType *a) const
|
||||
{
|
||||
return a->idname == idname;
|
||||
}
|
||||
};
|
||||
|
||||
static auto &get_list_type_map()
|
||||
{
|
||||
static blender::VectorSet<uiListType *,
|
||||
blender::DefaultProbingStrategy,
|
||||
ListTypePointerHash,
|
||||
ListTypePointerNameEqual>
|
||||
map;
|
||||
struct IDNameGetter {
|
||||
StringRef operator()(const uiListType *value) const
|
||||
{
|
||||
return StringRef(value->idname);
|
||||
}
|
||||
};
|
||||
static blender::CustomIDVectorSet<uiListType *, IDNameGetter> map;
|
||||
return map;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user