Add a new HashMap implementation

Adds a new, cleaned up, HashMap implementation.

* Uses Robin Hood Hashing (https://en.wikipedia.org/wiki/Hash_table#Robin_Hood_hashing).
* Keeps elements in a double linked list for simpler, ordered, iteration.
* Allows keeping iterators for later use in removal (Unlike Map<>, it does not do much
  for performance vs keeping the key, but helps replace old code).
* Uses a more modern C++ iterator API, deprecates the old one.
* Supports custom allocator (in case there is a wish to use a paged one).

This class aims to unify all the associative template usage and replace it by this one:
* Map<> (whereas key order does not matter, which is 99% of cases)
* HashMap<>
* OrderedHashMap<>
* OAHashMap<>
This commit is contained in:
reduz 2022-05-08 10:09:19 +02:00 committed by Rémi Verschelde
parent 9b7e16a6b8
commit 8b7c7f5a75
95 changed files with 1434 additions and 1874 deletions

View file

@ -173,7 +173,7 @@ struct NamesCache {
}
};
typedef OrderedHashMap<StringName, ExposedClass> ExposedClasses;
typedef HashMap<StringName, ExposedClass> ExposedClasses;
struct Context {
Vector<StringName> enum_types;
@ -183,13 +183,13 @@ struct Context {
NamesCache names_cache;
const ExposedClass *find_exposed_class(const StringName &p_name) const {
ExposedClasses::ConstElement elem = exposed_classes.find(p_name);
return elem ? &elem.value() : nullptr;
ExposedClasses::ConstIterator elem = exposed_classes.find(p_name);
return elem ? &elem->value : nullptr;
}
const ExposedClass *find_exposed_class(const TypeReference &p_type_ref) const {
ExposedClasses::ConstElement elem = exposed_classes.find(p_type_ref.name);
return elem ? &elem.value() : nullptr;
ExposedClasses::ConstIterator elem = exposed_classes.find(p_type_ref.name);
return elem ? &elem->value : nullptr;
}
bool has_type(const TypeReference &p_type_ref) const {
@ -676,12 +676,11 @@ void add_exposed_classes(Context &r_context) {
// Add signals
const HashMap<StringName, MethodInfo> &signal_map = class_info->signal_map;
const StringName *k = nullptr;
while ((k = signal_map.next(k))) {
for (const KeyValue<StringName, MethodInfo> &K : signal_map) {
SignalData signal;
const MethodInfo &method_info = signal_map.get(*k);
const MethodInfo &method_info = signal_map.get(K.key);
signal.name = method_info.name;
@ -734,14 +733,12 @@ void add_exposed_classes(Context &r_context) {
ClassDB::get_integer_constant_list(class_name, &constants, true);
const HashMap<StringName, List<StringName>> &enum_map = class_info->enum_map;
k = nullptr;
while ((k = enum_map.next(k))) {
for (const KeyValue<StringName, List<StringName>> &K : enum_map) {
EnumData enum_;
enum_.name = *k;
enum_.name = K.key;
const List<StringName> &enum_constants = enum_map.get(*k);
for (const StringName &E : enum_constants) {
for (const StringName &E : K.value) {
const StringName &constant_name = E;
TEST_FAIL_COND(String(constant_name).find("::") != -1,
"Enum constant contains '::', check bindings to remove the scope: '",
@ -760,7 +757,7 @@ void add_exposed_classes(Context &r_context) {
exposed_class.enums.push_back(enum_);
r_context.enum_types.push_back(String(class_name) + "." + String(*k));
r_context.enum_types.push_back(String(class_name) + "." + String(K.key));
}
for (const String &E : constants) {
@ -850,8 +847,8 @@ TEST_SUITE("[ClassDB]") {
TEST_FAIL_COND(object_class->base != StringName(),
"Object class derives from another class: '", object_class->base, "'.");
for (ExposedClasses::Element E = context.exposed_classes.front(); E; E = E.next()) {
validate_class(context, E.value());
for (const KeyValue<StringName, ExposedClass> &E : context.exposed_classes) {
validate_class(context, E.value);
}
}
}