You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
272 lines
9.2 KiB
272 lines
9.2 KiB
//===- 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();
|
|
}
|