blob: 86fef24ad89e8c2d92f596847d04573cb4e6d779 [file] [log] [blame]
/* ------------------------------------------------------------------
* Copyright (C) 1998-2009 PacketVideo
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied.
* See the License for the specific language governing permissions
* and limitations under the License.
* -------------------------------------------------------------------
*/
// -*- c++ -*-
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
// H A S H T A B L E C L A S S
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
#ifndef HASHTABLE_H
#define HASHTABLE_H
// - - Inclusion - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#include "sorted_list.h"
#include "hash_functions.h"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
template <class keyclass, class hashclass> struct HashListElement;
template <class keyclass, class hashclass> int
operator==(const HashListElement<keyclass, hashclass>& a,
const HashListElement<keyclass, hashclass>& b)
{
return ((a.fullkey == b.fullkey) && (a.data == b.data));
}
template <class keyclass, class hashclass> struct HashListElement
{
keyclass fullkey;
hashclass data;
// #if defined( PV_OS_HPUX )
// friend int operator==
// ( HashListElement<keyclass,hashclass> &a,
// HashListElement<keyclass,hashclass> &b );
// #else
friend int operator==<keyclass, hashclass>
(const HashListElement<keyclass, hashclass> & a,
const HashListElement<keyclass, hashclass> & b);
// #endif
};
/*
template <class keyclass, class hashclass> int
operator==( const HashListElement<keyclass,hashclass>& a,
const HashListElement<keyclass,hashclass>& b)
{
return ((a.fullkey == b.fullkey) && (a.data == b.data));
}
*/
template <class keyclass, class hashclass> int
operator<(const HashListElement<keyclass, hashclass>& a,
const HashListElement<keyclass, hashclass>& b)
{
return ((a.fullkey < b.fullkey));
}
template <class keyclass, class hashclass> int
operator<=(const HashListElement<keyclass, hashclass>& a,
const HashListElement<keyclass, hashclass>& b)
{
return ((a.fullkey <= b.fullkey));
}
template <class keyclass, class hashclass> int
operator>(const HashListElement<keyclass, hashclass>& a,
const HashListElement<keyclass, hashclass>& b)
{
return ((a.fullkey > b.fullkey));
}
template <class keyclass, class hashclass> int
operator>=(const HashListElement<keyclass, hashclass>& a,
const HashListElement<keyclass, hashclass>& b)
{
return ((a.fullkey >= b.fullkey));
}
template <class keyclass, class hashclass> class HashTable
{
public:
HashTable(int in_hash_table_size);
~HashTable();
int is_unique(const keyclass& fullkey);
int add_element(const keyclass& fullkey, const hashclass& data);
int add_element(uint32 key, const keyclass& fullkey, const hashclass& data);
int remove_element(uint32 key, const keyclass& fullkey);
int remove_element(const keyclass& fullkey);
int get_element(uint32 key, const keyclass& fullkey, hashclass& data);
int get_element(const keyclass& fullkey, hashclass& data);
int get_element(int index, uint32& key, keyclass& fullkey,
hashclass& data);
int get_num_elements()
{
return num_elements;
};
private:
SortedList<HashListElement<keyclass, hashclass> >* hash_table;
uint32 hash_mask;
uint32 hash_table_size;
int num_elements;
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
template <class keyclass, class hashclass> int HashTable<keyclass, hashclass>::is_unique(const keyclass& key)
{
HashListElement<keyclass, hashclass> tmp;
uint32 hash = compute_hash(key);
uint32 masked_hash = hash & hash_mask;
int list_elements = hash_table[masked_hash].get_num_elements();
for (int ii = 0; ii < list_elements; ++ii)
{
hash_table[masked_hash].get_element(ii, tmp);
// if (tmp.key == key)
if (tmp.fullkey == key)
return 0;
}
return 1;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
template <class keyclass, class hashclass>
int HashTable<keyclass, hashclass>::add_element(const keyclass& fullkey,
const hashclass& data)
{
uint32 key = compute_hash(fullkey);
return add_element(key, fullkey, data);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
template <class keyclass, class hashclass>
int HashTable<keyclass, hashclass>::add_element(uint32 key,
const keyclass& fullkey,
const hashclass& data)
{
HashListElement<keyclass, hashclass> tmp;
uint32 masked_key = key & hash_mask;
tmp.fullkey = fullkey;
tmp.data = data;
hashclass tmp2;
if (get_element(fullkey, tmp2))
{
// bark - hash table corruption
//#define HASH_CORRUPTION_DEBUG 1
return 0;
}
hash_table[masked_key].add_element(tmp);
++num_elements;
return 1;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
template <class keyclass, class hashclass>
int HashTable<keyclass, hashclass>::remove_element(const keyclass& fullkey)
{
uint32 key = compute_hash(fullkey);
return remove_element(key, fullkey);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
template <class keyclass, class hashclass>
int HashTable<keyclass, hashclass>::remove_element(uint32 key,
const keyclass& fullkey)
{
HashListElement<keyclass, hashclass> tmp;
uint32 masked_key = key & hash_mask;
int list_elements = hash_table[masked_key].get_num_elements();
for (int ii = 0; ii < list_elements; ++ii)
{
hash_table[masked_key].get_element(ii, tmp);
if (tmp.fullkey == fullkey)
{
hash_table[masked_key].remove_element(tmp);
--num_elements;
return 1;
}
else if (tmp.fullkey > fullkey)
{
return 0;
}
}
return 0;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
template <class keyclass, class hashclass>
int HashTable<keyclass, hashclass>::get_element(const keyclass& fullkey,
hashclass& data)
{
uint32 key = compute_hash(fullkey);
return get_element(key, fullkey, data);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
template <class keyclass, class hashclass>
int HashTable<keyclass, hashclass>::get_element(uint32 key,
const keyclass& fullkey,
hashclass& data)
{
HashListElement<keyclass, hashclass> tmp;
uint32 masked_key = key & hash_mask;
int list_elements = hash_table[masked_key].get_num_elements();
for (int ii = 0; ii < list_elements; ++ii)
{
hash_table[masked_key].get_element(ii, tmp);
if (tmp.fullkey == fullkey)
{
data = tmp.data;
return 1;
}
else if (tmp.fullkey > fullkey)
{
return 0;
}
}
return 0;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
template <class keyclass, class hashclass>
int HashTable<keyclass, hashclass>::get_element(int index,
uint32& key, keyclass& fullkey,
hashclass& data)
{
HashListElement<keyclass, hashclass> tmp;
unsigned int hash_idx;
if (index < 0 || index >= num_elements)
return 0;
// find the proper hash element
for (hash_idx = 0; hash_idx < hash_table_size; ++hash_idx)
{
if (index < hash_table[hash_idx].get_num_elements())
break;
index -= hash_table[hash_idx].get_num_elements();
}
assert(index >= 0);
if (!hash_table[hash_idx].get_element(index, tmp))
return 0;
data = tmp.data;
key = compute_hash(tmp.fullkey);
fullkey = tmp.fullkey;
return 1;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
template <class keyclass, class hashclass> HashTable<keyclass, hashclass>::HashTable(int in_hash_table_size)
{
hash_mask = in_hash_table_size - 1;
hash_table_size = in_hash_table_size;
if (hash_mask & in_hash_table_size)
{
int tmp, cnt;
// find next larger power of two
for (tmp = in_hash_table_size, cnt = 0; tmp; tmp >>= 1, ++cnt);
hash_table_size = (1 << cnt);
hash_mask = hash_table_size - 1;
// bark - hash table size is not a power of two, changing
}
hash_table = new SortedList< HashListElement<keyclass, hashclass> >[hash_table_size];
num_elements = 0;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
template <class keyclass, class hashclass> HashTable<keyclass, hashclass>::~HashTable()
{
delete[] hash_table;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
template <class keyclass, class hashclass> class MTHashTable
{
public:
MTHashTable(int in_hash_table_size);
~MTHashTable();
int is_unique(const keyclass& fullkey);
int add_element(const keyclass& fullkey, const hashclass& data);
int add_element(uint32 key, const keyclass& fullkey, const hashclass& data);
int remove_element(uint32 key, const keyclass& fullkey);
int remove_element(const keyclass& fullkey);
int get_element(uint32 key, const keyclass& fullkey, hashclass& data);
int get_element(const keyclass& fullkey, hashclass& data);
int get_element(int index, uint32& key, keyclass& fullkey,
hashclass& data);
int get_num_elements()
{
if (the_hash)
{
return the_hash->get_num_elements();
}
return 0;
};
private:
HashTable<keyclass, hashclass> *the_hash;
PVMutex mutex;
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
template <class keyclass, class hashclass> int MTHashTable<keyclass, hashclass>::is_unique(const keyclass& key)
{
int status;
mutex.Lock();
status = the_hash->is_unique(key);
mutex.Unlock();
return status;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
template <class keyclass, class hashclass>
int MTHashTable<keyclass, hashclass>::add_element(const keyclass& fullkey,
const hashclass& data)
{
int status;
mutex.Lock();
status = the_hash->add_element(fullkey, data);
mutex.Unlock();
return status;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
template <class keyclass, class hashclass>
int MTHashTable<keyclass, hashclass>::add_element(uint32 key,
const keyclass& fullkey,
const hashclass& data)
{
int status;
mutex.Lock();
status = the_hash->add_element(key, fullkey, data);
mutex.Unlock();
return status;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
template <class keyclass, class hashclass>
int MTHashTable<keyclass, hashclass>::remove_element(const keyclass& fullkey)
{
int status;
mutex.Lock();
status = the_hash->remove_element(fullkey);
mutex.Unlock();
return status;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
template <class keyclass, class hashclass>
int MTHashTable<keyclass, hashclass>::remove_element(uint32 key,
const keyclass& fullkey)
{
int status;
mutex.Lock();
status = the_hash->remove_element(key, fullkey);
mutex.Unlock();
return status;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
template <class keyclass, class hashclass>
int MTHashTable<keyclass, hashclass>::get_element(const keyclass& fullkey,
hashclass& data)
{
int status;
mutex.Lock();
status = the_hash->get_element(fullkey, data);
mutex.Unlock();
return status;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
template <class keyclass, class hashclass>
int MTHashTable<keyclass, hashclass>::get_element(uint32 key,
const keyclass& fullkey,
hashclass& data)
{
int status;
mutex.Lock();
status = the_hash->get_element(key, fullkey, data);
mutex.Unlock();
return status;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
template <class keyclass, class hashclass>
int MTHashTable<keyclass, hashclass>::get_element(int index,
uint32& key, keyclass& fullkey,
hashclass& data)
{
int status;
mutex.Lock();
status = the_hash->get_element(index, key, fullkey, data);
mutex.Unlock();
return status;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
template <class keyclass, class hashclass> MTHashTable<keyclass, hashclass>::MTHashTable(int in_hash_table_size)
{
the_hash = OSCL_NEW(HashTable<keyclass, hashclass>, (in_hash_table_size));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
template <class keyclass, class hashclass> MTHashTable<keyclass, hashclass>::~MTHashTable()
{
OSCL_DELETE(the_hash);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#endif // HASHTABLE_H