hashTable.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2013 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #ifndef _HASHTABLE_H_
  23. #define _HASHTABLE_H_
  24. #include "vector.h"
  25. #include "platform/platform.h"
  26. #include "string/stringTable.h"
  27. namespace Hash
  28. {
  29. //-Mat this was copied from StringTable
  30. void initTolowerTable();
  31. U32 hash(const char *str);
  32. //-Mat
  33. inline U32 hash(U32 data)
  34. {
  35. return data;
  36. }
  37. inline U32 hash(const void *data)
  38. {
  39. #ifdef TORQUE_CPU_X64
  40. return (U32)((U64)data);
  41. #else
  42. return (U32)data;
  43. #endif
  44. }
  45. U32 nextPrime(U32);
  46. };
  47. namespace tKeyCompare
  48. {
  49. template<typename Key>
  50. inline bool equals( Key keya, Key keyb )
  51. {
  52. return ( keya == keyb );
  53. }
  54. template<>
  55. inline bool equals<>( const char *keya, const char *keyb )
  56. {
  57. //-Mat make sure this is an accurate compare (do we check case?)
  58. return ( dStricmp( keya, keyb ) == 0 );
  59. }
  60. };
  61. /// A HashTable template class.
  62. ///
  63. /// The hash table class maps between a key and an associated value. Access
  64. /// using the key is performed using a hash table. The class provides
  65. /// methods for both unique and equal keys. The global ::hash(Type) function
  66. /// is used for hashing, see util/hash.h
  67. /// @ingroup UtilContainers
  68. template<typename Key, typename Value >
  69. class HashTable
  70. {
  71. public:
  72. struct Pair {
  73. Key key;
  74. Value value;
  75. Pair() {}
  76. Pair(Key k,Value v): key(k), value(v) {}
  77. };
  78. private:
  79. struct Node {
  80. Node* mNext;
  81. Pair mPair;
  82. Node(): mNext(0) {}
  83. Node(Pair p,Node* n): mPair(p),mNext(n) {}
  84. };
  85. Node** mTable; ///< Hash table
  86. S32 mTableSize; ///< Hash table size
  87. U32 mSize; ///< Number of keys in the table
  88. U32 _hash(const Key& key) const;
  89. U32 _index(const Key& key) const;
  90. Node* _next(U32 index) const;
  91. void _resize(U32 size);
  92. void _destroy();
  93. public:
  94. // iterator support
  95. template<typename U,typename E, typename M>
  96. class _Iterator {
  97. friend class HashTable;
  98. E* mLink;
  99. M* mtHashTable;
  100. operator E*();
  101. public:
  102. typedef U ValueType;
  103. typedef U* Pointer;
  104. typedef U& Reference;
  105. _Iterator()
  106. {
  107. mtHashTable = 0;
  108. mLink = 0;
  109. }
  110. _Iterator(M* table,E* ptr)
  111. {
  112. mtHashTable = table;
  113. mLink = ptr;
  114. }
  115. _Iterator& operator++()
  116. {
  117. mLink = mLink->mNext? mLink->mNext :
  118. mtHashTable->_next(mtHashTable->_index(mLink->mPair.key) + 1);
  119. return *this;
  120. }
  121. _Iterator operator++(int)
  122. {
  123. _Iterator itr(*this);
  124. ++(*this);
  125. return itr;
  126. }
  127. //-Mat to check if mLink is bad
  128. Value getValue() {
  129. if( mLink ) {
  130. return mLink->mPair.value;
  131. }
  132. return (Value)(0);
  133. }
  134. bool operator==(const _Iterator& b) const
  135. {
  136. return mtHashTable == b.mtHashTable && mLink == b.mLink;
  137. }
  138. bool operator!=(const _Iterator& b) const
  139. {
  140. return !(*this == b);
  141. }
  142. U* operator->() const
  143. {
  144. return &mLink->mPair;
  145. }
  146. U& operator*() const
  147. {
  148. return mLink->mPair;
  149. }
  150. };
  151. // Types
  152. typedef Pair ValueType;
  153. typedef Pair& Reference;
  154. typedef const Pair& ConstReference;
  155. typedef S32 DifferenceType;
  156. typedef U32 SizeType;
  157. typedef _Iterator<Pair,Node,HashTable> iterator;
  158. typedef _Iterator<const Pair,const Node,const HashTable> const_iterator;
  159. // Initialization
  160. HashTable();
  161. ~HashTable();
  162. HashTable(const HashTable& p);
  163. // Management
  164. U32 size() const; ///< Return the number of elements
  165. U32 tableSize() const; ///< Return the size of the hash bucket table
  166. void clear(); ///< Empty the HashTable
  167. void resize(U32 size);
  168. bool isEmpty() const; ///< Returns true if the table is empty
  169. F32 collisions() const; ///< Returns the average number of nodes per bucket
  170. // Insert & erase elements
  171. iterator insertEqual(const Key& key, const Value&);
  172. iterator insertUnique(const Key& key, const Value&);
  173. void erase(iterator); ///< Erase the given entry
  174. void erase(const Key& key); ///< Erase all matching keys from the table
  175. // HashTable lookup
  176. iterator findOrInsert(const Key& key);
  177. iterator find(const Key&); ///< Find the first entry for the given key
  178. const_iterator find(const Key&) const; ///< Find the first entry for the given key
  179. S32 count(const Key&); ///< Count the number of matching keys in the table
  180. // Forward iterator access
  181. iterator begin(); ///< iterator to first element
  182. const_iterator begin() const; ///< iterator to first element
  183. iterator end(); ///< iterator to last element + 1
  184. const_iterator end() const; ///< iterator to last element + 1
  185. void operator=(const HashTable& p);
  186. };
  187. template<typename Key, typename Value> HashTable<Key,Value>::HashTable()
  188. {
  189. mTableSize = 0;
  190. mTable = 0;
  191. mSize = 0;
  192. }
  193. template<typename Key, typename Value> HashTable<Key,Value>::HashTable(const HashTable& p)
  194. {
  195. mSize = 0;
  196. mTableSize = 0;
  197. mTable = 0;
  198. *this = p;
  199. }
  200. template<typename Key, typename Value> HashTable<Key,Value>::~HashTable()
  201. {
  202. _destroy();
  203. }
  204. //-----------------------------------------------------------------------------
  205. template<typename Key, typename Value>
  206. inline U32 HashTable<Key,Value>::_hash(const Key& key) const
  207. {
  208. return Hash::hash(key);
  209. }
  210. template<typename Key, typename Value>
  211. inline U32 HashTable<Key,Value>::_index(const Key& key) const
  212. {
  213. return _hash(key) % mTableSize;
  214. }
  215. template<typename Key, typename Value>
  216. typename HashTable<Key,Value>::Node* HashTable<Key,Value>::_next(U32 index) const
  217. {
  218. for (; index < (U32)mTableSize; index++)
  219. if (Node* node = mTable[index])
  220. return node;
  221. return 0;
  222. }
  223. template<typename Key, typename Value>
  224. void HashTable<Key,Value>::_resize(U32 size)
  225. {
  226. S32 currentSize = mTableSize;
  227. mTableSize = Hash::nextPrime(size);
  228. Node** table = new Node*[mTableSize];
  229. dMemset(table,0,mTableSize * sizeof(Node*));
  230. for (S32 i = 0; i < currentSize; i++)
  231. for (Node* node = mTable[i]; node; )
  232. {
  233. // Get groups of matching keys
  234. Node* last = node;
  235. while (last->mNext && last->mNext->mPair.key == node->mPair.key)
  236. last = last->mNext;
  237. // Move the chain to the new table
  238. Node** link = &table[_index(node->mPair.key)];
  239. Node* tmp = last->mNext;
  240. last->mNext = *link;
  241. *link = node;
  242. node = tmp;
  243. }
  244. delete[] mTable;
  245. mTable = table;
  246. }
  247. template<typename Key, typename Value>
  248. void HashTable<Key,Value>::_destroy()
  249. {
  250. for (S32 i = 0; i < mTableSize; i++)
  251. for (Node* ptr = mTable[i]; ptr; )
  252. {
  253. Node *tmp = ptr;
  254. ptr = ptr->mNext;
  255. delete tmp;
  256. }
  257. delete[] mTable;
  258. mTable = NULL;
  259. }
  260. //-----------------------------------------------------------------------------
  261. // management
  262. template<typename Key, typename Value>
  263. inline U32 HashTable<Key,Value>::size() const
  264. {
  265. return mSize;
  266. }
  267. template<typename Key, typename Value>
  268. inline U32 HashTable<Key,Value>::tableSize() const
  269. {
  270. return mTableSize;
  271. }
  272. template<typename Key, typename Value>
  273. inline void HashTable<Key,Value>::clear()
  274. {
  275. _destroy();
  276. mTableSize = 0;
  277. mSize = 0;
  278. }
  279. /// Resize the bucket table for an estimated number of elements.
  280. /// This method will optimize the hash bucket table size to hold the given
  281. /// number of elements. The size argument is a hint, and will not be the
  282. /// exact size of the table. If the table is sized down below it's optimal
  283. /// size, the next insert will cause it to be resized again. Normally this
  284. /// function is used to avoid resizes when the number of elements that will
  285. /// be inserted is known in advance.
  286. template<typename Key, typename Value>
  287. inline void HashTable<Key,Value>::resize(U32 size)
  288. {
  289. _resize(size);
  290. }
  291. template<typename Key, typename Value>
  292. inline bool HashTable<Key,Value>::isEmpty() const
  293. {
  294. return mSize == 0;
  295. }
  296. template<typename Key, typename Value>
  297. inline F32 HashTable<Key,Value>::collisions() const
  298. {
  299. S32 chains = 0;
  300. for (S32 i = 0; i < mTableSize; i++)
  301. if (mTable[i])
  302. chains++;
  303. return F32(mSize) / chains;
  304. }
  305. //-----------------------------------------------------------------------------
  306. // add & remove elements
  307. /// Insert the key value pair but don't insert duplicates.
  308. /// This insert method does not insert duplicate keys. If the key already exists in
  309. /// the table the function will fail and end() is returned.
  310. template<typename Key, typename Value>
  311. typename HashTable<Key,Value>::iterator HashTable<Key,Value>::insertUnique(const Key& key, const Value& x)
  312. {
  313. if (mSize >= (U32)mTableSize)
  314. _resize(mSize + 1);
  315. Node** table = &mTable[_index(key)];
  316. for (Node* itr = *table; itr; itr = itr->mNext)
  317. if ( tKeyCompare::equals<Key>( itr->mPair.key, key) )
  318. return end();
  319. mSize++;
  320. *table = new Node(Pair(key,x),*table);
  321. return iterator(this,*table);
  322. }
  323. /// Insert the key value pair and allow duplicates.
  324. /// This insert method allows duplicate keys. Keys are grouped together but
  325. /// are not sorted.
  326. template<typename Key, typename Value>
  327. typename HashTable<Key,Value>::iterator HashTable<Key,Value>::insertEqual(const Key& key, const Value& x)
  328. {
  329. if (mSize >= (U32)mTableSize)
  330. _resize(mSize + 1);
  331. // The new key is inserted at the head of any group of matching keys.
  332. Node** prev = &mTable[_index(key)];
  333. for (Node* itr = *prev; itr; prev = &itr->mNext, itr = itr->mNext)
  334. if ( tKeyCompare::equals<Key>( itr->mPair.key, key ) )
  335. break;
  336. mSize++;
  337. *prev = new Node(Pair(key,x),*prev);
  338. return iterator(this,*prev);
  339. }
  340. template<typename Key, typename Value>
  341. void HashTable<Key,Value>::erase(const Key& key)
  342. {
  343. if (!mSize)
  344. return;
  345. Node** prev = &mTable[_index(key)];
  346. for (Node* itr = *prev; itr; prev = &itr->mNext, itr = itr->mNext)
  347. if ( tKeyCompare::equals<Key>( itr->mPair.key, key ) ) {
  348. // Delete matching keys, which should be grouped together.
  349. do {
  350. Node* tmp = itr;
  351. itr = itr->mNext;
  352. delete tmp;
  353. mSize--;
  354. } while (itr && tKeyCompare::equals<Key>( itr->mPair.key, key ) );
  355. *prev = itr;
  356. return;
  357. }
  358. }
  359. template<typename Key, typename Value>
  360. void HashTable<Key,Value>::erase(iterator node)
  361. {
  362. Node** prev = &mTable[_index(node->key)];
  363. for (Node* itr = *prev; itr; prev = &itr->mNext, itr = itr->mNext)
  364. if (itr == node.mLink) {
  365. *prev = itr->mNext;
  366. delete itr;
  367. mSize--;
  368. return;
  369. }
  370. }
  371. //-----------------------------------------------------------------------------
  372. /// Find the key, or insert a one if it doesn't exist.
  373. /// Returns the first key in the table that matches, or inserts one if there
  374. /// are none.
  375. template<typename Key, typename Value>
  376. typename HashTable<Key,Value>::iterator HashTable<Key,Value>::findOrInsert(const Key& key)
  377. {
  378. if (mSize >= (U32)mTableSize)
  379. _resize(mSize + 1);
  380. Node** table = &mTable[_index(key)];
  381. for (Node* itr = *table; itr; itr = itr->mNext)
  382. if ( tKeyCompare::equals<Key>( itr->mPair.key, key ) )
  383. return iterator(this,itr);
  384. mSize++;
  385. *table = new Node(Pair(key,Value()),*table);
  386. return iterator(this,*table);
  387. }
  388. template<typename Key, typename Value>
  389. typename HashTable<Key,Value>::iterator HashTable<Key,Value>::find(const Key& key)
  390. {
  391. if (mTableSize)
  392. for (Node* itr = mTable[_index(key)]; itr; itr = itr->mNext)
  393. if ( tKeyCompare::equals<Key>( itr->mPair.key, key ) )
  394. return iterator(this,itr);
  395. return iterator(this,0);
  396. }
  397. template<typename Key, typename Value>
  398. S32 HashTable<Key,Value>::count(const Key& key)
  399. {
  400. S32 count = 0;
  401. if (mTableSize)
  402. for (Node* itr = mTable[_index(key)]; itr; itr = itr->mNext)
  403. if ( tKeyCompare::equals<Key>( itr->mPair.key, key ) ) {
  404. // Matching keys should be grouped together.
  405. do {
  406. count++;
  407. itr = itr->mNext;
  408. } while (itr && tKeyCompare::equals<Key>( itr->mPair.key, key ) );
  409. break;
  410. }
  411. return count;
  412. }
  413. //-----------------------------------------------------------------------------
  414. // iterator access
  415. template<typename Key, typename Value>
  416. inline typename HashTable<Key,Value>::iterator HashTable<Key,Value>::begin()
  417. {
  418. return iterator(this,_next(0));
  419. }
  420. template<typename Key, typename Value>
  421. inline typename HashTable<Key,Value>::const_iterator HashTable<Key,Value>::begin() const
  422. {
  423. return const_iterator(this,_next(0));
  424. }
  425. template<typename Key, typename Value>
  426. inline typename HashTable<Key,Value>::iterator HashTable<Key,Value>::end()
  427. {
  428. return iterator(this,0);
  429. }
  430. template<typename Key, typename Value>
  431. inline typename HashTable<Key,Value>::const_iterator HashTable<Key,Value>::end() const
  432. {
  433. return const_iterator(this,0);
  434. }
  435. //-----------------------------------------------------------------------------
  436. // operators
  437. template<typename Key, typename Value>
  438. void HashTable<Key,Value>::operator=(const HashTable& p)
  439. {
  440. _destroy();
  441. mTableSize = p.mTableSize;
  442. mTable = new Node*[mTableSize];
  443. mSize = p.mSize;
  444. for (S32 i = 0; i < mTableSize; i++)
  445. if (Node* itr = p.mTable[i])
  446. {
  447. Node** head = &mTable[i];
  448. do
  449. {
  450. *head = new Node(itr->mPair,0);
  451. head = &(*head)->mNext;
  452. itr = itr->mNext;
  453. } while (itr);
  454. }
  455. else
  456. mTable[i] = 0;
  457. }
  458. //-----------------------------------------------------------------------------
  459. // iterator class
  460. /// A HashMap template class.
  461. /// The map class maps between a key and an associated value. Keys
  462. /// are unique.
  463. /// The hash table class is used as the default implementation so the
  464. /// the key must be hashable, see util/hash.h for details.
  465. /// @ingroup UtilContainers
  466. template<typename Key, typename Value, class Sequence = HashTable<Key,Value> >
  467. class HashMap: private Sequence
  468. {
  469. typedef HashTable<Key,Value> Parent;
  470. private:
  471. Sequence mHashMap;
  472. public:
  473. // types
  474. typedef typename Parent::Pair Pair;
  475. typedef Pair ValueType;
  476. typedef Pair& Reference;
  477. typedef const Pair& ConstReference;
  478. typedef typename Parent::iterator iterator;
  479. typedef typename Parent::const_iterator const_iterator;
  480. typedef S32 DifferenceType;
  481. typedef U32 SizeType;
  482. // initialization
  483. HashMap() {}
  484. ~HashMap() {}
  485. HashMap(const HashMap& p);
  486. // management
  487. U32 size() const; ///< Return the number of elements
  488. void clear(); ///< Empty the HashMap
  489. bool isEmpty() const; ///< Returns true if the map is empty
  490. // insert & erase elements
  491. iterator insert(const Key& key, const Value&); // Documented below...
  492. void erase(iterator); ///< Erase the given entry
  493. void erase(const Key& key); ///< Erase the key from the map
  494. // HashMap lookup
  495. iterator find(const Key&); ///< Find entry for the given key
  496. const_iterator find(const Key&) const; ///< Find entry for the given key
  497. bool contains(const Key&a)
  498. {
  499. return mHashMap.count(a) > 0;
  500. }
  501. // forward iterator access
  502. iterator begin(); ///< iterator to first element
  503. const_iterator begin() const; ///< iterator to first element
  504. iterator end(); ///< IIterator to last element + 1
  505. const_iterator end() const; ///< iterator to last element + 1
  506. // operators
  507. Value& operator[](const Key&); ///< Index using the given key. If the key is not currently in the map it is added.
  508. };
  509. template<typename Key, typename Value, class Sequence> HashMap<Key,Value,Sequence>::HashMap(const HashMap& p)
  510. {
  511. *this = p;
  512. }
  513. //-----------------------------------------------------------------------------
  514. // management
  515. template<typename Key, typename Value, class Sequence>
  516. inline U32 HashMap<Key,Value,Sequence>::size() const
  517. {
  518. return mHashMap.size();
  519. }
  520. template<typename Key, typename Value, class Sequence>
  521. inline void HashMap<Key,Value,Sequence>::clear()
  522. {
  523. mHashMap.clear();
  524. }
  525. template<typename Key, typename Value, class Sequence>
  526. inline bool HashMap<Key,Value,Sequence>::isEmpty() const
  527. {
  528. return mHashMap.isEmpty();
  529. }
  530. //-----------------------------------------------------------------------------
  531. // add & remove elements
  532. /// Insert the key value pair but don't allow duplicates.
  533. /// The map class does not allow duplicates keys. If the key already exists in
  534. /// the map the function will fail and return end().
  535. template<typename Key, typename Value, class Sequence>
  536. typename HashMap<Key,Value,Sequence>::iterator HashMap<Key,Value,Sequence>::insert(const Key& key, const Value& x)
  537. {
  538. return mHashMap.insertUnique(key,x);
  539. }
  540. template<typename Key, typename Value, class Sequence>
  541. void HashMap<Key,Value,Sequence>::erase(const Key& key)
  542. {
  543. mHashMap.erase(key);
  544. }
  545. template<typename Key, typename Value, class Sequence>
  546. void HashMap<Key,Value,Sequence>::erase(iterator node)
  547. {
  548. mHashMap.erase(node);
  549. }
  550. //-----------------------------------------------------------------------------
  551. // Searching
  552. template<typename Key, typename Value, class Sequence>
  553. typename HashMap<Key,Value,Sequence>::iterator HashMap<Key,Value,Sequence>::find(const Key& key)
  554. {
  555. return mHashMap.find(key);
  556. }
  557. //-----------------------------------------------------------------------------
  558. // iterator access
  559. template<typename Key, typename Value, class Sequence>
  560. inline typename HashMap<Key,Value,Sequence>::iterator HashMap<Key,Value,Sequence>::begin()
  561. {
  562. return mHashMap.begin();
  563. }
  564. template<typename Key, typename Value, class Sequence>
  565. inline typename HashMap<Key,Value,Sequence>::const_iterator HashMap<Key,Value,Sequence>::begin() const
  566. {
  567. return mHashMap.begin();
  568. }
  569. template<typename Key, typename Value, class Sequence>
  570. inline typename HashMap<Key,Value,Sequence>::iterator HashMap<Key,Value,Sequence>::end()
  571. {
  572. return mHashMap.end();
  573. }
  574. template<typename Key, typename Value, class Sequence>
  575. inline typename HashMap<Key,Value,Sequence>::const_iterator HashMap<Key,Value,Sequence>::end() const
  576. {
  577. return mHashMap.end();
  578. }
  579. //-----------------------------------------------------------------------------
  580. // operators
  581. template<typename Key, typename Value, class Sequence>
  582. inline Value& HashMap<Key,Value,Sequence>::operator[](const Key& key)
  583. {
  584. return mHashMap.findOrInsert(key)->value;
  585. }
  586. #endif// _HASHTABLE_H_