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 21 #ifndef WTF_HashMap_h 22 #define WTF_HashMap_h 23 24 #include "wtf/FastAllocBase.h" 25 #include "wtf/HashTable.h" 26 27 namespace WTF { 28 29 template<typename KeyTraits, typename MappedTraits> struct HashMapValueTraits; 30 31 template<typename T> struct ReferenceTypeMaker { 32 typedef T& ReferenceType; 33 }; 34 template<typename T> struct ReferenceTypeMaker<T&> { 35 typedef T& ReferenceType; 36 }; 37 38 template<typename T> struct KeyValuePairKeyExtractor { 39 static const typename T::KeyType& extract(const T& p) { return p.key; } 40 }; 41 42 template<typename KeyArg, typename MappedArg, typename HashArg = typename DefaultHash<KeyArg>::Hash, 43 typename KeyTraitsArg = HashTraits<KeyArg>, typename MappedTraitsArg = HashTraits<MappedArg> > 44 class HashMap { 45 WTF_MAKE_FAST_ALLOCATED; 46 private: 47 typedef KeyTraitsArg KeyTraits; 48 typedef MappedTraitsArg MappedTraits; 49 typedef HashMapValueTraits<KeyTraits, MappedTraits> ValueTraits; 50 51 public: 52 typedef typename KeyTraits::TraitType KeyType; 53 typedef typename MappedTraits::TraitType MappedType; 54 typedef typename ValueTraits::TraitType ValueType; 55 56 private: 57 typedef typename MappedTraits::PassInType MappedPassInType; 58 typedef typename MappedTraits::PassOutType MappedPassOutType; 59 typedef typename MappedTraits::PeekType MappedPeekType; 60 61 typedef typename ReferenceTypeMaker<MappedPassInType>::ReferenceType MappedPassInReferenceType; 62 63 typedef HashArg HashFunctions; 64 65 typedef HashTable<KeyType, ValueType, KeyValuePairKeyExtractor<ValueType>, 66 HashFunctions, ValueTraits, KeyTraits> HashTableType; 67 68 class HashMapKeysProxy; 69 class HashMapValuesProxy; 70 71 public: 72 typedef HashTableIteratorAdapter<HashTableType, ValueType> iterator; 73 typedef HashTableConstIteratorAdapter<HashTableType, ValueType> const_iterator; 74 typedef typename HashTableType::AddResult AddResult; 75 76 public: 77 void swap(HashMap&); 78 79 unsigned size() const; 80 unsigned capacity() const; 81 bool isEmpty() const; 82 83 // iterators iterate over pairs of keys and values 84 iterator begin(); 85 iterator end(); 86 const_iterator begin() const; 87 const_iterator end() const; 88 89 HashMapKeysProxy& keys() { return static_cast<HashMapKeysProxy&>(*this); } 90 const HashMapKeysProxy& keys() const { return static_cast<const HashMapKeysProxy&>(*this); } 91 92 HashMapValuesProxy& values() { return static_cast<HashMapValuesProxy&>(*this); } 93 const HashMapValuesProxy& values() const { return static_cast<const HashMapValuesProxy&>(*this); } 94 95 iterator find(const KeyType&); 96 const_iterator find(const KeyType&) const; 97 bool contains(const KeyType&) const; 98 MappedPeekType get(const KeyType&) const; 99 100 // replaces value but not key if key is already present 101 // return value is a pair of the iterator to the key location, 102 // and a boolean that's true if a new value was actually added 103 AddResult set(const KeyType&, MappedPassInType); 104 105 // does nothing if key is already present 106 // return value is a pair of the iterator to the key location, 107 // and a boolean that's true if a new value was actually added 108 AddResult add(const KeyType&, MappedPassInType); 109 110 void remove(const KeyType&); 111 void remove(iterator); 112 void clear(); 113 114 MappedPassOutType take(const KeyType&); // efficient combination of get with remove 115 116 // An alternate version of find() that finds the object by hashing and comparing 117 // with some other type, to avoid the cost of type conversion. HashTranslator 118 // must have the following function members: 119 // static unsigned hash(const T&); 120 // static bool equal(const ValueType&, const T&); 121 template<typename HashTranslator, typename T> iterator find(const T&); 122 template<typename HashTranslator, typename T> const_iterator find(const T&) const; 123 template<typename HashTranslator, typename T> bool contains(const T&) const; 124 125 // An alternate version of add() that finds the object by hashing and comparing 126 // with some other type, to avoid the cost of type conversion if the object is already 127 // in the table. HashTranslator must have the following function members: 128 // static unsigned hash(const T&); 129 // static bool equal(const ValueType&, const T&); 130 // static translate(ValueType&, const T&, unsigned hashCode); 131 template<typename HashTranslator, typename T> AddResult add(const T&, MappedPassInType); 132 133 static bool isValidKey(const KeyType&); 134 135 private: 136 AddResult inlineAdd(const KeyType&, MappedPassInReferenceType); 137 138 HashTableType m_impl; 139 }; 140 141 template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg> 142 class HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>::HashMapKeysProxy : 143 private HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg> { 144 public: 145 typedef HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg> HashMapType; 146 typedef typename HashMapType::iterator::Keys iterator; 147 typedef typename HashMapType::const_iterator::Keys const_iterator; 148 149 iterator begin() 150 { 151 return HashMapType::begin().keys(); 152 } 153 154 iterator end() 155 { 156 return HashMapType::end().keys(); 157 } 158 159 const_iterator begin() const 160 { 161 return HashMapType::begin().keys(); 162 } 163 164 const_iterator end() const 165 { 166 return HashMapType::end().keys(); 167 } 168 169 private: 170 friend class HashMap; 171 172 // These are intentionally not implemented. 173 HashMapKeysProxy(); 174 HashMapKeysProxy(const HashMapKeysProxy&); 175 HashMapKeysProxy& operator=(const HashMapKeysProxy&); 176 ~HashMapKeysProxy(); 177 }; 178 179 template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg> 180 class HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>::HashMapValuesProxy : 181 private HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg> { 182 public: 183 typedef HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg> HashMapType; 184 typedef typename HashMapType::iterator::Values iterator; 185 typedef typename HashMapType::const_iterator::Values const_iterator; 186 187 iterator begin() 188 { 189 return HashMapType::begin().values(); 190 } 191 192 iterator end() 193 { 194 return HashMapType::end().values(); 195 } 196 197 const_iterator begin() const 198 { 199 return HashMapType::begin().values(); 200 } 201 202 const_iterator end() const 203 { 204 return HashMapType::end().values(); 205 } 206 207 private: 208 friend class HashMap; 209 210 // These are intentionally not implemented. 211 HashMapValuesProxy(); 212 HashMapValuesProxy(const HashMapValuesProxy&); 213 HashMapValuesProxy& operator=(const HashMapValuesProxy&); 214 ~HashMapValuesProxy(); 215 }; 216 217 template<typename KeyTraits, typename MappedTraits> struct HashMapValueTraits : KeyValuePairHashTraits<KeyTraits, MappedTraits> { 218 static const bool hasIsEmptyValueFunction = true; 219 static bool isEmptyValue(const typename KeyValuePairHashTraits<KeyTraits, MappedTraits>::TraitType& value) 220 { 221 return isHashTraitsEmptyValue<KeyTraits>(value.key); 222 } 223 }; 224 225 template<typename ValueTraits, typename HashFunctions> 226 struct HashMapTranslator { 227 template<typename T> static unsigned hash(const T& key) { return HashFunctions::hash(key); } 228 template<typename T, typename U> static bool equal(const T& a, const U& b) { return HashFunctions::equal(a, b); } 229 template<typename T, typename U, typename V> static void translate(T& location, const U& key, const V& mapped) 230 { 231 location.key = key; 232 ValueTraits::ValueTraits::store(mapped, location.value); 233 } 234 }; 235 236 template<typename ValueTraits, typename Translator> 237 struct HashMapTranslatorAdapter { 238 template<typename T> static unsigned hash(const T& key) { return Translator::hash(key); } 239 template<typename T, typename U> static bool equal(const T& a, const U& b) { return Translator::equal(a, b); } 240 template<typename T, typename U, typename V> static void translate(T& location, const U& key, const V& mapped, unsigned hashCode) 241 { 242 Translator::translate(location.key, key, hashCode); 243 ValueTraits::ValueTraits::store(mapped, location.value); 244 } 245 }; 246 247 template<typename T, typename U, typename V, typename W, typename X> 248 inline void HashMap<T, U, V, W, X>::swap(HashMap& other) 249 { 250 m_impl.swap(other.m_impl); 251 } 252 253 template<typename T, typename U, typename V, typename W, typename X> 254 inline unsigned HashMap<T, U, V, W, X>::size() const 255 { 256 return m_impl.size(); 257 } 258 259 template<typename T, typename U, typename V, typename W, typename X> 260 inline unsigned HashMap<T, U, V, W, X>::capacity() const 261 { 262 return m_impl.capacity(); 263 } 264 265 template<typename T, typename U, typename V, typename W, typename X> 266 inline bool HashMap<T, U, V, W, X>::isEmpty() const 267 { 268 return m_impl.isEmpty(); 269 } 270 271 template<typename T, typename U, typename V, typename W, typename X> 272 inline typename HashMap<T, U, V, W, X>::iterator HashMap<T, U, V, W, X>::begin() 273 { 274 return m_impl.begin(); 275 } 276 277 template<typename T, typename U, typename V, typename W, typename X> 278 inline typename HashMap<T, U, V, W, X>::iterator HashMap<T, U, V, W, X>::end() 279 { 280 return m_impl.end(); 281 } 282 283 template<typename T, typename U, typename V, typename W, typename X> 284 inline typename HashMap<T, U, V, W, X>::const_iterator HashMap<T, U, V, W, X>::begin() const 285 { 286 return m_impl.begin(); 287 } 288 289 template<typename T, typename U, typename V, typename W, typename X> 290 inline typename HashMap<T, U, V, W, X>::const_iterator HashMap<T, U, V, W, X>::end() const 291 { 292 return m_impl.end(); 293 } 294 295 template<typename T, typename U, typename V, typename W, typename X> 296 inline typename HashMap<T, U, V, W, X>::iterator HashMap<T, U, V, W, X>::find(const KeyType& key) 297 { 298 return m_impl.find(key); 299 } 300 301 template<typename T, typename U, typename V, typename W, typename X> 302 inline typename HashMap<T, U, V, W, X>::const_iterator HashMap<T, U, V, W, X>::find(const KeyType& key) const 303 { 304 return m_impl.find(key); 305 } 306 307 template<typename T, typename U, typename V, typename W, typename X> 308 inline bool HashMap<T, U, V, W, X>::contains(const KeyType& key) const 309 { 310 return m_impl.contains(key); 311 } 312 313 template<typename T, typename U, typename V, typename W, typename X> 314 template<typename HashTranslator, typename TYPE> 315 inline typename HashMap<T, U, V, W, X>::iterator 316 HashMap<T, U, V, W, X>::find(const TYPE& value) 317 { 318 return m_impl.template find<HashMapTranslatorAdapter<ValueTraits, HashTranslator> >(value); 319 } 320 321 template<typename T, typename U, typename V, typename W, typename X> 322 template<typename HashTranslator, typename TYPE> 323 inline typename HashMap<T, U, V, W, X>::const_iterator 324 HashMap<T, U, V, W, X>::find(const TYPE& value) const 325 { 326 return m_impl.template find<HashMapTranslatorAdapter<ValueTraits, HashTranslator> >(value); 327 } 328 329 template<typename T, typename U, typename V, typename W, typename X> 330 template<typename HashTranslator, typename TYPE> 331 inline bool 332 HashMap<T, U, V, W, X>::contains(const TYPE& value) const 333 { 334 return m_impl.template contains<HashMapTranslatorAdapter<ValueTraits, HashTranslator> >(value); 335 } 336 337 template<typename T, typename U, typename V, typename W, typename X> 338 typename HashMap<T, U, V, W, X>::AddResult 339 HashMap<T, U, V, W, X>::inlineAdd(const KeyType& key, MappedPassInReferenceType mapped) 340 { 341 return m_impl.template add<HashMapTranslator<ValueTraits, HashFunctions> >(key, mapped); 342 } 343 344 template<typename T, typename U, typename V, typename W, typename X> 345 typename HashMap<T, U, V, W, X>::AddResult 346 HashMap<T, U, V, W, X>::set(const KeyType& key, MappedPassInType mapped) 347 { 348 AddResult result = inlineAdd(key, mapped); 349 if (!result.isNewEntry) { 350 // The inlineAdd call above found an existing hash table entry; we need to set the mapped value. 351 MappedTraits::store(mapped, result.iterator->value); 352 } 353 return result; 354 } 355 356 template<typename T, typename U, typename V, typename W, typename X> 357 template<typename HashTranslator, typename TYPE> 358 typename HashMap<T, U, V, W, X>::AddResult 359 HashMap<T, U, V, W, X>::add(const TYPE& key, MappedPassInType value) 360 { 361 return m_impl.template addPassingHashCode<HashMapTranslatorAdapter<ValueTraits, HashTranslator> >(key, value); 362 } 363 364 template<typename T, typename U, typename V, typename W, typename X> 365 typename HashMap<T, U, V, W, X>::AddResult 366 HashMap<T, U, V, W, X>::add(const KeyType& key, MappedPassInType mapped) 367 { 368 return inlineAdd(key, mapped); 369 } 370 371 template<typename T, typename U, typename V, typename W, typename MappedTraits> 372 typename HashMap<T, U, V, W, MappedTraits>::MappedPeekType 373 HashMap<T, U, V, W, MappedTraits>::get(const KeyType& key) const 374 { 375 ValueType* entry = const_cast<HashTableType&>(m_impl).lookup(key); 376 if (!entry) 377 return MappedTraits::peek(MappedTraits::emptyValue()); 378 return MappedTraits::peek(entry->value); 379 } 380 381 template<typename T, typename U, typename V, typename W, typename X> 382 inline void HashMap<T, U, V, W, X>::remove(iterator it) 383 { 384 m_impl.remove(it.m_impl); 385 } 386 387 template<typename T, typename U, typename V, typename W, typename X> 388 inline void HashMap<T, U, V, W, X>::remove(const KeyType& key) 389 { 390 remove(find(key)); 391 } 392 393 template<typename T, typename U, typename V, typename W, typename X> 394 inline void HashMap<T, U, V, W, X>::clear() 395 { 396 m_impl.clear(); 397 } 398 399 template<typename T, typename U, typename V, typename W, typename MappedTraits> 400 typename HashMap<T, U, V, W, MappedTraits>::MappedPassOutType 401 HashMap<T, U, V, W, MappedTraits>::take(const KeyType& key) 402 { 403 iterator it = find(key); 404 if (it == end()) 405 return MappedTraits::passOut(MappedTraits::emptyValue()); 406 MappedPassOutType result = MappedTraits::passOut(it->value); 407 remove(it); 408 return result; 409 } 410 411 template<typename T, typename U, typename V, typename W, typename X> 412 inline bool HashMap<T, U, V, W, X>::isValidKey(const KeyType& key) 413 { 414 if (KeyTraits::isDeletedValue(key)) 415 return false; 416 417 if (HashFunctions::safeToCompareToEmptyOrDeleted) { 418 if (key == KeyTraits::emptyValue()) 419 return false; 420 } else { 421 if (isHashTraitsEmptyValue<KeyTraits>(key)) 422 return false; 423 } 424 425 return true; 426 } 427 428 template<typename T, typename U, typename V, typename W, typename X> 429 bool operator==(const HashMap<T, U, V, W, X>& a, const HashMap<T, U, V, W, X>& b) 430 { 431 if (a.size() != b.size()) 432 return false; 433 434 typedef typename HashMap<T, U, V, W, X>::const_iterator const_iterator; 435 436 const_iterator aEnd = a.end(); 437 const_iterator bEnd = b.end(); 438 for (const_iterator it = a.begin(); it != aEnd; ++it) { 439 const_iterator bPos = b.find(it->key); 440 if (bPos == bEnd || it->value != bPos->value) 441 return false; 442 } 443 444 return true; 445 } 446 447 template<typename T, typename U, typename V, typename W, typename X> 448 inline bool operator!=(const HashMap<T, U, V, W, X>& a, const HashMap<T, U, V, W, X>& b) 449 { 450 return !(a == b); 451 } 452 453 template<typename T, typename U, typename V, typename W, typename X> 454 inline void deleteAllValues(const HashMap<T, U, V, W, X>& collection) 455 { 456 typedef typename HashMap<T, U, V, W, X>::const_iterator iterator; 457 iterator end = collection.end(); 458 for (iterator it = collection.begin(); it != end; ++it) 459 delete it->value; 460 } 461 462 template<typename T, typename U, typename V, typename W, typename X> 463 inline void deleteAllKeys(const HashMap<T, U, V, W, X>& collection) 464 { 465 typedef typename HashMap<T, U, V, W, X>::const_iterator iterator; 466 iterator end = collection.end(); 467 for (iterator it = collection.begin(); it != end; ++it) 468 delete it->key; 469 } 470 471 template<typename T, typename U, typename V, typename W, typename X, typename Y> 472 inline void copyKeysToVector(const HashMap<T, U, V, W, X>& collection, Y& vector) 473 { 474 typedef typename HashMap<T, U, V, W, X>::const_iterator::Keys iterator; 475 476 vector.resize(collection.size()); 477 478 iterator it = collection.begin().keys(); 479 iterator end = collection.end().keys(); 480 for (unsigned i = 0; it != end; ++it, ++i) 481 vector[i] = *it; 482 } 483 484 template<typename T, typename U, typename V, typename W, typename X, typename Y> 485 inline void copyValuesToVector(const HashMap<T, U, V, W, X>& collection, Y& vector) 486 { 487 typedef typename HashMap<T, U, V, W, X>::const_iterator::Values iterator; 488 489 vector.resize(collection.size()); 490 491 iterator it = collection.begin().values(); 492 iterator end = collection.end().values(); 493 for (unsigned i = 0; it != end; ++it, ++i) 494 vector[i] = *it; 495 } 496 497 } // namespace WTF 498 499 using WTF::HashMap; 500 501 #include "wtf/RefPtrHashMap.h" 502 503 #endif /* WTF_HashMap_h */ 504