2
0

HashMap.h 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448
  1. // Copyright (C) 2014, Panagiotis Christopoulos Charitos.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #pragma once
  6. #include "anki/util/Allocator.h"
  7. #include "anki/util/Functions.h"
  8. #include "anki/util/NonCopyable.h"
  9. namespace anki {
  10. /// @addtogroup util_containers
  11. /// @{
  12. namespace detail {
  13. /// HashMap node. It's not a traditional bucket because it doesn't contain more
  14. /// than one values.
  15. /// @internal
  16. template<typename TValue>
  17. class HashMapNode
  18. {
  19. public:
  20. U64 m_hash;
  21. HashMapNode* m_left;
  22. HashMapNode* m_right;
  23. TValue m_value;
  24. HashMapNode* m_parent; ///< Used for iterating.
  25. template<typename... TArgs>
  26. HashMapNode(TArgs&&... args)
  27. : m_hash(0)
  28. , m_left(nullptr)
  29. , m_right(nullptr)
  30. , m_value(args...)
  31. , m_parent(nullptr)
  32. {}
  33. TValue& getValue()
  34. {
  35. return m_value;
  36. }
  37. const TValue& getValue() const
  38. {
  39. return m_value;
  40. }
  41. };
  42. /// HashMap forward-only iterator.
  43. /// @internal
  44. template<typename TNodePointer, typename TValuePointer,
  45. typename TValueReference>
  46. class HashMapIterator
  47. {
  48. template<typename, typename, typename, typename>
  49. friend class HashMap;
  50. template<typename, typename, typename, typename>
  51. friend class HashMapAllocFree;
  52. public:
  53. /// Default constructor.
  54. HashMapIterator()
  55. : m_node(nullptr)
  56. {}
  57. /// Copy.
  58. HashMapIterator(const HashMapIterator& b)
  59. : m_node(b.m_node)
  60. {}
  61. /// Allow conversion from iterator to const iterator.
  62. template<typename YNodePointer, typename YValuePointer,
  63. typename YValueReference>
  64. HashMapIterator(const HashMapIterator<YNodePointer, YValuePointer,
  65. YValueReference>& b)
  66. : m_node(b.m_node)
  67. {}
  68. HashMapIterator(TNodePointer node)
  69. : m_node(node)
  70. {}
  71. TValueReference operator*() const
  72. {
  73. ANKI_ASSERT(m_node);
  74. return m_node->getValue();
  75. }
  76. TValuePointer operator->() const
  77. {
  78. ANKI_ASSERT(m_node);
  79. return &m_node->getValue();
  80. }
  81. HashMapIterator& operator++()
  82. {
  83. ANKI_ASSERT(m_node);
  84. TNodePointer node = m_node;
  85. if(node->m_left)
  86. {
  87. node = node->m_left;
  88. }
  89. else if(node->m_right)
  90. {
  91. node = node->m_right;
  92. }
  93. else
  94. {
  95. // Node without children
  96. TNodePointer prevNode = node;
  97. node = node->m_parent;
  98. while(node)
  99. {
  100. if(node->m_right
  101. && node->m_right != prevNode)
  102. {
  103. node = node->m_right;
  104. break;
  105. }
  106. prevNode = node;
  107. node = node->m_parent;
  108. }
  109. }
  110. m_node = node;
  111. return *this;
  112. }
  113. HashMapIterator operator++(int)
  114. {
  115. ANKI_ASSERT(m_node);
  116. HashMapIterator out = *this;
  117. ++(*this);
  118. return out;
  119. }
  120. HashMapIterator operator+(U n) const
  121. {
  122. HashMapIterator it = *this;
  123. while(n-- != 0)
  124. {
  125. ++it;
  126. }
  127. return it;
  128. }
  129. HashMapIterator& operator+=(U n)
  130. {
  131. while(n-- != 0)
  132. {
  133. ++(*this);
  134. }
  135. return *this;
  136. }
  137. Bool operator==(const HashMapIterator& b) const
  138. {
  139. return m_node == b.m_node;
  140. }
  141. Bool operator!=(const HashMapIterator& b) const
  142. {
  143. return !(*this == b);
  144. }
  145. private:
  146. TNodePointer m_node;
  147. };
  148. /// Hash map base.
  149. /// @tparam TKey The key of the map.
  150. /// @tparam TValue The value of the map.
  151. /// @internal
  152. template<typename TKey, typename TValue, typename THasher, typename TCompare,
  153. typename TNode>
  154. class HashMapBase: public NonCopyable
  155. {
  156. public:
  157. using Key = TKey;
  158. using Value = TValue;
  159. using Reference = Value&;
  160. using ConstReference = const Value&;
  161. using Pointer = Value*;
  162. using ConstPointer = const Value*;
  163. using Iterator = HashMapIterator<TNode*, Pointer, Reference>;
  164. using ConstIterator =
  165. HashMapIterator<const TNode*, ConstPointer, ConstReference>;
  166. /// Default constructor.
  167. HashMapBase()
  168. : m_root(nullptr)
  169. {}
  170. ~HashMapBase() = default;
  171. /// Get begin.
  172. Iterator getBegin()
  173. {
  174. return Iterator(m_root);
  175. }
  176. /// Get begin.
  177. ConstIterator getBegin() const
  178. {
  179. return ConstIterator(m_root);
  180. }
  181. /// Get end.
  182. Iterator getEnd()
  183. {
  184. return Iterator();
  185. }
  186. /// Get end.
  187. ConstIterator getEnd() const
  188. {
  189. return ConstIterator();
  190. }
  191. /// Get begin.
  192. Iterator begin()
  193. {
  194. return getBegin();
  195. }
  196. /// Get begin.
  197. ConstIterator begin() const
  198. {
  199. return getBegin();
  200. }
  201. /// Get end.
  202. Iterator end()
  203. {
  204. return getEnd();
  205. }
  206. /// Get end.
  207. ConstIterator end() const
  208. {
  209. return getEnd();
  210. }
  211. /// Return true if map is empty.
  212. Bool isEmpty() const
  213. {
  214. return m_root == nullptr;
  215. }
  216. /// Find item.
  217. Iterator find(const Key& key);
  218. protected:
  219. /// @privatesection
  220. TNode* m_root = nullptr;
  221. void move(HashMapBase& b)
  222. {
  223. m_root = b.m_root;
  224. b.m_root = nullptr;
  225. }
  226. /// Add a node in the tree.
  227. void insertNode(TNode* node);
  228. /// Remove a node from the tree.
  229. void removeNode(TNode* node);
  230. };
  231. } // end namespace detail
  232. /// Hash map template.
  233. template<typename TKey, typename TValue, typename THasher, typename TCompare>
  234. class HashMap: public detail::HashMapBase<TKey, TValue, THasher, TCompare,
  235. detail::HashMapNode<TValue>>
  236. {
  237. private:
  238. using Base = detail::HashMapBase<TKey, TValue, THasher, TCompare,
  239. detail::HashMapNode<TValue>>;
  240. using Node = detail::HashMapNode<TValue>;
  241. public:
  242. /// Default constructor.
  243. HashMap()
  244. : Base()
  245. {}
  246. /// Move.
  247. HashMap(HashMap&& b)
  248. : Base()
  249. {
  250. Base::move(b);
  251. }
  252. /// You need to manually destroy the map.
  253. /// @see HashMap::destroy
  254. ~HashMap()
  255. {
  256. ANKI_ASSERT(Base::m_root == nullptr && "Requires manual destruction");
  257. }
  258. /// Move.
  259. HashMap& operator=(HashMap&& b)
  260. {
  261. Base::move(b);
  262. return *this;
  263. }
  264. /// Destroy the list.
  265. template<typename TAllocator>
  266. void destroy(TAllocator alloc);
  267. /// Copy an element in the map.
  268. template<typename TAllocator>
  269. void pushBack(TAllocator alloc, const TKey& key, const TValue& x)
  270. {
  271. Node* node = alloc.template newInstance<Node>(x);
  272. node->m_hash = THasher()(key);
  273. Base::insertNode(node);
  274. }
  275. /// Construct an element inside the map.
  276. template<typename TAllocator, typename... TArgs>
  277. void emplaceBack(TAllocator alloc, const TKey& key, TArgs&&... args)
  278. {
  279. Node* node = alloc.template newInstance<Node>(
  280. std::forward<TArgs>(args)...);
  281. node->m_hash = THasher()(key);
  282. Base::insertNode(node);
  283. }
  284. /// Erase element.
  285. template<typename TAllocator>
  286. void erase(TAllocator alloc, typename Base::Iterator it)
  287. {
  288. Node* del = it.m_node;
  289. Base::removeNode(del);
  290. alloc.deleteInstance(del);
  291. }
  292. private:
  293. template<typename TAllocator>
  294. void destroyInternal(TAllocator alloc, Node* node);
  295. };
  296. /// The classes that will use the HashMapAllocFree need to inherit from this
  297. /// one.
  298. template<typename TClass>
  299. class HashMapAllocFreeEnabled
  300. {
  301. template<typename TKey, typename TValue, typename THasher,
  302. typename TCompare, typename TNode>
  303. friend class detail::HashMapBase;
  304. template<typename TNodePointer, typename TValuePointer,
  305. typename TValueReference>
  306. friend class detail::HashMapIterator;
  307. template<typename TKey, typename TValue, typename THasher,
  308. typename TCompare>
  309. friend class HashMapAllocFree;
  310. friend TClass;
  311. private:
  312. U64 m_hash;
  313. TClass* m_left;
  314. TClass* m_right;
  315. TClass* m_parent; ///< Used for iterating.
  316. HashMapAllocFreeEnabled()
  317. : m_hash(0)
  318. , m_left(nullptr)
  319. , m_right(nullptr)
  320. , m_parent(nullptr)
  321. {}
  322. TClass& getValue()
  323. {
  324. return *static_cast<TClass*>(this);
  325. }
  326. const TClass& getValue() const
  327. {
  328. return *static_cast<const TClass*>(this);
  329. }
  330. };
  331. /// Hash map that doesn't perform any allocations. To work the TValue nodes will
  332. /// have to inherit from HashMapAllocFree.
  333. template<typename TKey, typename TValue, typename THasher, typename TCompare>
  334. class HashMapAllocFree: public detail::HashMapBase<TKey, TValue, THasher,
  335. TCompare, TValue>
  336. {
  337. private:
  338. using Base = detail::HashMapBase<TKey, TValue, THasher, TCompare, TValue>;
  339. using Node = TValue;
  340. public:
  341. /// Default constructor.
  342. HashMapAllocFree()
  343. : Base()
  344. {}
  345. /// Move.
  346. HashMapAllocFree(HashMapAllocFree&& b)
  347. : Base()
  348. {
  349. Base::move(b);
  350. }
  351. ~HashMapAllocFree() = default;
  352. /// Move.
  353. HashMapAllocFree& operator=(HashMapAllocFree&& b)
  354. {
  355. Base::move(b);
  356. return *this;
  357. }
  358. /// Add an element to the map.
  359. void pushBack(const TKey& key, TValue* x)
  360. {
  361. ANKI_ASSERT(x);
  362. HashMapAllocFreeEnabled<TValue>* e =
  363. static_cast<HashMapAllocFreeEnabled<TValue>*>(x);
  364. e->m_hash = THasher()(key);
  365. Base::insertNode(x);
  366. }
  367. /// Erase element.
  368. void erase(typename Base::Iterator it)
  369. {
  370. Node* del = it.m_node;
  371. Base::removeNode(del);
  372. }
  373. };
  374. /// @}
  375. } // end namespace anki
  376. #include "anki/util/HashMap.inl.h"