360 lines
8.5 KiB
C++
360 lines
8.5 KiB
C++
|
/*******************************************************************************
|
||
|
* Simplified Wrapper and Interface Generator (SWIG)
|
||
|
*
|
||
|
* Author : David Beazley
|
||
|
*
|
||
|
* Department of Computer Science
|
||
|
* University of Chicago
|
||
|
* 1100 E 58th Street
|
||
|
* Chicago, IL 60637
|
||
|
* beazley@cs.uchicago.edu
|
||
|
*
|
||
|
* Please read the file LICENSE for the copyright and terms by which SWIG
|
||
|
* can be used and distributed.
|
||
|
*******************************************************************************/
|
||
|
|
||
|
#include "internal.h"
|
||
|
|
||
|
/*******************************************************************************
|
||
|
* $Header$
|
||
|
*
|
||
|
* File : hash.cxx
|
||
|
*
|
||
|
* A very simple Hash table class. Could probably make it more elegant with
|
||
|
* templates, but templates are pure evil...
|
||
|
*******************************************************************************/
|
||
|
|
||
|
#define INIT_SIZE 119
|
||
|
|
||
|
// -----------------------------------------------------------------------------
|
||
|
// Hash::Hash()
|
||
|
//
|
||
|
// Constructor. Creates a new hash table.
|
||
|
//
|
||
|
// Inputs : None
|
||
|
//
|
||
|
// Output : New Hash object.
|
||
|
//
|
||
|
// Side Effects : None
|
||
|
// -----------------------------------------------------------------------------
|
||
|
|
||
|
Hash::Hash() {
|
||
|
int i;
|
||
|
hashsize = INIT_SIZE;
|
||
|
hashtable = new Node *[hashsize];
|
||
|
for (i = 0; i < hashsize; i++) {
|
||
|
hashtable[i] = 0;
|
||
|
}
|
||
|
index = -1;
|
||
|
current = 0;
|
||
|
}
|
||
|
|
||
|
// -----------------------------------------------------------------------------
|
||
|
// Hash::~Hash()
|
||
|
//
|
||
|
// Destructor.
|
||
|
//
|
||
|
// Inputs : None
|
||
|
//
|
||
|
// Output : None
|
||
|
//
|
||
|
// Side Effects : Total destruction.
|
||
|
// -----------------------------------------------------------------------------
|
||
|
|
||
|
Hash::~Hash() {
|
||
|
int i;
|
||
|
Node *n,*next;
|
||
|
|
||
|
for (i = 0; i < hashsize; i++) {
|
||
|
if (hashtable[i]) {
|
||
|
n = hashtable[i];
|
||
|
while (n) {
|
||
|
next = n->next;
|
||
|
delete n;
|
||
|
n = next;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
delete [] hashtable;
|
||
|
}
|
||
|
|
||
|
// -----------------------------------------------------------------------------
|
||
|
// int Hash::h1(const char *key)
|
||
|
//
|
||
|
// Hashing function.
|
||
|
//
|
||
|
// Inputs : ASCII character string.
|
||
|
//
|
||
|
// Output : Hash table index.
|
||
|
//
|
||
|
// Side Effects : None
|
||
|
// -----------------------------------------------------------------------------
|
||
|
|
||
|
int Hash::h1(const char *key) {
|
||
|
int h = 0;
|
||
|
const char *c;
|
||
|
|
||
|
c = key;
|
||
|
while (*c) {
|
||
|
h = (128*h + *c) % hashsize;
|
||
|
c++;
|
||
|
}
|
||
|
return h;
|
||
|
}
|
||
|
|
||
|
// -----------------------------------------------------------------------------
|
||
|
// int Hash::add(const char *k, void *obj)
|
||
|
//
|
||
|
// Adds a new object to the hash table.
|
||
|
//
|
||
|
// Inputs :
|
||
|
// k = Hash key
|
||
|
// obj = Pointer to an object
|
||
|
//
|
||
|
// Output : 0 on success, -1 if item is already in hash table.
|
||
|
//
|
||
|
// Side Effects :
|
||
|
// Makes a new hash table entry.
|
||
|
// -----------------------------------------------------------------------------
|
||
|
|
||
|
int Hash::add(const char *k, void *obj) {
|
||
|
|
||
|
int hv;
|
||
|
Node *n,*prev;
|
||
|
|
||
|
hv = h1(k); // Get hash value
|
||
|
n = hashtable[hv];
|
||
|
prev = n;
|
||
|
while (n) {
|
||
|
if (strcmp(n->key,k) == 0) return -1; // Already in hash table
|
||
|
prev = n;
|
||
|
n = n->next;
|
||
|
}
|
||
|
|
||
|
// Safe to add this to the table
|
||
|
|
||
|
n = new Node(k,obj,0);
|
||
|
if (prev) prev->next = n;
|
||
|
else hashtable[hv] = n;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
// -----------------------------------------------------------------------------
|
||
|
// int Hash::add(const char *k, void *obj, void (*d)(void *))
|
||
|
//
|
||
|
// Adds a new object to the hash table. Allows additional specification of
|
||
|
// a callback function for object deletion.
|
||
|
//
|
||
|
// Inputs :
|
||
|
// k = Hash key
|
||
|
// obj = Object pointer
|
||
|
// d = Deletion function
|
||
|
//
|
||
|
// Output : 0 on success, -1 if item is already in hash table.
|
||
|
//
|
||
|
// Side Effects :
|
||
|
// Adds an entry to the hash table
|
||
|
// -----------------------------------------------------------------------------
|
||
|
|
||
|
int Hash::add(const char *k, void *obj, void (*d)(void *)) {
|
||
|
|
||
|
int hv;
|
||
|
Node *n,*prev;
|
||
|
|
||
|
hv = h1(k); // Get hash value
|
||
|
n = hashtable[hv];
|
||
|
prev = n;
|
||
|
while (n) {
|
||
|
if (strcmp(n->key,k) == 0) return -1; // Already in hash table
|
||
|
prev = n;
|
||
|
n = n->next;
|
||
|
}
|
||
|
|
||
|
// Safe to add this to the table
|
||
|
|
||
|
n = new Node(k,obj,d);
|
||
|
if (prev) prev->next = n;
|
||
|
else hashtable[hv] = n;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
// -----------------------------------------------------------------------------
|
||
|
// void *Hash::lookup(const char *k)
|
||
|
//
|
||
|
// Looks up a value in the hash table. Returns a pointer to the object if found.
|
||
|
//
|
||
|
// Inputs : k = key value
|
||
|
//
|
||
|
// Output : Pointer to object or NULL if not found.
|
||
|
//
|
||
|
// Side Effects : None
|
||
|
// -----------------------------------------------------------------------------
|
||
|
|
||
|
void *Hash::lookup(const char *k) {
|
||
|
int hv;
|
||
|
Node *n;
|
||
|
|
||
|
hv = h1(k); // Get hash value
|
||
|
n = hashtable[hv];
|
||
|
|
||
|
while (n) {
|
||
|
if (strcmp(n->key,k) == 0) return n->object;
|
||
|
n = n->next;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
// -----------------------------------------------------------------------------
|
||
|
// void Hash::remove(const char *k)
|
||
|
//
|
||
|
// Removes an item from the hash table. Does nothing if item isn't in the
|
||
|
// hash table to begin with.
|
||
|
//
|
||
|
// Inputs : k = Key value
|
||
|
//
|
||
|
// Output : None
|
||
|
//
|
||
|
// Side Effects : Deletes item from hash table.
|
||
|
// -----------------------------------------------------------------------------
|
||
|
|
||
|
void Hash::remove(const char *k) {
|
||
|
|
||
|
int hv;
|
||
|
Node *n,*prev;
|
||
|
|
||
|
hv = h1(k); // Get hash value
|
||
|
n = hashtable[hv];
|
||
|
prev = 0;
|
||
|
while (n) {
|
||
|
if (strcmp(n->key,k) == 0) {
|
||
|
// Found it, kill the thing
|
||
|
if (prev) {
|
||
|
prev->next = n->next;
|
||
|
} else {
|
||
|
hashtable[hv] = n->next;
|
||
|
}
|
||
|
delete n;
|
||
|
return;
|
||
|
}
|
||
|
prev = n;
|
||
|
n = n->next;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// -----------------------------------------------------------------------------
|
||
|
// void *Hash::first()
|
||
|
//
|
||
|
// Gets the first item from the hash table or NULL if empty.
|
||
|
//
|
||
|
// Inputs : None
|
||
|
//
|
||
|
// Output : First object in hash table or NULL if hash table is empty.
|
||
|
//
|
||
|
// Side Effects : Resets an internal iterator variable on the hash table.
|
||
|
// -----------------------------------------------------------------------------
|
||
|
|
||
|
void *Hash::first() {
|
||
|
index = 0;
|
||
|
current = 0;
|
||
|
|
||
|
while (!hashtable[index] && (index < hashsize))
|
||
|
index++;
|
||
|
|
||
|
if (index >= hashsize) return 0;
|
||
|
current = hashtable[index];
|
||
|
return current->object;
|
||
|
}
|
||
|
|
||
|
|
||
|
// -----------------------------------------------------------------------------
|
||
|
// char *Hash::firstkey()
|
||
|
//
|
||
|
// Gets the first key from the hash table or NULL if empty.
|
||
|
//
|
||
|
// Inputs : None
|
||
|
//
|
||
|
// Output : First key in hash table or NULL if hash table is empty.
|
||
|
//
|
||
|
// Side Effects : Resets an internal iterator variable on the hash table.
|
||
|
// -----------------------------------------------------------------------------
|
||
|
|
||
|
char *Hash::firstkey() {
|
||
|
index = 0;
|
||
|
current = 0;
|
||
|
|
||
|
while ((index < hashsize) && (!hashtable[index]))
|
||
|
index++;
|
||
|
|
||
|
if (index >= hashsize) return 0;
|
||
|
current = hashtable[index];
|
||
|
return current->key;
|
||
|
}
|
||
|
|
||
|
// -----------------------------------------------------------------------------
|
||
|
// void *Hash::next()
|
||
|
//
|
||
|
// Returns the next item in the hash table or NULL if there are no more entries.
|
||
|
// A call to first() should generally be made before using this function.
|
||
|
//
|
||
|
// Inputs : None
|
||
|
//
|
||
|
// Output : Pointer to next object or NULL if there are no more objects.
|
||
|
//
|
||
|
// Side Effects : Updates an iterator variable private to the hash table.
|
||
|
// -----------------------------------------------------------------------------
|
||
|
|
||
|
void *Hash::next() {
|
||
|
if (index < 0) return first();
|
||
|
|
||
|
// Try to move to the next entry
|
||
|
|
||
|
current = current->next;
|
||
|
|
||
|
if (current) {
|
||
|
return current->object;
|
||
|
} else {
|
||
|
index++;
|
||
|
while ((index < hashsize) && (!hashtable[index]))
|
||
|
index++;
|
||
|
if (index >= hashsize) return 0;
|
||
|
current = hashtable[index];
|
||
|
return current->object;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
// -----------------------------------------------------------------------------
|
||
|
// char *Hash::nextkey()
|
||
|
//
|
||
|
// Returns the next key in the hash table or NULL if there are no more entries.
|
||
|
// A call to firstkey() should generally be made before using this function.
|
||
|
//
|
||
|
// Inputs : None
|
||
|
//
|
||
|
// Output : Pointer to next key or NULL if there are no more objects.
|
||
|
//
|
||
|
// Side Effects : Updates an iterator variable private to the hash table.
|
||
|
// -----------------------------------------------------------------------------
|
||
|
|
||
|
char *Hash::nextkey() {
|
||
|
if (index < 0) return firstkey();
|
||
|
|
||
|
// Try to move to the next entry
|
||
|
|
||
|
current = current->next;
|
||
|
|
||
|
if (current) {
|
||
|
return current->key;
|
||
|
} else {
|
||
|
index++;
|
||
|
while (!hashtable[index] && (index < hashsize))
|
||
|
index++;
|
||
|
if (index >= hashsize) return 0;
|
||
|
current = hashtable[index];
|
||
|
return current->key;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|