1 /* 2 * Copyright (C) 2005, 2006, 2007, 2008 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 "HashTable.h" 25 26 namespace WTF { 27 28 template<typename PairType> struct PairFirstExtractor; 29 30 template<typename KeyArg, typename MappedArg, typename HashArg = typename DefaultHash<KeyArg>::Hash, 31 typename KeyTraitsArg = HashTraits<KeyArg>, typename MappedTraitsArg = HashTraits<MappedArg> > 32 class HashMap : public FastAllocBase { 33 private: 34 typedef KeyTraitsArg KeyTraits; 35 typedef MappedTraitsArg MappedTraits; 36 typedef PairHashTraits<KeyTraits, MappedTraits> ValueTraits; 37 38 public: 39 typedef typename KeyTraits::TraitType KeyType; 40 typedef typename MappedTraits::TraitType MappedType; 41 typedef typename ValueTraits::TraitType ValueType; 42 43 private: 44 typedef HashArg HashFunctions; 45 46 typedef HashTable<KeyType, ValueType, PairFirstExtractor<ValueType>, 47 HashFunctions, ValueTraits, KeyTraits> HashTableType; 48 49 public: 50 typedef HashTableIteratorAdapter<HashTableType, ValueType> iterator; 51 typedef HashTableConstIteratorAdapter<HashTableType, ValueType> const_iterator; 52 53 void swap(HashMap&); 54 55 int size() const; 56 int capacity() const; 57 bool isEmpty() const; 58 59 // iterators iterate over pairs of keys and values 60 iterator begin(); 61 iterator end(); 62 const_iterator begin() const; 63 const_iterator end() const; 64 65 iterator find(const KeyType&); 66 const_iterator find(const KeyType&) const; 67 bool contains(const KeyType&) const; 68 MappedType get(const KeyType&) const; 69 70 // replaces value but not key if key is already present 71 // return value is a pair of the iterator to the key location, 72 // and a boolean that's true if a new value was actually added 73 pair<iterator, bool> set(const KeyType&, const MappedType&); 74 75 // does nothing if key is already present 76 // return value is a pair of the iterator to the key location, 77 // and a boolean that's true if a new value was actually added 78 pair<iterator, bool> add(const KeyType&, const MappedType&); 79 80 void remove(const KeyType&); 81 void remove(iterator); 82 void clear(); 83 84 MappedType take(const KeyType&); // efficient combination of get with remove 85 86 private: 87 pair<iterator, bool> inlineAdd(const KeyType&, const MappedType&); 88 89 HashTableType m_impl; 90 }; 91 92 template<typename PairType> struct PairFirstExtractor { extractPairFirstExtractor93 static const typename PairType::first_type& extract(const PairType& p) { return p.first; } 94 }; 95 96 template<typename ValueType, typename ValueTraits, typename HashFunctions> 97 struct HashMapTranslator { 98 typedef typename ValueType::first_type KeyType; 99 typedef typename ValueType::second_type MappedType; 100 hashHashMapTranslator101 static unsigned hash(const KeyType& key) { return HashFunctions::hash(key); } equalHashMapTranslator102 static bool equal(const KeyType& a, const KeyType& b) { return HashFunctions::equal(a, b); } translateHashMapTranslator103 static void translate(ValueType& location, const KeyType& key, const MappedType& mapped) 104 { 105 location.first = key; 106 location.second = mapped; 107 } 108 }; 109 110 template<typename T, typename U, typename V, typename W, typename X> swap(HashMap & other)111 inline void HashMap<T, U, V, W, X>::swap(HashMap& other) 112 { 113 m_impl.swap(other.m_impl); 114 } 115 116 template<typename T, typename U, typename V, typename W, typename X> size()117 inline int HashMap<T, U, V, W, X>::size() const 118 { 119 return m_impl.size(); 120 } 121 122 template<typename T, typename U, typename V, typename W, typename X> capacity()123 inline int HashMap<T, U, V, W, X>::capacity() const 124 { 125 return m_impl.capacity(); 126 } 127 128 template<typename T, typename U, typename V, typename W, typename X> isEmpty()129 inline bool HashMap<T, U, V, W, X>::isEmpty() const 130 { 131 return m_impl.isEmpty(); 132 } 133 134 template<typename T, typename U, typename V, typename W, typename X> begin()135 inline typename HashMap<T, U, V, W, X>::iterator HashMap<T, U, V, W, X>::begin() 136 { 137 return m_impl.begin(); 138 } 139 140 template<typename T, typename U, typename V, typename W, typename X> end()141 inline typename HashMap<T, U, V, W, X>::iterator HashMap<T, U, V, W, X>::end() 142 { 143 return m_impl.end(); 144 } 145 146 template<typename T, typename U, typename V, typename W, typename X> begin()147 inline typename HashMap<T, U, V, W, X>::const_iterator HashMap<T, U, V, W, X>::begin() const 148 { 149 return m_impl.begin(); 150 } 151 152 template<typename T, typename U, typename V, typename W, typename X> end()153 inline typename HashMap<T, U, V, W, X>::const_iterator HashMap<T, U, V, W, X>::end() const 154 { 155 return m_impl.end(); 156 } 157 158 template<typename T, typename U, typename V, typename W, typename X> find(const KeyType & key)159 inline typename HashMap<T, U, V, W, X>::iterator HashMap<T, U, V, W, X>::find(const KeyType& key) 160 { 161 return m_impl.find(key); 162 } 163 164 template<typename T, typename U, typename V, typename W, typename X> find(const KeyType & key)165 inline typename HashMap<T, U, V, W, X>::const_iterator HashMap<T, U, V, W, X>::find(const KeyType& key) const 166 { 167 return m_impl.find(key); 168 } 169 170 template<typename T, typename U, typename V, typename W, typename X> contains(const KeyType & key)171 inline bool HashMap<T, U, V, W, X>::contains(const KeyType& key) const 172 { 173 return m_impl.contains(key); 174 } 175 176 template<typename T, typename U, typename V, typename W, typename X> 177 inline pair<typename HashMap<T, U, V, W, X>::iterator, bool> inlineAdd(const KeyType & key,const MappedType & mapped)178 HashMap<T, U, V, W, X>::inlineAdd(const KeyType& key, const MappedType& mapped) 179 { 180 typedef HashMapTranslator<ValueType, ValueTraits, HashFunctions> TranslatorType; 181 return m_impl.template add<KeyType, MappedType, TranslatorType>(key, mapped); 182 } 183 184 template<typename T, typename U, typename V, typename W, typename X> 185 pair<typename HashMap<T, U, V, W, X>::iterator, bool> set(const KeyType & key,const MappedType & mapped)186 HashMap<T, U, V, W, X>::set(const KeyType& key, const MappedType& mapped) 187 { 188 pair<iterator, bool> result = inlineAdd(key, mapped); 189 if (!result.second) { 190 // add call above didn't change anything, so set the mapped value 191 result.first->second = mapped; 192 } 193 return result; 194 } 195 196 template<typename T, typename U, typename V, typename W, typename X> 197 pair<typename HashMap<T, U, V, W, X>::iterator, bool> add(const KeyType & key,const MappedType & mapped)198 HashMap<T, U, V, W, X>::add(const KeyType& key, const MappedType& mapped) 199 { 200 return inlineAdd(key, mapped); 201 } 202 203 template<typename T, typename U, typename V, typename W, typename MappedTraits> 204 typename HashMap<T, U, V, W, MappedTraits>::MappedType get(const KeyType & key)205 HashMap<T, U, V, W, MappedTraits>::get(const KeyType& key) const 206 { 207 ValueType* entry = const_cast<HashTableType&>(m_impl).lookup(key); 208 if (!entry) 209 return MappedTraits::emptyValue(); 210 return entry->second; 211 } 212 213 template<typename T, typename U, typename V, typename W, typename X> remove(iterator it)214 inline void HashMap<T, U, V, W, X>::remove(iterator it) 215 { 216 if (it.m_impl == m_impl.end()) 217 return; 218 m_impl.checkTableConsistency(); 219 m_impl.removeWithoutEntryConsistencyCheck(it.m_impl); 220 } 221 222 template<typename T, typename U, typename V, typename W, typename X> remove(const KeyType & key)223 inline void HashMap<T, U, V, W, X>::remove(const KeyType& key) 224 { 225 remove(find(key)); 226 } 227 228 template<typename T, typename U, typename V, typename W, typename X> clear()229 inline void HashMap<T, U, V, W, X>::clear() 230 { 231 m_impl.clear(); 232 } 233 234 template<typename T, typename U, typename V, typename W, typename MappedTraits> 235 typename HashMap<T, U, V, W, MappedTraits>::MappedType take(const KeyType & key)236 HashMap<T, U, V, W, MappedTraits>::take(const KeyType& key) 237 { 238 // This can probably be made more efficient to avoid ref/deref churn. 239 iterator it = find(key); 240 if (it == end()) 241 return MappedTraits::emptyValue(); 242 typename HashMap<T, U, V, W, MappedTraits>::MappedType result = it->second; 243 remove(it); 244 return result; 245 } 246 247 template<typename T, typename U, typename V, typename W, typename X> 248 bool operator==(const HashMap<T, U, V, W, X>& a, const HashMap<T, U, V, W, X>& b) 249 { 250 if (a.size() != b.size()) 251 return false; 252 253 typedef typename HashMap<T, U, V, W, X>::const_iterator const_iterator; 254 255 const_iterator end = a.end(); 256 const_iterator notFound = b.end(); 257 for (const_iterator it = a.begin(); it != end; ++it) { 258 const_iterator bPos = b.find(it->first); 259 if (bPos == notFound || it->second != bPos->second) 260 return false; 261 } 262 263 return true; 264 } 265 266 template<typename T, typename U, typename V, typename W, typename X> 267 inline bool operator!=(const HashMap<T, U, V, W, X>& a, const HashMap<T, U, V, W, X>& b) 268 { 269 return !(a == b); 270 } 271 272 template<typename MappedType, typename HashTableType> deleteAllPairSeconds(HashTableType & collection)273 void deleteAllPairSeconds(HashTableType& collection) 274 { 275 typedef typename HashTableType::const_iterator iterator; 276 iterator end = collection.end(); 277 for (iterator it = collection.begin(); it != end; ++it) 278 delete it->second; 279 } 280 281 template<typename T, typename U, typename V, typename W, typename X> deleteAllValues(const HashMap<T,U,V,W,X> & collection)282 inline void deleteAllValues(const HashMap<T, U, V, W, X>& collection) 283 { 284 deleteAllPairSeconds<typename HashMap<T, U, V, W, X>::MappedType>(collection); 285 } 286 287 template<typename KeyType, typename HashTableType> deleteAllPairFirsts(HashTableType & collection)288 void deleteAllPairFirsts(HashTableType& collection) 289 { 290 typedef typename HashTableType::const_iterator iterator; 291 iterator end = collection.end(); 292 for (iterator it = collection.begin(); it != end; ++it) 293 delete it->first; 294 } 295 296 template<typename T, typename U, typename V, typename W, typename X> deleteAllKeys(const HashMap<T,U,V,W,X> & collection)297 inline void deleteAllKeys(const HashMap<T, U, V, W, X>& collection) 298 { 299 deleteAllPairFirsts<typename HashMap<T, U, V, W, X>::KeyType>(collection); 300 } 301 302 template<typename T, typename U, typename V, typename W, typename X, typename Y> copyKeysToVector(const HashMap<T,U,V,W,X> & collection,Y & vector)303 inline void copyKeysToVector(const HashMap<T, U, V, W, X>& collection, Y& vector) 304 { 305 typedef typename HashMap<T, U, V, W, X>::const_iterator::Keys iterator; 306 307 vector.resize(collection.size()); 308 309 iterator it = collection.begin().keys(); 310 iterator end = collection.end().keys(); 311 for (unsigned i = 0; it != end; ++it, ++i) 312 vector[i] = *it; 313 } 314 315 template<typename T, typename U, typename V, typename W, typename X, typename Y> copyValuesToVector(const HashMap<T,U,V,W,X> & collection,Y & vector)316 inline void copyValuesToVector(const HashMap<T, U, V, W, X>& collection, Y& vector) 317 { 318 typedef typename HashMap<T, U, V, W, X>::const_iterator::Values iterator; 319 320 vector.resize(collection.size()); 321 322 iterator it = collection.begin().values(); 323 iterator end = collection.end().values(); 324 for (unsigned i = 0; it != end; ++it, ++i) 325 vector[i] = *it; 326 } 327 328 } // namespace WTF 329 330 using WTF::HashMap; 331 332 #include "RefPtrHashMap.h" 333 334 #endif /* WTF_HashMap_h */ 335