1
static const char rcsid[] = "$Id: hsearch.c,v 1.12 2004/04/30 17:00:58 will Exp $";
3
* hsearch.c --- PD simple implementation of System V hsearch(3c) routine
4
* It is by Arnold Robbins (arnold@skeeve.atl.ga.us) -- thanks!
11
static ELEMENT **Table = NULL; /* pointer to dynamicly allocated table */
12
static int Num_elem = -1; /* number of elements */
17
* table of primes just below 2^n, n=2..31 for use in finding the right prime
18
* number to be the table size. this table may be generally useful...
21
static unsigned int primetab[] = {
23
* comment these out, so that table will always have a minimal size...
26
127, 251, 509, 1021, 2039, 4093, 8191, 16381, 32749, 65521, 131071,
27
262139, 524287, 1048573, 2097143, 4194301, 8388593, 16777213, 33554393,
28
67108859, 134217689, 268435399, 536870909, 1073741789, 2147483647
31
/* hcreate --- create a hash table at least how_many big */
33
int hcreate (how_many)
34
register unsigned int how_many;
39
* find first prime number >= how_many, and use it for table size
42
if (Num_elem != -1) /* already a table out there */
43
hdestroy(); /* remove it */
45
j = sizeof (primetab) / sizeof (primetab[0]);
46
for (i = 0; i < j; i++)
47
if (primetab[i] >= how_many)
50
if (i >= j) /* how_many bigger than any prime we have, use it */
53
Num_elem = primetab[i];
55
if ((Table = (ELEMENT **) calloc ((unsigned) Num_elem, sizeof (ELEMENT *))) == NULL)
61
/* idestroy --- destroy a single element on a chain */
63
static void idestroy (elem)
68
idestroy (elem->next);
73
/* hdestroy --- nuke the existing hash table */
77
register unsigned int i;
81
/* free all the chains */
82
for (i = 0; i < Num_elem; i++)
85
/* now the table itself */
86
free ((char *) Table);
92
/* hsearch --- lookup or enter an item in the hash table */
94
ENTRY *hsearch (entry, action)
106
hindex = hashit (entry.key);
107
if (Table[hindex] == NULL) /* nothing there */
113
/* add it to the table */
116
if ((Table[hindex] = (ELEMENT *) calloc (1, sizeof (ELEMENT))) == NULL)
119
return (& Table[hindex]->item);
124
/* something in bucket, see if already on chain */
125
for (ep = Table[hindex]; ep != NULL; ep = ep->next)
127
if (strcmp (ep->item.key, entry.key) == 0)
130
ep->item.data = entry.data;
131
/* already there, just change data */
132
/* or action was just find it */
138
/* at this point, item was not in table */
139
/* ep2 points at last element on the list */
142
if ((ep2->next = (ELEMENT *) calloc (1, sizeof (ELEMENT))) == NULL)
144
ep2->next->item = entry;
145
ep2->next->next = NULL;
146
return (& ep2->next->item);
154
/* hashit --- do the hashing algorithm */
157
* algorithm is sum of string elements, plus string length
161
static int hashit (text)
164
register long int sum = 0;
167
for (i = 0; text[i] != '\0'; i++)
171
return (sum % Num_elem);
175
* Prints all elements of the table, in no particular order.
179
void (*f)(); /* (*f) is a function that will be called by hprint, is passed
180
* (hashIndex, ptrToKey, ptrToData), and should print these.
185
for (i=0; i<Num_elem; i++) {
186
for (p = Table[i]; p; p = p->next)
187
(*f)(i, p->item.key, p->item.data);
192
* A function suitable for passing to hprint, if both key and data are text
193
* suitable for passing to printf. You can use this one or supply your
197
htext(indx, key, data)
202
printf("(%d)\t%s :\t%s\n", indx, key, data);