HashMap.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510
  1. /*
  2. * Copyright (C) 2005, 2006, 2007, 2008, 2011 Apple Inc. All rights reserved.
  3. *
  4. * This library is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Library General Public
  6. * License as published by the Free Software Foundation; either
  7. * version 2 of the License, or (at your option) any later version.
  8. *
  9. * This library is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * Library General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Library General Public License
  15. * along with this library; see the file COPYING.LIB. If not, write to
  16. * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  17. * Boston, MA 02110-1301, USA.
  18. *
  19. */
  20. #ifndef WTF_HashMap_h
  21. #define WTF_HashMap_h
  22. #include <wtf/HashTable.h>
  23. namespace WTF {
  24. template<typename KeyTraits, typename MappedTraits, bool shared> struct HashMapValueTraits;
  25. template<typename T> struct ReferenceTypeMaker {
  26. typedef T& ReferenceType;
  27. };
  28. template<typename T> struct ReferenceTypeMaker<T&> {
  29. typedef T& ReferenceType;
  30. };
  31. template<typename T> struct KeyValuePairKeyExtractor {
  32. static const typename T::KeyType& extract(const T& p) { return p.key; }
  33. };
  34. template<typename KeyArg, typename MappedArg, typename HashArg = typename DefaultHash<KeyArg>::Hash,
  35. typename KeyTraitsArg = HashTraits<KeyArg>, typename MappedTraitsArg = HashTraits<MappedArg>, bool shared = false>
  36. class HashMap {
  37. WTF_MAKE_FAST_ALLOCATED;
  38. private:
  39. typedef KeyTraitsArg KeyTraits;
  40. typedef MappedTraitsArg MappedTraits;
  41. typedef HashMapValueTraits<KeyTraits, MappedTraits, shared> ValueTraits;
  42. public:
  43. typedef typename KeyTraits::TraitType KeyType;
  44. typedef typename MappedTraits::TraitType MappedType;
  45. typedef typename ValueTraits::TraitType ValueType;
  46. private:
  47. typedef typename MappedTraits::PassInType MappedPassInType;
  48. typedef typename MappedTraits::PassOutType MappedPassOutType;
  49. typedef typename MappedTraits::PeekType MappedPeekType;
  50. typedef typename ReferenceTypeMaker<MappedPassInType>::ReferenceType MappedPassInReferenceType;
  51. typedef HashArg HashFunctions;
  52. typedef HashTable<KeyType, ValueType, KeyValuePairKeyExtractor<ValueType>,
  53. HashFunctions, ValueTraits, KeyTraits> HashTableType;
  54. class HashMapKeysProxy;
  55. class HashMapValuesProxy;
  56. public:
  57. typedef HashTableIteratorAdapter<HashTableType, ValueType> iterator;
  58. typedef HashTableConstIteratorAdapter<HashTableType, ValueType> const_iterator;
  59. typedef typename HashTableType::AddResult AddResult;
  60. public:
  61. void swap(HashMap&);
  62. int size() const;
  63. int capacity() const;
  64. bool isEmpty() const;
  65. // iterators iterate over pairs of keys and values
  66. iterator begin();
  67. iterator end();
  68. const_iterator begin() const;
  69. const_iterator end() const;
  70. HashMapKeysProxy& keys() { return static_cast<HashMapKeysProxy&>(*this); }
  71. const HashMapKeysProxy& keys() const { return static_cast<const HashMapKeysProxy&>(*this); }
  72. HashMapValuesProxy& values() { return static_cast<HashMapValuesProxy&>(*this); }
  73. const HashMapValuesProxy& values() const { return static_cast<const HashMapValuesProxy&>(*this); }
  74. iterator find(const KeyType&);
  75. const_iterator find(const KeyType&) const;
  76. bool contains(const KeyType&) const;
  77. MappedPeekType get(const KeyType&) const;
  78. // replaces value but not key if key is already present
  79. // return value is a pair of the iterator to the key location,
  80. // and a boolean that's true if a new value was actually added
  81. AddResult set(const KeyType&, MappedPassInType);
  82. // does nothing if key is already present
  83. // return value is a pair of the iterator to the key location,
  84. // and a boolean that's true if a new value was actually added
  85. AddResult add(const KeyType&, MappedPassInType);
  86. void remove(const KeyType&);
  87. void remove(iterator);
  88. void clear();
  89. MappedPassOutType take(const KeyType&); // efficient combination of get with remove
  90. // An alternate version of find() that finds the object by hashing and comparing
  91. // with some other type, to avoid the cost of type conversion. HashTranslator
  92. // must have the following function members:
  93. // static unsigned hash(const T&);
  94. // static bool equal(const ValueType&, const T&);
  95. template<typename T, typename HashTranslator> iterator find(const T&);
  96. template<typename T, typename HashTranslator> const_iterator find(const T&) const;
  97. template<typename T, typename HashTranslator> bool contains(const T&) const;
  98. // An alternate version of add() that finds the object by hashing and comparing
  99. // with some other type, to avoid the cost of type conversion if the object is already
  100. // in the table. HashTranslator must have the following function members:
  101. // static unsigned hash(const T&);
  102. // static bool equal(const ValueType&, const T&);
  103. // static translate(ValueType&, const T&, unsigned hashCode);
  104. template<typename T, typename HashTranslator> AddResult add(const T&, MappedPassInType);
  105. void checkConsistency() const;
  106. static bool isValidKey(const KeyType&);
  107. private:
  108. AddResult inlineAdd(const KeyType&, MappedPassInReferenceType);
  109. HashTableType m_impl;
  110. };
  111. template<typename KeyArg, typename MappedArg, typename HashArg = typename DefaultHash<KeyArg>::Hash,
  112. typename KeyTraitsArg = HashTraits<KeyArg>, typename MappedTraitsArg = HashTraits<MappedArg> >
  113. class HashMap_shared : public HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg, true> {};
  114. template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg, bool shared>
  115. class HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg, shared>::HashMapKeysProxy :
  116. private HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg> {
  117. public:
  118. typedef HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg> HashMapType;
  119. typedef typename HashMapType::iterator::Keys iterator;
  120. typedef typename HashMapType::const_iterator::Keys const_iterator;
  121. iterator begin()
  122. {
  123. return HashMapType::begin().keys();
  124. }
  125. iterator end()
  126. {
  127. return HashMapType::end().keys();
  128. }
  129. const_iterator begin() const
  130. {
  131. return HashMapType::begin().keys();
  132. }
  133. const_iterator end() const
  134. {
  135. return HashMapType::end().keys();
  136. }
  137. private:
  138. friend class HashMap;
  139. // These are intentionally not implemented.
  140. HashMapKeysProxy();
  141. HashMapKeysProxy(const HashMapKeysProxy&);
  142. HashMapKeysProxy& operator=(const HashMapKeysProxy&);
  143. ~HashMapKeysProxy();
  144. };
  145. template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg, bool shared>
  146. class HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg, shared>::HashMapValuesProxy :
  147. private HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg> {
  148. public:
  149. typedef HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg> HashMapType;
  150. typedef typename HashMapType::iterator::Values iterator;
  151. typedef typename HashMapType::const_iterator::Values const_iterator;
  152. iterator begin()
  153. {
  154. return HashMapType::begin().values();
  155. }
  156. iterator end()
  157. {
  158. return HashMapType::end().values();
  159. }
  160. const_iterator begin() const
  161. {
  162. return HashMapType::begin().values();
  163. }
  164. const_iterator end() const
  165. {
  166. return HashMapType::end().values();
  167. }
  168. private:
  169. friend class HashMap;
  170. // These are intentionally not implemented.
  171. HashMapValuesProxy();
  172. HashMapValuesProxy(const HashMapValuesProxy&);
  173. HashMapValuesProxy& operator=(const HashMapValuesProxy&);
  174. ~HashMapValuesProxy();
  175. };
  176. template<typename KeyTraits, typename MappedTraits, bool shared> struct HashMapValueTraits : KeyValuePairHashTraits<KeyTraits, MappedTraits, shared> {
  177. static const bool hasIsEmptyValueFunction = true;
  178. static bool isEmptyValue(const typename KeyValuePairHashTraits<KeyTraits, MappedTraits>::TraitType& value)
  179. {
  180. return isHashTraitsEmptyValue<KeyTraits>(value.key);
  181. }
  182. };
  183. template<typename ValueTraits, typename HashFunctions>
  184. struct HashMapTranslator {
  185. template<typename T> static unsigned hash(const T& key) { return HashFunctions::hash(key); }
  186. template<typename T, typename U> static bool equal(const T& a, const U& b) { return HashFunctions::equal(a, b); }
  187. template<typename T, typename U, typename V> static void translate(T& location, const U& key, const V& mapped)
  188. {
  189. location.key = key;
  190. ValueTraits::ValueTraits::store(mapped, location.value);
  191. }
  192. };
  193. template<typename ValueTraits, typename Translator>
  194. struct HashMapTranslatorAdapter {
  195. template<typename T> static unsigned hash(const T& key) { return Translator::hash(key); }
  196. template<typename T, typename U> static bool equal(const T& a, const U& b) { return Translator::equal(a, b); }
  197. template<typename T, typename U, typename V> static void translate(T& location, const U& key, const V& mapped, unsigned hashCode)
  198. {
  199. Translator::translate(location.key, key, hashCode);
  200. ValueTraits::ValueTraits::store(mapped, location.value);
  201. }
  202. };
  203. template<typename T, typename U, typename V, typename W, typename X, bool shared>
  204. inline void HashMap<T, U, V, W, X, shared>::swap(HashMap& other)
  205. {
  206. m_impl.swap(other.m_impl);
  207. }
  208. template<typename T, typename U, typename V, typename W, typename X, bool shared>
  209. inline int HashMap<T, U, V, W, X, shared>::size() const
  210. {
  211. return m_impl.size();
  212. }
  213. template<typename T, typename U, typename V, typename W, typename X, bool shared>
  214. inline int HashMap<T, U, V, W, X, shared>::capacity() const
  215. {
  216. return m_impl.capacity();
  217. }
  218. template<typename T, typename U, typename V, typename W, typename X, bool shared>
  219. inline bool HashMap<T, U, V, W, X, shared>::isEmpty() const
  220. {
  221. return m_impl.isEmpty();
  222. }
  223. template<typename T, typename U, typename V, typename W, typename X, bool shared>
  224. inline typename HashMap<T, U, V, W, X, shared>::iterator HashMap<T, U, V, W, X, shared>::begin()
  225. {
  226. return m_impl.begin();
  227. }
  228. template<typename T, typename U, typename V, typename W, typename X, bool shared>
  229. inline typename HashMap<T, U, V, W, X, shared>::iterator HashMap<T, U, V, W, X, shared>::end()
  230. {
  231. return m_impl.end();
  232. }
  233. template<typename T, typename U, typename V, typename W, typename X, bool shared>
  234. inline typename HashMap<T, U, V, W, X, shared>::const_iterator HashMap<T, U, V, W, X, shared>::begin() const
  235. {
  236. return m_impl.begin();
  237. }
  238. template<typename T, typename U, typename V, typename W, typename X, bool shared>
  239. inline typename HashMap<T, U, V, W, X, shared>::const_iterator HashMap<T, U, V, W, X, shared>::end() const
  240. {
  241. return m_impl.end();
  242. }
  243. template<typename T, typename U, typename V, typename W, typename X, bool shared>
  244. inline typename HashMap<T, U, V, W, X, shared>::iterator HashMap<T, U, V, W, X, shared>::find(const KeyType& key)
  245. {
  246. return m_impl.find(key);
  247. }
  248. template<typename T, typename U, typename V, typename W, typename X, bool shared>
  249. inline typename HashMap<T, U, V, W, X, shared>::const_iterator HashMap<T, U, V, W, X, shared>::find(const KeyType& key) const
  250. {
  251. return m_impl.find(key);
  252. }
  253. template<typename T, typename U, typename V, typename W, typename X, bool shared>
  254. inline bool HashMap<T, U, V, W, X, shared>::contains(const KeyType& key) const
  255. {
  256. return m_impl.contains(key);
  257. }
  258. template<typename T, typename U, typename V, typename W, typename X, bool shared>
  259. template<typename TYPE, typename HashTranslator>
  260. inline typename HashMap<T, U, V, W, X, shared>::iterator
  261. HashMap<T, U, V, W, X, shared>::find(const TYPE& value)
  262. {
  263. return m_impl.template find<HashMapTranslatorAdapter<ValueTraits, HashTranslator> >(value);
  264. }
  265. template<typename T, typename U, typename V, typename W, typename X, bool shared>
  266. template<typename TYPE, typename HashTranslator>
  267. inline typename HashMap<T, U, V, W, X, shared>::const_iterator
  268. HashMap<T, U, V, W, X, shared>::find(const TYPE& value) const
  269. {
  270. return m_impl.template find<HashMapTranslatorAdapter<ValueTraits, HashTranslator> >(value);
  271. }
  272. template<typename T, typename U, typename V, typename W, typename X, bool shared>
  273. template<typename TYPE, typename HashTranslator>
  274. inline bool
  275. HashMap<T, U, V, W, X, shared>::contains(const TYPE& value) const
  276. {
  277. return m_impl.template contains<HashMapTranslatorAdapter<ValueTraits, HashTranslator> >(value);
  278. }
  279. template<typename T, typename U, typename V, typename W, typename X, bool shared>
  280. typename HashMap<T, U, V, W, X, shared>::AddResult
  281. HashMap<T, U, V, W, X, shared>::inlineAdd(const KeyType& key, MappedPassInReferenceType mapped)
  282. {
  283. return m_impl.template add<HashMapTranslator<ValueTraits, HashFunctions> >(key, mapped);
  284. }
  285. template<typename T, typename U, typename V, typename W, typename X, bool shared>
  286. typename HashMap<T, U, V, W, X, shared>::AddResult
  287. HashMap<T, U, V, W, X, shared>::set(const KeyType& key, MappedPassInType mapped)
  288. {
  289. AddResult result = inlineAdd(key, mapped);
  290. if (!result.isNewEntry) {
  291. // The inlineAdd call above found an existing hash table entry; we need to set the mapped value.
  292. MappedTraits::store(mapped, result.iterator->value);
  293. }
  294. return result;
  295. }
  296. template<typename T, typename U, typename V, typename W, typename X, bool shared>
  297. template<typename TYPE, typename HashTranslator>
  298. typename HashMap<T, U, V, W, X, shared>::AddResult
  299. HashMap<T, U, V, W, X, shared>::add(const TYPE& key, MappedPassInType value)
  300. {
  301. return m_impl.template addPassingHashCode<HashMapTranslatorAdapter<ValueTraits, HashTranslator> >(key, value);
  302. }
  303. template<typename T, typename U, typename V, typename W, typename X, bool shared>
  304. typename HashMap<T, U, V, W, X, shared>::AddResult
  305. HashMap<T, U, V, W, X, shared>::add(const KeyType& key, MappedPassInType mapped)
  306. {
  307. return inlineAdd(key, mapped);
  308. }
  309. template<typename T, typename U, typename V, typename W, typename MappedTraits, bool shared>
  310. typename HashMap<T, U, V, W, MappedTraits, shared>::MappedPeekType
  311. HashMap<T, U, V, W, MappedTraits, shared>::get(const KeyType& key) const
  312. {
  313. ValueType* entry = const_cast<HashTableType&>(m_impl).lookup(key);
  314. if (!entry)
  315. return MappedTraits::peek(MappedTraits::emptyValue());
  316. return MappedTraits::peek(entry->value);
  317. }
  318. template<typename T, typename U, typename V, typename W, typename X, bool shared>
  319. inline void HashMap<T, U, V, W, X, shared>::remove(iterator it)
  320. {
  321. if (it.m_impl == m_impl.end())
  322. return;
  323. m_impl.internalCheckTableConsistency();
  324. m_impl.removeWithoutEntryConsistencyCheck(it.m_impl);
  325. }
  326. template<typename T, typename U, typename V, typename W, typename X, bool shared>
  327. inline void HashMap<T, U, V, W, X, shared>::remove(const KeyType& key)
  328. {
  329. remove(find(key));
  330. }
  331. template<typename T, typename U, typename V, typename W, typename X, bool shared>
  332. inline void HashMap<T, U, V, W, X, shared>::clear()
  333. {
  334. m_impl.clear();
  335. }
  336. template<typename T, typename U, typename V, typename W, typename MappedTraits, bool shared>
  337. typename HashMap<T, U, V, W, MappedTraits, shared>::MappedPassOutType
  338. HashMap<T, U, V, W, MappedTraits, shared>::take(const KeyType& key)
  339. {
  340. iterator it = find(key);
  341. if (it == end())
  342. return MappedTraits::passOut(MappedTraits::emptyValue());
  343. MappedPassOutType result = MappedTraits::passOut(it->value);
  344. remove(it);
  345. return result;
  346. }
  347. template<typename T, typename U, typename V, typename W, typename X, bool shared>
  348. inline void HashMap<T, U, V, W, X, shared>::checkConsistency() const
  349. {
  350. m_impl.checkTableConsistency();
  351. }
  352. template<typename T, typename U, typename V, typename W, typename X, bool shared>
  353. inline bool HashMap<T, U, V, W, X, shared>::isValidKey(const KeyType& key)
  354. {
  355. if (KeyTraits::isDeletedValue(key))
  356. return false;
  357. if (HashFunctions::safeToCompareToEmptyOrDeleted) {
  358. if (key == KeyTraits::emptyValue())
  359. return false;
  360. } else {
  361. if (isHashTraitsEmptyValue<KeyTraits>(key))
  362. return false;
  363. }
  364. return true;
  365. }
  366. template<typename T, typename U, typename V, typename W, typename X, bool shared>
  367. bool operator==(const HashMap<T, U, V, W, X, shared>& a, const HashMap<T, U, V, W, X, shared>& b)
  368. {
  369. if (a.size() != b.size())
  370. return false;
  371. typedef typename HashMap<T, U, V, W, X, shared>::const_iterator const_iterator;
  372. const_iterator end = a.end();
  373. const_iterator notFound = b.end();
  374. for (const_iterator it = a.begin(); it != end; ++it) {
  375. const_iterator bPos = b.find(it->key);
  376. if (bPos == notFound || it->value != bPos->value)
  377. return false;
  378. }
  379. return true;
  380. }
  381. template<typename T, typename U, typename V, typename W, typename X, bool shared>
  382. inline bool operator!=(const HashMap<T, U, V, W, X, shared>& a, const HashMap<T, U, V, W, X, shared>& b)
  383. {
  384. return !(a == b);
  385. }
  386. template<typename T, typename U, typename V, typename W, typename X, bool shared>
  387. inline void deleteAllValues(const HashMap<T, U, V, W, X, shared>& collection)
  388. {
  389. typedef typename HashMap<T, U, V, W, X, shared>::const_iterator iterator;
  390. iterator end = collection.end();
  391. for (iterator it = collection.begin(); it != end; ++it)
  392. delete it->value;
  393. }
  394. template<typename T, typename U, typename V, typename W, typename X, typename Y, bool shared>
  395. inline void copyKeysToVector(const HashMap<T, U, V, W, X, shared>& collection, Y& vector)
  396. {
  397. typedef typename HashMap<T, U, V, W, X, shared>::const_iterator::Keys iterator;
  398. vector.resize(collection.size());
  399. iterator it = collection.begin().keys();
  400. iterator end = collection.end().keys();
  401. for (unsigned i = 0; it != end; ++it, ++i)
  402. vector[i] = *it;
  403. }
  404. template<typename T, typename U, typename V, typename W, typename X, typename Y, bool shared>
  405. inline void copyValuesToVector(const HashMap<T, U, V, W, X, shared>& collection, Y& vector)
  406. {
  407. typedef typename HashMap<T, U, V, W, X, shared>::const_iterator::Values iterator;
  408. vector.resize(collection.size());
  409. iterator it = collection.begin().values();
  410. iterator end = collection.end().values();
  411. for (unsigned i = 0; it != end; ++it, ++i)
  412. vector[i] = *it;
  413. }
  414. } // namespace WTF
  415. using WTF::HashMap;
  416. using WTF::HashMap_shared;
  417. #include <wtf/RefPtrHashMap.h>
  418. #endif /* WTF_HashMap_h */