xref: /386bsd/usr/src/lib/libg++/g++-include/gen/CHMap.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>.CHMap.h"
28
29// The nodes are linked together serially via a version
30// of a trick used in some vtables: odd pointers are
31// actually links to the next table entry.
32// Not terrible, but not wonderful either
33
34static inline int goodCHptr(<T><C>CHNode* t)
35{
36  return ((((unsigned)t) & 1) == 0);
37}
38
39static inline <T><C>CHNode* index_to_CHptr(int i)
40{
41  return (<T><C>CHNode*)((i << 1) + 1);
42}
43
44static inline int CHptr_to_index(<T><C>CHNode* t)
45{
46  return ( ((unsigned) t) >> 1);
47}
48
49<T><C>CHMap::<T><C>CHMap(<C&> dflt, unsigned int sz)
50     :<T><C>Map(dflt)
51{
52  tab = (<T><C>CHNode**)(new <T><C>CHNodePtr[size = sz]);
53  for (unsigned int i = 0; i < size; ++i) tab[i] = index_to_CHptr(i+1);
54  count = 0;
55}
56
57<T><C>CHMap::<T><C>CHMap(<T><C>CHMap& a) :<T><C>Map(a.def)
58{
59  tab = (<T><C>CHNode**)(new <T><C>CHNodePtr[size = a.size]);
60  for (unsigned int i = 0; i < size; ++i) tab[i] = index_to_CHptr(i+1);
61  count = 0;
62  for (Pix p = a.first(); p; a.next(p)) (*this)[a.key(p)] = a.contents(p);
63}
64
65
66Pix <T><C>CHMap::seek(<T&> key)
67{
68  unsigned int h = <T>HASH(key) % size;
69
70  for (<T><C>CHNode* t = tab[h]; goodCHptr(t); t = t->tl)
71    if (<T>EQ(key, t->hd))
72      return Pix(t);
73
74  return 0;
75}
76
77
78<C>& <T><C>CHMap::operator [](<T&> item)
79{
80  unsigned int h = <T>HASH(item) % size;
81
82  for (<T><C>CHNode* t = tab[h]; goodCHptr(t); t = t->tl)
83    if (<T>EQ(item, t->hd))
84      return t->cont;
85
86  t = new <T><C>CHNode(item, def, tab[h]);
87  tab[h] = t;
88  ++count;
89  return t->cont;
90}
91
92
93void <T><C>CHMap::del(<T&> key)
94{
95  unsigned int h = <T>HASH(key) % size;
96
97  <T><C>CHNode* t = tab[h];
98  <T><C>CHNode* trail = t;
99  while (goodCHptr(t))
100  {
101    if (<T>EQ(key, t->hd))
102    {
103      if (trail == t)
104        tab[h] = t->tl;
105      else
106        trail->tl = t->tl;
107      delete t;
108      --count;
109      return;
110    }
111    trail = t;
112    t = t->tl;
113  }
114}
115
116
117void <T><C>CHMap::clear()
118{
119  for (unsigned int i = 0; i < size; ++i)
120  {
121    <T><C>CHNode* p = tab[i];
122    tab[i] = index_to_CHptr(i+1);
123    while (goodCHptr(p))
124    {
125      <T><C>CHNode* nxt = p->tl;
126      delete(p);
127      p = nxt;
128    }
129  }
130  count = 0;
131}
132
133Pix <T><C>CHMap::first()
134{
135  for (unsigned int i = 0; i < size; ++i) if (goodCHptr(tab[i])) return Pix(tab[i]);
136  return 0;
137}
138
139void <T><C>CHMap::next(Pix& p)
140{
141  <T><C>CHNode* t = ((<T><C>CHNode*)p)->tl;
142  if (goodCHptr(t))
143    p = Pix(t);
144  else
145  {
146    for (unsigned int i = CHptr_to_index(t); i < size; ++i)
147    {
148      if (goodCHptr(tab[i]))
149      {
150        p =  Pix(tab[i]);
151        return;
152      }
153    }
154    p = 0;
155  }
156}
157
158
159int <T><C>CHMap::OK()
160{
161  int v = tab != 0;
162  int n = 0;
163  for (unsigned int i = 0; i < size; ++i)
164  {
165    for (<T><C>CHNode* p = tab[i]; goodCHptr(p); p = p->tl) ++n;
166    v &= CHptr_to_index(p) == i + 1;
167  }
168  v &= count == n;
169  if (!v) error("invariant failure");
170  return v;
171}
172