// Emacs: -*- C++ -*-

//
//	Copyright 1993, Center for Computer Vision and Visualization,
//	University of Florida.  All rights reserved.
//

#ifndef IA_NO_RCS_STATIC_DATA
static char copyright[] = "Copyright 1993, Center for Computer Vision and Visualization,\nUniversity of Florida.  All rights reserved.\n";

static char rcsid[] = "$Id: HashTable.c,v 1.12 1994/11/10 19:53:56 ljr Exp thoth $";
#endif

// 
// $Log: HashTable.c,v $
// Revision 1.12  1994/11/10  19:53:56  ljr
// Added IA_NO_RCS_STATIC_DATA guard.
//
// Revision 1.11  1994/11/10  19:51:27  fjsoria
// blah
//
// Revision 1.10  1994/10/06  17:39:00  fjsoria
// commented rscid[] line
//
// Revision 1.9  1994/01/31  16:36:55  thoth
// We now document internal errors when they occur.
//
// Revision 1.8  1993/05/28  15:05:25  thoth
// removed dependency on with-ia-pointset*
//
// Revision 1.7  93/05/27  18:05:06  thoth
// eliminated dependency on internal testing file.
// 
// Revision 1.6  93/05/26  16:57:42  thoth
// Copyright Notices
// 
// Revision 1.5  93/02/12  16:21:21  thoth
// more comments
// 
// Revision 1.4  92/12/16  14:48:03  thoth
// conversion to IA_ mostly complete
// 
// Revision 1.3  92/09/14  10:09:36  thoth
// the hash table data pointers are now the responsibility of IntPointSet
// 
// Revision 1.2  92/08/26  13:42:45  thoth
// eliminated cruft to work around g++ brokenness
// 
// Revision 1.1  92/08/23  13:30:04  thoth
// Initial revision
// 
// 
#ifdef IA_PRII
#pragma implementation "HashTable.h"
#endif

#include <stdlib.h>
#include "HashTable.h"

IA_HashTable::IA_HashTable() {
    for (int i=0; i<TBLSIZE; i++)
	this->buckets[i] = 0;
}
IA_HashTable::~IA_HashTable() {
    for (int i=0; i<TBLSIZE; i++) {
	link *scan=this->buckets[i];
	while (scan) {
	    link *temp = scan;
	    scan = scan->next;
	    delete temp;
	}
    }
}

int IA_HashTable::reference(HType in, HType *out)
{
    *out = in;

    link	**scan;

    for (scan = &this->buckets[in->hash_self(TBLSIZE)];
	 *scan && !(*scan)->data->equal(in);
	 scan = &(*scan)->next) {
    }

    if (*scan) {
	// we found an ->equal()
	*out = (*scan)->data;
	return 1;
    } else {
	// there are none ->equal()
	*scan = new link;
	(*scan)->next = 0;
	(*scan)->data = in;
	return 0;
    }
}

void IA_HashTable:: remove(HType in)
{
    link	**target;

    for (target = &this->buckets[in->hash_self(TBLSIZE)];
	 *target && (*target)->data != in;
	 target = &(*target)->next) {
    }

    link	*temp;
    temp = *target;

    if (temp==0) {
	IA::internal_error(__FILE__, __LINE__);
    }

    *target = temp->next;
    // the data is not our responsibility
    delete temp;
}

void IA_HashTable::print(ostream &o) const
{
    int	start, end;
    start =0;

    while (start<TBLSIZE) {
	for (end=start; end<TBLSIZE && buckets[end]==0; end++)
	    ;
	if (end>start+1) {
	    o << "buckets " << start << " through " << end-1 << " are empty\n";
	} else if (end>start) {
	    o << "bucket " << start << " is empty\n";
	}
	if (end<TBLSIZE) {
	    o << "bucket " << end << " has:\n";
	    link *scan = buckets[end];
	    while (scan) {
		o << "   pointset: " << hex << long(scan->data) << "\n";
		scan->data->output(o,8);
		scan = scan->next;
	    }
	    o<< "    end of bucket "<<end<<"\n";
	}
	start = end+1;
    }
}
