1 /*-----------------------------------------------------------------
2 SDCChast.c - contains support routines for hashtables
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 In other words, you are welcome to use, share and improve this program.
21 You are forbidden to forbid anyone else to use, share and improve
22 what you give them. Help stamp out software-hoarding!
23 -------------------------------------------------------------------------*/
29 #include "SDCChasht.h"
31 #define DEFAULT_HTAB_SIZE 128
33 /*-----------------------------------------------------------------*/
34 /* newHashtItem - creates a new hashtable Item */
35 /*-----------------------------------------------------------------*/
36 static hashtItem *_newHashtItem (int key, void *pkey, void *item)
40 ALLOC(htip,sizeof(hashtItem));
49 /*-----------------------------------------------------------------*/
50 /* newHashTable - allocates a new hashtable of size */
51 /*-----------------------------------------------------------------*/
52 hTab *newHashTable (int size)
56 ALLOC(htab,sizeof(hTab));
58 if (!(htab->table = GC_malloc((size +1)* sizeof(hashtItem *)))) {
59 fprintf(stderr,"out of virtual memory %s %d\n",
60 __FILE__,(size +1)* sizeof(hashtItem *));
63 htab->minKey = htab->size = size ;
68 void hTabAddItemLong(hTab **htab, int key, void *pkey, void *item)
74 *htab = newHashTable ( DEFAULT_HTAB_SIZE );
76 if (key > (*htab)->size ) {
78 (*htab)->table = GC_realloc ((*htab)->table,
79 (key*2 + 2)*sizeof(hashtItem *));
80 for ( i = (*htab)->size +1; i <= (key*2 + 1); i++ )
81 (*htab)->table[i] = NULL ;
82 (*htab)->size = key*2 + 1;
86 if ((*htab)->maxKey < key )
87 (*htab)->maxKey = key ;
89 if ((*htab)->minKey > key )
90 (*htab)->minKey = key ;
93 htip = _newHashtItem(key, pkey, item);
95 /* if there is a clash then goto end of chain */
96 if ((last = (*htab)->table[key])) {
101 /* else just add it */
102 (*htab)->table[key] = htip ;
106 /*-----------------------------------------------------------------*/
107 /* hTabAddItem - adds an item to the hash table */
108 /*-----------------------------------------------------------------*/
109 void hTabAddItem (hTab **htab, int key, void *item )
111 hTabAddItemLong(htab, key, NULL, item);
114 /*-----------------------------------------------------------------*/
115 /* hTabDeleteItem - either delete an item */
116 /*-----------------------------------------------------------------*/
117 void hTabDeleteItem (hTab **htab, int key ,
118 const void *item, DELETE_ACTION action,
119 int (*compareFunc)(const void *, const void *))
121 hashtItem *htip, **htipp ;
126 /* first check if anything exists in the slot */
127 if (! (*htab)->table[key] )
130 /* if delete chain */
131 if ( action == DELETE_CHAIN )
132 (*htab)->table[key] = NULL ;
135 /* delete specific item */
136 /* if a compare function is given then use the compare */
137 /* function to find the item, else just compare the items */
139 htipp = &((*htab)->table[key]);
140 htip = (*htab)->table[key];
141 for (; htip; htip = htip->next) {
143 if (compareFunc ? compareFunc(item,htip->item) :
144 (item == htip->item) ) {
156 if (!(*htab)->nItems) {
161 /*-----------------------------------------------------------------*/
162 /* hTabDeleteAll - deletes all items in a hash table to reduce mem */
163 /* leaks written by */
164 /* "BESSIERE Jerome" <BESSIERE_Jerome@stna.dgac.fr> */
165 /*-----------------------------------------------------------------*/
166 void hTabDeleteAll(hTab * p)
170 register hashtItem *jc,*jn;
171 for (i=0;i<p->size;i++) {
173 if (!(jc = p->table[i])) continue;
177 if((jc=jn)) jn = jc->next;
185 /*-----------------------------------------------------------------*/
186 /* hTabClearAll - clear all entries in the table (does not free) */
187 /*-----------------------------------------------------------------*/
188 void hTabClearAll (hTab *htab)
191 if (!htab || !htab->table) {
192 printf("null table\n");
195 memset(htab->table, 0, htab->size*sizeof(hashtItem *));
197 htab->minKey = htab->size;
198 htab->currKey = htab->nItems = htab->maxKey = 0;
201 static const hashtItem *_findItem(hTab *htab, int key, void *item, int (*compareFunc)(void *, void *))
205 for (htip = htab->table[key] ; htip ; htip = htip->next ) {
206 /* if a compare function is given use it */
207 if (compareFunc && compareFunc(item,htip->item))
210 if (item == htip->item)
216 static const hashtItem *_findByKey(hTab *htab, int key, const void *pkey, int (*compare)(const void *, const void *))
225 for (htip = htab->table[key] ; htip ; htip = htip->next ) {
226 /* if a compare function is given use it */
227 if (compare && compare(pkey, htip->pkey))
230 if (pkey == htip->pkey)
236 void *hTabFindByKey(hTab *h, int key, const void *pkey, int (*compare)(const void *, const void *))
238 const hashtItem *item;
240 if ((item = _findByKey(h, key, pkey, compare)))
245 int hTabDeleteByKey(hTab **h, int key, const void *pkey, int (*compare)(const void *, const void *))
247 hashtItem *htip, **htipp ;
252 /* first check if anything exists in the slot */
253 if (! (*h)->table[key] )
256 /* delete specific item */
257 /* if a compare function is given then use the compare */
258 /* function to find the item, else just compare the items */
260 htipp = &((*h)->table[key]);
261 htip = (*h)->table[key];
262 for (; htip; htip = htip->next) {
264 (compare && compare(pkey, htip->pkey)) ||
265 pkey == htip->pkey) {
279 /*-----------------------------------------------------------------*/
280 /* hTabIsInTable - will determine if an Item is in the hasht */
281 /*-----------------------------------------------------------------*/
282 int hTabIsInTable (hTab *htab, int key,
283 void *item , int (*compareFunc)(void *,void *))
285 if (_findItem(htab, key, item, compareFunc))
290 /*-----------------------------------------------------------------*/
291 /* hTabFirstItem - returns the first Item in the hTab */
292 /*-----------------------------------------------------------------*/
293 void *hTabFirstItem (hTab *htab, int *k)
300 for ( key = htab->minKey ; key <= htab->maxKey ; key++ ) {
301 if (htab->table[key]) {
302 htab->currItem = htab->table[key];
303 htab->currKey = key ;
305 return htab->table[key]->item;
311 /*-----------------------------------------------------------------*/
312 /* hTabNextItem - returns the next item in the hTab */
313 /*-----------------------------------------------------------------*/
314 void *hTabNextItem (hTab *htab, int *k)
321 /* if this chain not ended then */
322 if (htab->currItem->next) {
323 *k = htab->currItem->key ;
324 return (htab->currItem = htab->currItem->next)->item ;
327 /* find the next chain which has something */
328 for ( key = htab->currKey + 1; key <= htab->maxKey ; key++ ) {
329 if (htab->table[key]) {
330 htab->currItem = htab->table[key];
331 *k = htab->currKey = key ;
332 return htab->table[key]->item;
339 /*-----------------------------------------------------------------*/
340 /* hTabFirstItemWK - returns the first Item in the hTab for a key */
341 /*-----------------------------------------------------------------*/
342 void *hTabFirstItemWK (hTab *htab, int wk)
348 if (wk < htab->minKey || wk > htab->maxKey )
351 htab->currItem = htab->table[wk] ;
354 return (htab->table[wk] ? htab->table[wk]->item : NULL);
357 /*-----------------------------------------------------------------*/
358 /* hTabNextItem - returns the next item in the hTab for a key */
359 /*-----------------------------------------------------------------*/
360 void *hTabNextItemWK (hTab *htab )
366 /* if this chain not ended then */
367 if (htab->currItem->next) {
368 return (htab->currItem = htab->currItem->next)->item ;
374 /*-----------------------------------------------------------------*/
375 /* hTabFromTable - hash Table from a hash table */
376 /*-----------------------------------------------------------------*/
377 hTab *hTabFromTable (hTab *htab)
386 nhtab = newHashTable(htab->size);
388 for (key = htab->minKey; key <= htab->maxKey ; key++ ) {
390 for (htip = htab->table[key] ; htip ; htip = htip->next)
391 hTabAddItem (&nhtab, htip->key, htip->item);
397 /*-----------------------------------------------------------------*/
398 /* isHtabsEqual - returns 1 if all items in htab1 is found in htab2*/
399 /*-----------------------------------------------------------------*/
400 int isHtabsEqual (hTab *htab1, hTab *htab2,
401 int (*compareFunc)(void *,void *))
406 if ( htab1 == htab2 )
409 if (htab1 == NULL || htab2 == NULL )
412 /* if they are different sizes then */
413 if ( htab1->nItems != htab2->nItems)
416 /* now do an item by item check */
417 for ( item = hTabFirstItem (htab1,&key) ;item;
418 item = hTabNextItem (htab1,&key))
419 if (!hTabIsInTable (htab2, key, item, compareFunc))
426 /*-----------------------------------------------------------------*/
427 /* hTabSearch - returns the first Item with the specified key */
428 /*-----------------------------------------------------------------*/
429 hashtItem *hTabSearch (hTab *htab, int key )
434 if ((key < htab->minKey)||(key>htab->maxKey))
437 if (!htab->table[key])
440 return htab->table[key] ;
443 /*-----------------------------------------------------------------*/
444 /* hTabItemWithKey - returns the first item with the given key */
445 /*-----------------------------------------------------------------*/
446 void *hTabItemWithKey (hTab *htab, int key )
450 if (!(htip = hTabSearch(htab,key)))
456 /*-----------------------------------------------------------------*/
457 /*hTabAddItemIfNotP - adds an item with nothing found with key */
458 /*-----------------------------------------------------------------*/
459 void hTabAddItemIfNotP (hTab **htab, int key, void *item)
462 hTabAddItem (htab,key,item);
466 if (hTabItemWithKey(*htab,key))
469 hTabAddItem(htab,key,item);
472 /** Simple implementation of a hash table which uses
473 string (key, value) pairs. If a key already exists in the
474 table, the newly added value will replace it.
475 This is used for the assembler token table. The replace existing
476 condition is used to implement inheritance.
478 static int _compare(const void *s1, const void *s2)
480 return !strcmp(s1, s2);
483 static int _hash(const char *sz)
489 void shash_add(hTab **h, const char *szKey, const char *szValue)
491 int key = _hash(szKey);
492 /* First, delete any that currently exist */
493 hTabDeleteByKey(h, key, szKey, _compare);
494 /* Now add in ours */
495 hTabAddItemLong(h, key, gc_strdup(szKey), gc_strdup(szValue));
498 const char *shash_find(hTab *h, const char *szKey)
500 int key = _hash(szKey);
501 return (char *)hTabFindByKey(h, key, szKey, _compare);