blob: 4d5e8dc67b0d04b3a6863e9531859938f3f24420 [file] [log] [blame]
//===- 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 <typename HashEntryTy,
typename HashFunctionTy,
typename EntryFactoryTy>
HashTable<HashEntryTy, HashFunctionTy, EntryFactoryTy>::HashTable(
size_type pSize)
: HashTableImpl<HashEntryTy, HashFunctionTy>(pSize), m_EntryFactory() {
}
template <typename HashEntryTy,
typename HashFunctionTy,
typename EntryFactoryTy>
HashTable<HashEntryTy, HashFunctionTy, EntryFactoryTy>::~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 <typename HashEntryTy,
typename HashFunctionTy,
typename EntryFactoryTy>
void HashTable<HashEntryTy, HashFunctionTy, EntryFactoryTy>::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::clear();
}
/// insert - insert a new element to the container. If the element already
// exist, return the element.
template <typename HashEntryTy,
typename HashFunctionTy,
typename EntryFactoryTy>
typename HashTable<HashEntryTy, HashFunctionTy, EntryFactoryTy>::entry_type*
HashTable<HashEntryTy, HashFunctionTy, EntryFactoryTy>::insert(
const typename HashTable<HashEntryTy,
HashFunctionTy,
EntryFactoryTy>::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 HashEntryTy,
typename HashFunctionTy,
typename EntryFactoryTy>
typename HashTable<HashEntryTy, HashFunctionTy, EntryFactoryTy>::size_type
HashTable<HashEntryTy, HashFunctionTy, EntryFactoryTy>::erase(
const typename HashTable<HashEntryTy,
HashFunctionTy,
EntryFactoryTy>::key_type& pKey) {
int index;
if ((index = BaseTy::findKey(pKey)) == -1)
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 HashEntryTy,
typename HashFunctionTy,
typename EntryFactoryTy>
typename HashTable<HashEntryTy, HashFunctionTy, EntryFactoryTy>::iterator
HashTable<HashEntryTy, HashFunctionTy, EntryFactoryTy>::find(
const typename HashTable<HashEntryTy,
HashFunctionTy,
EntryFactoryTy>::key_type& pKey) {
int index;
if ((index = BaseTy::findKey(pKey)) == -1)
return end();
return iterator(this, index);
}
template <typename HashEntryTy,
typename HashFunctionTy,
typename EntryFactoryTy>
typename HashTable<HashEntryTy, HashFunctionTy, EntryFactoryTy>::const_iterator
HashTable<HashEntryTy, HashFunctionTy, EntryFactoryTy>::find(
const typename HashTable<HashEntryTy,
HashFunctionTy,
EntryFactoryTy>::key_type& pKey) const {
int index;
if ((index = BaseTy::findKey(pKey)) == -1)
return end();
return const_iterator(this, index);
}
template <typename HashEntryTy,
typename HashFunctionTy,
typename EntryFactoryTy>
typename HashTable<HashEntryTy, HashFunctionTy, EntryFactoryTy>::size_type
HashTable<HashEntryTy, HashFunctionTy, EntryFactoryTy>::count(
const typename HashTable<HashEntryTy,
HashFunctionTy,
EntryFactoryTy>::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 <typename HashEntryTy,
typename HashFunctionTy,
typename EntryFactoryTy>
float HashTable<HashEntryTy, HashFunctionTy, EntryFactoryTy>::load_factor()
const {
return ((float)BaseTy::m_NumOfEntries / (float)BaseTy::m_NumOfBuckets);
}
template <typename HashEntryTy,
typename HashFunctionTy,
typename EntryFactoryTy>
void HashTable<HashEntryTy, HashFunctionTy, EntryFactoryTy>::rehash() {
BaseTy::mayRehash();
}
template <typename HashEntryTy,
typename HashFunctionTy,
typename EntryFactoryTy>
void HashTable<HashEntryTy, HashFunctionTy, EntryFactoryTy>::rehash(
typename HashTable<HashEntryTy, HashFunctionTy, EntryFactoryTy>::size_type
pCount) {
BaseTy::doRehash(pCount);
}
template <typename HashEntryTy,
typename HashFunctionTy,
typename EntryFactoryTy>
typename HashTable<HashEntryTy, HashFunctionTy, EntryFactoryTy>::iterator
HashTable<HashEntryTy, HashFunctionTy, EntryFactoryTy>::begin() {
if (BaseTy::empty())
return end();
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 HashEntryTy,
typename HashFunctionTy,
typename EntryFactoryTy>
typename HashTable<HashEntryTy, HashFunctionTy, EntryFactoryTy>::iterator
HashTable<HashEntryTy, HashFunctionTy, EntryFactoryTy>::end() {
return iterator(NULL, 0);
}
template <typename HashEntryTy,
typename HashFunctionTy,
typename EntryFactoryTy>
typename HashTable<HashEntryTy, HashFunctionTy, EntryFactoryTy>::const_iterator
HashTable<HashEntryTy, HashFunctionTy, EntryFactoryTy>::begin() const {
if (BaseTy::empty())
return end();
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 HashEntryTy,
typename HashFunctionTy,
typename EntryFactoryTy>
typename HashTable<HashEntryTy, HashFunctionTy, EntryFactoryTy>::const_iterator
HashTable<HashEntryTy, HashFunctionTy, EntryFactoryTy>::end() const {
return const_iterator(NULL, 0);
}
template <typename HashEntryTy,
typename HashFunctionTy,
typename EntryFactoryTy>
typename HashTable<HashEntryTy, HashFunctionTy, EntryFactoryTy>::chain_iterator
HashTable<HashEntryTy, HashFunctionTy, EntryFactoryTy>::begin(
const typename HashTable<HashEntryTy,
HashFunctionTy,
EntryFactoryTy>::key_type& pKey) {
return chain_iterator(this, pKey, 0x0);
}
template <typename HashEntryTy,
typename HashFunctionTy,
typename EntryFactoryTy>
typename HashTable<HashEntryTy, HashFunctionTy, EntryFactoryTy>::chain_iterator
HashTable<HashEntryTy, HashFunctionTy, EntryFactoryTy>::end(
const typename HashTable<HashEntryTy,
HashFunctionTy,
EntryFactoryTy>::key_type& pKey) {
return chain_iterator();
}
template <typename HashEntryTy,
typename HashFunctionTy,
typename EntryFactoryTy>
typename HashTable<HashEntryTy,
HashFunctionTy,
EntryFactoryTy>::const_chain_iterator
HashTable<HashEntryTy, HashFunctionTy, EntryFactoryTy>::begin(
const typename HashTable<HashEntryTy,
HashFunctionTy,
EntryFactoryTy>::key_type& pKey) const {
return const_chain_iterator(this, pKey, 0x0);
}
template <typename HashEntryTy,
typename HashFunctionTy,
typename EntryFactoryTy>
typename HashTable<HashEntryTy,
HashFunctionTy,
EntryFactoryTy>::const_chain_iterator
HashTable<HashEntryTy, HashFunctionTy, EntryFactoryTy>::end(
const typename HashTable<HashEntryTy,
HashFunctionTy,
EntryFactoryTy>::key_type& pKey) const {
return const_chain_iterator();
}