home *** CD-ROM | disk | FTP | other *** search
- /*---------------------------------------------------------------------------
- *
- * Copyright (c) 1991 by Westmount Technology B.V., Delft, The Netherlands.
- *
- * This software is furnished under a license and may be used only in
- * accordance with the terms of such license and with the inclusion of
- * the above copyright notice. This software or any other copies thereof
- * may not be provided or otherwise made available to any other person.
- * No title to and ownership of the software is hereby transferred.
- *
- * The information in this software is subject to change without notice
- * and should not be construed as a commitment by Westmount Technology B.V.
- *
- *---------------------------------------------------------------------------
- *
- * File : @(#)HashTbl.cxx 1.2 (1.5) (1.2)
- * Author : sipi (original by K.E. Gorlen)
- * Original date : Wed Apr 15 15:39:04 MET DST 1992
- * Description : implementation of hash tables
- *
- *---------------------------------------------------------------------------
- */
- static const char SccsId[]="@(#)HashTbl.cxx 1.2 (1.5) (1.2) 11 Nov 1993 Copyright 1991 Westmount Technology";
-
- #ifndef HASHTBL_HXX
- #include <HashTbl.hxx>
- #endif
- #include <iostream.h>
- Hashable::~Hashable() {}
-
- #if ! HAS_TEMPLATES
- implement(FlexArray,hashptr);
- #endif
-
- unsigned HashTbl::DEFAULT_SIZE = 64;
- unsigned HashTbl::EXPANSION_FACTOR = 2;
-
- HashTbl::HashTbl(unsigned size):
- contents(setCapacity(size))
- {
- contents.clear(0);
- }
-
- HashTbl::HashTbl(const HashTbl& tbl):
- count (tbl.count),
- nbits (tbl.nbits),
- mask (tbl.mask),
- current (tbl.current),
- contents (tbl.contents)
- { /* empty */ }
-
- HashTbl::~HashTbl()
- { /* empty */ }
-
- HashTbl&
- HashTbl::operator=(const HashTbl& tbl)
- {
- count = tbl.count;
- nbits = tbl.nbits;
- mask = tbl.mask;
- current = tbl.current;
- contents = tbl.contents;
- return *this;
- }
-
- Hashable*
- HashTbl::add(Hashable& object)
- {
- register int i = findIndexOf(object);
- if ( contents.at(i) ) return contents.at(i);
- contents.at(i) = &object;
- if (++count > capacity()) reSize(capacity()*HashTbl::EXPANSION_FACTOR);
- return &object;
- }
-
- void
- HashTbl::addAll(const HashTbl& tbl)
- {
- register unsigned n = tbl.contents.capacity();
- for (register int i = 0; i < n; i++)
- if ( tbl.contents.at(i) ) add( *(tbl.contents.at(i)) );
- }
-
- Hashable*
- HashTbl::remove(const Hashable& object)
- /* Algorithm R, Knuth Vol. 3 p. 527 */
- {
- register int i = findIndexOf(object);
- Hashable* rob = contents.at(i);
- if (!rob) /* object does not exist */ return 0;
- register int j,r;
- while (1) {
- contents.at(j=i) = 0;
- do {
- i = (i-1)&mask;
- if (contents.at(i)==0) {
- count--;
- return rob;
- }
- r = getIndex(contents.at(i)->hash());
- } while ((i<=r&&r<j) || (r<j&&j<i) || (j<i&&i<=r));
- contents.at(j) = contents.at(i);
- }
- }
-
- void
- HashTbl::removeAll()
- {
- contents.clear(0);
- count = 0;
- }
-
- void
- HashTbl::removeAll(const HashTbl& tbl)
- {
- register unsigned n = tbl.contents.capacity();
- for (register int i = 0; i < n; i++)
- if ( tbl.contents.at(i) ) remove( *(tbl.contents.at(i)) );
- }
-
- void
- HashTbl::destructAll()
- {
- register unsigned n = contents.capacity();
- for (register int i = 0; i < n; i++)
- if (contents.at(i)) {
- hashptr tmp = contents.at(i);
- delete tmp;
- }
- contents.clear(0);
- count = 0;
- }
-
- int
- HashTbl::operator==(const HashTbl& tbl) const
- {
- if (count!=tbl.count) return 0;
- register unsigned n = contents.capacity();
- for (register int i=0; i<n; i++) {
- if (contents.at(i) &&
- tbl.contents.at(findIndexOf( *(contents.at(i)) )) == 0 )
- return 0;
- }
- return 1;
- }
-
- Hashable*
- HashTbl::first()
- {
- if(count == 0) return 0;
- register unsigned n = contents.capacity();
- for (current=0; current<n; current++)
- if (contents.at(current)) return contents.at(current);
- return 0;
- }
-
- Hashable*
- HashTbl::next()
- {
- register unsigned n = contents.capacity();
- for (++current;current<n; current++)
- if (contents.at(current)) return contents.at(current);
- return 0;
- }
-
- unsigned
- HashTbl::setCapacity(unsigned size)
- {
- if (size==0) /* error but ignore it */ size++;
- current = 0;
- count = 0;
- nbits = 0;
- for (register unsigned s=size; s!=0; s>>=1) nbits++;
- if ((size&(size-1)) != 0) nbits++; // round up if not power of 2
- size = 1<<nbits;
- mask = size-1;
- return size; // return hash table size
- }
-
- int
- HashTbl::getIndex(unsigned long K) const
- /* Knuth Vol. 3, Section 6.4, pp. 508-512 */
- {
- const unsigned long Aw = 0x9E3779B9;
- // const unsigned long Aw = 2654435769UL;
- // const unsigned long Aw = 40503; use for 16 bit machines?
- return ((Aw*K)>>((8*sizeof(unsigned))-nbits)) & mask;
- }
-
- int
- HashTbl::findIndexOf(const Hashable& object) const
- /* Algorithm L, Knuth Vol. 3, p. 519 */
- {
- register int i;
- for (i = getIndex(object.hash()); contents.at(i)!=0; i = (i-1)&mask)
- if ((contents.at(i))->isEqual(object)) return i;
- return i;
- }
-
- void
- HashTbl::reSize(unsigned new_size)
- {
- if (new_size <= count) return;
- if (count > 0) {
- hashList tmp = contents;
- contents.reSize(setCapacity(new_size));
- contents.clear(0);
- unsigned n = tmp.capacity();
- for (int i=0; i < n; i++) {
- if (tmp.at(i)) add( *(tmp.at(i)) );
- }
- }
- else contents.reSize(setCapacity(new_size));
- }
-
- hash_iter::hash_iter(const HashTbl& t) :
- tbl(t),
- curr_idx(-1)
- {
- rewind();
- }
-
- hash_iter::~hash_iter()
- {
- /* empty */
- }
-
- void hash_iter::rewind(void)
- {
- if (tbl.size() == 0) {
- curr_idx = -1;
- return;
- }
- register unsigned n = tbl.contents.capacity();
- for(curr_idx = 0; curr_idx < n; curr_idx++) {
- if (tbl.at(curr_idx))
- return;
- }
- curr_idx = -1;
- }
-
- void hash_iter::advance(void)
- {
- if ( end_of_iteration() )
- return;
-
- register unsigned n = tbl.contents.capacity();
- for (++curr_idx; curr_idx < n; curr_idx++) {
- if (tbl.at(curr_idx))
- return;
- }
- curr_idx = -1;
- }
-