HashIterator.h revision 5460a1f25d9ddecb5c70667267d66d51af177a99
1//===- HashIterator.h -----------------------------------------------------===// 2// 3// The MCLinker Project 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9#ifndef MCLD_HASH_ITERATOR_H 10#define MCLD_HASH_ITERATOR_H 11#ifdef ENABLE_UNITTEST 12#include <gtest.h> 13#endif 14 15namespace mcld { 16 17/** \class ChainIteratorBase 18 * \brief ChaintIteratorBase follows the HashEntryTy with the same hash value. 19 */ 20template<typename HashTableImplTy> 21class ChainIteratorBase 22{ 23public: 24 typedef HashTableImplTy hash_table; 25 typedef typename HashTableImplTy::key_type key_type; 26 typedef typename HashTableImplTy::entry_type entry_type; 27 typedef typename HashTableImplTy::bucket_type bucket_type; 28 29public: 30 ChainIteratorBase() 31 : m_pHashTable(0), m_HashValue(0), m_Index(0), m_EndIndex(0) 32 { } 33 34 ChainIteratorBase(HashTableImplTy* pTable, const key_type& pKey) 35 : m_pHashTable(pTable) 36 { 37 m_HashValue = pTable->hash()(pKey); 38 m_EndIndex = m_Index = m_HashValue % m_pHashTable->m_NumOfBuckets; 39 const unsigned int probe = 1; 40 while(true) { 41 bucket_type &bucket = m_pHashTable->m_Buckets[m_Index]; 42 if (bucket_type::getTombstone() == bucket.Entry) { 43 // Ignore tombstones. 44 } 45 else if (m_HashValue == bucket.FullHashValue) { 46 if (bucket.Entry->compare(pKey)) { 47 m_EndIndex = m_Index; 48 break; 49 } 50 } 51 m_Index += probe; 52 if (m_Index == m_pHashTable->m_NumOfBuckets) 53 m_Index = 0; 54 // doesn't exist 55 if (m_EndIndex == m_Index) { 56 reset(); 57 break; 58 } 59 } 60 } 61 62 ChainIteratorBase(const ChainIteratorBase& pCopy) 63 : m_pHashTable(pCopy.m_pHashTable), 64 m_Index(pCopy.m_Index), 65 m_EndIndex(pCopy.m_EndIndex), 66 m_HashValue(pCopy.m_HashValue) 67 { } 68 69 ChainIteratorBase& assign(const ChainIteratorBase& pCopy) { 70 m_pHashTable = pCopy.m_pHashTable; 71 m_Index = pCopy.m_Index; 72 m_EndIndex = pCopy.m_EndIndex; 73 m_HashValue = pCopy.m_HashValue; 74 return *this; 75 } 76 77 inline bucket_type* getBucket() { 78 if (0 == m_pHashTable) 79 return 0; 80 return &(m_pHashTable->m_Buckets[m_Index]); 81 } 82 83 inline const bucket_type* getBucket() const { 84 if (0 == m_pHashTable) 85 return 0; 86 return &(m_pHashTable->m_Buckets[m_Index]); 87 } 88 89 inline entry_type* getEntry() { 90 if (0 == m_pHashTable) 91 return 0; 92 return m_pHashTable->m_Buckets[m_Index].Entry; 93 } 94 95 inline const entry_type* getEntry() const { 96 if (0 == m_pHashTable) 97 return 0; 98 return m_pHashTable->m_Buckets[m_Index].Entry; 99 } 100 101 inline void reset() { 102 m_pHashTable = 0; 103 m_Index = 0; 104 m_EndIndex = 0; 105 m_HashValue = 0; 106 } 107 108 inline void advance() { 109 if (0 == m_pHashTable) 110 return; 111 const unsigned int probe = 1; 112 while(true) { 113 m_Index += probe; 114 if (m_Index == m_pHashTable->m_NumOfBuckets) 115 m_Index = 0; 116 // reach end() 117 if (m_Index == m_EndIndex) { 118 reset(); 119 return; 120 } 121 122 bucket_type &bucket = m_pHashTable->m_Buckets[m_Index]; 123 124 if (bucket_type::getTombstone() == bucket.Entry || 125 bucket_type::getEmptyBucket() == bucket.Entry) { 126 // Ignore tombstones. 127 } 128 else if (m_HashValue == bucket.FullHashValue) { 129 return; 130 } 131 } 132 } 133 134 bool operator==(const ChainIteratorBase& pCopy) const { 135 if (m_pHashTable == pCopy.m_pHashTable) { 136 if (0 == m_pHashTable) 137 return true; 138 return ((m_HashValue == pCopy.m_HashValue) && 139 (m_EndIndex == pCopy.m_EndIndex) && 140 (m_Index == pCopy.m_Index)); 141 } 142 return false; 143 } 144 145 bool operator!=(const ChainIteratorBase& pCopy) const 146 { return !(*this == pCopy); } 147 148private: 149 HashTableImplTy* m_pHashTable; 150 unsigned int m_Index; 151 unsigned int m_HashValue; 152 unsigned int m_EndIndex; 153}; 154 155/** \class EntryIteratorBase 156 * \brief EntryIteratorBase walks over hash table by the natural layout of the 157 * buckets 158 */ 159template<typename HashTableImplTy> 160class EntryIteratorBase 161{ 162public: 163 typedef HashTableImplTy hash_table; 164 typedef typename HashTableImplTy::key_type key_type; 165 typedef typename HashTableImplTy::entry_type entry_type; 166 typedef typename HashTableImplTy::bucket_type bucket_type; 167 168public: 169 EntryIteratorBase() 170 : m_pHashTable(0), m_Index(0) 171 { } 172 173 EntryIteratorBase(HashTableImplTy* pTable, 174 unsigned int pIndex) 175 : m_pHashTable(pTable), m_Index(pIndex) 176 { } 177 178 EntryIteratorBase(const EntryIteratorBase& pCopy) 179 : m_pHashTable(pCopy.m_pHashTable), m_Index(pCopy.m_Index) 180 { } 181 182 EntryIteratorBase& assign(const EntryIteratorBase& pCopy) { 183 m_pHashTable = pCopy.m_pHashTable; 184 m_Index = pCopy.m_Index; 185 return *this; 186 } 187 188 inline bucket_type* getBucket() { 189 if (0 == m_pHashTable) 190 return 0; 191 return &(m_pHashTable->m_Buckets[m_Index]); 192 } 193 194 inline const bucket_type* getBucket() const { 195 if (0 == m_pHashTable) 196 return 0; 197 return &(m_pHashTable->m_Buckets[m_Index]); 198 } 199 200 inline entry_type* getEntry() { 201 if (0 == m_pHashTable) 202 return 0; 203 return m_pHashTable->m_Buckets[m_Index].Entry; 204 } 205 206 inline const entry_type* getEntry() const { 207 if (0 == m_pHashTable) 208 return 0; 209 return m_pHashTable->m_Buckets[m_Index].Entry; 210 } 211 212 inline void reset() { 213 m_pHashTable = 0; 214 m_Index = 0; 215 } 216 217 inline void advance() { 218 if (0 == m_pHashTable) 219 return; 220 do { 221 ++m_Index; 222 if (m_pHashTable->m_NumOfBuckets == m_Index) { // to the end 223 reset(); 224 return; 225 } 226 } while(bucket_type::getEmptyBucket() == m_pHashTable->m_Buckets[m_Index].Entry || 227 bucket_type::getTombstone() == m_pHashTable->m_Buckets[m_Index].Entry); 228 } 229 230 bool operator==(const EntryIteratorBase& pCopy) const 231 { return ((m_pHashTable == pCopy.m_pHashTable) && 232 (m_Index == pCopy.m_Index)); } 233 234 bool operator!=(const EntryIteratorBase& pCopy) const 235 { return !(*this == pCopy); } 236 237private: 238 HashTableImplTy* m_pHashTable; 239 unsigned int m_Index; 240 241}; 242 243/** \class HashIterator 244 * \brief HashIterator provides a policy-based iterator. 245 * 246 * HashTable has two kinds of iterators. One is used to traverse buckets 247 * with the same hash value; the other is used to traverse all entries of the 248 * hash table. 249 * 250 * HashIterator is a template policy-based iterator, which can change its 251 * behavior by change the template argument IteratorBase. HashTable defines 252 * above two iterators by defining HashIterators with different IteratorBase. 253 */ 254template<typename IteratorBase, 255 typename Traits> 256class HashIterator : public IteratorBase 257{ 258public: 259 typedef Traits traits; 260 typedef typename traits::pointer pointer; 261 typedef typename traits::reference reference; 262 typedef size_t size_type; 263 typedef ptrdiff_t difference_type; 264 typedef IteratorBase Base; 265 266 typedef HashIterator<IteratorBase, 267 Traits> Self; 268 269 typedef typename traits::nonconst_traits nonconst_traits; 270 typedef HashIterator<IteratorBase, 271 nonconst_traits> iterator; 272 273 typedef typename traits::const_traits const_traits; 274 typedef HashIterator<IteratorBase, 275 const_traits> const_iterator; 276 typedef std::forward_iterator_tag iterator_category; 277 278public: 279 HashIterator() 280 : IteratorBase() 281 { } 282 283 /// HashIterator - constructor for EntryIterator 284 HashIterator(typename IteratorBase::hash_table* pTable, unsigned int pIndex) 285 : IteratorBase(pTable, pIndex) 286 { } 287 288 /// HashIterator - constructor for ChainIterator 289 explicit HashIterator(typename IteratorBase::hash_table* pTable, 290 const typename IteratorBase::key_type& pKey, 291 int) 292 : IteratorBase(pTable, pKey) 293 { } 294 295 HashIterator(const HashIterator& pCopy) 296 : IteratorBase(pCopy) 297 { } 298 299 ~HashIterator() 300 { } 301 302 HashIterator& operator=(const HashIterator& pCopy) { 303 IteratorBase::assign(pCopy); 304 return *this; 305 } 306 307 // ----- operators ----- // 308 Self& operator++() { 309 this->Base::advance(); 310 return *this; 311 } 312 313 Self operator++(int) { 314 Self tmp = *this; 315 this->Base::advance(); 316 return tmp; 317 } 318}; 319 320} // namespace of mcld 321 322#endif 323 324