diff options
Diffstat (limited to 'core/hash_map.h')
-rw-r--r-- | core/hash_map.h | 141 |
1 files changed, 52 insertions, 89 deletions
diff --git a/core/hash_map.h b/core/hash_map.h index f27a86cc02..78592f8d82 100644 --- a/core/hash_map.h +++ b/core/hash_map.h @@ -59,7 +59,6 @@ template <class TKey, class TData, class Hasher = HashMapHasherDefault, class Co class HashMap { public: struct Pair { - TKey key; TData data; @@ -75,8 +74,8 @@ public: friend class HashMap; uint32_t hash; - Element *next; - Element() { next = 0; } + Element *next = nullptr; + Element() {} Pair pair; public: @@ -94,34 +93,32 @@ public: }; private: - Element **hash_table; - uint8_t hash_table_power; - uint32_t elements; + Element **hash_table = nullptr; + uint8_t hash_table_power = 0; + uint32_t elements = 0; void make_hash_table() { - ERR_FAIL_COND(hash_table); hash_table = memnew_arr(Element *, (1 << MIN_HASH_TABLE_POWER)); hash_table_power = MIN_HASH_TABLE_POWER; elements = 0; - for (int i = 0; i < (1 << MIN_HASH_TABLE_POWER); i++) - hash_table[i] = 0; + for (int i = 0; i < (1 << MIN_HASH_TABLE_POWER); i++) { + hash_table[i] = nullptr; + } } void erase_hash_table() { - ERR_FAIL_COND_MSG(elements, "Cannot erase hash table if there are still elements inside."); memdelete_arr(hash_table); - hash_table = 0; + hash_table = nullptr; hash_table_power = 0; elements = 0; } void check_hash_table() { - int new_hash_table_power = -1; if ((int)elements > ((1 << hash_table_power) * RELATIONSHIP)) { @@ -129,40 +126,36 @@ private: new_hash_table_power = hash_table_power + 1; while ((int)elements > ((1 << new_hash_table_power) * RELATIONSHIP)) { - new_hash_table_power++; } } else if ((hash_table_power > (int)MIN_HASH_TABLE_POWER) && ((int)elements < ((1 << (hash_table_power - 1)) * RELATIONSHIP))) { - /* rehash down */ new_hash_table_power = hash_table_power - 1; while ((int)elements < ((1 << (new_hash_table_power - 1)) * RELATIONSHIP)) { - new_hash_table_power--; } - if (new_hash_table_power < (int)MIN_HASH_TABLE_POWER) + if (new_hash_table_power < (int)MIN_HASH_TABLE_POWER) { new_hash_table_power = MIN_HASH_TABLE_POWER; + } } - if (new_hash_table_power == -1) + if (new_hash_table_power == -1) { return; + } Element **new_hash_table = memnew_arr(Element *, ((uint64_t)1 << new_hash_table_power)); ERR_FAIL_COND_MSG(!new_hash_table, "Out of memory."); for (int i = 0; i < (1 << new_hash_table_power); i++) { - - new_hash_table[i] = 0; + new_hash_table[i] = nullptr; } if (hash_table) { for (int i = 0; i < (1 << hash_table_power); i++) { - while (hash_table[i]) { - Element *se = hash_table[i]; hash_table[i] = se->next; int new_pos = se->hash & ((1 << new_hash_table_power) - 1); @@ -179,17 +172,14 @@ private: /* I want to have only one function.. */ _FORCE_INLINE_ const Element *get_element(const TKey &p_key) const { - uint32_t hash = Hasher::hash(p_key); uint32_t index = hash & ((1 << hash_table_power) - 1); Element *e = hash_table[index]; while (e) { - /* checking hash first avoids comparing key, which may take longer */ if (e->hash == hash && Comparator::compare(e->pair.key, p_key)) { - /* the pair exists in this hashtable, so just update data */ return e; } @@ -201,7 +191,6 @@ private: } Element *create_element(const TKey &p_key) { - /* if element doesn't exist, create it */ Element *e = memnew(Element); ERR_FAIL_COND_V_MSG(!e, nullptr, "Out of memory."); @@ -219,27 +208,26 @@ private: } void copy_from(const HashMap &p_t) { - - if (&p_t == this) + if (&p_t == this) { return; /* much less bother with that */ + } clear(); - if (!p_t.hash_table || p_t.hash_table_power == 0) + if (!p_t.hash_table || p_t.hash_table_power == 0) { return; /* not copying from empty table */ + } hash_table = memnew_arr(Element *, (uint64_t)1 << p_t.hash_table_power); hash_table_power = p_t.hash_table_power; elements = p_t.elements; for (int i = 0; i < (1 << p_t.hash_table_power); i++) { - hash_table[i] = nullptr; const Element *e = p_t.hash_table[i]; while (e) { - Element *le = memnew(Element); /* local element */ *le = *e; /* copy data */ @@ -259,20 +247,20 @@ public: } Element *set(const Pair &p_pair) { - Element *e = nullptr; - if (!hash_table) + if (!hash_table) { make_hash_table(); // if no table, make one - else + } else { e = const_cast<Element *>(get_element(p_pair.key)); + } /* if we made it up to here, the pair doesn't exist, create and assign */ if (!e) { - e = create_element(p_pair.key); - if (!e) + if (!e) { return nullptr; + } check_hash_table(); // perform mantenience routine } @@ -281,7 +269,6 @@ public: } bool has(const TKey &p_key) const { - return getptr(p_key) != nullptr; } @@ -292,14 +279,12 @@ public: */ const TData &get(const TKey &p_key) const { - const TData *res = getptr(p_key); ERR_FAIL_COND_V(!res, *res); return *res; } TData &get(const TKey &p_key) { - TData *res = getptr(p_key); ERR_FAIL_COND_V(!res, *res); return *res; @@ -311,27 +296,29 @@ public: */ _FORCE_INLINE_ TData *getptr(const TKey &p_key) { - - if (unlikely(!hash_table)) + if (unlikely(!hash_table)) { return nullptr; + } Element *e = const_cast<Element *>(get_element(p_key)); - if (e) + if (e) { return &e->pair.data; + } return nullptr; } _FORCE_INLINE_ const TData *getptr(const TKey &p_key) const { - - if (unlikely(!hash_table)) + if (unlikely(!hash_table)) { return nullptr; + } const Element *e = const_cast<Element *>(get_element(p_key)); - if (e) + if (e) { return &e->pair.data; + } return nullptr; } @@ -343,9 +330,9 @@ public: template <class C> _FORCE_INLINE_ TData *custom_getptr(C p_custom_key, uint32_t p_custom_hash) { - - if (unlikely(!hash_table)) + if (unlikely(!hash_table)) { return nullptr; + } uint32_t hash = p_custom_hash; uint32_t index = hash & ((1 << hash_table_power) - 1); @@ -353,10 +340,8 @@ public: Element *e = hash_table[index]; while (e) { - /* checking hash first avoids comparing key, which may take longer */ if (e->hash == hash && Comparator::compare(e->pair.key, p_custom_key)) { - /* the pair exists in this hashtable, so just update data */ return &e->pair.data; } @@ -369,9 +354,9 @@ public: template <class C> _FORCE_INLINE_ const TData *custom_getptr(C p_custom_key, uint32_t p_custom_hash) const { - - if (unlikely(!hash_table)) + if (unlikely(!hash_table)) { return nullptr; + } uint32_t hash = p_custom_hash; uint32_t index = hash & ((1 << hash_table_power) - 1); @@ -379,10 +364,8 @@ public: const Element *e = hash_table[index]; while (e) { - /* checking hash first avoids comparing key, which may take longer */ if (e->hash == hash && Comparator::compare(e->pair.key, p_custom_key)) { - /* the pair exists in this hashtable, so just update data */ return &e->pair.data; } @@ -398,9 +381,9 @@ public: */ bool erase(const TKey &p_key) { - - if (unlikely(!hash_table)) + if (unlikely(!hash_table)) { return false; + } uint32_t hash = Hasher::hash(p_key); uint32_t index = hash & ((1 << hash_table_power) - 1); @@ -408,12 +391,9 @@ public: Element *e = hash_table[index]; Element *p = nullptr; while (e) { - /* checking hash first avoids comparing key, which may take longer */ if (e->hash == hash && Comparator::compare(e->pair.key, p_key)) { - if (p) { - p->next = e->next; } else { //begin of list @@ -423,10 +403,11 @@ public: memdelete(e); elements--; - if (elements == 0) + if (elements == 0) { erase_hash_table(); - else + } else { check_hash_table(); + } return true; } @@ -444,14 +425,14 @@ public: inline TData &operator[](const TKey &p_key) { //assignment Element *e = nullptr; - if (!hash_table) + if (!hash_table) { make_hash_table(); // if no table, make one - else + } else { e = const_cast<Element *>(get_element(p_key)); + } /* if we made it up to here, the pair doesn't exist, create */ if (!e) { - e = create_element(p_key); CRASH_COND(!e); check_hash_table(); // perform mantenience routine @@ -476,14 +457,13 @@ public: * */ const TKey *next(const TKey *p_key) const { - - if (unlikely(!hash_table)) + if (unlikely(!hash_table)) { return nullptr; + } if (!p_key) { /* get the first key */ for (int i = 0; i < (1 << hash_table_power); i++) { - if (hash_table[i]) { return &hash_table[i]->pair.key; } @@ -501,7 +481,6 @@ public: uint32_t index = e->hash & ((1 << hash_table_power) - 1); index++; for (int i = index; i < (1 << hash_table_power); i++) { - if (hash_table[i]) { return &hash_table[i]->pair.key; } @@ -515,23 +494,18 @@ public: } inline unsigned int size() const { - return elements; } inline bool empty() const { - return elements == 0; } void clear() { - /* clean up */ if (hash_table) { for (int i = 0; i < (1 << hash_table_power); i++) { - while (hash_table[i]) { - Element *e = hash_table[i]; hash_table[i] = e->next; memdelete(e); @@ -541,27 +515,20 @@ public: memdelete_arr(hash_table); } - hash_table = 0; + hash_table = nullptr; hash_table_power = 0; elements = 0; } void operator=(const HashMap &p_table) { - copy_from(p_table); } - HashMap() { - hash_table = nullptr; - elements = 0; - hash_table_power = 0; - } - void get_key_value_ptr_array(const Pair **p_pairs) const { - if (unlikely(!hash_table)) + if (unlikely(!hash_table)) { return; + } for (int i = 0; i < (1 << hash_table_power); i++) { - Element *e = hash_table[i]; while (e) { *p_pairs = &e->pair; @@ -572,10 +539,10 @@ public: } void get_key_list(List<TKey> *p_keys) const { - if (unlikely(!hash_table)) + if (unlikely(!hash_table)) { return; + } for (int i = 0; i < (1 << hash_table_power); i++) { - Element *e = hash_table[i]; while (e) { p_keys->push_back(e->pair.key); @@ -584,17 +551,13 @@ public: } } - HashMap(const HashMap &p_table) { - - hash_table = nullptr; - elements = 0; - hash_table_power = 0; + HashMap() {} + HashMap(const HashMap &p_table) { copy_from(p_table); } ~HashMap() { - clear(); } }; |