diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 1995-10-18 08:53:40 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 1995-10-18 08:53:40 +0000 |
commit | d6583bb2a13f329cf0332ef2570eb8bb8fc0e39c (patch) | |
tree | ece253b876159b39c620e62b6c9b1174642e070e /gnu/lib/libg++/g++-include/gen/VHMap.ccP |
initial import of NetBSD tree
Diffstat (limited to 'gnu/lib/libg++/g++-include/gen/VHMap.ccP')
-rw-r--r-- | gnu/lib/libg++/g++-include/gen/VHMap.ccP | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/gnu/lib/libg++/g++-include/gen/VHMap.ccP b/gnu/lib/libg++/g++-include/gen/VHMap.ccP new file mode 100644 index 00000000000..b6129446606 --- /dev/null +++ b/gnu/lib/libg++/g++-include/gen/VHMap.ccP @@ -0,0 +1,215 @@ +// This may look like C code, but it is really -*- C++ -*- +/* +Copyright (C) 1988 Free Software Foundation + written by Doug Lea (dl@rocky.oswego.edu) + +This file is part of GNU CC. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY. No author or distributor +accepts responsibility to anyone for the consequences of using it +or for whether it serves any particular purpose or works at all, +unless he says so in writing. Refer to the GNU CC General Public +License for full details. + +Everyone is granted permission to copy, modify and redistribute +GNU CC, but only under the conditions described in the +GNU CC General Public License. A copy of this license is +supposed to have been given to you along with GNU CC so you +can know your rights and responsibilities. It should be in a +file named COPYING. Among other things, the copyright notice +and this notice must be preserved on all copies. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include "<T>.<C>.VHMap.h" + +/* codes for status fields */ + +#define EMPTYCELL 0 +#define VALIDCELL 1 +#define DELETEDCELL 2 + + +<T><C>VHMap::<T><C>VHMap(<C&> dflt, unsigned int sz) + :<T><C>Map(dflt) +{ + tab = new <T>[size = sz]; + cont = new <C>[size]; + status = new char[size]; + for (unsigned int i = 0; i < size; ++i) status[i] = EMPTYCELL; +} + +<T><C>VHMap::<T><C>VHMap(<T><C>VHMap& a) : <T><C>Map(a.def) +{ + tab = new <T>[size = a.size]; + cont = new <C>[size]; + status = new char[size]; + for (unsigned int i = 0; i < size; ++i) status[i] = EMPTYCELL; + count = 0; + for (Pix p = a.first(); p; a.next(p)) (*this)[a.key(p)] = a.contents(p); +} + + +/* + * hashing method: double hash based on high bits of hash fct, + * followed by linear probe. Can't do too much better if table + * sizes not constrained to be prime. +*/ + + +static inline unsigned int doublehashinc(unsigned int h, unsigned int s) +{ + unsigned int dh = ((h / s) % s); + return (dh > 1)? dh : 1; +} + +Pix <T><C>VHMap::seek(<T&> key) +{ + unsigned int hashval = <T>HASH(key); + unsigned int h = hashval % size; + for (unsigned int i = 0; i <= size; ++i) + { + if (status[h] == EMPTYCELL) + return 0; + else if (status[h] == VALIDCELL && <T>EQ(key, tab[h])) + return Pix(&tab[h]); + if (i == 0) + h = (h + doublehashinc(hashval, size)) % size; + else if (++h >= size) + h -= size; + } + return 0; +} + + +<C>& <T><C>VHMap::operator [](<T&> item) +{ + if (size <= count + 1) + resize(); + + unsigned int bestspot = size; + unsigned int hashval = <T>HASH(item); + unsigned int h = hashval % size; + for (unsigned int i = 0; i <= size; ++i) + { + if (status[h] == EMPTYCELL) + { + ++count; + if (bestspot >= size) bestspot = h; + tab[bestspot] = item; + status[bestspot] = VALIDCELL; + cont[bestspot] = def; + return cont[bestspot]; + } + else if (status[h] == DELETEDCELL) + { + if (bestspot >= size) bestspot = h; + } + else if (<T>EQ(tab[h],item)) + return cont[h]; + + if (i == 0) + h = (h + doublehashinc(hashval, size)) % size; + else if (++h >= size) + h -= size; + } + + ++count; + status[bestspot] = VALIDCELL; + tab[bestspot] = item; + cont[bestspot] = def; + return cont[bestspot]; +} + + +void <T><C>VHMap::del(<T&> key) +{ + unsigned int hashval = <T>HASH(key); + unsigned int h = hashval % size; + for (unsigned int i = 0; i <= size; ++i) + { + if (status[h] == EMPTYCELL) + return; + else if (status[h] == VALIDCELL && <T>EQ(key, tab[h])) + { + status[h] = DELETEDCELL; + --count; + return; + } + if (i == 0) + h = (h + doublehashinc(hashval, size)) % size; + else if (++h >= size) + h -= size; + } +} + + +void <T><C>VHMap::clear() +{ + for (unsigned int i = 0; i < size; ++i) status[i] = EMPTYCELL; + count = 0; +} + +void <T><C>VHMap::resize(unsigned int newsize) +{ + if (newsize <= count) + { + newsize = DEFAULT_INITIAL_CAPACITY; + while (newsize <= count) newsize <<= 1; + } + <T>* oldtab = tab; + <C>* oldcont = cont; + char* oldstatus = status; + unsigned int oldsize = size; + tab = new <T>[size = newsize]; + cont = new <C>[size]; + status = new char[size]; + for (unsigned int i = 0; i < size; ++i) status[i] = EMPTYCELL; + count = 0; + for (i = 0; i < oldsize; ++i) + if (oldstatus[i] == VALIDCELL) + (*this)[oldtab[i]] = oldcont[i]; + delete [oldsize] oldtab; + delete [oldsize] oldcont; + delete oldstatus; +} + +Pix <T><C>VHMap::first() +{ + for (unsigned int pos = 0; pos < size; ++pos) + if (status[pos] == VALIDCELL) return Pix(&tab[pos]); + return 0; +} + +void <T><C>VHMap::next(Pix& i) +{ + if (i == 0) return; + unsigned int pos = ((unsigned)i - (unsigned)tab) / sizeof(<T>) + 1; + for (; pos < size; ++pos) + if (status[pos] == VALIDCELL) + { + i = Pix(&tab[pos]); + return; + } + i = 0; +} + + +int <T><C>VHMap::OK() +{ + int v = tab != 0; + v &= status != 0; + int n = 0; + for (unsigned int i = 0; i < size; ++i) + { + if (status[i] == VALIDCELL) ++n; + else if (status[i] != DELETEDCELL && status[i] != EMPTYCELL) + v = 0; + } + v &= n == count; + if (!v) error("invariant failure"); + return v; +} |