hashTable.h 20 KB

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