xref: /386bsd/usr/src/lib/libg++/g++-include/gen/VHMap.ccP (revision a2142627)
1// This may look like C code, but it is really -*- C++ -*-
2/*
3Copyright (C) 1988 Free Software Foundation
4    written by Doug Lea (dl@rocky.oswego.edu)
5
6This file is part of GNU CC.
7
8GNU CC is distributed in the hope that it will be useful,
9but WITHOUT ANY WARRANTY.  No author or distributor
10accepts responsibility to anyone for the consequences of using it
11or for whether it serves any particular purpose or works at all,
12unless he says so in writing.  Refer to the GNU CC General Public
13License for full details.
14
15Everyone is granted permission to copy, modify and redistribute
16GNU CC, but only under the conditions described in the
17GNU CC General Public License.   A copy of this license is
18supposed to have been given to you along with GNU CC so you
19can know your rights and responsibilities.  It should be in a
20file named COPYING.  Among other things, the copyright notice
21and this notice must be preserved on all copies.
22*/
23
24#ifdef __GNUG__
25#pragma implementation
26#endif
27#include "<T>.<C>.VHMap.h"
28
29/* codes for status fields */
30
31#define EMPTYCELL   0
32#define VALIDCELL   1
33#define DELETEDCELL 2
34
35
36<T><C>VHMap::<T><C>VHMap(<C&> dflt, unsigned int sz)
37     :<T><C>Map(dflt)
38{
39  tab = new <T>[size = sz];
40  cont = new <C>[size];
41  status = new char[size];
42  for (unsigned int i = 0; i < size; ++i) status[i] = EMPTYCELL;
43}
44
45<T><C>VHMap::<T><C>VHMap(<T><C>VHMap& a) : <T><C>Map(a.def)
46{
47  tab = new <T>[size = a.size];
48  cont = new <C>[size];
49  status = new char[size];
50  for (unsigned int i = 0; i < size; ++i) status[i] = EMPTYCELL;
51  count = 0;
52  for (Pix p = a.first(); p; a.next(p)) (*this)[a.key(p)] = a.contents(p);
53}
54
55
56/*
57 * hashing method: double hash based on high bits of hash fct,
58 * followed by linear probe. Can't do too much better if table
59 * sizes not constrained to be prime.
60*/
61
62
63static inline unsigned int doublehashinc(unsigned int h, unsigned int s)
64{
65  unsigned int dh =  ((h / s) % s);
66  return (dh > 1)? dh : 1;
67}
68
69Pix <T><C>VHMap::seek(<T&> key)
70{
71  unsigned int hashval = <T>HASH(key);
72  unsigned int h = hashval % size;
73  for (unsigned int i = 0; i <= size; ++i)
74  {
75    if (status[h] == EMPTYCELL)
76      return 0;
77    else if (status[h] == VALIDCELL && <T>EQ(key, tab[h]))
78      return Pix(&tab[h]);
79    if (i == 0)
80      h = (h + doublehashinc(hashval, size)) % size;
81    else if (++h >= size)
82      h -= size;
83  }
84  return 0;
85}
86
87
88<C>& <T><C>VHMap::operator [](<T&> item)
89{
90  if (size <= count + 1)
91    resize();
92
93  unsigned int bestspot = size;
94  unsigned int hashval = <T>HASH(item);
95  unsigned int h = hashval % size;
96  for (unsigned int i = 0; i <= size; ++i)
97  {
98    if (status[h] == EMPTYCELL)
99    {
100      ++count;
101      if (bestspot >= size) bestspot = h;
102      tab[bestspot] = item;
103      status[bestspot] = VALIDCELL;
104      cont[bestspot] = def;
105      return cont[bestspot];
106    }
107    else if (status[h] == DELETEDCELL)
108    {
109      if (bestspot >= size) bestspot = h;
110    }
111    else if (<T>EQ(tab[h],item))
112      return cont[h];
113
114    if (i == 0)
115      h = (h + doublehashinc(hashval, size)) % size;
116    else if (++h >= size)
117      h -= size;
118  }
119
120  ++count;
121  status[bestspot] = VALIDCELL;
122  tab[bestspot] = item;
123  cont[bestspot] = def;
124  return cont[bestspot];
125}
126
127
128void <T><C>VHMap::del(<T&> key)
129{
130  unsigned int hashval = <T>HASH(key);
131  unsigned int h = hashval % size;
132  for (unsigned int i = 0; i <= size; ++i)
133  {
134    if (status[h] == EMPTYCELL)
135      return;
136    else if (status[h] == VALIDCELL && <T>EQ(key, tab[h]))
137    {
138      status[h] = DELETEDCELL;
139      --count;
140      return;
141    }
142    if (i == 0)
143      h = (h + doublehashinc(hashval, size)) % size;
144    else if (++h >= size)
145      h -= size;
146  }
147}
148
149
150void <T><C>VHMap::clear()
151{
152  for (unsigned int i = 0; i < size; ++i) status[i] = EMPTYCELL;
153  count = 0;
154}
155
156void <T><C>VHMap::resize(unsigned int newsize)
157{
158  if (newsize <= count)
159  {
160    newsize = DEFAULT_INITIAL_CAPACITY;
161    while (newsize <= count) newsize <<= 1;
162  }
163  <T>* oldtab = tab;
164  <C>* oldcont = cont;
165  char* oldstatus = status;
166  unsigned int oldsize = size;
167  tab = new <T>[size = newsize];
168  cont = new <C>[size];
169  status = new char[size];
170  for (unsigned int i = 0; i < size; ++i) status[i] = EMPTYCELL;
171  count = 0;
172  for (i = 0; i < oldsize; ++i)
173    if (oldstatus[i] == VALIDCELL)
174      (*this)[oldtab[i]] = oldcont[i];
175  delete [oldsize] oldtab;
176  delete [oldsize] oldcont;
177  delete oldstatus;
178}
179
180Pix <T><C>VHMap::first()
181{
182  for (unsigned int pos = 0; pos < size; ++pos)
183    if (status[pos] == VALIDCELL) return Pix(&tab[pos]);
184  return 0;
185}
186
187void <T><C>VHMap::next(Pix& i)
188{
189  if (i == 0) return;
190  unsigned int pos = ((unsigned)i - (unsigned)tab) / sizeof(<T>) + 1;
191  for (; pos < size; ++pos)
192    if (status[pos] == VALIDCELL)
193    {
194      i = Pix(&tab[pos]);
195      return;
196    }
197  i = 0;
198}
199
200
201int <T><C>VHMap::OK()
202{
203  int v = tab != 0;
204  v &= status != 0;
205  int n = 0;
206  for (unsigned int i = 0; i < size; ++i)
207  {
208    if (status[i] == VALIDCELL) ++n;
209    else if (status[i] != DELETEDCELL && status[i] != EMPTYCELL)
210      v = 0;
211  }
212  v &= n == count;
213  if (!v) error("invariant failure");
214  return v;
215}
216