Bringing apdf from vendor into main branch.
[AROS-Contrib.git] / apdf / goo / GHash.cc
blobb51a7643029f5555d83b932375225c01e5254a5c
1 //========================================================================
2 //
3 // GHash.cc
4 //
5 // Copyright 2001-2003 Glyph & Cog, LLC
6 //
7 //========================================================================
9 #include <aconf.h>
11 #ifdef USE_GCC_PRAGMAS
12 #pragma implementation
13 #endif
15 #include "gmem.h"
16 #include "GString.h"
17 #include "GHash.h"
19 //------------------------------------------------------------------------
21 struct GHashBucket {
22 GString *key;
23 union {
24 void *p;
25 int i;
26 } val;
27 GHashBucket *next;
30 struct GHashIter {
31 int h;
32 GHashBucket *p;
35 //------------------------------------------------------------------------
37 GHash::GHash(GBool deleteKeysA) {
38 int h;
40 deleteKeys = deleteKeysA;
41 size = 7;
42 tab = (GHashBucket **)gmallocn(size, sizeof(GHashBucket *));
43 for (h = 0; h < size; ++h) {
44 tab[h] = NULL;
46 len = 0;
49 GHash::~GHash() {
50 GHashBucket *p;
51 int h;
53 for (h = 0; h < size; ++h) {
54 while (tab[h]) {
55 p = tab[h];
56 tab[h] = p->next;
57 if (deleteKeys) {
58 delete p->key;
60 delete p;
63 gfree(tab);
66 void GHash::add(GString *key, void *val) {
67 GHashBucket *p;
68 int h;
70 // expand the table if necessary
71 if (len >= size) {
72 expand();
75 // add the new symbol
76 p = new GHashBucket;
77 p->key = key;
78 p->val.p = val;
79 h = hash(key);
80 p->next = tab[h];
81 tab[h] = p;
82 ++len;
85 void GHash::add(GString *key, int val) {
86 GHashBucket *p;
87 int h;
89 // expand the table if necessary
90 if (len >= size) {
91 expand();
94 // add the new symbol
95 p = new GHashBucket;
96 p->key = key;
97 p->val.i = val;
98 h = hash(key);
99 p->next = tab[h];
100 tab[h] = p;
101 ++len;
104 void GHash::replace(GString *key, void *val) {
105 GHashBucket *p;
106 int h;
108 if ((p = find(key, &h))) {
109 p->val.p = val;
110 delete key;
111 } else {
112 add(key, val);
116 void GHash::replace(GString *key, int val) {
117 GHashBucket *p;
118 int h;
120 if ((p = find(key, &h))) {
121 p->val.i = val;
122 delete key;
123 } else {
124 add(key, val);
128 void *GHash::lookup(GString *key) {
129 GHashBucket *p;
130 int h;
132 if (!(p = find(key, &h))) {
133 return NULL;
135 return p->val.p;
138 int GHash::lookupInt(GString *key) {
139 GHashBucket *p;
140 int h;
142 if (!(p = find(key, &h))) {
143 return 0;
145 return p->val.i;
148 void *GHash::lookup(char *key) {
149 GHashBucket *p;
150 int h;
152 if (!(p = find(key, &h))) {
153 return NULL;
155 return p->val.p;
158 int GHash::lookupInt(char *key) {
159 GHashBucket *p;
160 int h;
162 if (!(p = find(key, &h))) {
163 return 0;
165 return p->val.i;
168 void *GHash::remove(GString *key) {
169 GHashBucket *p;
170 GHashBucket **q;
171 void *val;
172 int h;
174 if (!(p = find(key, &h))) {
175 return NULL;
177 q = &tab[h];
178 while (*q != p) {
179 q = &((*q)->next);
181 *q = p->next;
182 if (deleteKeys) {
183 delete p->key;
185 val = p->val.p;
186 delete p;
187 --len;
188 return val;
191 int GHash::removeInt(GString *key) {
192 GHashBucket *p;
193 GHashBucket **q;
194 int val;
195 int h;
197 if (!(p = find(key, &h))) {
198 return 0;
200 q = &tab[h];
201 while (*q != p) {
202 q = &((*q)->next);
204 *q = p->next;
205 if (deleteKeys) {
206 delete p->key;
208 val = p->val.i;
209 delete p;
210 --len;
211 return val;
214 void *GHash::remove(char *key) {
215 GHashBucket *p;
216 GHashBucket **q;
217 void *val;
218 int h;
220 if (!(p = find(key, &h))) {
221 return NULL;
223 q = &tab[h];
224 while (*q != p) {
225 q = &((*q)->next);
227 *q = p->next;
228 if (deleteKeys) {
229 delete p->key;
231 val = p->val.p;
232 delete p;
233 --len;
234 return val;
237 int GHash::removeInt(char *key) {
238 GHashBucket *p;
239 GHashBucket **q;
240 int val;
241 int h;
243 if (!(p = find(key, &h))) {
244 return 0;
246 q = &tab[h];
247 while (*q != p) {
248 q = &((*q)->next);
250 *q = p->next;
251 if (deleteKeys) {
252 delete p->key;
254 val = p->val.i;
255 delete p;
256 --len;
257 return val;
260 void GHash::startIter(GHashIter **iter) {
261 *iter = new GHashIter;
262 (*iter)->h = -1;
263 (*iter)->p = NULL;
266 GBool GHash::getNext(GHashIter **iter, GString **key, void **val) {
267 if (!*iter) {
268 return gFalse;
270 if ((*iter)->p) {
271 (*iter)->p = (*iter)->p->next;
273 while (!(*iter)->p) {
274 if (++(*iter)->h == size) {
275 delete *iter;
276 *iter = NULL;
277 return gFalse;
279 (*iter)->p = tab[(*iter)->h];
281 *key = (*iter)->p->key;
282 *val = (*iter)->p->val.p;
283 return gTrue;
286 GBool GHash::getNext(GHashIter **iter, GString **key, int *val) {
287 if (!*iter) {
288 return gFalse;
290 if ((*iter)->p) {
291 (*iter)->p = (*iter)->p->next;
293 while (!(*iter)->p) {
294 if (++(*iter)->h == size) {
295 delete *iter;
296 *iter = NULL;
297 return gFalse;
299 (*iter)->p = tab[(*iter)->h];
301 *key = (*iter)->p->key;
302 *val = (*iter)->p->val.i;
303 return gTrue;
306 void GHash::killIter(GHashIter **iter) {
307 delete *iter;
308 *iter = NULL;
311 void GHash::expand() {
312 GHashBucket **oldTab;
313 GHashBucket *p;
314 int oldSize, h, i;
316 oldSize = size;
317 oldTab = tab;
318 size = 2*size + 1;
319 tab = (GHashBucket **)gmallocn(size, sizeof(GHashBucket *));
320 for (h = 0; h < size; ++h) {
321 tab[h] = NULL;
323 for (i = 0; i < oldSize; ++i) {
324 while (oldTab[i]) {
325 p = oldTab[i];
326 oldTab[i] = oldTab[i]->next;
327 h = hash(p->key);
328 p->next = tab[h];
329 tab[h] = p;
332 gfree(oldTab);
335 GHashBucket *GHash::find(GString *key, int *h) {
336 GHashBucket *p;
338 *h = hash(key);
339 for (p = tab[*h]; p; p = p->next) {
340 if (!p->key->cmp(key)) {
341 return p;
344 return NULL;
347 GHashBucket *GHash::find(char *key, int *h) {
348 GHashBucket *p;
350 *h = hash(key);
351 for (p = tab[*h]; p; p = p->next) {
352 if (!p->key->cmp(key)) {
353 return p;
356 return NULL;
359 int GHash::hash(GString *key) {
360 char *p;
361 unsigned int h;
362 int i;
364 h = 0;
365 for (p = key->getCString(), i = 0; i < key->getLength(); ++p, ++i) {
366 h = 17 * h + (int)(*p & 0xff);
368 return (int)(h % size);
371 int GHash::hash(char *key) {
372 char *p;
373 unsigned int h;
375 h = 0;
376 for (p = key; *p; ++p) {
377 h = 17 * h + (int)(*p & 0xff);
379 return (int)(h % size);