filters

GHash.cpp
1//========================================================================
2//
3// GHash.cpp
4//
5// Copyright 2001-2002 Glyph & Cog, LLC
6//
7//========================================================================
8
9#include <aconf.h>
10
11
12#include "gmem.h"
13#include "GString.h"
14#include "GHash.h"
15
16//------------------------------------------------------------------------
17
18struct GHashBucket {
19 GString *key;
20 void *val;
21 GHashBucket *next;
22};
23
24struct GHashIter {
25 int h;
26 GHashBucket *p;
27};
28
29//------------------------------------------------------------------------
30
31GHash::GHash(GBool deleteKeysA) {
32 int h;
33
34 deleteKeys = deleteKeysA;
35 size = 7;
36 tab = (GHashBucket **)gmalloc(size * sizeof(GHashBucket *));
37 for (h = 0; h < size; ++h) {
38 tab[h] = NULL;
39 }
40 len = 0;
41}
42
43GHash::~GHash() {
44 GHashBucket *p;
45 int h;
46
47 for (h = 0; h < size; ++h) {
48 while (tab[h]) {
49 p = tab[h];
50 tab[h] = p->next;
51 if (deleteKeys) {
52 delete p->key;
53 }
54 delete p;
55 }
56 }
57 gfree(tab);
58}
59
60void GHash::add(GString *key, void *val) {
61 GHashBucket **oldTab;
62 GHashBucket *p;
63 int oldSize, i, h;
64
65 // expand the table if necessary
66 if (len >= size) {
67 oldSize = size;
68 oldTab = tab;
69 size = 2*size + 1;
70 tab = (GHashBucket **)gmalloc(size * sizeof(GHashBucket *));
71 for (h = 0; h < size; ++h) {
72 tab[h] = NULL;
73 }
74 for (i = 0; i < oldSize; ++i) {
75 while (oldTab[i]) {
76 p = oldTab[i];
77 oldTab[i] = oldTab[i]->next;
78 h = hash(p->key);
79 p->next = tab[h];
80 tab[h] = p;
81 }
82 }
83 gfree(oldTab);
84 }
85
86 // add the new symbol
87 p = new GHashBucket;
88 p->key = key;
89 p->val = val;
90 h = hash(key);
91 p->next = tab[h];
92 tab[h] = p;
93 ++len;
94}
95
96void *GHash::lookup(const GString *key) {
97 GHashBucket *p;
98 int h;
99
100 if (!(p = find(key, &h))) {
101 return NULL;
102 }
103 return p->val;
104}
105
106void *GHash::lookup(const char *key) {
107 GHashBucket *p;
108 int h;
109
110 if (!(p = find(key, &h))) {
111 return NULL;
112 }
113 return p->val;
114}
115
116void *GHash::remove(const GString *key) {
117 GHashBucket *p;
118 GHashBucket **q;
119 void *val;
120 int h;
121
122 if (!(p = find(key, &h))) {
123 return NULL;
124 }
125 q = &tab[h];
126 while (*q != p) {
127 q = &((*q)->next);
128 }
129 *q = p->next;
130 if (deleteKeys) {
131 delete p->key;
132 }
133 val = p->val;
134 delete p;
135 --len;
136 return val;
137}
138
139void *GHash::remove(const char *key) {
140 GHashBucket *p;
141 GHashBucket **q;
142 void *val;
143 int h;
144
145 if (!(p = find(key, &h))) {
146 return NULL;
147 }
148 q = &tab[h];
149 while (*q != p) {
150 q = &((*q)->next);
151 }
152 *q = p->next;
153 if (deleteKeys) {
154 delete p->key;
155 }
156 val = p->val;
157 delete p;
158 --len;
159 return val;
160}
161
162void GHash::startIter(GHashIter **iter) {
163 *iter = new GHashIter;
164 (*iter)->h = -1;
165 (*iter)->p = NULL;
166}
167
168GBool GHash::getNext(GHashIter **iter, GString **key, void **val) {
169 if (!*iter) {
170 return gFalse;
171 }
172 if ((*iter)->p) {
173 (*iter)->p = (*iter)->p->next;
174 }
175 while (!(*iter)->p) {
176 if (++(*iter)->h == size) {
177 delete *iter;
178 *iter = NULL;
179 return gFalse;
180 }
181 (*iter)->p = tab[(*iter)->h];
182 }
183 *key = (*iter)->p->key;
184 *val = (*iter)->p->val;
185 return gTrue;
186}
187
188void GHash::killIter(GHashIter **iter) {
189 delete *iter;
190 *iter = NULL;
191}
192
193GHashBucket *GHash::find(const GString *key, int *h) {
194 GHashBucket *p;
195
196 *h = hash(key);
197 for (p = tab[*h]; p; p = p->next) {
198 if (!p->key->cmp(key)) {
199 return p;
200 }
201 }
202 return NULL;
203}
204
205GHashBucket *GHash::find(const char *key, int *h) {
206 GHashBucket *p;
207
208 *h = hash(key);
209 for (p = tab[*h]; p; p = p->next) {
210 if (!p->key->cmp(key)) {
211 return p;
212 }
213 }
214 return NULL;
215}
216
217int GHash::hash(const GString *key) {
218 const char *p;
219 unsigned int h;
220 int i;
221
222 h = 0;
223 for (p = key->getCString(), i = 0; i < key->getLength(); ++p, ++i) {
224 h = 17 * h + (int)(*p & 0xff);
225 }
226 return (int)(h % size);
227}
228
229int GHash::hash(const char *key) {
230 const char *p;
231 unsigned int h;
232
233 h = 0;
234 for (p = key; *p; ++p) {
235 h = 17 * h + (int)(*p & 0xff);
236 }
237 return (int)(h % size);
238}