/* -*-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 class FileEntry; class PrcsAttrs; template List* List::nreverse() { List *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 #define selftype HashTable #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* 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 #define selftype OrderedTable #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* member table() const { return _table; } generic Dynarray* member key_array() const { return _key_array; } generic Dynarray* member data_array() const { return _data_array; } #undef member #undef selftype #undef generic #if EXPLICIT_TEMPLATES #include "hash.tl" #endif