a_hash_map.h 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734
  1. /**************************************************************************/
  2. /* a_hash_map.h */
  3. /**************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /**************************************************************************/
  8. /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
  9. /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
  10. /* */
  11. /* Permission is hereby granted, free of charge, to any person obtaining */
  12. /* a copy of this software and associated documentation files (the */
  13. /* "Software"), to deal in the Software without restriction, including */
  14. /* without limitation the rights to use, copy, modify, merge, publish, */
  15. /* distribute, sublicense, and/or sell copies of the Software, and to */
  16. /* permit persons to whom the Software is furnished to do so, subject to */
  17. /* the following conditions: */
  18. /* */
  19. /* The above copyright notice and this permission notice shall be */
  20. /* included in all copies or substantial portions of the Software. */
  21. /* */
  22. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  23. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  24. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
  25. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  26. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  27. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  28. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  29. /**************************************************************************/
  30. #ifndef A_HASH_MAP_H
  31. #define A_HASH_MAP_H
  32. #include "core/templates/hash_map.h"
  33. struct HashMapData {
  34. union {
  35. struct
  36. {
  37. uint32_t hash;
  38. uint32_t hash_to_key;
  39. };
  40. uint64_t data;
  41. };
  42. };
  43. static_assert(sizeof(HashMapData) == 8);
  44. /**
  45. * An array-based implementation of a hash map. It is very efficient in terms of performance and
  46. * memory usage. Works like a dynamic array, adding elements to the end of the array, and
  47. * allows you to access array elements by their index by using `get_by_index` method.
  48. * Example:
  49. * ```
  50. * AHashMap<int, Object *> map;
  51. *
  52. * int get_object_id_by_number(int p_number) {
  53. * int id = map.get_index(p_number);
  54. * return id;
  55. * }
  56. *
  57. * Object *get_object_by_id(int p_id) {
  58. * map.get_by_index(p_id).value;
  59. * }
  60. * ```
  61. * Still, don`t erase the elements because ID can break.
  62. *
  63. * When an element erase, its place is taken by the element from the end.
  64. *
  65. * <-------------
  66. * | |
  67. * 6 8 X 9 32 -1 5 -10 7 X X X
  68. * 6 8 7 9 32 -1 5 -10 X X X X
  69. *
  70. *
  71. * Use RBMap if you need to iterate over sorted elements.
  72. *
  73. * Use HashMap if:
  74. * - You need to keep an iterator or const pointer to Key and you intend to add/remove elements in the meantime.
  75. * - You need to preserve the insertion order when using erase.
  76. *
  77. * It is recommended to use `HashMap` if `KeyValue` size is very large.
  78. */
  79. template <typename TKey, typename TValue,
  80. typename Hasher = HashMapHasherDefault,
  81. typename Comparator = HashMapComparatorDefault<TKey>>
  82. class AHashMap {
  83. public:
  84. // Must be a power of two.
  85. static constexpr uint32_t INITIAL_CAPACITY = 16;
  86. static constexpr uint32_t EMPTY_HASH = 0;
  87. static_assert(EMPTY_HASH == 0, "EMPTY_HASH must always be 0 for the memcpy() optimization.");
  88. private:
  89. typedef KeyValue<TKey, TValue> MapKeyValue;
  90. MapKeyValue *elements = nullptr;
  91. HashMapData *map_data = nullptr;
  92. // Due to optimization, this is `capacity - 1`. Use + 1 to get normal capacity.
  93. uint32_t capacity = 0;
  94. uint32_t num_elements = 0;
  95. uint32_t _hash(const TKey &p_key) const {
  96. uint32_t hash = Hasher::hash(p_key);
  97. if (unlikely(hash == EMPTY_HASH)) {
  98. hash = EMPTY_HASH + 1;
  99. }
  100. return hash;
  101. }
  102. static _FORCE_INLINE_ uint32_t _get_resize_count(uint32_t p_capacity) {
  103. return p_capacity ^ (p_capacity + 1) >> 2; // = get_capacity() * 0.75 - 1; Works only if p_capacity = 2^n - 1.
  104. }
  105. static _FORCE_INLINE_ uint32_t _get_probe_length(uint32_t p_pos, uint32_t p_hash, uint32_t p_local_capacity) {
  106. const uint32_t original_pos = p_hash & p_local_capacity;
  107. return (p_pos - original_pos + p_local_capacity + 1) & p_local_capacity;
  108. }
  109. bool _lookup_pos(const TKey &p_key, uint32_t &r_pos, uint32_t &r_hash_pos) const {
  110. if (unlikely(elements == nullptr)) {
  111. return false; // Failed lookups, no elements.
  112. }
  113. return _lookup_pos_with_hash(p_key, r_pos, r_hash_pos, _hash(p_key));
  114. }
  115. bool _lookup_pos_with_hash(const TKey &p_key, uint32_t &r_pos, uint32_t &r_hash_pos, uint32_t p_hash) const {
  116. if (unlikely(elements == nullptr)) {
  117. return false; // Failed lookups, no elements.
  118. }
  119. uint32_t pos = p_hash & capacity;
  120. HashMapData data = map_data[pos];
  121. if (data.hash == p_hash && Comparator::compare(elements[data.hash_to_key].key, p_key)) {
  122. r_pos = data.hash_to_key;
  123. r_hash_pos = pos;
  124. return true;
  125. }
  126. if (data.data == EMPTY_HASH) {
  127. return false;
  128. }
  129. // A collision occurred.
  130. pos = (pos + 1) & capacity;
  131. uint32_t distance = 1;
  132. while (true) {
  133. data = map_data[pos];
  134. if (data.hash == p_hash && Comparator::compare(elements[data.hash_to_key].key, p_key)) {
  135. r_pos = data.hash_to_key;
  136. r_hash_pos = pos;
  137. return true;
  138. }
  139. if (data.data == EMPTY_HASH) {
  140. return false;
  141. }
  142. if (distance > _get_probe_length(pos, data.hash, capacity)) {
  143. return false;
  144. }
  145. pos = (pos + 1) & capacity;
  146. distance++;
  147. }
  148. }
  149. uint32_t _insert_with_hash(uint32_t p_hash, uint32_t p_index) {
  150. uint32_t pos = p_hash & capacity;
  151. if (map_data[pos].data == EMPTY_HASH) {
  152. uint64_t data = ((uint64_t)p_index << 32) | p_hash;
  153. map_data[pos].data = data;
  154. return pos;
  155. }
  156. uint32_t distance = 1;
  157. pos = (pos + 1) & capacity;
  158. HashMapData c_data;
  159. c_data.hash = p_hash;
  160. c_data.hash_to_key = p_index;
  161. while (true) {
  162. if (map_data[pos].data == EMPTY_HASH) {
  163. #ifdef DEV_ENABLED
  164. if (unlikely(distance > 12)) {
  165. WARN_PRINT("Excessive collision count (" +
  166. itos(distance) + "), is the right hash function being used?");
  167. }
  168. #endif
  169. map_data[pos] = c_data;
  170. return pos;
  171. }
  172. // Not an empty slot, let's check the probing length of the existing one.
  173. uint32_t existing_probe_len = _get_probe_length(pos, map_data[pos].hash, capacity);
  174. if (existing_probe_len < distance) {
  175. SWAP(c_data, map_data[pos]);
  176. distance = existing_probe_len;
  177. }
  178. pos = (pos + 1) & capacity;
  179. distance++;
  180. }
  181. }
  182. void _resize_and_rehash(uint32_t p_new_capacity) {
  183. uint32_t real_old_capacity = capacity + 1;
  184. // Capacity can't be 0 and must be 2^n - 1.
  185. capacity = MAX(4u, p_new_capacity);
  186. uint32_t real_capacity = next_power_of_2(capacity);
  187. capacity = real_capacity - 1;
  188. HashMapData *old_map_data = map_data;
  189. map_data = reinterpret_cast<HashMapData *>(Memory::alloc_static(sizeof(HashMapData) * real_capacity));
  190. elements = reinterpret_cast<MapKeyValue *>(Memory::realloc_static(elements, sizeof(MapKeyValue) * (_get_resize_count(capacity) + 1)));
  191. memset(map_data, EMPTY_HASH, real_capacity * sizeof(HashMapData));
  192. if (num_elements != 0) {
  193. for (uint32_t i = 0; i < real_old_capacity; i++) {
  194. HashMapData data = old_map_data[i];
  195. if (data.data != EMPTY_HASH) {
  196. _insert_with_hash(data.hash, data.hash_to_key);
  197. }
  198. }
  199. }
  200. Memory::free_static(old_map_data);
  201. }
  202. int32_t _insert_element(const TKey &p_key, const TValue &p_value, uint32_t p_hash) {
  203. if (unlikely(elements == nullptr)) {
  204. // Allocate on demand to save memory.
  205. uint32_t real_capacity = capacity + 1;
  206. map_data = reinterpret_cast<HashMapData *>(Memory::alloc_static(sizeof(HashMapData) * real_capacity));
  207. elements = reinterpret_cast<MapKeyValue *>(Memory::alloc_static(sizeof(MapKeyValue) * (_get_resize_count(capacity) + 1)));
  208. memset(map_data, EMPTY_HASH, real_capacity * sizeof(HashMapData));
  209. }
  210. if (unlikely(num_elements > _get_resize_count(capacity))) {
  211. _resize_and_rehash(capacity * 2);
  212. }
  213. memnew_placement(&elements[num_elements], MapKeyValue(p_key, p_value));
  214. _insert_with_hash(p_hash, num_elements);
  215. num_elements++;
  216. return num_elements - 1;
  217. }
  218. void _init_from(const AHashMap &p_other) {
  219. capacity = p_other.capacity;
  220. uint32_t real_capacity = capacity + 1;
  221. num_elements = p_other.num_elements;
  222. if (p_other.num_elements == 0) {
  223. return;
  224. }
  225. map_data = reinterpret_cast<HashMapData *>(Memory::alloc_static(sizeof(HashMapData) * real_capacity));
  226. elements = reinterpret_cast<MapKeyValue *>(Memory::alloc_static(sizeof(MapKeyValue) * (_get_resize_count(capacity) + 1)));
  227. if constexpr (std::is_trivially_copyable_v<TKey> && std::is_trivially_copyable_v<TValue>) {
  228. void *destination = elements;
  229. const void *source = p_other.elements;
  230. memcpy(destination, source, sizeof(MapKeyValue) * num_elements);
  231. } else {
  232. for (uint32_t i = 0; i < num_elements; i++) {
  233. memnew_placement(&elements[i], MapKeyValue(p_other.elements[i]));
  234. }
  235. }
  236. memcpy(map_data, p_other.map_data, sizeof(HashMapData) * real_capacity);
  237. }
  238. public:
  239. /* Standard Godot Container API */
  240. _FORCE_INLINE_ uint32_t get_capacity() const { return capacity + 1; }
  241. _FORCE_INLINE_ uint32_t size() const { return num_elements; }
  242. _FORCE_INLINE_ bool is_empty() const {
  243. return num_elements == 0;
  244. }
  245. void clear() {
  246. if (elements == nullptr || num_elements == 0) {
  247. return;
  248. }
  249. memset(map_data, EMPTY_HASH, (capacity + 1) * sizeof(HashMapData));
  250. if constexpr (!(std::is_trivially_destructible_v<TKey> && std::is_trivially_destructible_v<TValue>)) {
  251. for (uint32_t i = 0; i < num_elements; i++) {
  252. elements[i].key.~TKey();
  253. elements[i].value.~TValue();
  254. }
  255. }
  256. num_elements = 0;
  257. }
  258. TValue &get(const TKey &p_key) {
  259. uint32_t pos = 0;
  260. uint32_t hash_pos = 0;
  261. bool exists = _lookup_pos(p_key, pos, hash_pos);
  262. CRASH_COND_MSG(!exists, "AHashMap key not found.");
  263. return elements[pos].value;
  264. }
  265. const TValue &get(const TKey &p_key) const {
  266. uint32_t pos = 0;
  267. uint32_t hash_pos = 0;
  268. bool exists = _lookup_pos(p_key, pos, hash_pos);
  269. CRASH_COND_MSG(!exists, "AHashMap key not found.");
  270. return elements[pos].value;
  271. }
  272. const TValue *getptr(const TKey &p_key) const {
  273. uint32_t pos = 0;
  274. uint32_t hash_pos = 0;
  275. bool exists = _lookup_pos(p_key, pos, hash_pos);
  276. if (exists) {
  277. return &elements[pos].value;
  278. }
  279. return nullptr;
  280. }
  281. TValue *getptr(const TKey &p_key) {
  282. uint32_t pos = 0;
  283. uint32_t hash_pos = 0;
  284. bool exists = _lookup_pos(p_key, pos, hash_pos);
  285. if (exists) {
  286. return &elements[pos].value;
  287. }
  288. return nullptr;
  289. }
  290. bool has(const TKey &p_key) const {
  291. uint32_t _pos = 0;
  292. uint32_t h_pos = 0;
  293. return _lookup_pos(p_key, _pos, h_pos);
  294. }
  295. bool erase(const TKey &p_key) {
  296. uint32_t pos = 0;
  297. uint32_t element_pos = 0;
  298. bool exists = _lookup_pos(p_key, element_pos, pos);
  299. if (!exists) {
  300. return false;
  301. }
  302. uint32_t next_pos = (pos + 1) & capacity;
  303. while (map_data[next_pos].hash != EMPTY_HASH && _get_probe_length(next_pos, map_data[next_pos].hash, capacity) != 0) {
  304. SWAP(map_data[next_pos], map_data[pos]);
  305. pos = next_pos;
  306. next_pos = (next_pos + 1) & capacity;
  307. }
  308. map_data[pos].data = EMPTY_HASH;
  309. elements[element_pos].key.~TKey();
  310. elements[element_pos].value.~TValue();
  311. num_elements--;
  312. if (element_pos < num_elements) {
  313. void *destination = &elements[element_pos];
  314. const void *source = &elements[num_elements];
  315. memcpy(destination, source, sizeof(MapKeyValue));
  316. uint32_t h_pos = 0;
  317. _lookup_pos(elements[num_elements].key, pos, h_pos);
  318. map_data[h_pos].hash_to_key = element_pos;
  319. }
  320. return true;
  321. }
  322. // Replace the key of an entry in-place, without invalidating iterators or changing the entries position during iteration.
  323. // p_old_key must exist in the map and p_new_key must not, unless it is equal to p_old_key.
  324. bool replace_key(const TKey &p_old_key, const TKey &p_new_key) {
  325. if (p_old_key == p_new_key) {
  326. return true;
  327. }
  328. uint32_t pos = 0;
  329. uint32_t element_pos = 0;
  330. ERR_FAIL_COND_V(_lookup_pos(p_new_key, element_pos, pos), false);
  331. ERR_FAIL_COND_V(!_lookup_pos(p_old_key, element_pos, pos), false);
  332. MapKeyValue &element = elements[element_pos];
  333. const_cast<TKey &>(element.key) = p_new_key;
  334. uint32_t next_pos = (pos + 1) & capacity;
  335. while (map_data[next_pos].hash != EMPTY_HASH && _get_probe_length(next_pos, map_data[next_pos].hash, capacity) != 0) {
  336. SWAP(map_data[next_pos], map_data[pos]);
  337. pos = next_pos;
  338. next_pos = (next_pos + 1) & capacity;
  339. }
  340. map_data[pos].data = EMPTY_HASH;
  341. uint32_t hash = _hash(p_new_key);
  342. _insert_with_hash(hash, element_pos);
  343. return true;
  344. }
  345. // Reserves space for a number of elements, useful to avoid many resizes and rehashes.
  346. // If adding a known (possibly large) number of elements at once, must be larger than old capacity.
  347. void reserve(uint32_t p_new_capacity) {
  348. ERR_FAIL_COND_MSG(p_new_capacity < get_capacity(), "It is impossible to reserve less capacity than is currently available.");
  349. if (elements == nullptr) {
  350. capacity = MAX(4u, p_new_capacity);
  351. capacity = next_power_of_2(capacity) - 1;
  352. return; // Unallocated yet.
  353. }
  354. _resize_and_rehash(p_new_capacity);
  355. }
  356. /** Iterator API **/
  357. struct ConstIterator {
  358. _FORCE_INLINE_ const MapKeyValue &operator*() const {
  359. return *pair;
  360. }
  361. _FORCE_INLINE_ const MapKeyValue *operator->() const {
  362. return pair;
  363. }
  364. _FORCE_INLINE_ ConstIterator &operator++() {
  365. pair++;
  366. return *this;
  367. }
  368. _FORCE_INLINE_ ConstIterator &operator--() {
  369. pair--;
  370. if (pair < begin) {
  371. pair = end;
  372. }
  373. return *this;
  374. }
  375. _FORCE_INLINE_ bool operator==(const ConstIterator &b) const { return pair == b.pair; }
  376. _FORCE_INLINE_ bool operator!=(const ConstIterator &b) const { return pair != b.pair; }
  377. _FORCE_INLINE_ explicit operator bool() const {
  378. return pair != end;
  379. }
  380. _FORCE_INLINE_ ConstIterator(MapKeyValue *p_key, MapKeyValue *p_begin, MapKeyValue *p_end) {
  381. pair = p_key;
  382. begin = p_begin;
  383. end = p_end;
  384. }
  385. _FORCE_INLINE_ ConstIterator() {}
  386. _FORCE_INLINE_ ConstIterator(const ConstIterator &p_it) {
  387. pair = p_it.pair;
  388. begin = p_it.begin;
  389. end = p_it.end;
  390. }
  391. _FORCE_INLINE_ void operator=(const ConstIterator &p_it) {
  392. pair = p_it.pair;
  393. begin = p_it.begin;
  394. end = p_it.end;
  395. }
  396. private:
  397. MapKeyValue *pair = nullptr;
  398. MapKeyValue *begin = nullptr;
  399. MapKeyValue *end = nullptr;
  400. };
  401. struct Iterator {
  402. _FORCE_INLINE_ MapKeyValue &operator*() const {
  403. return *pair;
  404. }
  405. _FORCE_INLINE_ MapKeyValue *operator->() const {
  406. return pair;
  407. }
  408. _FORCE_INLINE_ Iterator &operator++() {
  409. pair++;
  410. return *this;
  411. }
  412. _FORCE_INLINE_ Iterator &operator--() {
  413. pair--;
  414. if (pair < begin) {
  415. pair = end;
  416. }
  417. return *this;
  418. }
  419. _FORCE_INLINE_ bool operator==(const Iterator &b) const { return pair == b.pair; }
  420. _FORCE_INLINE_ bool operator!=(const Iterator &b) const { return pair != b.pair; }
  421. _FORCE_INLINE_ explicit operator bool() const {
  422. return pair != end;
  423. }
  424. _FORCE_INLINE_ Iterator(MapKeyValue *p_key, MapKeyValue *p_begin, MapKeyValue *p_end) {
  425. pair = p_key;
  426. begin = p_begin;
  427. end = p_end;
  428. }
  429. _FORCE_INLINE_ Iterator() {}
  430. _FORCE_INLINE_ Iterator(const Iterator &p_it) {
  431. pair = p_it.pair;
  432. begin = p_it.begin;
  433. end = p_it.end;
  434. }
  435. _FORCE_INLINE_ void operator=(const Iterator &p_it) {
  436. pair = p_it.pair;
  437. begin = p_it.begin;
  438. end = p_it.end;
  439. }
  440. operator ConstIterator() const {
  441. return ConstIterator(pair, begin, end);
  442. }
  443. private:
  444. MapKeyValue *pair = nullptr;
  445. MapKeyValue *begin = nullptr;
  446. MapKeyValue *end = nullptr;
  447. };
  448. _FORCE_INLINE_ Iterator begin() {
  449. return Iterator(elements, elements, elements + num_elements);
  450. }
  451. _FORCE_INLINE_ Iterator end() {
  452. return Iterator(elements + num_elements, elements, elements + num_elements);
  453. }
  454. _FORCE_INLINE_ Iterator last() {
  455. if (unlikely(num_elements == 0)) {
  456. return Iterator(nullptr, nullptr, nullptr);
  457. }
  458. return Iterator(elements + num_elements - 1, elements, elements + num_elements);
  459. }
  460. Iterator find(const TKey &p_key) {
  461. uint32_t pos = 0;
  462. uint32_t h_pos = 0;
  463. bool exists = _lookup_pos(p_key, pos, h_pos);
  464. if (!exists) {
  465. return end();
  466. }
  467. return Iterator(elements + pos, elements, elements + num_elements);
  468. }
  469. void remove(const Iterator &p_iter) {
  470. if (p_iter) {
  471. erase(p_iter->key);
  472. }
  473. }
  474. _FORCE_INLINE_ ConstIterator begin() const {
  475. return ConstIterator(elements, elements, elements + num_elements);
  476. }
  477. _FORCE_INLINE_ ConstIterator end() const {
  478. return ConstIterator(elements + num_elements, elements, elements + num_elements);
  479. }
  480. _FORCE_INLINE_ ConstIterator last() const {
  481. if (unlikely(num_elements == 0)) {
  482. return ConstIterator(nullptr, nullptr, nullptr);
  483. }
  484. return ConstIterator(elements + num_elements - 1, elements, elements + num_elements);
  485. }
  486. ConstIterator find(const TKey &p_key) const {
  487. uint32_t pos = 0;
  488. uint32_t h_pos = 0;
  489. bool exists = _lookup_pos(p_key, pos, h_pos);
  490. if (!exists) {
  491. return end();
  492. }
  493. return ConstIterator(elements + pos, elements, elements + num_elements);
  494. }
  495. /* Indexing */
  496. const TValue &operator[](const TKey &p_key) const {
  497. uint32_t pos = 0;
  498. uint32_t h_pos = 0;
  499. bool exists = _lookup_pos(p_key, pos, h_pos);
  500. CRASH_COND(!exists);
  501. return elements[pos].value;
  502. }
  503. TValue &operator[](const TKey &p_key) {
  504. uint32_t pos = 0;
  505. uint32_t h_pos = 0;
  506. uint32_t hash = _hash(p_key);
  507. bool exists = _lookup_pos_with_hash(p_key, pos, h_pos, hash);
  508. if (exists) {
  509. return elements[pos].value;
  510. } else {
  511. pos = _insert_element(p_key, TValue(), hash);
  512. return elements[pos].value;
  513. }
  514. }
  515. /* Insert */
  516. Iterator insert(const TKey &p_key, const TValue &p_value) {
  517. uint32_t pos = 0;
  518. uint32_t h_pos = 0;
  519. uint32_t hash = _hash(p_key);
  520. bool exists = _lookup_pos_with_hash(p_key, pos, h_pos, hash);
  521. if (!exists) {
  522. pos = _insert_element(p_key, p_value, hash);
  523. } else {
  524. elements[pos].value = p_value;
  525. }
  526. return Iterator(elements + pos, elements, elements + num_elements);
  527. }
  528. // Inserts an element without checking if it already exists.
  529. Iterator insert_new(const TKey &p_key, const TValue &p_value) {
  530. DEV_ASSERT(!has(p_key));
  531. uint32_t hash = _hash(p_key);
  532. uint32_t pos = _insert_element(p_key, p_value, hash);
  533. return Iterator(elements + pos, elements, elements + num_elements);
  534. }
  535. /* Array methods. */
  536. // Unsafe. Changing keys and going outside the bounds of an array can lead to undefined behavior.
  537. KeyValue<TKey, TValue> *get_elements_ptr() {
  538. return elements;
  539. }
  540. // Returns the element index. If not found, returns -1.
  541. int get_index(const TKey &p_key) {
  542. uint32_t pos = 0;
  543. uint32_t h_pos = 0;
  544. bool exists = _lookup_pos(p_key, pos, h_pos);
  545. if (!exists) {
  546. return -1;
  547. }
  548. return pos;
  549. }
  550. KeyValue<TKey, TValue> &get_by_index(uint32_t p_index) {
  551. CRASH_BAD_UNSIGNED_INDEX(p_index, num_elements);
  552. return elements[p_index];
  553. }
  554. bool erase_by_index(uint32_t p_index) {
  555. if (p_index >= size()) {
  556. return false;
  557. }
  558. return erase(elements[p_index].key);
  559. }
  560. /* Constructors */
  561. AHashMap(const AHashMap &p_other) {
  562. _init_from(p_other);
  563. }
  564. AHashMap(const HashMap<TKey, TValue> &p_other) {
  565. reserve(p_other.size());
  566. for (const KeyValue<TKey, TValue> &E : p_other) {
  567. uint32_t hash = _hash(E.key);
  568. _insert_element(E.key, E.value, hash);
  569. }
  570. }
  571. void operator=(const AHashMap &p_other) {
  572. if (this == &p_other) {
  573. return; // Ignore self assignment.
  574. }
  575. reset();
  576. _init_from(p_other);
  577. }
  578. void operator=(const HashMap<TKey, TValue> &p_other) {
  579. reset();
  580. if (p_other.size() > get_capacity()) {
  581. reserve(p_other.size());
  582. }
  583. for (const KeyValue<TKey, TValue> &E : p_other) {
  584. uint32_t hash = _hash(E.key);
  585. _insert_element(E.key, E.value, hash);
  586. }
  587. }
  588. AHashMap(uint32_t p_initial_capacity) {
  589. // Capacity can't be 0 and must be 2^n - 1.
  590. capacity = MAX(4u, p_initial_capacity);
  591. capacity = next_power_of_2(capacity) - 1;
  592. }
  593. AHashMap() :
  594. capacity(INITIAL_CAPACITY - 1) {
  595. }
  596. void reset() {
  597. if (elements != nullptr) {
  598. if constexpr (!(std::is_trivially_destructible_v<TKey> && std::is_trivially_destructible_v<TValue>)) {
  599. for (uint32_t i = 0; i < num_elements; i++) {
  600. elements[i].key.~TKey();
  601. elements[i].value.~TValue();
  602. }
  603. }
  604. Memory::free_static(elements);
  605. Memory::free_static(map_data);
  606. elements = nullptr;
  607. }
  608. capacity = INITIAL_CAPACITY - 1;
  609. num_elements = 0;
  610. }
  611. ~AHashMap() {
  612. reset();
  613. }
  614. };
  615. extern template class AHashMap<int, int>;
  616. extern template class AHashMap<String, int>;
  617. extern template class AHashMap<StringName, StringName>;
  618. extern template class AHashMap<StringName, Variant>;
  619. extern template class AHashMap<StringName, int>;
  620. #endif // A_HASH_MAP_H