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