/**************************************************************************
 * Source Id :
 *
 * $Id: hash.cpp,v 1.3 2001/04/20 10:15:01 georgetasker Exp $
 *-------------------------------------------------------------------------
 * Project Notes :
 *
 *  Diamond Base
 *  ============
 *      A solid database implementation, spurred on by the continuing
 *  Metal (Lead) Base saga.
 *
 *  Project Team :
 *        A. Davison
 *        K. Lentin
 *        D. Platt
 *
 *	Project Commenced : 05-02-1993
 *
 *-------------------------------------------------------------------------
 *  Module Notes :
 *
 *  Simple hash table module hashes int->void *
 *
 *  Original Author : Darren Platt
 *
 **************************************************************************/

// FOR NOW::
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"

#ifdef __BORLANDC__
    #pragma hdrstop
#endif

//
// Hash table definition
//
#include <diamond/hash.h>

DiaHash::DiaHash(int f_numBuckets)
{
	int i;
	numBuckets = f_numBuckets;
	bucket = new DiaHashBucket * [numBuckets];

	for(i=0;i<numBuckets;i++) {
		bucket[i] = 0;
	}
}

DiaHash::~DiaHash()
{
	DiaHashBucket *t1,*t2;

	int i;
	for(i=0;i<numBuckets;i++) {
		t1 = bucket[i];
		while (t1) {
			t2 = t1->next;
			delete t1;
			t1 = t2;
		}
	}
	delete [] bucket;
}

int DiaHash::hashToBucket(int32 key)
{
	return key % numBuckets;
}

void * DiaHash::operator [] (int32 key)
{
	DiaHashBucket *bp = bucket[hashToBucket(key)];
	while(bp) {
		if (bp->value == key) return bp->ptr;
		bp = bp->next;
	}
	return 0;
}

void DiaHash::add(int32 key,void *ptr)
{
	DiaHashBucket **bpp = &bucket[hashToBucket(key)];

	// If it's already there, replace the existing ptr.
	while(*bpp) {
		if ((*bpp)->value == key) {
			(*bpp)->ptr = ptr;
			return;
		}
		bpp = &((*bpp)->next);
	}
	DiaHashBucket *np = new DiaHashBucket;
	np->value = key;
	np->ptr = ptr;
	np->next = 0;
	*bpp = np;
}

void DiaHash::del(int32 key)
{
	DiaHashBucket **bpp = &bucket[hashToBucket(key)];

	// If it's already there, remove it.
	while(*bpp) {
		if ((*bpp)->value == key) {
			DiaHashBucket *tmp = *bpp;
			*bpp = (*bpp)->next;
			delete tmp;
			return;
		}
		bpp = &((*bpp)->next);
	}
}

void *DiaHash::first(void)
{
	currBucket = 0;
	while (currBucket<numBuckets && !bucket[currBucket]) currBucket++;
	if (currBucket<numBuckets) {
		nextBucket = bucket[currBucket];
		return nextBucket->ptr;
	} else {
		return 0;
	}
}

void *DiaHash::next(void)
{
	nextBucket = nextBucket->next;
	if (nextBucket) {
		return nextBucket->ptr;
	}
	for(currBucket++;currBucket<numBuckets && !bucket[currBucket];
		currBucket++)
	{
	}

	if (currBucket<numBuckets) {
		nextBucket = bucket[currBucket];
		return nextBucket->ptr;
	} else {
		return 0;
	}
}

bool DiaHash::last(void)
{
	if (currBucket >= numBuckets) return true; else return false;
}

#ifdef TEST_HASH
#include <iostream.h>

main()
{
	char str1[] = "string one\n";
	char str2[] = "string two\n";
	char str3[] = "string three\n";
	char str4[] = "string four\n";
	char str5[] = "string five\n";

	DiaHash	hash(2);

	hash.add(1,str1);
	hash.add(2,str2);
	hash.add(3,str3);
	hash.add(4,str4);
	hash.add(5,str5);

	void *p;

	p = hash[1];
	cout << (char *)p << endl;
	p = hash[2];
	cout << (char *)p << endl;
	p = hash[3];
	cout << (char *)p << endl;
	p = hash[4];
	cout << (char *)p << endl;
	p = hash[5];
	cout << (char *)p << endl;


	for(p=hash.first();!hash.last();p=hash.next()) {
		cout << (char *)p;
	}
}

#endif

//
// $Log: hash.cpp,v $
// Revision 1.3  2001/04/20 10:15:01  georgetasker
// Cygwin compilation fixes, compilation speed enhancements
// Code modified to get rid of some compiler warnings
//
// Revision 1.2  2001/04/19 21:12:54  georgetasker
// cygwin compilation fixes
//
// Revision 1.1  2001/04/04 12:05:49  aleksandras
// forgotten diamond .cpps
//
// Revision 1.1  1996/02/01  22:22:28  dmb
// Initial revision
//
//
