/* -*-Mode: C++;-*-
* PRCS - The Project Revision Control System
* Copyright (C) 1997 Josh MacDonald
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id: hash.cc 1.2.1.1.1.3.2.13 Sat, 30 Oct 1999 20:28:32 -0700 jmacd $
*/
#include "hash.h"
#include "config.h"
#include <string.h>
class FileEntry;
class PrcsAttrs;
template <class T>
List<T>* List<T>::nreverse()
{
List<T> *point, *prev, *next;
if(tail() == NULL)
return this;
prev = this;
point = tail();
next = tail()->tail();
while(true){
point->tail() = prev;
if ( next == NULL )
{
this->tail() = next;
return point;
}
prev = point;
point = next;
next = next->tail();
}
}
static const int primes[] = {
23, 47, 101, 211, 431, 863, 1733, 3467, 6949, 13901, 27803, 55609,
11239, 22481, 44963, 89939, 199999, 400009, 800029, 1600061,
16000627, 160006271};
const int NUM_PRIMES = sizeof(primes) / sizeof(primes[0]);
bool equal(const unsigned long long& x, const unsigned long long& y) {
return x == y;
}
bool equal(const long long& x, const long long& y) {
return x == y;
}
bool equal(const unsigned long& x, const unsigned long& y) {
return x == y;
}
bool equal(const unsigned int& x, const unsigned int& y) {
return x == y;
}
bool equal(const int& x, const int& y) {
return x == y;
}
bool equal(const char*const& x, const char*const& y) {
return strcmp(x, y) == 0;
}
bool equal(FileEntry*const& x, FileEntry*const& y) {
return x == y;
}
extern bool attrs_equal(const PrcsAttrs*const& x, const PrcsAttrs*const& y);
extern int attrs_hash(const PrcsAttrs*const& s, int M);
bool equal(const PrcsAttrs*const& x, const PrcsAttrs*const& y) {
return attrs_equal (x, y);
}
int hash(const PrcsAttrs*const& x, int M)
{
return attrs_hash (x, M);
}
int hash(const char *const & s, int M)
/* a char* hash function from Aho, Sethi, and Ullman */
{
const char *p;
unsigned int h(0), g;
for(p = s; *p != '\0'; p += 1) {
h = ( h << 4 ) + *p;
if ( ( g = h & 0xf0000000 ) ) {
h = h ^ (g >> 24);
h = h ^ g;
}
}
return h % M;
}
int hash(const int& x, int M)
{
return (unsigned int)x % M;
}
static int hash(const long long& x, int M)
{
return (long long)x % M;
}
static int hash(const unsigned long long& x, int M)
{
return (unsigned long long)x % M;
}
int hash(const unsigned long& x, int M)
{
return (unsigned long)x % M;
}
int hash(const unsigned int& x, int M)
{
return (unsigned int)x % M;
}
int hash(FileEntry*const& x, int M)
{
return (unsigned int)x % M;
}
#define generic template<class Key, class Data>
#define selftype HashTable<Key, Data>
#define member selftype::
generic void member init(int p)
/* Used to initialize a HashTable to be empty and with primes[p] */
/* buckets. */
{
N = 0;
prime = p;
M = primes[p];
L = new ItemList*[primes[p]];
for (int i = 0; i < M; i += 1)
L[i] = NULL;
}
generic member HashTable(int (*func0)(const Key&, int),
bool (*equal0)(const Key&, const Key&))
/* An empty HashTable. */
{
if(func0 == NULL) {
func = hash;
} else {
func = func0;
}
if(equal0 == NULL) {
equalfunc = equal;
} else {
equalfunc = equal0;
}
init(0);
}
generic member ~HashTable()
{
for (int i = 0; i < M; i += 1)
for (i=0; i < M; i += 1)
if (L[i] != NULL)
L[i]->deleteList();
delete [] L;
}
generic Data* member find(const Key& x, int hashValue) const
/* Internal routine to find a Data item on L[hashValue]. */
{
ItemList* p = L[hashValue];
while (p != NULL) {
if(equalfunc(x, p->head().x()))
break;
p = p->tail();
}
if (p == NULL)
return NULL;
else
return & p->head().y();
}
generic Data* member lookup(const Key& x) const
{
return find(x, func(x, M));
}
generic void member remove(const Key& x)
{
int hashValue = func (x, M);
ItemList* p = L[hashValue];
if (equalfunc (x, p->head().x())) {
L[hashValue] = p->tail();
delete p;
return;
}
for (; p && p->tail(); p = p->tail()) {
if(equalfunc (x, p->tail()->head().x())) {
ItemList* tmp = p->tail();
p->tail() = p->tail()->tail();
delete tmp;
return;
}
}
}
generic Pair<Key, Data>* member lookup_pair(const Key& x) const
{
int hashValue = func (x, M);
ItemList* p = L[hashValue];
while (p != NULL) {
if(equalfunc(x, p->head().x()))
break;
p = p->tail();
}
if (p == NULL)
return NULL;
else
return &p->head();
}
generic Data* member insert(const Key& x, const Data& init)
/* A pointer to the Data object currently hashed to by x. If there */
/* currently is none, adds an entry from x to a new Data object */
/* initialized with init, and returns a pointer to that new object. */
{
int h = func(x, M);
Data *dp = find(x, h);
if (dp == NULL) {
L[h] = new ItemList(HashItem(x, init), L[h]);
N += 1;
if (2*M < N && prime+1 < NUM_PRIMES) {
ItemList** bucketPointer(L);
ItemList* listPointer;
int newM = primes[prime + 1], j;
ItemList** tmp = new ItemList*[newM];
for ( j = 0; j < newM ; j += 1 )
tmp[j] = NULL;
while ( bucketPointer < L + M ) {
listPointer = *bucketPointer;
while (listPointer != NULL) {
int h = func(listPointer->head().x(), newM);
tmp[h] = new ItemList(HashItem(listPointer->head().x(),
listPointer->head().y()),
tmp[h]);
listPointer = listPointer->tail();
}
bucketPointer += 1;
}
for ( j=0; j < M; j += 1 )
if (L[j] != NULL)
L[j]->deleteList();
delete [] L;
L = tmp;
M = newM;
prime += 1;
return lookup(x);
}
else
return & L[h]->head().y();
} else
*dp = init;
return dp;
}
#undef member
#undef selftype
#undef generic
#define generic template<class Key, class Data>
#define selftype OrderedTable<Key, Data>
#define member selftype::
generic member ~OrderedTable ()
{
delete _key_array;
delete _data_array;
delete _table;
}
generic member OrderedTable ()
{
_key_array = new KeyArray;
_data_array = new DataArray;
_table = new Table;
}
generic Data* member insert(const Key& x, const Data& init)
{
remove (x);
_key_array->append (x);
_data_array->append (init);
return _table->insert (x, init);
}
generic Data* member lookup(const Key& x) const
{
return table()->lookup (x);
}
generic void member remove(const Key& x)
{
if (lookup (x)) {
for (int i = 0; i < _key_array->length(); i += 1) {
if (equal (x, _key_array->index(i))) {
for (int j = i; j < _key_array->length()-1; j += 1) {
_key_array->index(j, _key_array->index(j+1));
_data_array->index(j, _data_array->index(j+1));
}
_key_array->truncate (_key_array->length() - 1);
_data_array->truncate (_data_array->length() - 1);
break;
}
}
_table->remove (x);
}
}
generic HashTable<Key, Data>* member table() const { return _table; }
generic Dynarray<Key, 64, false>* member key_array() const { return _key_array; }
generic Dynarray<Data, 64, false>* member data_array() const { return _data_array; }
#undef member
#undef selftype
#undef generic
#if EXPLICIT_TEMPLATES
#include "hash.tl"
#endif
syntax highlighted by Code2HTML, v. 0.9.1