//===- HashTable.tcc ---------------------------------------------------------===// // // The MCLinker Project // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// //===--------------------------------------------------------------------===// // template implementation of HashTable template HashTable::HashTable(size_type pSize) : HashTableImpl(pSize), m_EntryFactory() { } template HashTable::~HashTable() { if (BaseTy::empty()) return; /** clean up **/ for (unsigned int i=0; i < BaseTy::m_NumOfBuckets; ++i) { if (bucket_type::getEmptyBucket() != BaseTy::m_Buckets[i].Entry && bucket_type::getTombstone() != BaseTy::m_Buckets[i].Entry ) { m_EntryFactory.destroy(BaseTy::m_Buckets[i].Entry); } } } template void HashTable::clear() { if (BaseTy::empty()) return; /** clean up **/ for (unsigned int i=0; i < BaseTy::m_NumOfBuckets; ++i) { if (bucket_type::getEmptyBucket() != BaseTy::m_Buckets[i].Entry ) { if (bucket_type::getTombstone() != BaseTy::m_Buckets[i].Entry ) { m_EntryFactory.destroy(BaseTy::m_Buckets[i].Entry); } BaseTy::m_Buckets[i].Entry = bucket_type::getEmptyBucket(); } } BaseTy::m_NumOfEntries = 0; BaseTy::m_NumOfTombstones = 0; } /// insert - insert a new element to the container. If the element already // exist, return the element. template typename HashTable::entry_type* HashTable::insert( const typename HashTable::key_type& pKey, bool& pExist) { unsigned int index = BaseTy::lookUpBucketFor(pKey); bucket_type& bucket = BaseTy::m_Buckets[index]; entry_type* entry = bucket.Entry; if (bucket_type::getEmptyBucket() != entry && bucket_type::getTombstone() != entry) { // Already exist in the table pExist = true; return entry; } // find a tombstone if (bucket_type::getTombstone() == entry) --BaseTy::m_NumOfTombstones; entry = bucket.Entry = m_EntryFactory.produce(pKey); ++BaseTy::m_NumOfEntries; BaseTy::mayRehash(); pExist = false; return entry; } /// erase - remove the elements with the pKey // @return the number of removed elements. template typename HashTable::size_type HashTable::erase( const typename HashTable::key_type& pKey) { int index; if (-1 == (index = BaseTy::findKey(pKey))) return 0; bucket_type& bucket = BaseTy::m_Buckets[index]; m_EntryFactory.destroy(bucket.Entry); bucket.Entry = bucket_type::getTombstone(); --BaseTy::m_NumOfEntries; ++BaseTy::m_NumOfTombstones; BaseTy::mayRehash(); return 1; } template typename HashTable::iterator HashTable::find( const typename HashTable::key_type& pKey) { int index; if (-1 == (index = BaseTy::findKey(pKey))) return end(); return iterator(this, index); } template typename HashTable::const_iterator HashTable::find( const typename HashTable::key_type& pKey) const { int index; if (-1 == (index = BaseTy::findKey(pKey))) return end(); return const_iterator(this, index); } template typename HashTable::size_type HashTable::count( const typename HashTable::key_type& pKey) const { const_chain_iterator bucket, bEnd = end(pKey); size_type count = 0; for (bucket = begin(pKey); bucket != bEnd; ++bucket) ++count; return count; } template float HashTable::load_factor() const { return ((float)BaseTy::m_NumOfEntries/(float)BaseTy::m_NumOfBuckets); } template void HashTable::rehash() { BaseTy::mayRehash(); } template void HashTable::rehash( typename HashTable::size_type pCount) { BaseTy::doRehash(pCount); } template typename HashTable::iterator HashTable::begin() { if (BaseTy::empty()) return iterator(this, 0); unsigned int index = 0; while (bucket_type::getTombstone() == BaseTy::m_Buckets[index].Entry || bucket_type::getEmptyBucket() == BaseTy::m_Buckets[index].Entry) { ++index; } return iterator(this, index); } template typename HashTable::iterator HashTable::end() { return iterator(NULL, 0); } template typename HashTable::const_iterator HashTable::begin() const { if (BaseTy::empty()) return const_iterator(this, 0); unsigned int index = 0; while (bucket_type::getTombstone() == BaseTy::m_Buckets[index].Entry || bucket_type::getEmptyBucket() == BaseTy::m_Buckets[index].Entry) { ++index; } return const_iterator(this, index); } template typename HashTable::const_iterator HashTable::end() const { return const_iterator(NULL, 0); } template typename HashTable::chain_iterator HashTable::begin( const typename HashTable::key_type& pKey) { return chain_iterator(this, pKey, 0x0); } template typename HashTable::chain_iterator HashTable::end( const typename HashTable::key_type& pKey) { return chain_iterator(); } template typename HashTable::const_chain_iterator HashTable::begin( const typename HashTable::key_type& pKey) const { return const_chain_iterator(this, pKey, 0x0); } template typename HashTable::const_chain_iterator HashTable::end( const typename HashTable::key_type& pKey) const { return const_chain_iterator(); }