Changeset 12162 in webkit for trunk/JavaScriptCore/kxmlcore
- Timestamp:
- Jan 17, 2006, 8:33:55 PM (19 years ago)
- Location:
- trunk/JavaScriptCore/kxmlcore
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/kxmlcore/HashTable.h
r12069 r12162 2 2 /* 3 3 * This file is part of the KDE libraries 4 * Copyright (C) 2005 Apple Computer, Inc.4 * Copyright (C) 2005, 2006 Apple Computer, Inc. 5 5 * 6 6 * This library is free software; you can redistribute it and/or … … 27 27 #include "HashTraits.h" 28 28 #include <assert.h> 29 #include <utility>30 29 #include <algorithm> 31 30 … … 34 33 #define DUMP_HASHTABLE_STATS 0 35 34 #define CHECK_HASHTABLE_CONSISTENCY 0 36 35 36 #if NDEBUG 37 #define CHECK_HASHTABLE_ITERATORS 0 38 #else 39 #define CHECK_HASHTABLE_ITERATORS 1 40 #endif 41 37 42 #if DUMP_HASHTABLE_STATS 38 43 39 44 struct HashTableStats { 40 ~HashTableStats(); 45 ~HashTableStats(); 41 46 static int numAccesses; 42 47 static int numCollisions; … … 48 53 static void recordCollisionAtCount(int count); 49 54 }; 50 51 #endif 52 53 #if !CHECK_HASHTABLE_CONSISTENCY 54 #define checkTableConsistency() ((void)0) 55 #define checkTableConsistencyExceptSize() ((void)0) 56 #endif 57 58 template<typename Key, typename Value, const Key& ExtractKey(const Value &), typename HashFunctions, typename Traits, typename KeyTraits> 55 56 #endif 57 58 template<typename Key, typename Value, const Key& ExtractKey(const Value&), typename HashFunctions, typename Traits, typename KeyTraits> 59 59 class HashTable; 60 61 template<typename Key, typename Value, const Key& ExtractKey(const Value &), typename HashFunctions, typename Traits, typename KeyTraits> 62 class HashTableIterator { 63 private: 64 typedef HashTable<Key, Value, ExtractKey, HashFunctions, Traits, KeyTraits> HashTableType; 65 typedef HashTableIterator<Key, Value, ExtractKey, HashFunctions, Traits, KeyTraits> iterator; 66 typedef Value ValueType; 67 typedef ValueType& ReferenceType; 68 typedef ValueType *PointerType; 69 70 friend class HashTable<Key, Value, ExtractKey, HashFunctions, Traits, KeyTraits>; 71 72 void skipEmptyBuckets() 73 { 74 while (m_position != m_endPosition && (HashTableType::isEmptyOrDeletedBucket(*m_position))) { 75 ++m_position; 76 } 77 } 78 79 HashTableIterator(PointerType position, PointerType endPosition) 80 : m_position(position), m_endPosition(endPosition) 81 { 82 skipEmptyBuckets(); 83 } 84 public: 85 HashTableIterator() {} 86 87 // default copy, assignment and destructor are ok 88 89 ReferenceType operator*() const { return *m_position; } 90 PointerType operator->() const { return &(operator*()); } 91 92 iterator& operator++() 93 { 94 ++m_position; 95 skipEmptyBuckets(); 96 return *this; 97 } 98 99 // postfix ++ intentionally omitted 100 101 // Comparison. 102 bool operator==(const iterator& other) const 103 { 104 return m_position == other.m_position; 105 } 106 107 bool operator!=(const iterator& other) const 108 { 109 return m_position != other.m_position; 110 } 111 112 private: 113 PointerType m_position; 114 PointerType m_endPosition; 115 }; 116 117 template<typename Key, typename Value, const Key& ExtractKey(const Value &), typename HashFunctions, typename Traits, typename KeyTraits> 60 template<typename Key, typename Value, const Key& ExtractKey(const Value&), typename HashFunctions, typename Traits, typename KeyTraits> 61 class HashTableIterator; 62 template<typename Key, typename Value, const Key& ExtractKey(const Value&), typename HashFunctions, typename Traits, typename KeyTraits> 63 class HashTableConstIterator; 64 65 #if CHECK_HASHTABLE_ITERATORS 66 template<typename Key, typename Value, const Key& ExtractKey(const Value&), typename HashFunctions, typename Traits, typename KeyTraits> 67 void addIterator(const HashTable<Key, Value, ExtractKey, HashFunctions, Traits, KeyTraits>*, 68 HashTableConstIterator<Key, Value, ExtractKey, HashFunctions, Traits, KeyTraits>*); 69 70 template<typename Key, typename Value, const Key& ExtractKey(const Value&), typename HashFunctions, typename Traits, typename KeyTraits> 71 void removeIterator(HashTableConstIterator<Key, Value, ExtractKey, HashFunctions, Traits, KeyTraits>*); 72 #else 73 template<typename Key, typename Value, const Key& ExtractKey(const Value&), typename HashFunctions, typename Traits, typename KeyTraits> 74 inline void addIterator(const HashTable<Key, Value, ExtractKey, HashFunctions, Traits, KeyTraits>*, 75 HashTableConstIterator<Key, Value, ExtractKey, HashFunctions, Traits, KeyTraits>*) { } 76 77 template<typename Key, typename Value, const Key& ExtractKey(const Value&), typename HashFunctions, typename Traits, typename KeyTraits> 78 inline void removeIterator(HashTableConstIterator<Key, Value, ExtractKey, HashFunctions, Traits, KeyTraits>*) { } 79 #endif 80 81 template<typename Key, typename Value, const Key& ExtractKey(const Value&), typename HashFunctions, typename Traits, typename KeyTraits> 118 82 class HashTableConstIterator { 119 83 private: … … 123 87 typedef Value ValueType; 124 88 typedef const ValueType& ReferenceType; 125 typedef const ValueType *PointerType;126 89 typedef const ValueType* PointerType; 90 127 91 friend class HashTable<Key, Value, ExtractKey, HashFunctions, Traits, KeyTraits>; 128 129 HashTableConstIterator(PointerType position, PointerType endPosition) 130 : m_position(position), m_endPosition(endPosition) 131 { 92 friend class HashTableIterator<Key, Value, ExtractKey, HashFunctions, Traits, KeyTraits>; 93 94 void skipEmptyBuckets() 95 { 96 while (m_position != m_endPosition && HashTableType::isEmptyOrDeletedBucket(*m_position)) 97 ++m_position; 98 } 99 100 HashTableConstIterator(const HashTableType* table, PointerType position, PointerType endPosition) 101 : m_position(position), m_endPosition(endPosition) 102 { 103 addIterator(table, this); 132 104 skipEmptyBuckets(); 133 105 } 106 134 107 public: 135 HashTableConstIterator() {} 136 HashTableConstIterator(const iterator &other) 137 : m_position(other.m_position), m_endPosition(other.m_endPosition) { } 138 139 // default copy, assignment and destructor are ok 140 141 ReferenceType operator*() const { return *m_position; } 142 PointerType operator->() const { return &(operator*()); } 143 144 void skipEmptyBuckets() 145 { 146 while (m_position != m_endPosition && (HashTableType::isEmptyOrDeletedBucket(*m_position))) { 147 ++m_position; 148 } 149 } 150 108 HashTableConstIterator() 109 { 110 addIterator(0, this); 111 } 112 113 HashTableConstIterator(const iterator& other) 114 : m_position(other.m_position), m_endPosition(other.m_endPosition) 115 { 116 #if CHECK_HASHTABLE_ITERATORS 117 addIterator(other.m_table, this); 118 #endif 119 } 120 121 // default copy, assignment and destructor are OK if CHECK_HASHTABLE_ITERATORS is 0 122 123 #if CHECK_HASHTABLE_ITERATORS 124 ~HashTableConstIterator() 125 { 126 removeIterator(this); 127 } 128 129 HashTableConstIterator(const const_iterator& other) 130 : m_position(other.m_position), m_endPosition(other.m_endPosition) 131 { 132 addIterator(other.m_table, this); 133 } 134 135 const_iterator& operator=(const const_iterator& other) 136 { 137 m_position = other.m_position; 138 m_endPosition = other.m_endPosition; 139 140 removeIterator(this); 141 addIterator(other.m_table, this); 142 } 143 #endif 144 145 ReferenceType operator*() const 146 { 147 checkValidity(); 148 return *m_position; 149 } 150 PointerType operator->() const { return &**this; } 151 151 152 const_iterator& operator++() 152 153 { 154 checkValidity(); 155 assert(m_position != m_endPosition); 153 156 ++m_position; 154 157 skipEmptyBuckets(); 155 158 return *this; 156 159 } 157 160 158 161 // postfix ++ intentionally omitted 159 162 160 163 // Comparison. 161 164 bool operator==(const const_iterator& other) const 162 { 163 return m_position == other.m_position; 164 } 165 166 bool operator!=(const const_iterator& other) const 167 { 168 return m_position != other.m_position; 169 } 170 165 { 166 checkValidity(other); 167 return m_position == other.m_position; 168 } 169 bool operator!=(const const_iterator& other) const 170 { 171 checkValidity(other); 172 return m_position != other.m_position; 173 } 174 171 175 private: 176 void checkValidity() const 177 { 178 #if CHECK_HASHTABLE_ITERATORS 179 assert(m_table); 180 #endif 181 } 182 183 void checkValidity(const const_iterator& other) const 184 { 185 #if CHECK_HASHTABLE_ITERATORS 186 assert(m_table); 187 assert(other.m_table); 188 assert(m_table == other.m_table); 189 #endif 190 } 191 172 192 PointerType m_position; 173 193 PointerType m_endPosition; 194 195 #if CHECK_HASHTABLE_ITERATORS 196 public: 197 mutable const HashTableType* m_table; 198 mutable const_iterator* m_next; 199 mutable const_iterator* m_previous; 200 #endif 174 201 }; 175 202 203 template<typename Key, typename Value, const Key& ExtractKey(const Value&), typename HashFunctions, typename Traits, typename KeyTraits> 204 class HashTableIterator { 205 private: 206 typedef HashTable<Key, Value, ExtractKey, HashFunctions, Traits, KeyTraits> HashTableType; 207 typedef HashTableIterator<Key, Value, ExtractKey, HashFunctions, Traits, KeyTraits> iterator; 208 typedef HashTableConstIterator<Key, Value, ExtractKey, HashFunctions, Traits, KeyTraits> const_iterator; 209 typedef Value ValueType; 210 typedef ValueType& ReferenceType; 211 typedef ValueType* PointerType; 212 213 friend class HashTable<Key, Value, ExtractKey, HashFunctions, Traits, KeyTraits>; 214 215 HashTableIterator(HashTableType* table, PointerType pos, PointerType end) : m_iterator(table, pos, end) { } 216 217 public: 218 HashTableIterator() { } 219 220 // default copy, assignment and destructor are OK 221 222 ReferenceType operator*() const { return const_cast<ReferenceType>(*m_iterator); } 223 PointerType operator->() const { return &**this; } 224 225 iterator& operator++() { ++m_iterator; return *this; } 226 227 // postfix ++ intentionally omitted 228 229 // Comparison. 230 bool operator==(const iterator& other) const { return m_iterator == other.m_iterator; } 231 bool operator!=(const iterator& other) const { return m_iterator != other.m_iterator; } 232 233 private: 234 const_iterator m_iterator; 235 }; 236 176 237 using std::swap; 177 238 178 #if ndefWIN32239 #if !WIN32 179 240 // Visual C++ has a swap for pairs defined. 241 180 242 // swap pairs by component, in case of pair members that specialize swap 181 template<typename T, typename U> 182 inline void swap(pair<T, U>& a, pair<T, U>& b) 243 template<typename T, typename U> inline void swap(pair<T, U>& a, pair<T, U>& b) 183 244 { 184 245 swap(a.first, b.first); … … 187 248 #endif 188 249 189 template<typename T, bool useSwap> 190 class Mover;191 192 template<typename T> 193 struct Mover<T, true>{194 static void move(T& from, T& to)195 {196 swap(from, to);197 }250 template<typename T, bool useSwap> struct Mover; 251 template<typename T> struct Mover<T, true> { static void move(T& from, T& to) { swap(from, to); } }; 252 template<typename T> struct Mover<T, false> { static void move(T& from, T& to) { to = from; } }; 253 254 template<typename Key, typename Value, typename HashFunctions> class IdentityHashTranslator { 255 public: 256 static unsigned hash(const Key& key) { return HashFunctions::hash(key); } 257 static bool equal(const Key& a, const Key& b) { return HashFunctions::equal(a, b); } 258 static void translate(Value& location, const Key& key, const Value& value, unsigned) { location = value; } 198 259 }; 199 260 200 template<typename T> 201 struct Mover<T, false> { 202 static void move(T& from, T& to) 203 { 204 to = from; 205 } 206 }; 207 208 template<typename Key, typename Value, typename HashFunctions> 209 class IdentityHashTranslator { 210 211 public: 212 static unsigned hash(const Key& key) 213 { 214 return HashFunctions::hash(key); 215 } 216 217 static bool equal(const Key& a, const Key& b) 218 { 219 return HashFunctions::equal(a, b); 220 } 221 222 static void translate(Value& location, const Key& key, const Value& value, unsigned) 223 { 224 location = value; 225 } 226 }; 227 228 template<typename Key, typename Value, const Key& ExtractKey(const Value &), typename HashFunctions, typename Traits, typename KeyTraits> 261 template<typename Key, typename Value, const Key& ExtractKey(const Value&), typename HashFunctions, typename Traits, typename KeyTraits> 229 262 class HashTable { 230 263 public: … … 234 267 typedef Value ValueType; 235 268 typedef IdentityHashTranslator<Key, Value, HashFunctions> IdentityTranslatorType; 236 237 HashTable() : m_table(0), m_tableSize(0), m_tableSizeMask(0), m_keyCount(0), m_deletedCount(0) {}238 ~HashTable() { deallocateTable(m_table, m_tableSize); }239 240 HashTable(const HashTable& other);241 void swap( const HashTable& other);242 HashTable& operator=(const HashTable& other);243 269 270 HashTable(); 271 ~HashTable() { invalidateIterators(); deallocateTable(m_table, m_tableSize); } 272 273 HashTable(const HashTable&); 274 void swap(HashTable&); 275 HashTable& operator=(const HashTable&); 276 244 277 iterator begin() { return makeIterator(m_table); } 245 278 iterator end() { return makeIterator(m_table + m_tableSize); } 246 279 const_iterator begin() const { return makeConstIterator(m_table); } 247 280 const_iterator end() const { return makeConstIterator(m_table + m_tableSize); } 248 281 249 282 int size() const { return m_keyCount; } 250 283 int capacity() const { return m_tableSize; } 251 284 252 285 pair<iterator, bool> insert(const ValueType& value) { return insert<KeyType, ValueType, IdentityTranslatorType>(ExtractKey(value), value); } 253 254 // aspecial version of insert() that finds the object by hashing and comparing286 287 // A special version of insert() that finds the object by hashing and comparing 255 288 // with some other type, to avoid the cost of type conversion if the object is already 256 // in the table 257 template<typename T, typename Extra, typename HashTranslator> 258 pair<iterator, bool> insert(const T& key, const Extra& extra); 259 260 iterator find(const KeyType& key); 261 const_iterator find(const KeyType& key) const; 262 bool contains(const KeyType& key) const; 263 264 void remove(const KeyType& key); 265 void remove(iterator it); 289 // in the table. 290 template<typename T, typename Extra, typename HashTranslator> pair<iterator, bool> insert(const T& key, const Extra&); 291 292 iterator find(const KeyType&); 293 const_iterator find(const KeyType&) const; 294 bool contains(const KeyType&) const; 295 296 void remove(const KeyType&); 297 void remove(iterator); 266 298 void clear(); 267 299 268 300 static bool isEmptyBucket(const ValueType& value) { return ExtractKey(value) == KeyTraits::emptyValue(); } 269 301 static bool isDeletedBucket(const ValueType& value) { return ExtractKey(value) == KeyTraits::deletedValue(); } 270 302 static bool isEmptyOrDeletedBucket(const ValueType& value) { return isEmptyBucket(value) || isDeletedBucket(value); } 271 303 272 304 private: 273 static ValueType *allocateTable(int size);274 static void deallocateTable(ValueType *table, int size);275 276 typedef pair<ValueType 305 static ValueType* allocateTable(int size); 306 static void deallocateTable(ValueType* table, int size); 307 308 typedef pair<ValueType*, bool> LookupType; 277 309 typedef pair<LookupType, unsigned> FullLookupType; 278 310 279 311 LookupType lookup(const Key& key) { return lookup<Key, IdentityTranslatorType>(key).first; } 280 template<typename T, typename HashTranslator> 281 FullLookupType lookup(const T&); 282 283 void remove(ValueType *); 284 312 template<typename T, typename HashTranslator> FullLookupType lookup(const T&); 313 314 void remove(ValueType*); 315 285 316 bool shouldExpand() const { return (m_keyCount + m_deletedCount) * m_maxLoad >= m_tableSize; } 286 317 bool mustRehashInPlace() const { return m_keyCount * m_minLoad < m_tableSize * 2; } … … 288 319 void expand(); 289 320 void shrink() { rehash(m_tableSize / 2); } 290 321 291 322 void rehash(int newTableSize); 292 323 void reinsert(ValueType&); 293 324 294 325 static void initializeBucket(ValueType& bucket) { new (&bucket) ValueType(Traits::emptyValue()); } 295 326 static void deleteBucket(ValueType& bucket) { assignDeleted<ValueType, Traits>(bucket); } 296 297 FullLookupType makeLookupResult(ValueType *position, bool found, unsigned hash) 298 { 299 return FullLookupType(LookupType(position, found), hash); 300 } 301 302 iterator makeIterator(ValueType *pos) { return iterator(pos, m_table + m_tableSize); } 303 const_iterator makeConstIterator(ValueType *pos) const { return const_iterator(pos, m_table + m_tableSize); } 304 327 328 FullLookupType makeLookupResult(ValueType* position, bool found, unsigned hash) 329 { return FullLookupType(LookupType(position, found), hash); } 330 331 iterator makeIterator(ValueType* pos) { return iterator(this, pos, m_table + m_tableSize); } 332 const_iterator makeConstIterator(ValueType* pos) const { return const_iterator(this, pos, m_table + m_tableSize); } 333 305 334 #if CHECK_HASHTABLE_CONSISTENCY 306 335 void checkTableConsistency() const; 307 336 void checkTableConsistencyExceptSize() const; 308 #endif 309 337 #else 338 static void checkTableConsistency() { } 339 static void checkTableConsistencyExceptSize() { } 340 #endif 341 342 #if CHECK_HASHTABLE_ITERATORS 343 void invalidateIterators(); 344 #else 345 static void invalidateIterators() { } 346 #endif 347 310 348 static const int m_minTableSize = 64; 311 349 static const int m_maxLoad = 2; 312 350 static const int m_minLoad = 6; 313 314 ValueType *m_table;351 352 ValueType* m_table; 315 353 int m_tableSize; 316 354 int m_tableSizeMask; 317 355 int m_keyCount; 318 356 int m_deletedCount; 357 358 #if CHECK_HASHTABLE_ITERATORS 359 public: 360 mutable const_iterator* m_iterators; 361 #endif 319 362 }; 320 321 template<typename Key, typename Value, const Key& ExtractKey(const Value &), typename HashFunctions, typename Traits, typename KeyTraits> 363 364 template<typename Key, typename Value, const Key& ExtractKey(const Value&), typename HashFunctions, typename Traits, typename KeyTraits> 365 inline HashTable<Key, Value, ExtractKey, HashFunctions, Traits, KeyTraits>::HashTable() 366 : m_table(0) 367 , m_tableSize(0) 368 , m_tableSizeMask(0) 369 , m_keyCount(0) 370 , m_deletedCount(0) 371 #if CHECK_HASHTABLE_ITERATORS 372 , m_iterators(0) 373 #endif 374 { 375 } 376 377 template<typename Key, typename Value, const Key& ExtractKey(const Value&), typename HashFunctions, typename Traits, typename KeyTraits> 322 378 template<typename T, typename HashTranslator> 323 379 inline typename HashTable<Key, Value, ExtractKey, HashFunctions, Traits, KeyTraits>::FullLookupType HashTable<Key, Value, ExtractKey, HashFunctions, Traits, KeyTraits>::lookup(const T& key) 324 380 { 325 381 assert(m_table); 326 382 327 383 unsigned h = HashTranslator::hash(key); 328 384 int sizeMask = m_tableSizeMask; 329 385 int i = h & sizeMask; 330 386 int k = 0; 331 387 332 388 #if DUMP_HASHTABLE_STATS 333 389 ++HashTableStats::numAccesses; 334 390 int probeCount = 0; 335 391 #endif 336 392 337 393 ValueType *table = m_table; 338 394 ValueType *entry; … … 351 407 i = (i + k) & sizeMask; 352 408 } 353 409 354 410 return makeLookupResult(deletedEntry ? deletedEntry : entry, false, h); 355 411 } 356 357 358 template<typename Key, typename Value, const Key& ExtractKey(const Value 359 template<typename T, typename Extra, typename HashTranslator> 412 413 414 template<typename Key, typename Value, const Key& ExtractKey(const Value&), typename HashFunctions, typename Traits, typename KeyTraits> 415 template<typename T, typename Extra, typename HashTranslator> 360 416 inline pair<typename HashTable<Key, Value, ExtractKey, HashFunctions, Traits, KeyTraits>::iterator, bool> HashTable<Key, Value, ExtractKey, HashFunctions, Traits, KeyTraits>::insert(const T& key, const Extra &extra) 361 417 { 418 invalidateIterators(); 419 362 420 if (!m_table) 363 421 expand(); 364 422 365 423 checkTableConsistency(); 366 424 367 425 FullLookupType lookupResult = lookup<T, HashTranslator>(key); 368 426 369 427 ValueType *entry = lookupResult.first.first; 370 428 bool found = lookupResult.first.second; 371 429 unsigned h = lookupResult.second; 372 373 if (found) {430 431 if (found) 374 432 return std::make_pair(makeIterator(entry), false); 375 } 376 433 377 434 if (isDeletedBucket(*entry)) 378 435 --m_deletedCount; 379 436 380 437 HashTranslator::translate(*entry, key, extra, h); 381 438 ++m_keyCount; 382 439 383 440 if (shouldExpand()) { 384 441 // FIXME: this makes an extra copy on expand. Probably not that bad since … … 389 446 return std::make_pair(find(enteredKey), true); 390 447 } 391 448 392 449 checkTableConsistency(); 393 450 394 451 return std::make_pair(makeIterator(entry), true); 395 452 } 396 397 template<typename Key, typename Value, const Key& ExtractKey(const Value 453 454 template<typename Key, typename Value, const Key& ExtractKey(const Value&), typename HashFunctions, typename Traits, typename KeyTraits> 398 455 inline void HashTable<Key, Value, ExtractKey, HashFunctions, Traits, KeyTraits>::reinsert(ValueType& entry) 399 456 { … … 404 461 ++HashTableStats::numReinserts; 405 462 #endif 406 463 407 464 Mover<ValueType, Traits::needsDestruction>::move(entry, *(lookup(ExtractKey(entry)).first)); 408 465 } 409 410 template<typename Key, typename Value, const Key& ExtractKey(const Value 466 467 template<typename Key, typename Value, const Key& ExtractKey(const Value&), typename HashFunctions, typename Traits, typename KeyTraits> 411 468 inline typename HashTable<Key, Value, ExtractKey, HashFunctions, Traits, KeyTraits>::iterator HashTable<Key, Value, ExtractKey, HashFunctions, Traits, KeyTraits>::find(const Key& key) 412 469 { 413 470 if (!m_table) 414 471 return end(); 415 472 416 473 LookupType result = lookup(key); 417 474 if (!result.second) … … 419 476 return makeIterator(result.first); 420 477 } 421 422 template<typename Key, typename Value, const Key& ExtractKey(const Value 478 479 template<typename Key, typename Value, const Key& ExtractKey(const Value&), typename HashFunctions, typename Traits, typename KeyTraits> 423 480 inline typename HashTable<Key, Value, ExtractKey, HashFunctions, Traits, KeyTraits>::const_iterator HashTable<Key, Value, ExtractKey, HashFunctions, Traits, KeyTraits>::find(const Key& key) const 424 481 { 425 482 if (!m_table) 426 483 return end(); 427 484 428 485 LookupType result = const_cast<HashTable *>(this)->lookup(key); 429 486 if (!result.second) … … 431 488 return makeConstIterator(result.first); 432 489 } 433 434 template<typename Key, typename Value, const Key& ExtractKey(const Value 435 inline bool HashTable<Key, Value, ExtractKey, HashFunctions, Traits, KeyTraits>::contains(const KeyType& key) const 490 491 template<typename Key, typename Value, const Key& ExtractKey(const Value&), typename HashFunctions, typename Traits, typename KeyTraits> 492 inline bool HashTable<Key, Value, ExtractKey, HashFunctions, Traits, KeyTraits>::contains(const KeyType& key) const 436 493 { 437 494 if (!m_table) 438 495 return false; 439 496 440 497 return const_cast<HashTable *>(this)->lookup(key).second; 441 498 } 442 443 template<typename Key, typename Value, const Key& ExtractKey(const Value &), typename HashFunctions, typename Traits, typename KeyTraits> 444 inline void HashTable<Key, Value, ExtractKey, HashFunctions, Traits, KeyTraits>::remove(ValueType *pos) 445 { 499 500 template<typename Key, typename Value, const Key& ExtractKey(const Value&), typename HashFunctions, typename Traits, typename KeyTraits> 501 inline void HashTable<Key, Value, ExtractKey, HashFunctions, Traits, KeyTraits>::remove(ValueType* pos) 502 { 503 invalidateIterators(); 446 504 checkTableConsistency(); 447 505 448 506 #if DUMP_HASHTABLE_STATS 449 507 ++HashTableStats::numRemoves; 450 508 #endif 451 509 452 510 deleteBucket(*pos); 453 511 ++m_deletedCount; 454 512 --m_keyCount; 455 513 456 514 if (shouldShrink()) 457 515 shrink(); 458 516 459 517 checkTableConsistency(); 460 518 } 461 462 template<typename Key, typename Value, const Key& ExtractKey(const Value 519 520 template<typename Key, typename Value, const Key& ExtractKey(const Value&), typename HashFunctions, typename Traits, typename KeyTraits> 463 521 inline void HashTable<Key, Value, ExtractKey, HashFunctions, Traits, KeyTraits>::remove(const KeyType& key) 464 { 522 { 465 523 if (!m_table) 466 524 return; 467 468 remove(find(key)); 469 } 470 471 template<typename Key, typename Value, const Key& ExtractKey(const Value 525 526 remove(find(key)); 527 } 528 529 template<typename Key, typename Value, const Key& ExtractKey(const Value&), typename HashFunctions, typename Traits, typename KeyTraits> 472 530 inline void HashTable<Key, Value, ExtractKey, HashFunctions, Traits, KeyTraits>::remove(iterator it) 473 { 531 { 474 532 if (it == end()) 475 533 return; 476 477 remove( it.m_position);478 } 479 480 481 template<typename Key, typename Value, const Key& ExtractKey(const Value 534 535 remove(const_cast<ValueType*>(it.m_iterator.m_position)); 536 } 537 538 539 template<typename Key, typename Value, const Key& ExtractKey(const Value&), typename HashFunctions, typename Traits, typename KeyTraits> 482 540 inline Value *HashTable<Key, Value, ExtractKey, HashFunctions, Traits, KeyTraits>::allocateTable(int size) 483 541 { … … 485 543 // gcc doesn't appear to support that 486 544 if (Traits::emptyValueIsZero) 487 return reinterpret_cast<ValueType *>(fastCalloc(size, sizeof(ValueType))); 545 return reinterpret_cast<ValueType *>(fastCalloc(size, sizeof(ValueType))); 488 546 else { 489 ValueType *result = reinterpret_cast<ValueType *>(fastMalloc(size * sizeof(ValueType))); 547 ValueType *result = reinterpret_cast<ValueType *>(fastMalloc(size * sizeof(ValueType))); 490 548 for (int i = 0; i < size; i++) { 491 549 initializeBucket(result[i]); … … 495 553 } 496 554 497 template<typename Key, typename Value, const Key& ExtractKey(const Value 555 template<typename Key, typename Value, const Key& ExtractKey(const Value&), typename HashFunctions, typename Traits, typename KeyTraits> 498 556 inline void HashTable<Key, Value, ExtractKey, HashFunctions, Traits, KeyTraits>::deallocateTable(ValueType *table, int size) 499 557 { … … 506 564 fastFree(table); 507 565 } 508 509 template<typename Key, typename Value, const Key& ExtractKey(const Value 566 567 template<typename Key, typename Value, const Key& ExtractKey(const Value&), typename HashFunctions, typename Traits, typename KeyTraits> 510 568 inline void HashTable<Key, Value, ExtractKey, HashFunctions, Traits, KeyTraits>::expand() 511 { 569 { 512 570 int newSize; 513 571 if (m_tableSize == 0) … … 517 575 else 518 576 newSize = m_tableSize * 2; 519 520 rehash(newSize); 521 } 522 523 template<typename Key, typename Value, const Key& ExtractKey(const Value 577 578 rehash(newSize); 579 } 580 581 template<typename Key, typename Value, const Key& ExtractKey(const Value&), typename HashFunctions, typename Traits, typename KeyTraits> 524 582 void HashTable<Key, Value, ExtractKey, HashFunctions, Traits, KeyTraits>::rehash(int newTableSize) 525 583 { 526 584 checkTableConsistencyExceptSize(); 527 585 528 586 int oldTableSize = m_tableSize; 529 587 ValueType *oldTable = m_table; 530 588 531 589 #if DUMP_HASHTABLE_STATS 532 590 if (oldTableSize != 0) 533 591 ++HashTableStats::numRehashes; 534 592 #endif 535 593 536 594 m_tableSize = newTableSize; 537 595 m_tableSizeMask = newTableSize - 1; 538 596 m_table = allocateTable(newTableSize); 539 597 540 598 for (int i = 0; i != oldTableSize; ++i) { 541 599 if (!isEmptyOrDeletedBucket(oldTable[i])) 542 600 reinsert(oldTable[i]); 543 601 } 544 602 545 603 m_deletedCount = 0; 546 604 547 605 deallocateTable(oldTable, oldTableSize); 548 606 549 607 checkTableConsistency(); 550 608 } 551 552 template<typename Key, typename Value, const Key& ExtractKey(const Value 609 610 template<typename Key, typename Value, const Key& ExtractKey(const Value&), typename HashFunctions, typename Traits, typename KeyTraits> 553 611 inline void HashTable<Key, Value, ExtractKey, HashFunctions, Traits, KeyTraits>::clear() 554 612 { 613 invalidateIterators(); 555 614 deallocateTable(m_table, m_tableSize); 556 615 m_table = 0; … … 559 618 m_keyCount = 0; 560 619 } 561 562 template<typename Key, typename Value, const Key& ExtractKey(const Value 620 621 template<typename Key, typename Value, const Key& ExtractKey(const Value&), typename HashFunctions, typename Traits, typename KeyTraits> 563 622 HashTable<Key, Value, ExtractKey, HashFunctions, Traits, KeyTraits>::HashTable(const HashTable& other) 564 623 : m_table(0) … … 567 626 , m_keyCount(0) 568 627 , m_deletedCount(0) 569 { 570 // doesn't matter if copying a hashtable is efficient so just 571 // do it the dumb way, by copying each element. 628 #if CHECK_HASHTABLE_ITERATORS 629 , m_iterators(0) 630 #endif 631 { 632 // Copy the hash table the dumb way, by inserting each element into the new table. 633 // It might be more efficient to copy the table slots, but it's not clear that efficiency is needed. 572 634 const_iterator end = other.end(); 573 for (const_iterator it = other.begin(); it != end; ++it) {635 for (const_iterator it = other.begin(); it != end; ++it) 574 636 insert(*it); 575 } 576 } 577 578 template<typename Key, typename Value, const Key& ExtractKey(const Value &), typename HashFunctions, typename Traits, typename KeyTraits> 579 void HashTable<Key, Value, ExtractKey, HashFunctions, Traits, KeyTraits>::swap(const HashTable& other) 580 { 637 } 638 639 template<typename Key, typename Value, const Key& ExtractKey(const Value&), typename HashFunctions, typename Traits, typename KeyTraits> 640 void HashTable<Key, Value, ExtractKey, HashFunctions, Traits, KeyTraits>::swap(HashTable& other) 641 { 642 invalidateIterators(); 643 other.invalidateIterators(); 644 581 645 ValueType *tmp_table = m_table; 582 646 m_table = other.m_table; 583 647 other.m_table = tmp_table; 584 648 585 649 int tmp_tableSize = m_tableSize; 586 650 m_tableSize = other.m_tableSize; 587 651 other.m_tableSize = tmp_tableSize; 588 652 589 653 int tmp_tableSizeMask = m_tableSizeMask; 590 654 m_tableSizeMask = other.m_tableSizeMask; 591 655 other.m_tableSizeMask = tmp_tableSizeMask; 592 656 593 657 int tmp_keyCount = m_keyCount; 594 658 m_keyCount = other.m_keyCount; 595 659 other.m_keyCount = tmp_keyCount; 596 660 597 661 int tmp_deletedCount = m_deletedCount; 598 662 m_deletedCount = other.m_deletedCount; 599 663 other.m_deletedCount = tmp_deletedCount; 600 664 } 601 602 template<typename Key, typename Value, const Key& ExtractKey(const Value 665 666 template<typename Key, typename Value, const Key& ExtractKey(const Value&), typename HashFunctions, typename Traits, typename KeyTraits> 603 667 HashTable<Key, Value, ExtractKey, HashFunctions, Traits, KeyTraits>& HashTable<Key, Value, ExtractKey, HashFunctions, Traits, KeyTraits>::operator=(const HashTable& other) 604 668 { … … 607 671 return *this; 608 672 } 609 673 610 674 #if CHECK_HASHTABLE_CONSISTENCY 611 612 template<typename Key, typename Value, const Key& ExtractKey(const Value 675 676 template<typename Key, typename Value, const Key& ExtractKey(const Value&), typename HashFunctions, typename Traits, typename KeyTraits> 613 677 void HashTable<Key, Value, ExtractKey, HashFunctions, Traits, KeyTraits>::checkTableConsistency() const 614 678 { … … 617 681 assert(!shouldShrink()); 618 682 } 619 620 template<typename Key, typename Value, const Key& ExtractKey(const Value 683 684 template<typename Key, typename Value, const Key& ExtractKey(const Value&), typename HashFunctions, typename Traits, typename KeyTraits> 621 685 void HashTable<Key, Value, ExtractKey, HashFunctions, Traits, KeyTraits>::checkTableConsistencyExceptSize() const 622 686 { 623 687 if (!m_table) 624 688 return; 625 689 626 690 int count = 0; 627 691 int deletedCount = 0; … … 630 694 if (isEmptyBucket(*entry)) 631 695 continue; 632 696 633 697 if (isDeletedBucket(*entry)) { 634 698 ++deletedCount; 635 699 continue; 636 700 } 637 701 638 702 const_iterator it = find(ExtractKey(*entry)); 639 703 assert(entry == it.m_position); 640 704 ++count; 641 705 } 642 706 643 707 assert(count == m_keyCount); 644 708 assert(deletedCount == m_deletedCount); … … 647 711 assert(m_tableSize == m_tableSizeMask + 1); 648 712 } 649 713 650 714 #endif // CHECK_HASHTABLE_CONSISTENCY 651 715 716 #if CHECK_HASHTABLE_ITERATORS 717 718 template<typename Key, typename Value, const Key& ExtractKey(const Value&), typename HashFunctions, typename Traits, typename KeyTraits> 719 void HashTable<Key, Value, ExtractKey, HashFunctions, Traits, KeyTraits>::invalidateIterators() 720 { 721 const_iterator* next; 722 for (const_iterator* p = m_iterators; p; p = next) { 723 next = p->m_next; 724 p->m_table = 0; 725 p->m_next = 0; 726 p->m_previous = 0; 727 } 728 m_iterators = 0; 729 } 730 731 template<typename Key, typename Value, const Key& ExtractKey(const Value&), typename HashFunctions, typename Traits, typename KeyTraits> 732 void addIterator(const HashTable<Key, Value, ExtractKey, HashFunctions, Traits, KeyTraits>* table, 733 HashTableConstIterator<Key, Value, ExtractKey, HashFunctions, Traits, KeyTraits>* it) 734 { 735 it->m_table = table; 736 it->m_previous = 0; 737 738 // Insert iterator at head of doubly-linked list of iterators. 739 if (!table) { 740 it->m_next = 0; 741 } else { 742 assert(table->m_iterators != it); 743 it->m_next = table->m_iterators; 744 table->m_iterators = it; 745 if (it->m_next) { 746 assert(!it->m_next->m_previous); 747 it->m_next->m_previous = it; 748 } 749 } 750 } 751 752 template<typename Key, typename Value, const Key& ExtractKey(const Value&), typename HashFunctions, typename Traits, typename KeyTraits> 753 void removeIterator(HashTableConstIterator<Key, Value, ExtractKey, HashFunctions, Traits, KeyTraits>* it) 754 { 755 typedef HashTable<Key, Value, ExtractKey, HashFunctions, Traits, KeyTraits> HashTableType; 756 typedef HashTableConstIterator<Key, Value, ExtractKey, HashFunctions, Traits, KeyTraits> const_iterator; 757 758 // Delete iterator from doubly-linked list of iterators. 759 if (!it->m_table) { 760 assert(!it->m_next); 761 assert(!it->m_previous); 762 } else { 763 if (it->m_next) { 764 assert(it->m_next->m_previous == it); 765 it->m_next->m_previous = it->m_previous; 766 } 767 if (it->m_previous) { 768 assert(it->m_table->m_iterators != it); 769 assert(it->m_previous->m_next == it); 770 it->m_previous->m_next = it->m_next; 771 } else { 772 assert(it->m_table->m_iterators == it); 773 it->m_table->m_iterators = it->m_next; 774 } 775 } 776 777 it->m_table = 0; 778 it->m_next = 0; 779 it->m_previous = 0; 780 } 781 782 #endif // CHECK_HASHTABLE_ITERATORS 783 652 784 } // namespace KXMLCore 653 785 -
trunk/JavaScriptCore/kxmlcore/HashTraits.h
r11962 r12162 2 2 /* 3 3 * This file is part of the KDE libraries 4 * Copyright (C) 2005 Apple Computer, Inc.4 * Copyright (C) 2005, 2006 Apple Computer, Inc. 5 5 * 6 6 * This library is free software; you can redistribute it and/or … … 30 30 31 31 using std::pair; 32 32 33 33 template <typename T> struct IsInteger { static const bool value = false; }; 34 34 template <> struct IsInteger<bool> { static const bool value = true; }; … … 44 44 template <> struct IsInteger<long long> { static const bool value = true; }; 45 45 template <> struct IsInteger<unsigned long long> { static const bool value = true; }; 46 47 template<typename T> 48 struct GenericHashTraits { 46 47 template<typename T> struct GenericHashTraits { 49 48 typedef T TraitType; 50 49 static const bool emptyValueIsZero = IsInteger<T>::value; … … 53 52 }; 54 53 55 template<typename T> 56 struct HashTraits : GenericHashTraits<T> { 57 }; 54 template<typename T> struct HashTraits : GenericHashTraits<T> { }; 58 55 59 // may not be appropriate for all uses since it would disallow 0 and -1 as keys 60 template<> 61 struct HashTraits<int> : GenericHashTraits<int> { 56 // may not be appropriate for all uses since it disallows 0 and -1 as keys 57 template<> struct HashTraits<int> : GenericHashTraits<int> { 62 58 static TraitType deletedValue() { return -1; } 63 59 }; 64 60 65 template<typename P> 66 struct HashTraits<P *> : GenericHashTraits<P *> { 67 typedef P *TraitType; 61 template<typename P> struct HashTraits<P*> : GenericHashTraits<P*> { 62 typedef P* TraitType; 68 63 static const bool emptyValueIsZero = true; 69 64 static const bool needsDestruction = false; 70 static TraitType emptyValue() { return reinterpret_cast<P *>(0); }71 static TraitType deletedValue() { return reinterpret_cast<P 65 static TraitType emptyValue() { return 0; } 66 static TraitType deletedValue() { return reinterpret_cast<P*>(-1); } 72 67 }; 73 68 74 template<typename P> 75 struct HashTraits<RefPtr<P> > : GenericHashTraits<RefPtr<P> > { 69 template<typename P> struct HashTraits<RefPtr<P> > : GenericHashTraits<RefPtr<P> > { 76 70 static const bool emptyValueIsZero = true; 77 71 }; 78 72 79 template<typename T, typename Traits> 80 class DeletedValueAssigner; 73 template<typename T, typename Traits> class DeletedValueAssigner; 81 74 82 template<typename T, typename Traits> 83 inline void assignDeleted(T& location) 75 template<typename T, typename Traits> inline void assignDeleted(T& location) 84 76 { 85 77 DeletedValueAssigner<T, Traits>::assignDeletedValue(location); … … 96 88 static const bool emptyValueIsZero = FirstTraits::emptyValueIsZero && SecondTraits::emptyValueIsZero; 97 89 static const bool needsDestruction = FirstTraits::needsDestruction || SecondTraits::needsDestruction; 98 99 static TraitType emptyValue() 90 91 static TraitType emptyValue() 100 92 { 101 93 return TraitType(FirstTraits::emptyValue(), SecondTraits::emptyValue()); 102 94 } 103 95 104 static TraitType deletedValue() 96 static TraitType deletedValue() 105 97 { 106 98 return TraitType(FirstTraits::deletedValue(), SecondTraits::emptyValue()); … … 115 107 116 108 template<typename First, typename Second> 117 struct HashTraits<pair<First, Second> > : public PairHashTraits<HashTraits<First>, HashTraits<Second> > { 118 }; 109 struct HashTraits<pair<First, Second> > : public PairHashTraits<HashTraits<First>, HashTraits<Second> > { }; 119 110 120 template<typename T, typename Traits> 121 struct DeletedValueAssigner 122 { 123 static void assignDeletedValue(T& location) 124 { 125 location = Traits::deletedValue(); 126 } 111 template<typename T, typename Traits> struct DeletedValueAssigner { 112 static void assignDeletedValue(T& location) { location = Traits::deletedValue(); } 127 113 }; 128 114 … … 130 116 struct DeletedValueAssigner<pair<typename FirstTraits::TraitType, typename SecondTraits::TraitType>, PairHashTraits<FirstTraits, SecondTraits> > 131 117 { 132 static void assignDeletedValue(pair<typename FirstTraits::TraitType, typename SecondTraits::TraitType>& location) 133 { 118 static void assignDeletedValue(pair<typename FirstTraits::TraitType, typename SecondTraits::TraitType>& location) 119 { 134 120 PairHashTraits<FirstTraits, SecondTraits>::assignDeletedValue(location); 135 121 } … … 139 125 struct DeletedValueAssigner<pair<First, Second>, HashTraits<pair<First, Second> > > 140 126 { 141 static void assignDeletedValue(pair<First, Second>& location) 142 { 127 static void assignDeletedValue(pair<First, Second>& location) 128 { 143 129 HashTraits<pair<First, Second> >::assignDeletedValue(location); 144 130 }
Note:
See TracChangeset
for help on using the changeset viewer.