xref: /minix3/external/bsd/top/dist/hash.c (revision b89261ba018da33f0bd8cd05f5a1fe9e7a9c837b)
1*b89261baSDavid van Moolenbroek /*
2*b89261baSDavid van Moolenbroek  * Copyright (c) 1984 through 2008, William LeFebvre
3*b89261baSDavid van Moolenbroek  * All rights reserved.
4*b89261baSDavid van Moolenbroek  *
5*b89261baSDavid van Moolenbroek  * Redistribution and use in source and binary forms, with or without
6*b89261baSDavid van Moolenbroek  * modification, are permitted provided that the following conditions are met:
7*b89261baSDavid van Moolenbroek  *
8*b89261baSDavid van Moolenbroek  *     * Redistributions of source code must retain the above copyright
9*b89261baSDavid van Moolenbroek  * notice, this list of conditions and the following disclaimer.
10*b89261baSDavid van Moolenbroek  *
11*b89261baSDavid van Moolenbroek  *     * Redistributions in binary form must reproduce the above
12*b89261baSDavid van Moolenbroek  * copyright notice, this list of conditions and the following disclaimer
13*b89261baSDavid van Moolenbroek  * in the documentation and/or other materials provided with the
14*b89261baSDavid van Moolenbroek  * distribution.
15*b89261baSDavid van Moolenbroek  *
16*b89261baSDavid van Moolenbroek  *     * Neither the name of William LeFebvre nor the names of other
17*b89261baSDavid van Moolenbroek  * contributors may be used to endorse or promote products derived from
18*b89261baSDavid van Moolenbroek  * this software without specific prior written permission.
19*b89261baSDavid van Moolenbroek  *
20*b89261baSDavid van Moolenbroek  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21*b89261baSDavid van Moolenbroek  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22*b89261baSDavid van Moolenbroek  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23*b89261baSDavid van Moolenbroek  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24*b89261baSDavid van Moolenbroek  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25*b89261baSDavid van Moolenbroek  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26*b89261baSDavid van Moolenbroek  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27*b89261baSDavid van Moolenbroek  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28*b89261baSDavid van Moolenbroek  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29*b89261baSDavid van Moolenbroek  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30*b89261baSDavid van Moolenbroek  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31*b89261baSDavid van Moolenbroek  */
32*b89261baSDavid van Moolenbroek 
33*b89261baSDavid van Moolenbroek /* hash.m4c */
34*b89261baSDavid van Moolenbroek 
35*b89261baSDavid van Moolenbroek /* The file hash.c is generated from hash.m4c via the preprocessor M4 */
36*b89261baSDavid van Moolenbroek 
37*b89261baSDavid van Moolenbroek /*
38*b89261baSDavid van Moolenbroek  * Hash table functions:  init, add, lookup, first, next, sizeinfo.
39*b89261baSDavid van Moolenbroek  * This is a conventional "bucket hash".  The key is hashed in to a number
40*b89261baSDavid van Moolenbroek  * less than or equal to the number of buckets and the result is used
41*b89261baSDavid van Moolenbroek  * to index in to the array of buckets.  Each bucket is a linked list
42*b89261baSDavid van Moolenbroek  * that contains all the key/value pairs which hashed to that index.
43*b89261baSDavid van Moolenbroek  */
44*b89261baSDavid van Moolenbroek 
45*b89261baSDavid van Moolenbroek #include "os.h"
46*b89261baSDavid van Moolenbroek 
47*b89261baSDavid van Moolenbroek #ifdef HAVE_MATH_H
48*b89261baSDavid van Moolenbroek #include <math.h>
49*b89261baSDavid van Moolenbroek #endif
50*b89261baSDavid van Moolenbroek 
51*b89261baSDavid van Moolenbroek #include "hash.h"
52*b89261baSDavid van Moolenbroek 
53*b89261baSDavid van Moolenbroek static int
next_prime(int x)54*b89261baSDavid van Moolenbroek next_prime(int x)
55*b89261baSDavid van Moolenbroek 
56*b89261baSDavid van Moolenbroek {
57*b89261baSDavid van Moolenbroek     double i, j;
58*b89261baSDavid van Moolenbroek     int f;
59*b89261baSDavid van Moolenbroek 
60*b89261baSDavid van Moolenbroek     i = x;
61*b89261baSDavid van Moolenbroek     while (i++)
62*b89261baSDavid van Moolenbroek     {
63*b89261baSDavid van Moolenbroek 	f=1;
64*b89261baSDavid van Moolenbroek 	for (j=2; j<i; j++)
65*b89261baSDavid van Moolenbroek 	{
66*b89261baSDavid van Moolenbroek 	    if ((i/j)==floor(i/j))
67*b89261baSDavid van Moolenbroek 	    {
68*b89261baSDavid van Moolenbroek 		f=0;
69*b89261baSDavid van Moolenbroek 		break;
70*b89261baSDavid van Moolenbroek 	    }
71*b89261baSDavid van Moolenbroek 	}
72*b89261baSDavid van Moolenbroek 	if (f)
73*b89261baSDavid van Moolenbroek 	{
74*b89261baSDavid van Moolenbroek 	    return (int)i;
75*b89261baSDavid van Moolenbroek 	}
76*b89261baSDavid van Moolenbroek     }
77*b89261baSDavid van Moolenbroek     return 1;
78*b89261baSDavid van Moolenbroek }
79*b89261baSDavid van Moolenbroek 
80*b89261baSDavid van Moolenbroek /* string hashes */
81*b89261baSDavid van Moolenbroek 
82*b89261baSDavid van Moolenbroek static int
string_hash(hash_table * ht,char * key)83*b89261baSDavid van Moolenbroek string_hash(hash_table *ht, char *key)
84*b89261baSDavid van Moolenbroek 
85*b89261baSDavid van Moolenbroek {
86*b89261baSDavid van Moolenbroek     unsigned long s = 0;
87*b89261baSDavid van Moolenbroek     unsigned char ch;
88*b89261baSDavid van Moolenbroek     int shifting = 24;
89*b89261baSDavid van Moolenbroek 
90*b89261baSDavid van Moolenbroek     while ((ch = (unsigned char)*key++) != '\0')
91*b89261baSDavid van Moolenbroek     {
92*b89261baSDavid van Moolenbroek 	if (shifting == 0)
93*b89261baSDavid van Moolenbroek 	{
94*b89261baSDavid van Moolenbroek 	    s = s + ch;
95*b89261baSDavid van Moolenbroek 	    shifting = 24;
96*b89261baSDavid van Moolenbroek 	}
97*b89261baSDavid van Moolenbroek 	else
98*b89261baSDavid van Moolenbroek 	{
99*b89261baSDavid van Moolenbroek 	    s = s + (ch << shifting);
100*b89261baSDavid van Moolenbroek 	    shifting -= 8;
101*b89261baSDavid van Moolenbroek 	}
102*b89261baSDavid van Moolenbroek     }
103*b89261baSDavid van Moolenbroek 
104*b89261baSDavid van Moolenbroek     return (s % ht->num_buckets);
105*b89261baSDavid van Moolenbroek }
106*b89261baSDavid van Moolenbroek 
ll_init(llist * q)107*b89261baSDavid van Moolenbroek static void ll_init(llist *q)
108*b89261baSDavid van Moolenbroek 
109*b89261baSDavid van Moolenbroek {
110*b89261baSDavid van Moolenbroek     q->head = NULL;
111*b89261baSDavid van Moolenbroek     q->count = 0;
112*b89261baSDavid van Moolenbroek }
113*b89261baSDavid van Moolenbroek 
ll_newitem(int size)114*b89261baSDavid van Moolenbroek static llistitem *ll_newitem(int size)
115*b89261baSDavid van Moolenbroek 
116*b89261baSDavid van Moolenbroek {
117*b89261baSDavid van Moolenbroek     llistitem *qi;
118*b89261baSDavid van Moolenbroek 
119*b89261baSDavid van Moolenbroek     qi = emalloc(sizeof(llistitem) + size);
120*b89261baSDavid van Moolenbroek     qi->datum = ((char *)qi + sizeof(llistitem));
121*b89261baSDavid van Moolenbroek     return qi;
122*b89261baSDavid van Moolenbroek }
123*b89261baSDavid van Moolenbroek 
ll_freeitem(llistitem * li)124*b89261baSDavid van Moolenbroek static void ll_freeitem(llistitem *li)
125*b89261baSDavid van Moolenbroek 
126*b89261baSDavid van Moolenbroek {
127*b89261baSDavid van Moolenbroek     free(li);
128*b89261baSDavid van Moolenbroek }
129*b89261baSDavid van Moolenbroek 
ll_add(llist * q,llistitem * new)130*b89261baSDavid van Moolenbroek static void ll_add(llist *q, llistitem *new)
131*b89261baSDavid van Moolenbroek 
132*b89261baSDavid van Moolenbroek {
133*b89261baSDavid van Moolenbroek     new->next = q->head;
134*b89261baSDavid van Moolenbroek     q->head = new;
135*b89261baSDavid van Moolenbroek     q->count++;
136*b89261baSDavid van Moolenbroek }
137*b89261baSDavid van Moolenbroek 
ll_extract(llist * q,llistitem * qi,llistitem * last)138*b89261baSDavid van Moolenbroek static void ll_extract(llist *q, llistitem *qi, llistitem *last)
139*b89261baSDavid van Moolenbroek 
140*b89261baSDavid van Moolenbroek {
141*b89261baSDavid van Moolenbroek     if (last == NULL)
142*b89261baSDavid van Moolenbroek     {
143*b89261baSDavid van Moolenbroek 	q->head = qi->next;
144*b89261baSDavid van Moolenbroek     }
145*b89261baSDavid van Moolenbroek     else
146*b89261baSDavid van Moolenbroek     {
147*b89261baSDavid van Moolenbroek 	last->next = qi->next;
148*b89261baSDavid van Moolenbroek     }
149*b89261baSDavid van Moolenbroek     qi->next = NULL;
150*b89261baSDavid van Moolenbroek     q->count--;
151*b89261baSDavid van Moolenbroek }
152*b89261baSDavid van Moolenbroek 
153*b89261baSDavid van Moolenbroek #define LL_FIRST(q) ((q)->head)
154*b89261baSDavid van Moolenbroek #define LL_NEXT(q, qi)  ((qi) != NULL ? (qi)->next : NULL)
155*b89261baSDavid van Moolenbroek #define LL_ISEMPTY(ll)  ((ll)->count == 0)
156*b89261baSDavid van Moolenbroek 
157*b89261baSDavid van Moolenbroek #ifdef notdef
158*b89261baSDavid van Moolenbroek static llistitem *
ll_first(llist * q)159*b89261baSDavid van Moolenbroek ll_first(llist *q)
160*b89261baSDavid van Moolenbroek 
161*b89261baSDavid van Moolenbroek {
162*b89261baSDavid van Moolenbroek     return q->head;
163*b89261baSDavid van Moolenbroek }
164*b89261baSDavid van Moolenbroek 
165*b89261baSDavid van Moolenbroek static llistitem *
ll_next(llist * q,llistitem * qi)166*b89261baSDavid van Moolenbroek ll_next(llist *q, llistitem *qi)
167*b89261baSDavid van Moolenbroek 
168*b89261baSDavid van Moolenbroek {
169*b89261baSDavid van Moolenbroek     return (qi != NULL ? qi->next : NULL);
170*b89261baSDavid van Moolenbroek }
171*b89261baSDavid van Moolenbroek 
172*b89261baSDavid van Moolenbroek static int
ll_isempty(llist * ll)173*b89261baSDavid van Moolenbroek ll_isempty(llist *ll)
174*b89261baSDavid van Moolenbroek 
175*b89261baSDavid van Moolenbroek {
176*b89261baSDavid van Moolenbroek     return (ll->count == 0);
177*b89261baSDavid van Moolenbroek }
178*b89261baSDavid van Moolenbroek #endif
179*b89261baSDavid van Moolenbroek 
180*b89261baSDavid van Moolenbroek /*
181*b89261baSDavid van Moolenbroek  * hash_table *hash_create(int num)
182*b89261baSDavid van Moolenbroek  *
183*b89261baSDavid van Moolenbroek  * Creates a hash table structure with at least "num" buckets.
184*b89261baSDavid van Moolenbroek  */
185*b89261baSDavid van Moolenbroek 
186*b89261baSDavid van Moolenbroek hash_table *
hash_create(int num)187*b89261baSDavid van Moolenbroek hash_create(int num)
188*b89261baSDavid van Moolenbroek 
189*b89261baSDavid van Moolenbroek {
190*b89261baSDavid van Moolenbroek     hash_table *result;
191*b89261baSDavid van Moolenbroek     bucket_t *b;
192*b89261baSDavid van Moolenbroek     int bytes;
193*b89261baSDavid van Moolenbroek     int i;
194*b89261baSDavid van Moolenbroek 
195*b89261baSDavid van Moolenbroek     /* create the resultant structure */
196*b89261baSDavid van Moolenbroek     result = emalloc(sizeof(hash_table));
197*b89261baSDavid van Moolenbroek 
198*b89261baSDavid van Moolenbroek     /* adjust bucket count to be prime */
199*b89261baSDavid van Moolenbroek     num = next_prime(num);
200*b89261baSDavid van Moolenbroek 
201*b89261baSDavid van Moolenbroek     /* create the buckets */
202*b89261baSDavid van Moolenbroek     bytes = sizeof(bucket_t) * num;
203*b89261baSDavid van Moolenbroek     result->buckets = b = emalloc(bytes);
204*b89261baSDavid van Moolenbroek     result->num_buckets = num;
205*b89261baSDavid van Moolenbroek 
206*b89261baSDavid van Moolenbroek     /* create each bucket as a linked list */
207*b89261baSDavid van Moolenbroek     i = num;
208*b89261baSDavid van Moolenbroek     while (--i >= 0)
209*b89261baSDavid van Moolenbroek     {
210*b89261baSDavid van Moolenbroek 	ll_init(&(b->list));
211*b89261baSDavid van Moolenbroek 	b++;
212*b89261baSDavid van Moolenbroek     }
213*b89261baSDavid van Moolenbroek 
214*b89261baSDavid van Moolenbroek     return result;
215*b89261baSDavid van Moolenbroek }
216*b89261baSDavid van Moolenbroek 
217*b89261baSDavid van Moolenbroek /*
218*b89261baSDavid van Moolenbroek  * unsigned int hash_count(hash_table *ht)
219*b89261baSDavid van Moolenbroek  *
220*b89261baSDavid van Moolenbroek  * Return total number of elements contained in hash table.
221*b89261baSDavid van Moolenbroek  */
222*b89261baSDavid van Moolenbroek 
223*b89261baSDavid van Moolenbroek #ifdef notdef
224*b89261baSDavid van Moolenbroek static unsigned int
hash_count(hash_table * ht)225*b89261baSDavid van Moolenbroek hash_count(hash_table *ht)
226*b89261baSDavid van Moolenbroek 
227*b89261baSDavid van Moolenbroek {
228*b89261baSDavid van Moolenbroek     register int i = 0;
229*b89261baSDavid van Moolenbroek     register int cnt = 0;
230*b89261baSDavid van Moolenbroek     register bucket_t *bucket;
231*b89261baSDavid van Moolenbroek 
232*b89261baSDavid van Moolenbroek     bucket = ht->buckets;
233*b89261baSDavid van Moolenbroek     while (i++ < ht->num_buckets)
234*b89261baSDavid van Moolenbroek     {
235*b89261baSDavid van Moolenbroek 	cnt += bucket->list.count;
236*b89261baSDavid van Moolenbroek 	bucket++;
237*b89261baSDavid van Moolenbroek     }
238*b89261baSDavid van Moolenbroek 
239*b89261baSDavid van Moolenbroek     return cnt;
240*b89261baSDavid van Moolenbroek }
241*b89261baSDavid van Moolenbroek #endif
242*b89261baSDavid van Moolenbroek 
243*b89261baSDavid van Moolenbroek /*
244*b89261baSDavid van Moolenbroek  * void hash_sizeinfo(unsigned int *sizes, int max, hash_table *ht)
245*b89261baSDavid van Moolenbroek  *
246*b89261baSDavid van Moolenbroek  * Fill in "sizes" with information about bucket lengths in hash
247*b89261baSDavid van Moolenbroek  * table "max".
248*b89261baSDavid van Moolenbroek  */
249*b89261baSDavid van Moolenbroek 
250*b89261baSDavid van Moolenbroek void
hash_sizeinfo(unsigned int * sizes,int max,hash_table * ht)251*b89261baSDavid van Moolenbroek hash_sizeinfo(unsigned int *sizes, int max, hash_table *ht)
252*b89261baSDavid van Moolenbroek 
253*b89261baSDavid van Moolenbroek {
254*b89261baSDavid van Moolenbroek     register int i;
255*b89261baSDavid van Moolenbroek     register int idx;
256*b89261baSDavid van Moolenbroek     register bucket_t *bucket;
257*b89261baSDavid van Moolenbroek 
258*b89261baSDavid van Moolenbroek     memzero(sizes, max * sizeof(unsigned int));
259*b89261baSDavid van Moolenbroek 
260*b89261baSDavid van Moolenbroek     bucket = ht->buckets;
261*b89261baSDavid van Moolenbroek     i = 0;
262*b89261baSDavid van Moolenbroek     while (i++ < ht->num_buckets)
263*b89261baSDavid van Moolenbroek     {
264*b89261baSDavid van Moolenbroek 	idx = bucket->list.count;
265*b89261baSDavid van Moolenbroek 	sizes[idx >= max ? max-1 : idx]++;
266*b89261baSDavid van Moolenbroek 	bucket++;
267*b89261baSDavid van Moolenbroek     }
268*b89261baSDavid van Moolenbroek }
269*b89261baSDavid van Moolenbroek 
270*b89261baSDavid van Moolenbroek 
271*b89261baSDavid van Moolenbroek 
272*b89261baSDavid van Moolenbroek 
273*b89261baSDavid van Moolenbroek 
274*b89261baSDavid van Moolenbroek 
275*b89261baSDavid van Moolenbroek 
276*b89261baSDavid van Moolenbroek /*
277*b89261baSDavid van Moolenbroek  * void hash_add_uint(hash_table *ht, unsigned int key, void *value)
278*b89261baSDavid van Moolenbroek  *
279*b89261baSDavid van Moolenbroek  * Add an element to table "ht".  The element is described by
280*b89261baSDavid van Moolenbroek  * "key" and "value".  Return NULL on success.  If the key
281*b89261baSDavid van Moolenbroek  * already exists in the table, then no action is taken and
282*b89261baSDavid van Moolenbroek  * the data for the existing element is returned.
283*b89261baSDavid van Moolenbroek  * Key type is unsigned int
284*b89261baSDavid van Moolenbroek  */
285*b89261baSDavid van Moolenbroek 
286*b89261baSDavid van Moolenbroek void *
hash_add_uint(hash_table * ht,unsigned int key,void * value)287*b89261baSDavid van Moolenbroek hash_add_uint(hash_table *ht, unsigned int key, void *value)
288*b89261baSDavid van Moolenbroek 
289*b89261baSDavid van Moolenbroek {
290*b89261baSDavid van Moolenbroek     bucket_t *bucket;
291*b89261baSDavid van Moolenbroek     hash_item_uint *hi;
292*b89261baSDavid van Moolenbroek     hash_item_uint *h;
293*b89261baSDavid van Moolenbroek     llist *ll;
294*b89261baSDavid van Moolenbroek     llistitem *li;
295*b89261baSDavid van Moolenbroek     llistitem *newli;
296*b89261baSDavid van Moolenbroek     unsigned int k1;
297*b89261baSDavid van Moolenbroek 
298*b89261baSDavid van Moolenbroek     /* allocate the space we will need */
299*b89261baSDavid van Moolenbroek     newli = ll_newitem(sizeof(hash_item_uint));
300*b89261baSDavid van Moolenbroek     hi = (hash_item_uint *)newli->datum;
301*b89261baSDavid van Moolenbroek 
302*b89261baSDavid van Moolenbroek     /* fill in the values */
303*b89261baSDavid van Moolenbroek     hi->key = key;
304*b89261baSDavid van Moolenbroek     hi->value = value;
305*b89261baSDavid van Moolenbroek 
306*b89261baSDavid van Moolenbroek     /* hash to the bucket */
307*b89261baSDavid van Moolenbroek     bucket = &(ht->buckets[(key % ht->num_buckets)]);
308*b89261baSDavid van Moolenbroek 
309*b89261baSDavid van Moolenbroek     /* walk the list to make sure we do not have a duplicate */
310*b89261baSDavid van Moolenbroek     ll = &(bucket->list);
311*b89261baSDavid van Moolenbroek     li = LL_FIRST(ll);
312*b89261baSDavid van Moolenbroek     while (li != NULL)
313*b89261baSDavid van Moolenbroek     {
314*b89261baSDavid van Moolenbroek 	h = (hash_item_uint *)li->datum;
315*b89261baSDavid van Moolenbroek 	k1 = h->key;
316*b89261baSDavid van Moolenbroek 	if (key == k1)
317*b89261baSDavid van Moolenbroek 	{
318*b89261baSDavid van Moolenbroek 	    /* found one */
319*b89261baSDavid van Moolenbroek 	    break;
320*b89261baSDavid van Moolenbroek 	}
321*b89261baSDavid van Moolenbroek 	li = LL_NEXT(ll, li);
322*b89261baSDavid van Moolenbroek     }
323*b89261baSDavid van Moolenbroek     li = NULL;
324*b89261baSDavid van Moolenbroek 
325*b89261baSDavid van Moolenbroek     /* is there already one there? */
326*b89261baSDavid van Moolenbroek     if (li == NULL)
327*b89261baSDavid van Moolenbroek     {
328*b89261baSDavid van Moolenbroek 	/* add the unique element to the buckets list */
329*b89261baSDavid van Moolenbroek 	ll_add(&(bucket->list), newli);
330*b89261baSDavid van Moolenbroek 	return NULL;
331*b89261baSDavid van Moolenbroek     }
332*b89261baSDavid van Moolenbroek     else
333*b89261baSDavid van Moolenbroek     {
334*b89261baSDavid van Moolenbroek 	/* free the stuff we just allocated */
335*b89261baSDavid van Moolenbroek 	ll_freeitem(newli);
336*b89261baSDavid van Moolenbroek 	return ((hash_item_uint *)(li->datum))->value;
337*b89261baSDavid van Moolenbroek     }
338*b89261baSDavid van Moolenbroek }
339*b89261baSDavid van Moolenbroek 
340*b89261baSDavid van Moolenbroek /*
341*b89261baSDavid van Moolenbroek  * void *hash_replace_uint(hash_table *ht, unsigned int key, void *value)
342*b89261baSDavid van Moolenbroek  *
343*b89261baSDavid van Moolenbroek  * Replace an existing value in the hash table with a new one and
344*b89261baSDavid van Moolenbroek  * return the old value.  If the key does not already exist in
345*b89261baSDavid van Moolenbroek  * the hash table, add a new element and return NULL.
346*b89261baSDavid van Moolenbroek  * Key type is unsigned int
347*b89261baSDavid van Moolenbroek  */
348*b89261baSDavid van Moolenbroek 
349*b89261baSDavid van Moolenbroek void *
hash_replace_uint(hash_table * ht,unsigned int key,void * value)350*b89261baSDavid van Moolenbroek hash_replace_uint(hash_table *ht, unsigned int key, void *value)
351*b89261baSDavid van Moolenbroek 
352*b89261baSDavid van Moolenbroek {
353*b89261baSDavid van Moolenbroek     bucket_t *bucket;
354*b89261baSDavid van Moolenbroek     hash_item_uint *hi;
355*b89261baSDavid van Moolenbroek     llist *ll;
356*b89261baSDavid van Moolenbroek     llistitem *li;
357*b89261baSDavid van Moolenbroek     void *result = NULL;
358*b89261baSDavid van Moolenbroek     unsigned int k1;
359*b89261baSDavid van Moolenbroek 
360*b89261baSDavid van Moolenbroek     /* find the bucket */
361*b89261baSDavid van Moolenbroek     bucket = &(ht->buckets[(key % ht->num_buckets)]);
362*b89261baSDavid van Moolenbroek 
363*b89261baSDavid van Moolenbroek     /* walk the list until we find the existing item */
364*b89261baSDavid van Moolenbroek     ll = &(bucket->list);
365*b89261baSDavid van Moolenbroek     li = LL_FIRST(ll);
366*b89261baSDavid van Moolenbroek     while (li != NULL)
367*b89261baSDavid van Moolenbroek     {
368*b89261baSDavid van Moolenbroek 	hi = (hash_item_uint *)li->datum;
369*b89261baSDavid van Moolenbroek 	k1 = hi->key;
370*b89261baSDavid van Moolenbroek 	if (key == k1)
371*b89261baSDavid van Moolenbroek 	{
372*b89261baSDavid van Moolenbroek 	    /* found it: now replace the value with the new one */
373*b89261baSDavid van Moolenbroek 	    result = hi->value;
374*b89261baSDavid van Moolenbroek 	    hi->value = value;
375*b89261baSDavid van Moolenbroek 	    break;
376*b89261baSDavid van Moolenbroek 	}
377*b89261baSDavid van Moolenbroek 	li = LL_NEXT(ll, li);
378*b89261baSDavid van Moolenbroek     }
379*b89261baSDavid van Moolenbroek 
380*b89261baSDavid van Moolenbroek     /* if the element wasnt found, add it */
381*b89261baSDavid van Moolenbroek     if (result == NULL)
382*b89261baSDavid van Moolenbroek     {
383*b89261baSDavid van Moolenbroek 	li = ll_newitem(sizeof(hash_item_uint));
384*b89261baSDavid van Moolenbroek 	hi = (hash_item_uint *)li->datum;
385*b89261baSDavid van Moolenbroek 	hi->key = key;
386*b89261baSDavid van Moolenbroek 	hi->value = value;
387*b89261baSDavid van Moolenbroek 	ll_add(&(bucket->list), li);
388*b89261baSDavid van Moolenbroek     }
389*b89261baSDavid van Moolenbroek 
390*b89261baSDavid van Moolenbroek     /* return the old value (so it can be freed) */
391*b89261baSDavid van Moolenbroek     return result;
392*b89261baSDavid van Moolenbroek }
393*b89261baSDavid van Moolenbroek 
394*b89261baSDavid van Moolenbroek /*
395*b89261baSDavid van Moolenbroek  * void *hash_lookup_uint(hash_table *ht, unsigned int key)
396*b89261baSDavid van Moolenbroek  *
397*b89261baSDavid van Moolenbroek  * Look up "key" in "ht" and return the associated value.  If "key"
398*b89261baSDavid van Moolenbroek  * is not found, return NULL.  Key type is unsigned int
399*b89261baSDavid van Moolenbroek  */
400*b89261baSDavid van Moolenbroek 
401*b89261baSDavid van Moolenbroek void *
hash_lookup_uint(hash_table * ht,unsigned int key)402*b89261baSDavid van Moolenbroek hash_lookup_uint(hash_table *ht, unsigned int key)
403*b89261baSDavid van Moolenbroek 
404*b89261baSDavid van Moolenbroek {
405*b89261baSDavid van Moolenbroek     bucket_t *bucket;
406*b89261baSDavid van Moolenbroek     llist *ll;
407*b89261baSDavid van Moolenbroek     llistitem *li;
408*b89261baSDavid van Moolenbroek     hash_item_uint *h;
409*b89261baSDavid van Moolenbroek     void *result;
410*b89261baSDavid van Moolenbroek     unsigned int k1;
411*b89261baSDavid van Moolenbroek 
412*b89261baSDavid van Moolenbroek     result = NULL;
413*b89261baSDavid van Moolenbroek     if ((bucket = &(ht->buckets[(key % ht->num_buckets)])) != NULL)
414*b89261baSDavid van Moolenbroek     {
415*b89261baSDavid van Moolenbroek 	ll = &(bucket->list);
416*b89261baSDavid van Moolenbroek 	li = LL_FIRST(ll);
417*b89261baSDavid van Moolenbroek 	while (li != NULL)
418*b89261baSDavid van Moolenbroek 	{
419*b89261baSDavid van Moolenbroek 	    h = (hash_item_uint *)li->datum;
420*b89261baSDavid van Moolenbroek 	    k1 = h->key;
421*b89261baSDavid van Moolenbroek 	    if (key == k1)
422*b89261baSDavid van Moolenbroek 	    {
423*b89261baSDavid van Moolenbroek 		result = h->value;
424*b89261baSDavid van Moolenbroek 		break;
425*b89261baSDavid van Moolenbroek 	    }
426*b89261baSDavid van Moolenbroek 	    li = LL_NEXT(ll, li);
427*b89261baSDavid van Moolenbroek 	}
428*b89261baSDavid van Moolenbroek     }
429*b89261baSDavid van Moolenbroek     return result;
430*b89261baSDavid van Moolenbroek }
431*b89261baSDavid van Moolenbroek 
432*b89261baSDavid van Moolenbroek /*
433*b89261baSDavid van Moolenbroek  * void *hash_remove_uint(hash_table *ht, unsigned int key)
434*b89261baSDavid van Moolenbroek  *
435*b89261baSDavid van Moolenbroek  * Remove the element associated with "key" from the hash table
436*b89261baSDavid van Moolenbroek  * "ht".  Return the value or NULL if the key was not found.
437*b89261baSDavid van Moolenbroek  */
438*b89261baSDavid van Moolenbroek 
439*b89261baSDavid van Moolenbroek void *
hash_remove_uint(hash_table * ht,unsigned int key)440*b89261baSDavid van Moolenbroek hash_remove_uint(hash_table *ht, unsigned int key)
441*b89261baSDavid van Moolenbroek 
442*b89261baSDavid van Moolenbroek {
443*b89261baSDavid van Moolenbroek     bucket_t *bucket;
444*b89261baSDavid van Moolenbroek     llist *ll;
445*b89261baSDavid van Moolenbroek     llistitem *li;
446*b89261baSDavid van Moolenbroek     llistitem *lilast;
447*b89261baSDavid van Moolenbroek     hash_item_uint *hi;
448*b89261baSDavid van Moolenbroek     void *result;
449*b89261baSDavid van Moolenbroek     unsigned int k1;
450*b89261baSDavid van Moolenbroek 
451*b89261baSDavid van Moolenbroek     result = NULL;
452*b89261baSDavid van Moolenbroek     if ((bucket = &(ht->buckets[(key % ht->num_buckets)])) != NULL)
453*b89261baSDavid van Moolenbroek     {
454*b89261baSDavid van Moolenbroek 	ll = &(bucket->list);
455*b89261baSDavid van Moolenbroek 	li = LL_FIRST(ll);
456*b89261baSDavid van Moolenbroek 	lilast = NULL;
457*b89261baSDavid van Moolenbroek 	while (li != NULL)
458*b89261baSDavid van Moolenbroek 	{
459*b89261baSDavid van Moolenbroek 	    hi = (hash_item_uint *)li->datum;
460*b89261baSDavid van Moolenbroek 	    k1 = hi->key;
461*b89261baSDavid van Moolenbroek 	    if (key == k1)
462*b89261baSDavid van Moolenbroek 	    {
463*b89261baSDavid van Moolenbroek 		ll_extract(ll, li, lilast);
464*b89261baSDavid van Moolenbroek 		result = hi->value;
465*b89261baSDavid van Moolenbroek 		key = hi->key;
466*b89261baSDavid van Moolenbroek 		;
467*b89261baSDavid van Moolenbroek 		ll_freeitem(li);
468*b89261baSDavid van Moolenbroek 		break;
469*b89261baSDavid van Moolenbroek 	    }
470*b89261baSDavid van Moolenbroek 	    lilast = li;
471*b89261baSDavid van Moolenbroek 	    li = LL_NEXT(ll, li);
472*b89261baSDavid van Moolenbroek 	}
473*b89261baSDavid van Moolenbroek     }
474*b89261baSDavid van Moolenbroek     return result;
475*b89261baSDavid van Moolenbroek }
476*b89261baSDavid van Moolenbroek 
477*b89261baSDavid van Moolenbroek /*
478*b89261baSDavid van Moolenbroek  * hash_item_uint *hash_first_uint(hash_table *ht, hash_pos *pos)
479*b89261baSDavid van Moolenbroek  *
480*b89261baSDavid van Moolenbroek  * First function to call when iterating through all items in the hash
481*b89261baSDavid van Moolenbroek  * table.  Returns the first item in "ht" and initializes "*pos" to track
482*b89261baSDavid van Moolenbroek  * the current position.
483*b89261baSDavid van Moolenbroek  */
484*b89261baSDavid van Moolenbroek 
485*b89261baSDavid van Moolenbroek hash_item_uint *
hash_first_uint(hash_table * ht,hash_pos * pos)486*b89261baSDavid van Moolenbroek hash_first_uint(hash_table *ht, hash_pos *pos)
487*b89261baSDavid van Moolenbroek 
488*b89261baSDavid van Moolenbroek {
489*b89261baSDavid van Moolenbroek     /* initialize pos for first item in first bucket */
490*b89261baSDavid van Moolenbroek     pos->num_buckets = ht->num_buckets;
491*b89261baSDavid van Moolenbroek     pos->hash_bucket = ht->buckets;
492*b89261baSDavid van Moolenbroek     pos->curr = 0;
493*b89261baSDavid van Moolenbroek     pos->ll_last = NULL;
494*b89261baSDavid van Moolenbroek 
495*b89261baSDavid van Moolenbroek     /* find the first non-empty bucket */
496*b89261baSDavid van Moolenbroek     while(pos->hash_bucket->list.count == 0)
497*b89261baSDavid van Moolenbroek     {
498*b89261baSDavid van Moolenbroek 	pos->hash_bucket++;
499*b89261baSDavid van Moolenbroek 	if (++pos->curr >= pos->num_buckets)
500*b89261baSDavid van Moolenbroek 	{
501*b89261baSDavid van Moolenbroek 	    return NULL;
502*b89261baSDavid van Moolenbroek 	}
503*b89261baSDavid van Moolenbroek     }
504*b89261baSDavid van Moolenbroek 
505*b89261baSDavid van Moolenbroek     /* set and return the first item */
506*b89261baSDavid van Moolenbroek     pos->ll_item = LL_FIRST(&(pos->hash_bucket->list));
507*b89261baSDavid van Moolenbroek     return (hash_item_uint *)pos->ll_item->datum;
508*b89261baSDavid van Moolenbroek }
509*b89261baSDavid van Moolenbroek 
510*b89261baSDavid van Moolenbroek 
511*b89261baSDavid van Moolenbroek /*
512*b89261baSDavid van Moolenbroek  * hash_item_uint *hash_next_uint(hash_pos *pos)
513*b89261baSDavid van Moolenbroek  *
514*b89261baSDavid van Moolenbroek  * Return the next item in the hash table, using "pos" as a description
515*b89261baSDavid van Moolenbroek  * of the present position in the hash table.  "pos" also identifies the
516*b89261baSDavid van Moolenbroek  * specific hash table.  Return NULL if there are no more elements.
517*b89261baSDavid van Moolenbroek  */
518*b89261baSDavid van Moolenbroek 
519*b89261baSDavid van Moolenbroek hash_item_uint *
hash_next_uint(hash_pos * pos)520*b89261baSDavid van Moolenbroek hash_next_uint(hash_pos *pos)
521*b89261baSDavid van Moolenbroek 
522*b89261baSDavid van Moolenbroek {
523*b89261baSDavid van Moolenbroek     llistitem *li;
524*b89261baSDavid van Moolenbroek 
525*b89261baSDavid van Moolenbroek     /* move item to last and check for NULL */
526*b89261baSDavid van Moolenbroek     if ((pos->ll_last = pos->ll_item) == NULL)
527*b89261baSDavid van Moolenbroek     {
528*b89261baSDavid van Moolenbroek 	/* are we really at the end of the hash table? */
529*b89261baSDavid van Moolenbroek 	if (pos->curr >= pos->num_buckets)
530*b89261baSDavid van Moolenbroek 	{
531*b89261baSDavid van Moolenbroek 	    /* yes: return NULL */
532*b89261baSDavid van Moolenbroek 	    return NULL;
533*b89261baSDavid van Moolenbroek 	}
534*b89261baSDavid van Moolenbroek 	/* no: regrab first item in current bucket list (might be NULL) */
535*b89261baSDavid van Moolenbroek 	li = LL_FIRST(&(pos->hash_bucket->list));
536*b89261baSDavid van Moolenbroek     }
537*b89261baSDavid van Moolenbroek     else
538*b89261baSDavid van Moolenbroek     {
539*b89261baSDavid van Moolenbroek 	/* get the next item in the llist */
540*b89261baSDavid van Moolenbroek 	li = LL_NEXT(&(pos->hash_bucket->list), pos->ll_item);
541*b89261baSDavid van Moolenbroek     }
542*b89261baSDavid van Moolenbroek 
543*b89261baSDavid van Moolenbroek     /* if its NULL we have to find another bucket */
544*b89261baSDavid van Moolenbroek     while (li == NULL)
545*b89261baSDavid van Moolenbroek     {
546*b89261baSDavid van Moolenbroek 	/* locate another bucket */
547*b89261baSDavid van Moolenbroek 	pos->ll_last = NULL;
548*b89261baSDavid van Moolenbroek 
549*b89261baSDavid van Moolenbroek 	/* move to the next one */
550*b89261baSDavid van Moolenbroek 	pos->hash_bucket++;
551*b89261baSDavid van Moolenbroek 	if (++pos->curr >= pos->num_buckets)
552*b89261baSDavid van Moolenbroek 	{
553*b89261baSDavid van Moolenbroek 	    /* at the end of the hash table */
554*b89261baSDavid van Moolenbroek 	    pos->ll_item = NULL;
555*b89261baSDavid van Moolenbroek 	    return NULL;
556*b89261baSDavid van Moolenbroek 	}
557*b89261baSDavid van Moolenbroek 
558*b89261baSDavid van Moolenbroek 	/* get the first element (might be NULL) */
559*b89261baSDavid van Moolenbroek 	li = LL_FIRST(&(pos->hash_bucket->list));
560*b89261baSDavid van Moolenbroek     }
561*b89261baSDavid van Moolenbroek 
562*b89261baSDavid van Moolenbroek     /* li is the next element to dish out */
563*b89261baSDavid van Moolenbroek     pos->ll_item = li;
564*b89261baSDavid van Moolenbroek     return (hash_item_uint *)li->datum;
565*b89261baSDavid van Moolenbroek }
566*b89261baSDavid van Moolenbroek 
567*b89261baSDavid van Moolenbroek /*
568*b89261baSDavid van Moolenbroek  * void *hash_remove_pos_uint(hash_pos *pos)
569*b89261baSDavid van Moolenbroek  *
570*b89261baSDavid van Moolenbroek  * Remove the hash table entry pointed to by position marker "pos".
571*b89261baSDavid van Moolenbroek  * The data from the entry is returned upon success, otherwise NULL.
572*b89261baSDavid van Moolenbroek  */
573*b89261baSDavid van Moolenbroek 
574*b89261baSDavid van Moolenbroek 
575*b89261baSDavid van Moolenbroek void *
hash_remove_pos_uint(hash_pos * pos)576*b89261baSDavid van Moolenbroek hash_remove_pos_uint(hash_pos *pos)
577*b89261baSDavid van Moolenbroek 
578*b89261baSDavid van Moolenbroek {
579*b89261baSDavid van Moolenbroek     llistitem *li;
580*b89261baSDavid van Moolenbroek     void *ans;
581*b89261baSDavid van Moolenbroek     hash_item_uint *hi;
582*b89261baSDavid van Moolenbroek 
583*b89261baSDavid van Moolenbroek     /* sanity checks */
584*b89261baSDavid van Moolenbroek     if (pos == NULL || pos->ll_last == pos->ll_item)
585*b89261baSDavid van Moolenbroek     {
586*b89261baSDavid van Moolenbroek 	return NULL;
587*b89261baSDavid van Moolenbroek     }
588*b89261baSDavid van Moolenbroek 
589*b89261baSDavid van Moolenbroek     /* at this point pos contains the item to remove (ll_item)
590*b89261baSDavid van Moolenbroek        and its predecesor (ll_last) */
591*b89261baSDavid van Moolenbroek     /* extract the item from the llist */
592*b89261baSDavid van Moolenbroek     li = pos->ll_item;
593*b89261baSDavid van Moolenbroek     ll_extract(&(pos->hash_bucket->list), li, pos->ll_last);
594*b89261baSDavid van Moolenbroek 
595*b89261baSDavid van Moolenbroek     /* retain the data */
596*b89261baSDavid van Moolenbroek     hi = (hash_item_uint *)li->datum;
597*b89261baSDavid van Moolenbroek     ans = hi->value;
598*b89261baSDavid van Moolenbroek 
599*b89261baSDavid van Moolenbroek     ll_freeitem(li);
600*b89261baSDavid van Moolenbroek 
601*b89261baSDavid van Moolenbroek     /* back up to previous item */
602*b89261baSDavid van Moolenbroek     /* its okay for ll_item to be null: hash_next will detect it */
603*b89261baSDavid van Moolenbroek     pos->ll_item = pos->ll_last;
604*b89261baSDavid van Moolenbroek 
605*b89261baSDavid van Moolenbroek     return ans;
606*b89261baSDavid van Moolenbroek }
607*b89261baSDavid van Moolenbroek 
608*b89261baSDavid van Moolenbroek 
609*b89261baSDavid van Moolenbroek 
610*b89261baSDavid van Moolenbroek /*
611*b89261baSDavid van Moolenbroek  * void hash_add_pid(hash_table *ht, pid_t key, void *value)
612*b89261baSDavid van Moolenbroek  *
613*b89261baSDavid van Moolenbroek  * Add an element to table "ht".  The element is described by
614*b89261baSDavid van Moolenbroek  * "key" and "value".  Return NULL on success.  If the key
615*b89261baSDavid van Moolenbroek  * already exists in the table, then no action is taken and
616*b89261baSDavid van Moolenbroek  * the data for the existing element is returned.
617*b89261baSDavid van Moolenbroek  * Key type is pid_t
618*b89261baSDavid van Moolenbroek  */
619*b89261baSDavid van Moolenbroek 
620*b89261baSDavid van Moolenbroek void *
hash_add_pid(hash_table * ht,pid_t key,void * value)621*b89261baSDavid van Moolenbroek hash_add_pid(hash_table *ht, pid_t key, void *value)
622*b89261baSDavid van Moolenbroek 
623*b89261baSDavid van Moolenbroek {
624*b89261baSDavid van Moolenbroek     bucket_t *bucket;
625*b89261baSDavid van Moolenbroek     hash_item_pid *hi;
626*b89261baSDavid van Moolenbroek     hash_item_pid *h;
627*b89261baSDavid van Moolenbroek     llist *ll;
628*b89261baSDavid van Moolenbroek     llistitem *li;
629*b89261baSDavid van Moolenbroek     llistitem *newli;
630*b89261baSDavid van Moolenbroek     pid_t k1;
631*b89261baSDavid van Moolenbroek 
632*b89261baSDavid van Moolenbroek     /* allocate the space we will need */
633*b89261baSDavid van Moolenbroek     newli = ll_newitem(sizeof(hash_item_pid));
634*b89261baSDavid van Moolenbroek     hi = (hash_item_pid *)newli->datum;
635*b89261baSDavid van Moolenbroek 
636*b89261baSDavid van Moolenbroek     /* fill in the values */
637*b89261baSDavid van Moolenbroek     hi->key = key;
638*b89261baSDavid van Moolenbroek     hi->value = value;
639*b89261baSDavid van Moolenbroek 
640*b89261baSDavid van Moolenbroek     /* hash to the bucket */
641*b89261baSDavid van Moolenbroek     bucket = &(ht->buckets[(key % ht->num_buckets)]);
642*b89261baSDavid van Moolenbroek 
643*b89261baSDavid van Moolenbroek     /* walk the list to make sure we do not have a duplicate */
644*b89261baSDavid van Moolenbroek     ll = &(bucket->list);
645*b89261baSDavid van Moolenbroek     li = LL_FIRST(ll);
646*b89261baSDavid van Moolenbroek     while (li != NULL)
647*b89261baSDavid van Moolenbroek     {
648*b89261baSDavid van Moolenbroek 	h = (hash_item_pid *)li->datum;
649*b89261baSDavid van Moolenbroek 	k1 = h->key;
650*b89261baSDavid van Moolenbroek 	if (key == k1)
651*b89261baSDavid van Moolenbroek 	{
652*b89261baSDavid van Moolenbroek 	    /* found one */
653*b89261baSDavid van Moolenbroek 	    break;
654*b89261baSDavid van Moolenbroek 	}
655*b89261baSDavid van Moolenbroek 	li = LL_NEXT(ll, li);
656*b89261baSDavid van Moolenbroek     }
657*b89261baSDavid van Moolenbroek     li = NULL;
658*b89261baSDavid van Moolenbroek 
659*b89261baSDavid van Moolenbroek     /* is there already one there? */
660*b89261baSDavid van Moolenbroek     if (li == NULL)
661*b89261baSDavid van Moolenbroek     {
662*b89261baSDavid van Moolenbroek 	/* add the unique element to the buckets list */
663*b89261baSDavid van Moolenbroek 	ll_add(&(bucket->list), newli);
664*b89261baSDavid van Moolenbroek 	return NULL;
665*b89261baSDavid van Moolenbroek     }
666*b89261baSDavid van Moolenbroek     else
667*b89261baSDavid van Moolenbroek     {
668*b89261baSDavid van Moolenbroek 	/* free the stuff we just allocated */
669*b89261baSDavid van Moolenbroek 	ll_freeitem(newli);
670*b89261baSDavid van Moolenbroek 	return ((hash_item_pid *)(li->datum))->value;
671*b89261baSDavid van Moolenbroek     }
672*b89261baSDavid van Moolenbroek }
673*b89261baSDavid van Moolenbroek 
674*b89261baSDavid van Moolenbroek /*
675*b89261baSDavid van Moolenbroek  * void *hash_replace_pid(hash_table *ht, pid_t key, void *value)
676*b89261baSDavid van Moolenbroek  *
677*b89261baSDavid van Moolenbroek  * Replace an existing value in the hash table with a new one and
678*b89261baSDavid van Moolenbroek  * return the old value.  If the key does not already exist in
679*b89261baSDavid van Moolenbroek  * the hash table, add a new element and return NULL.
680*b89261baSDavid van Moolenbroek  * Key type is pid_t
681*b89261baSDavid van Moolenbroek  */
682*b89261baSDavid van Moolenbroek 
683*b89261baSDavid van Moolenbroek void *
hash_replace_pid(hash_table * ht,pid_t key,void * value)684*b89261baSDavid van Moolenbroek hash_replace_pid(hash_table *ht, pid_t key, void *value)
685*b89261baSDavid van Moolenbroek 
686*b89261baSDavid van Moolenbroek {
687*b89261baSDavid van Moolenbroek     bucket_t *bucket;
688*b89261baSDavid van Moolenbroek     hash_item_pid *hi;
689*b89261baSDavid van Moolenbroek     llist *ll;
690*b89261baSDavid van Moolenbroek     llistitem *li;
691*b89261baSDavid van Moolenbroek     void *result = NULL;
692*b89261baSDavid van Moolenbroek     pid_t k1;
693*b89261baSDavid van Moolenbroek 
694*b89261baSDavid van Moolenbroek     /* find the bucket */
695*b89261baSDavid van Moolenbroek     bucket = &(ht->buckets[(key % ht->num_buckets)]);
696*b89261baSDavid van Moolenbroek 
697*b89261baSDavid van Moolenbroek     /* walk the list until we find the existing item */
698*b89261baSDavid van Moolenbroek     ll = &(bucket->list);
699*b89261baSDavid van Moolenbroek     li = LL_FIRST(ll);
700*b89261baSDavid van Moolenbroek     while (li != NULL)
701*b89261baSDavid van Moolenbroek     {
702*b89261baSDavid van Moolenbroek 	hi = (hash_item_pid *)li->datum;
703*b89261baSDavid van Moolenbroek 	k1 = hi->key;
704*b89261baSDavid van Moolenbroek 	if (key == k1)
705*b89261baSDavid van Moolenbroek 	{
706*b89261baSDavid van Moolenbroek 	    /* found it: now replace the value with the new one */
707*b89261baSDavid van Moolenbroek 	    result = hi->value;
708*b89261baSDavid van Moolenbroek 	    hi->value = value;
709*b89261baSDavid van Moolenbroek 	    break;
710*b89261baSDavid van Moolenbroek 	}
711*b89261baSDavid van Moolenbroek 	li = LL_NEXT(ll, li);
712*b89261baSDavid van Moolenbroek     }
713*b89261baSDavid van Moolenbroek 
714*b89261baSDavid van Moolenbroek     /* if the element wasnt found, add it */
715*b89261baSDavid van Moolenbroek     if (result == NULL)
716*b89261baSDavid van Moolenbroek     {
717*b89261baSDavid van Moolenbroek 	li = ll_newitem(sizeof(hash_item_pid));
718*b89261baSDavid van Moolenbroek 	hi = (hash_item_pid *)li->datum;
719*b89261baSDavid van Moolenbroek 	hi->key = key;
720*b89261baSDavid van Moolenbroek 	hi->value = value;
721*b89261baSDavid van Moolenbroek 	ll_add(&(bucket->list), li);
722*b89261baSDavid van Moolenbroek     }
723*b89261baSDavid van Moolenbroek 
724*b89261baSDavid van Moolenbroek     /* return the old value (so it can be freed) */
725*b89261baSDavid van Moolenbroek     return result;
726*b89261baSDavid van Moolenbroek }
727*b89261baSDavid van Moolenbroek 
728*b89261baSDavid van Moolenbroek /*
729*b89261baSDavid van Moolenbroek  * void *hash_lookup_pid(hash_table *ht, pid_t key)
730*b89261baSDavid van Moolenbroek  *
731*b89261baSDavid van Moolenbroek  * Look up "key" in "ht" and return the associated value.  If "key"
732*b89261baSDavid van Moolenbroek  * is not found, return NULL.  Key type is pid_t
733*b89261baSDavid van Moolenbroek  */
734*b89261baSDavid van Moolenbroek 
735*b89261baSDavid van Moolenbroek void *
hash_lookup_pid(hash_table * ht,pid_t key)736*b89261baSDavid van Moolenbroek hash_lookup_pid(hash_table *ht, pid_t key)
737*b89261baSDavid van Moolenbroek 
738*b89261baSDavid van Moolenbroek {
739*b89261baSDavid van Moolenbroek     bucket_t *bucket;
740*b89261baSDavid van Moolenbroek     llist *ll;
741*b89261baSDavid van Moolenbroek     llistitem *li;
742*b89261baSDavid van Moolenbroek     hash_item_pid *h;
743*b89261baSDavid van Moolenbroek     void *result;
744*b89261baSDavid van Moolenbroek     pid_t k1;
745*b89261baSDavid van Moolenbroek 
746*b89261baSDavid van Moolenbroek     result = NULL;
747*b89261baSDavid van Moolenbroek     if ((bucket = &(ht->buckets[(key % ht->num_buckets)])) != NULL)
748*b89261baSDavid van Moolenbroek     {
749*b89261baSDavid van Moolenbroek 	ll = &(bucket->list);
750*b89261baSDavid van Moolenbroek 	li = LL_FIRST(ll);
751*b89261baSDavid van Moolenbroek 	while (li != NULL)
752*b89261baSDavid van Moolenbroek 	{
753*b89261baSDavid van Moolenbroek 	    h = (hash_item_pid *)li->datum;
754*b89261baSDavid van Moolenbroek 	    k1 = h->key;
755*b89261baSDavid van Moolenbroek 	    if (key == k1)
756*b89261baSDavid van Moolenbroek 	    {
757*b89261baSDavid van Moolenbroek 		result = h->value;
758*b89261baSDavid van Moolenbroek 		break;
759*b89261baSDavid van Moolenbroek 	    }
760*b89261baSDavid van Moolenbroek 	    li = LL_NEXT(ll, li);
761*b89261baSDavid van Moolenbroek 	}
762*b89261baSDavid van Moolenbroek     }
763*b89261baSDavid van Moolenbroek     return result;
764*b89261baSDavid van Moolenbroek }
765*b89261baSDavid van Moolenbroek 
766*b89261baSDavid van Moolenbroek /*
767*b89261baSDavid van Moolenbroek  * void *hash_remove_pid(hash_table *ht, pid_t key)
768*b89261baSDavid van Moolenbroek  *
769*b89261baSDavid van Moolenbroek  * Remove the element associated with "key" from the hash table
770*b89261baSDavid van Moolenbroek  * "ht".  Return the value or NULL if the key was not found.
771*b89261baSDavid van Moolenbroek  */
772*b89261baSDavid van Moolenbroek 
773*b89261baSDavid van Moolenbroek void *
hash_remove_pid(hash_table * ht,pid_t key)774*b89261baSDavid van Moolenbroek hash_remove_pid(hash_table *ht, pid_t key)
775*b89261baSDavid van Moolenbroek 
776*b89261baSDavid van Moolenbroek {
777*b89261baSDavid van Moolenbroek     bucket_t *bucket;
778*b89261baSDavid van Moolenbroek     llist *ll;
779*b89261baSDavid van Moolenbroek     llistitem *li;
780*b89261baSDavid van Moolenbroek     llistitem *lilast;
781*b89261baSDavid van Moolenbroek     hash_item_pid *hi;
782*b89261baSDavid van Moolenbroek     void *result;
783*b89261baSDavid van Moolenbroek     pid_t k1;
784*b89261baSDavid van Moolenbroek 
785*b89261baSDavid van Moolenbroek     result = NULL;
786*b89261baSDavid van Moolenbroek     if ((bucket = &(ht->buckets[(key % ht->num_buckets)])) != NULL)
787*b89261baSDavid van Moolenbroek     {
788*b89261baSDavid van Moolenbroek 	ll = &(bucket->list);
789*b89261baSDavid van Moolenbroek 	li = LL_FIRST(ll);
790*b89261baSDavid van Moolenbroek 	lilast = NULL;
791*b89261baSDavid van Moolenbroek 	while (li != NULL)
792*b89261baSDavid van Moolenbroek 	{
793*b89261baSDavid van Moolenbroek 	    hi = (hash_item_pid *)li->datum;
794*b89261baSDavid van Moolenbroek 	    k1 = hi->key;
795*b89261baSDavid van Moolenbroek 	    if (key == k1)
796*b89261baSDavid van Moolenbroek 	    {
797*b89261baSDavid van Moolenbroek 		ll_extract(ll, li, lilast);
798*b89261baSDavid van Moolenbroek 		result = hi->value;
799*b89261baSDavid van Moolenbroek 		key = hi->key;
800*b89261baSDavid van Moolenbroek 		;
801*b89261baSDavid van Moolenbroek 		ll_freeitem(li);
802*b89261baSDavid van Moolenbroek 		break;
803*b89261baSDavid van Moolenbroek 	    }
804*b89261baSDavid van Moolenbroek 	    lilast = li;
805*b89261baSDavid van Moolenbroek 	    li = LL_NEXT(ll, li);
806*b89261baSDavid van Moolenbroek 	}
807*b89261baSDavid van Moolenbroek     }
808*b89261baSDavid van Moolenbroek     return result;
809*b89261baSDavid van Moolenbroek }
810*b89261baSDavid van Moolenbroek 
811*b89261baSDavid van Moolenbroek /*
812*b89261baSDavid van Moolenbroek  * hash_item_pid *hash_first_pid(hash_table *ht, hash_pos *pos)
813*b89261baSDavid van Moolenbroek  *
814*b89261baSDavid van Moolenbroek  * First function to call when iterating through all items in the hash
815*b89261baSDavid van Moolenbroek  * table.  Returns the first item in "ht" and initializes "*pos" to track
816*b89261baSDavid van Moolenbroek  * the current position.
817*b89261baSDavid van Moolenbroek  */
818*b89261baSDavid van Moolenbroek 
819*b89261baSDavid van Moolenbroek hash_item_pid *
hash_first_pid(hash_table * ht,hash_pos * pos)820*b89261baSDavid van Moolenbroek hash_first_pid(hash_table *ht, hash_pos *pos)
821*b89261baSDavid van Moolenbroek 
822*b89261baSDavid van Moolenbroek {
823*b89261baSDavid van Moolenbroek     /* initialize pos for first item in first bucket */
824*b89261baSDavid van Moolenbroek     pos->num_buckets = ht->num_buckets;
825*b89261baSDavid van Moolenbroek     pos->hash_bucket = ht->buckets;
826*b89261baSDavid van Moolenbroek     pos->curr = 0;
827*b89261baSDavid van Moolenbroek     pos->ll_last = NULL;
828*b89261baSDavid van Moolenbroek 
829*b89261baSDavid van Moolenbroek     /* find the first non-empty bucket */
830*b89261baSDavid van Moolenbroek     while(pos->hash_bucket->list.count == 0)
831*b89261baSDavid van Moolenbroek     {
832*b89261baSDavid van Moolenbroek 	pos->hash_bucket++;
833*b89261baSDavid van Moolenbroek 	if (++pos->curr >= pos->num_buckets)
834*b89261baSDavid van Moolenbroek 	{
835*b89261baSDavid van Moolenbroek 	    return NULL;
836*b89261baSDavid van Moolenbroek 	}
837*b89261baSDavid van Moolenbroek     }
838*b89261baSDavid van Moolenbroek 
839*b89261baSDavid van Moolenbroek     /* set and return the first item */
840*b89261baSDavid van Moolenbroek     pos->ll_item = LL_FIRST(&(pos->hash_bucket->list));
841*b89261baSDavid van Moolenbroek     return (hash_item_pid *)pos->ll_item->datum;
842*b89261baSDavid van Moolenbroek }
843*b89261baSDavid van Moolenbroek 
844*b89261baSDavid van Moolenbroek 
845*b89261baSDavid van Moolenbroek /*
846*b89261baSDavid van Moolenbroek  * hash_item_pid *hash_next_pid(hash_pos *pos)
847*b89261baSDavid van Moolenbroek  *
848*b89261baSDavid van Moolenbroek  * Return the next item in the hash table, using "pos" as a description
849*b89261baSDavid van Moolenbroek  * of the present position in the hash table.  "pos" also identifies the
850*b89261baSDavid van Moolenbroek  * specific hash table.  Return NULL if there are no more elements.
851*b89261baSDavid van Moolenbroek  */
852*b89261baSDavid van Moolenbroek 
853*b89261baSDavid van Moolenbroek hash_item_pid *
hash_next_pid(hash_pos * pos)854*b89261baSDavid van Moolenbroek hash_next_pid(hash_pos *pos)
855*b89261baSDavid van Moolenbroek 
856*b89261baSDavid van Moolenbroek {
857*b89261baSDavid van Moolenbroek     llistitem *li;
858*b89261baSDavid van Moolenbroek 
859*b89261baSDavid van Moolenbroek     /* move item to last and check for NULL */
860*b89261baSDavid van Moolenbroek     if ((pos->ll_last = pos->ll_item) == NULL)
861*b89261baSDavid van Moolenbroek     {
862*b89261baSDavid van Moolenbroek 	/* are we really at the end of the hash table? */
863*b89261baSDavid van Moolenbroek 	if (pos->curr >= pos->num_buckets)
864*b89261baSDavid van Moolenbroek 	{
865*b89261baSDavid van Moolenbroek 	    /* yes: return NULL */
866*b89261baSDavid van Moolenbroek 	    return NULL;
867*b89261baSDavid van Moolenbroek 	}
868*b89261baSDavid van Moolenbroek 	/* no: regrab first item in current bucket list (might be NULL) */
869*b89261baSDavid van Moolenbroek 	li = LL_FIRST(&(pos->hash_bucket->list));
870*b89261baSDavid van Moolenbroek     }
871*b89261baSDavid van Moolenbroek     else
872*b89261baSDavid van Moolenbroek     {
873*b89261baSDavid van Moolenbroek 	/* get the next item in the llist */
874*b89261baSDavid van Moolenbroek 	li = LL_NEXT(&(pos->hash_bucket->list), pos->ll_item);
875*b89261baSDavid van Moolenbroek     }
876*b89261baSDavid van Moolenbroek 
877*b89261baSDavid van Moolenbroek     /* if its NULL we have to find another bucket */
878*b89261baSDavid van Moolenbroek     while (li == NULL)
879*b89261baSDavid van Moolenbroek     {
880*b89261baSDavid van Moolenbroek 	/* locate another bucket */
881*b89261baSDavid van Moolenbroek 	pos->ll_last = NULL;
882*b89261baSDavid van Moolenbroek 
883*b89261baSDavid van Moolenbroek 	/* move to the next one */
884*b89261baSDavid van Moolenbroek 	pos->hash_bucket++;
885*b89261baSDavid van Moolenbroek 	if (++pos->curr >= pos->num_buckets)
886*b89261baSDavid van Moolenbroek 	{
887*b89261baSDavid van Moolenbroek 	    /* at the end of the hash table */
888*b89261baSDavid van Moolenbroek 	    pos->ll_item = NULL;
889*b89261baSDavid van Moolenbroek 	    return NULL;
890*b89261baSDavid van Moolenbroek 	}
891*b89261baSDavid van Moolenbroek 
892*b89261baSDavid van Moolenbroek 	/* get the first element (might be NULL) */
893*b89261baSDavid van Moolenbroek 	li = LL_FIRST(&(pos->hash_bucket->list));
894*b89261baSDavid van Moolenbroek     }
895*b89261baSDavid van Moolenbroek 
896*b89261baSDavid van Moolenbroek     /* li is the next element to dish out */
897*b89261baSDavid van Moolenbroek     pos->ll_item = li;
898*b89261baSDavid van Moolenbroek     return (hash_item_pid *)li->datum;
899*b89261baSDavid van Moolenbroek }
900*b89261baSDavid van Moolenbroek 
901*b89261baSDavid van Moolenbroek /*
902*b89261baSDavid van Moolenbroek  * void *hash_remove_pos_pid(hash_pos *pos)
903*b89261baSDavid van Moolenbroek  *
904*b89261baSDavid van Moolenbroek  * Remove the hash table entry pointed to by position marker "pos".
905*b89261baSDavid van Moolenbroek  * The data from the entry is returned upon success, otherwise NULL.
906*b89261baSDavid van Moolenbroek  */
907*b89261baSDavid van Moolenbroek 
908*b89261baSDavid van Moolenbroek 
909*b89261baSDavid van Moolenbroek void *
hash_remove_pos_pid(hash_pos * pos)910*b89261baSDavid van Moolenbroek hash_remove_pos_pid(hash_pos *pos)
911*b89261baSDavid van Moolenbroek 
912*b89261baSDavid van Moolenbroek {
913*b89261baSDavid van Moolenbroek     llistitem *li;
914*b89261baSDavid van Moolenbroek     void *ans;
915*b89261baSDavid van Moolenbroek     hash_item_pid *hi;
916*b89261baSDavid van Moolenbroek 
917*b89261baSDavid van Moolenbroek     /* sanity checks */
918*b89261baSDavid van Moolenbroek     if (pos == NULL || pos->ll_last == pos->ll_item)
919*b89261baSDavid van Moolenbroek     {
920*b89261baSDavid van Moolenbroek 	return NULL;
921*b89261baSDavid van Moolenbroek     }
922*b89261baSDavid van Moolenbroek 
923*b89261baSDavid van Moolenbroek     /* at this point pos contains the item to remove (ll_item)
924*b89261baSDavid van Moolenbroek        and its predecesor (ll_last) */
925*b89261baSDavid van Moolenbroek     /* extract the item from the llist */
926*b89261baSDavid van Moolenbroek     li = pos->ll_item;
927*b89261baSDavid van Moolenbroek     ll_extract(&(pos->hash_bucket->list), li, pos->ll_last);
928*b89261baSDavid van Moolenbroek 
929*b89261baSDavid van Moolenbroek     /* retain the data */
930*b89261baSDavid van Moolenbroek     hi = (hash_item_pid *)li->datum;
931*b89261baSDavid van Moolenbroek     ans = hi->value;
932*b89261baSDavid van Moolenbroek 
933*b89261baSDavid van Moolenbroek     /* free up the space */
934*b89261baSDavid van Moolenbroek     ll_freeitem(li);
935*b89261baSDavid van Moolenbroek 
936*b89261baSDavid van Moolenbroek     /* back up to previous item */
937*b89261baSDavid van Moolenbroek     /* its okay for ll_item to be null: hash_next will detect it */
938*b89261baSDavid van Moolenbroek     pos->ll_item = pos->ll_last;
939*b89261baSDavid van Moolenbroek 
940*b89261baSDavid van Moolenbroek     return ans;
941*b89261baSDavid van Moolenbroek }
942*b89261baSDavid van Moolenbroek 
943*b89261baSDavid van Moolenbroek 
944*b89261baSDavid van Moolenbroek 
945*b89261baSDavid van Moolenbroek /*
946*b89261baSDavid van Moolenbroek  * void hash_add_string(hash_table *ht, char * key, void *value)
947*b89261baSDavid van Moolenbroek  *
948*b89261baSDavid van Moolenbroek  * Add an element to table "ht".  The element is described by
949*b89261baSDavid van Moolenbroek  * "key" and "value".  Return NULL on success.  If the key
950*b89261baSDavid van Moolenbroek  * already exists in the table, then no action is taken and
951*b89261baSDavid van Moolenbroek  * the data for the existing element is returned.
952*b89261baSDavid van Moolenbroek  * Key type is char *
953*b89261baSDavid van Moolenbroek  */
954*b89261baSDavid van Moolenbroek 
955*b89261baSDavid van Moolenbroek void *
hash_add_string(hash_table * ht,char * key,void * value)956*b89261baSDavid van Moolenbroek hash_add_string(hash_table *ht, char * key, void *value)
957*b89261baSDavid van Moolenbroek 
958*b89261baSDavid van Moolenbroek {
959*b89261baSDavid van Moolenbroek     bucket_t *bucket;
960*b89261baSDavid van Moolenbroek     hash_item_string *hi;
961*b89261baSDavid van Moolenbroek     hash_item_string *h;
962*b89261baSDavid van Moolenbroek     llist *ll;
963*b89261baSDavid van Moolenbroek     llistitem *li;
964*b89261baSDavid van Moolenbroek     llistitem *newli;
965*b89261baSDavid van Moolenbroek     char * k1;
966*b89261baSDavid van Moolenbroek 
967*b89261baSDavid van Moolenbroek     /* allocate the space we will need */
968*b89261baSDavid van Moolenbroek     newli = ll_newitem(sizeof(hash_item_string));
969*b89261baSDavid van Moolenbroek     hi = (hash_item_string *)newli->datum;
970*b89261baSDavid van Moolenbroek 
971*b89261baSDavid van Moolenbroek     /* fill in the values */
972*b89261baSDavid van Moolenbroek     hi->key = estrdup(key);
973*b89261baSDavid van Moolenbroek     hi->value = value;
974*b89261baSDavid van Moolenbroek 
975*b89261baSDavid van Moolenbroek     /* hash to the bucket */
976*b89261baSDavid van Moolenbroek     bucket = &(ht->buckets[string_hash(ht, key)]);
977*b89261baSDavid van Moolenbroek 
978*b89261baSDavid van Moolenbroek     /* walk the list to make sure we do not have a duplicate */
979*b89261baSDavid van Moolenbroek     ll = &(bucket->list);
980*b89261baSDavid van Moolenbroek     li = LL_FIRST(ll);
981*b89261baSDavid van Moolenbroek     while (li != NULL)
982*b89261baSDavid van Moolenbroek     {
983*b89261baSDavid van Moolenbroek 	h = (hash_item_string *)li->datum;
984*b89261baSDavid van Moolenbroek 	k1 = h->key;
985*b89261baSDavid van Moolenbroek 	if (strcmp(key, k1) == 0)
986*b89261baSDavid van Moolenbroek 	{
987*b89261baSDavid van Moolenbroek 	    /* found one */
988*b89261baSDavid van Moolenbroek 	    break;
989*b89261baSDavid van Moolenbroek 	}
990*b89261baSDavid van Moolenbroek 	li = LL_NEXT(ll, li);
991*b89261baSDavid van Moolenbroek     }
992*b89261baSDavid van Moolenbroek     li = NULL;
993*b89261baSDavid van Moolenbroek 
994*b89261baSDavid van Moolenbroek     /* is there already one there? */
995*b89261baSDavid van Moolenbroek     if (li == NULL)
996*b89261baSDavid van Moolenbroek     {
997*b89261baSDavid van Moolenbroek 	/* add the unique element to the buckets list */
998*b89261baSDavid van Moolenbroek 	ll_add(&(bucket->list), newli);
999*b89261baSDavid van Moolenbroek 	return NULL;
1000*b89261baSDavid van Moolenbroek     }
1001*b89261baSDavid van Moolenbroek     else
1002*b89261baSDavid van Moolenbroek     {
1003*b89261baSDavid van Moolenbroek 	/* free the stuff we just allocated */
1004*b89261baSDavid van Moolenbroek 	ll_freeitem(newli);
1005*b89261baSDavid van Moolenbroek 	return ((hash_item_string *)(li->datum))->value;
1006*b89261baSDavid van Moolenbroek     }
1007*b89261baSDavid van Moolenbroek }
1008*b89261baSDavid van Moolenbroek 
1009*b89261baSDavid van Moolenbroek /*
1010*b89261baSDavid van Moolenbroek  * void *hash_replace_string(hash_table *ht, char * key, void *value)
1011*b89261baSDavid van Moolenbroek  *
1012*b89261baSDavid van Moolenbroek  * Replace an existing value in the hash table with a new one and
1013*b89261baSDavid van Moolenbroek  * return the old value.  If the key does not already exist in
1014*b89261baSDavid van Moolenbroek  * the hash table, add a new element and return NULL.
1015*b89261baSDavid van Moolenbroek  * Key type is char *
1016*b89261baSDavid van Moolenbroek  */
1017*b89261baSDavid van Moolenbroek 
1018*b89261baSDavid van Moolenbroek void *
hash_replace_string(hash_table * ht,char * key,void * value)1019*b89261baSDavid van Moolenbroek hash_replace_string(hash_table *ht, char * key, void *value)
1020*b89261baSDavid van Moolenbroek 
1021*b89261baSDavid van Moolenbroek {
1022*b89261baSDavid van Moolenbroek     bucket_t *bucket;
1023*b89261baSDavid van Moolenbroek     hash_item_string *hi;
1024*b89261baSDavid van Moolenbroek     llist *ll;
1025*b89261baSDavid van Moolenbroek     llistitem *li;
1026*b89261baSDavid van Moolenbroek     void *result = NULL;
1027*b89261baSDavid van Moolenbroek     char * k1;
1028*b89261baSDavid van Moolenbroek 
1029*b89261baSDavid van Moolenbroek     /* find the bucket */
1030*b89261baSDavid van Moolenbroek     bucket = &(ht->buckets[string_hash(ht, key)]);
1031*b89261baSDavid van Moolenbroek 
1032*b89261baSDavid van Moolenbroek     /* walk the list until we find the existing item */
1033*b89261baSDavid van Moolenbroek     ll = &(bucket->list);
1034*b89261baSDavid van Moolenbroek     li = LL_FIRST(ll);
1035*b89261baSDavid van Moolenbroek     while (li != NULL)
1036*b89261baSDavid van Moolenbroek     {
1037*b89261baSDavid van Moolenbroek 	hi = (hash_item_string *)li->datum;
1038*b89261baSDavid van Moolenbroek 	k1 = hi->key;
1039*b89261baSDavid van Moolenbroek 	if (strcmp(key, k1) == 0)
1040*b89261baSDavid van Moolenbroek 	{
1041*b89261baSDavid van Moolenbroek 	    /* found it: now replace the value with the new one */
1042*b89261baSDavid van Moolenbroek 	    result = hi->value;
1043*b89261baSDavid van Moolenbroek 	    hi->value = value;
1044*b89261baSDavid van Moolenbroek 	    break;
1045*b89261baSDavid van Moolenbroek 	}
1046*b89261baSDavid van Moolenbroek 	li = LL_NEXT(ll, li);
1047*b89261baSDavid van Moolenbroek     }
1048*b89261baSDavid van Moolenbroek 
1049*b89261baSDavid van Moolenbroek     /* if the element wasnt found, add it */
1050*b89261baSDavid van Moolenbroek     if (result == NULL)
1051*b89261baSDavid van Moolenbroek     {
1052*b89261baSDavid van Moolenbroek 	li = ll_newitem(sizeof(hash_item_string));
1053*b89261baSDavid van Moolenbroek 	hi = (hash_item_string *)li->datum;
1054*b89261baSDavid van Moolenbroek 	hi->key = estrdup(key);
1055*b89261baSDavid van Moolenbroek 	hi->value = value;
1056*b89261baSDavid van Moolenbroek 	ll_add(&(bucket->list), li);
1057*b89261baSDavid van Moolenbroek     }
1058*b89261baSDavid van Moolenbroek 
1059*b89261baSDavid van Moolenbroek     /* return the old value (so it can be freed) */
1060*b89261baSDavid van Moolenbroek     return result;
1061*b89261baSDavid van Moolenbroek }
1062*b89261baSDavid van Moolenbroek 
1063*b89261baSDavid van Moolenbroek /*
1064*b89261baSDavid van Moolenbroek  * void *hash_lookup_string(hash_table *ht, char * key)
1065*b89261baSDavid van Moolenbroek  *
1066*b89261baSDavid van Moolenbroek  * Look up "key" in "ht" and return the associated value.  If "key"
1067*b89261baSDavid van Moolenbroek  * is not found, return NULL.  Key type is char *
1068*b89261baSDavid van Moolenbroek  */
1069*b89261baSDavid van Moolenbroek 
1070*b89261baSDavid van Moolenbroek void *
hash_lookup_string(hash_table * ht,char * key)1071*b89261baSDavid van Moolenbroek hash_lookup_string(hash_table *ht, char * key)
1072*b89261baSDavid van Moolenbroek 
1073*b89261baSDavid van Moolenbroek {
1074*b89261baSDavid van Moolenbroek     bucket_t *bucket;
1075*b89261baSDavid van Moolenbroek     llist *ll;
1076*b89261baSDavid van Moolenbroek     llistitem *li;
1077*b89261baSDavid van Moolenbroek     hash_item_string *h;
1078*b89261baSDavid van Moolenbroek     void *result;
1079*b89261baSDavid van Moolenbroek     char * k1;
1080*b89261baSDavid van Moolenbroek 
1081*b89261baSDavid van Moolenbroek     result = NULL;
1082*b89261baSDavid van Moolenbroek     if ((bucket = &(ht->buckets[string_hash(ht, key)])) != NULL)
1083*b89261baSDavid van Moolenbroek     {
1084*b89261baSDavid van Moolenbroek 	ll = &(bucket->list);
1085*b89261baSDavid van Moolenbroek 	li = LL_FIRST(ll);
1086*b89261baSDavid van Moolenbroek 	while (li != NULL)
1087*b89261baSDavid van Moolenbroek 	{
1088*b89261baSDavid van Moolenbroek 	    h = (hash_item_string *)li->datum;
1089*b89261baSDavid van Moolenbroek 	    k1 = h->key;
1090*b89261baSDavid van Moolenbroek 	    if (strcmp(key, k1) == 0)
1091*b89261baSDavid van Moolenbroek 	    {
1092*b89261baSDavid van Moolenbroek 		result = h->value;
1093*b89261baSDavid van Moolenbroek 		break;
1094*b89261baSDavid van Moolenbroek 	    }
1095*b89261baSDavid van Moolenbroek 	    li = LL_NEXT(ll, li);
1096*b89261baSDavid van Moolenbroek 	}
1097*b89261baSDavid van Moolenbroek     }
1098*b89261baSDavid van Moolenbroek     return result;
1099*b89261baSDavid van Moolenbroek }
1100*b89261baSDavid van Moolenbroek 
1101*b89261baSDavid van Moolenbroek /*
1102*b89261baSDavid van Moolenbroek  * void *hash_remove_string(hash_table *ht, char * key)
1103*b89261baSDavid van Moolenbroek  *
1104*b89261baSDavid van Moolenbroek  * Remove the element associated with "key" from the hash table
1105*b89261baSDavid van Moolenbroek  * "ht".  Return the value or NULL if the key was not found.
1106*b89261baSDavid van Moolenbroek  */
1107*b89261baSDavid van Moolenbroek 
1108*b89261baSDavid van Moolenbroek void *
hash_remove_string(hash_table * ht,char * key)1109*b89261baSDavid van Moolenbroek hash_remove_string(hash_table *ht, char * key)
1110*b89261baSDavid van Moolenbroek 
1111*b89261baSDavid van Moolenbroek {
1112*b89261baSDavid van Moolenbroek     bucket_t *bucket;
1113*b89261baSDavid van Moolenbroek     llist *ll;
1114*b89261baSDavid van Moolenbroek     llistitem *li;
1115*b89261baSDavid van Moolenbroek     llistitem *lilast;
1116*b89261baSDavid van Moolenbroek     hash_item_string *hi;
1117*b89261baSDavid van Moolenbroek     void *result;
1118*b89261baSDavid van Moolenbroek     char * k1;
1119*b89261baSDavid van Moolenbroek 
1120*b89261baSDavid van Moolenbroek     result = NULL;
1121*b89261baSDavid van Moolenbroek     if ((bucket = &(ht->buckets[string_hash(ht, key)])) != NULL)
1122*b89261baSDavid van Moolenbroek     {
1123*b89261baSDavid van Moolenbroek 	ll = &(bucket->list);
1124*b89261baSDavid van Moolenbroek 	li = LL_FIRST(ll);
1125*b89261baSDavid van Moolenbroek 	lilast = NULL;
1126*b89261baSDavid van Moolenbroek 	while (li != NULL)
1127*b89261baSDavid van Moolenbroek 	{
1128*b89261baSDavid van Moolenbroek 	    hi = (hash_item_string *)li->datum;
1129*b89261baSDavid van Moolenbroek 	    k1 = hi->key;
1130*b89261baSDavid van Moolenbroek 	    if (strcmp(key, k1) == 0)
1131*b89261baSDavid van Moolenbroek 	    {
1132*b89261baSDavid van Moolenbroek 		ll_extract(ll, li, lilast);
1133*b89261baSDavid van Moolenbroek 		result = hi->value;
1134*b89261baSDavid van Moolenbroek 		key = hi->key;
1135*b89261baSDavid van Moolenbroek 		free(key);
1136*b89261baSDavid van Moolenbroek 		ll_freeitem(li);
1137*b89261baSDavid van Moolenbroek 		break;
1138*b89261baSDavid van Moolenbroek 	    }
1139*b89261baSDavid van Moolenbroek 	    lilast = li;
1140*b89261baSDavid van Moolenbroek 	    li = LL_NEXT(ll, li);
1141*b89261baSDavid van Moolenbroek 	}
1142*b89261baSDavid van Moolenbroek     }
1143*b89261baSDavid van Moolenbroek     return result;
1144*b89261baSDavid van Moolenbroek }
1145*b89261baSDavid van Moolenbroek 
1146*b89261baSDavid van Moolenbroek /*
1147*b89261baSDavid van Moolenbroek  * hash_item_string *hash_first_string(hash_table *ht, hash_pos *pos)
1148*b89261baSDavid van Moolenbroek  *
1149*b89261baSDavid van Moolenbroek  * First function to call when iterating through all items in the hash
1150*b89261baSDavid van Moolenbroek  * table.  Returns the first item in "ht" and initializes "*pos" to track
1151*b89261baSDavid van Moolenbroek  * the current position.
1152*b89261baSDavid van Moolenbroek  */
1153*b89261baSDavid van Moolenbroek 
1154*b89261baSDavid van Moolenbroek hash_item_string *
hash_first_string(hash_table * ht,hash_pos * pos)1155*b89261baSDavid van Moolenbroek hash_first_string(hash_table *ht, hash_pos *pos)
1156*b89261baSDavid van Moolenbroek 
1157*b89261baSDavid van Moolenbroek {
1158*b89261baSDavid van Moolenbroek     /* initialize pos for first item in first bucket */
1159*b89261baSDavid van Moolenbroek     pos->num_buckets = ht->num_buckets;
1160*b89261baSDavid van Moolenbroek     pos->hash_bucket = ht->buckets;
1161*b89261baSDavid van Moolenbroek     pos->curr = 0;
1162*b89261baSDavid van Moolenbroek     pos->ll_last = NULL;
1163*b89261baSDavid van Moolenbroek 
1164*b89261baSDavid van Moolenbroek     /* find the first non-empty bucket */
1165*b89261baSDavid van Moolenbroek     while(pos->hash_bucket->list.count == 0)
1166*b89261baSDavid van Moolenbroek     {
1167*b89261baSDavid van Moolenbroek 	pos->hash_bucket++;
1168*b89261baSDavid van Moolenbroek 	if (++pos->curr >= pos->num_buckets)
1169*b89261baSDavid van Moolenbroek 	{
1170*b89261baSDavid van Moolenbroek 	    return NULL;
1171*b89261baSDavid van Moolenbroek 	}
1172*b89261baSDavid van Moolenbroek     }
1173*b89261baSDavid van Moolenbroek 
1174*b89261baSDavid van Moolenbroek     /* set and return the first item */
1175*b89261baSDavid van Moolenbroek     pos->ll_item = LL_FIRST(&(pos->hash_bucket->list));
1176*b89261baSDavid van Moolenbroek     return (hash_item_string *)pos->ll_item->datum;
1177*b89261baSDavid van Moolenbroek }
1178*b89261baSDavid van Moolenbroek 
1179*b89261baSDavid van Moolenbroek 
1180*b89261baSDavid van Moolenbroek /*
1181*b89261baSDavid van Moolenbroek  * hash_item_string *hash_next_string(hash_pos *pos)
1182*b89261baSDavid van Moolenbroek  *
1183*b89261baSDavid van Moolenbroek  * Return the next item in the hash table, using "pos" as a description
1184*b89261baSDavid van Moolenbroek  * of the present position in the hash table.  "pos" also identifies the
1185*b89261baSDavid van Moolenbroek  * specific hash table.  Return NULL if there are no more elements.
1186*b89261baSDavid van Moolenbroek  */
1187*b89261baSDavid van Moolenbroek 
1188*b89261baSDavid van Moolenbroek hash_item_string *
hash_next_string(hash_pos * pos)1189*b89261baSDavid van Moolenbroek hash_next_string(hash_pos *pos)
1190*b89261baSDavid van Moolenbroek 
1191*b89261baSDavid van Moolenbroek {
1192*b89261baSDavid van Moolenbroek     llistitem *li;
1193*b89261baSDavid van Moolenbroek 
1194*b89261baSDavid van Moolenbroek     /* move item to last and check for NULL */
1195*b89261baSDavid van Moolenbroek     if ((pos->ll_last = pos->ll_item) == NULL)
1196*b89261baSDavid van Moolenbroek     {
1197*b89261baSDavid van Moolenbroek 	/* are we really at the end of the hash table? */
1198*b89261baSDavid van Moolenbroek 	if (pos->curr >= pos->num_buckets)
1199*b89261baSDavid van Moolenbroek 	{
1200*b89261baSDavid van Moolenbroek 	    /* yes: return NULL */
1201*b89261baSDavid van Moolenbroek 	    return NULL;
1202*b89261baSDavid van Moolenbroek 	}
1203*b89261baSDavid van Moolenbroek 	/* no: regrab first item in current bucket list (might be NULL) */
1204*b89261baSDavid van Moolenbroek 	li = LL_FIRST(&(pos->hash_bucket->list));
1205*b89261baSDavid van Moolenbroek     }
1206*b89261baSDavid van Moolenbroek     else
1207*b89261baSDavid van Moolenbroek     {
1208*b89261baSDavid van Moolenbroek 	/* get the next item in the llist */
1209*b89261baSDavid van Moolenbroek 	li = LL_NEXT(&(pos->hash_bucket->list), pos->ll_item);
1210*b89261baSDavid van Moolenbroek     }
1211*b89261baSDavid van Moolenbroek 
1212*b89261baSDavid van Moolenbroek     /* if its NULL we have to find another bucket */
1213*b89261baSDavid van Moolenbroek     while (li == NULL)
1214*b89261baSDavid van Moolenbroek     {
1215*b89261baSDavid van Moolenbroek 	/* locate another bucket */
1216*b89261baSDavid van Moolenbroek 	pos->ll_last = NULL;
1217*b89261baSDavid van Moolenbroek 
1218*b89261baSDavid van Moolenbroek 	/* move to the next one */
1219*b89261baSDavid van Moolenbroek 	pos->hash_bucket++;
1220*b89261baSDavid van Moolenbroek 	if (++pos->curr >= pos->num_buckets)
1221*b89261baSDavid van Moolenbroek 	{
1222*b89261baSDavid van Moolenbroek 	    /* at the end of the hash table */
1223*b89261baSDavid van Moolenbroek 	    pos->ll_item = NULL;
1224*b89261baSDavid van Moolenbroek 	    return NULL;
1225*b89261baSDavid van Moolenbroek 	}
1226*b89261baSDavid van Moolenbroek 
1227*b89261baSDavid van Moolenbroek 	/* get the first element (might be NULL) */
1228*b89261baSDavid van Moolenbroek 	li = LL_FIRST(&(pos->hash_bucket->list));
1229*b89261baSDavid van Moolenbroek     }
1230*b89261baSDavid van Moolenbroek 
1231*b89261baSDavid van Moolenbroek     /* li is the next element to dish out */
1232*b89261baSDavid van Moolenbroek     pos->ll_item = li;
1233*b89261baSDavid van Moolenbroek     return (hash_item_string *)li->datum;
1234*b89261baSDavid van Moolenbroek }
1235*b89261baSDavid van Moolenbroek 
1236*b89261baSDavid van Moolenbroek /*
1237*b89261baSDavid van Moolenbroek  * void *hash_remove_pos_string(hash_pos *pos)
1238*b89261baSDavid van Moolenbroek  *
1239*b89261baSDavid van Moolenbroek  * Remove the hash table entry pointed to by position marker "pos".
1240*b89261baSDavid van Moolenbroek  * The data from the entry is returned upon success, otherwise NULL.
1241*b89261baSDavid van Moolenbroek  */
1242*b89261baSDavid van Moolenbroek 
1243*b89261baSDavid van Moolenbroek 
1244*b89261baSDavid van Moolenbroek void *
hash_remove_pos_string(hash_pos * pos)1245*b89261baSDavid van Moolenbroek hash_remove_pos_string(hash_pos *pos)
1246*b89261baSDavid van Moolenbroek 
1247*b89261baSDavid van Moolenbroek {
1248*b89261baSDavid van Moolenbroek     llistitem *li;
1249*b89261baSDavid van Moolenbroek     void *ans;
1250*b89261baSDavid van Moolenbroek     hash_item_string *hi;
1251*b89261baSDavid van Moolenbroek     char * key;
1252*b89261baSDavid van Moolenbroek 
1253*b89261baSDavid van Moolenbroek     /* sanity checks */
1254*b89261baSDavid van Moolenbroek     if (pos == NULL || pos->ll_last == pos->ll_item)
1255*b89261baSDavid van Moolenbroek     {
1256*b89261baSDavid van Moolenbroek 	return NULL;
1257*b89261baSDavid van Moolenbroek     }
1258*b89261baSDavid van Moolenbroek 
1259*b89261baSDavid van Moolenbroek     /* at this point pos contains the item to remove (ll_item)
1260*b89261baSDavid van Moolenbroek        and its predecesor (ll_last) */
1261*b89261baSDavid van Moolenbroek     /* extract the item from the llist */
1262*b89261baSDavid van Moolenbroek     li = pos->ll_item;
1263*b89261baSDavid van Moolenbroek     ll_extract(&(pos->hash_bucket->list), li, pos->ll_last);
1264*b89261baSDavid van Moolenbroek 
1265*b89261baSDavid van Moolenbroek     /* retain the data */
1266*b89261baSDavid van Moolenbroek     hi = (hash_item_string *)li->datum;
1267*b89261baSDavid van Moolenbroek     ans = hi->value;
1268*b89261baSDavid van Moolenbroek 
1269*b89261baSDavid van Moolenbroek     /* free up the space */
1270*b89261baSDavid van Moolenbroek     key = hi->key;
1271*b89261baSDavid van Moolenbroek     free(key);
1272*b89261baSDavid van Moolenbroek     ll_freeitem(li);
1273*b89261baSDavid van Moolenbroek 
1274*b89261baSDavid van Moolenbroek     /* back up to previous item */
1275*b89261baSDavid van Moolenbroek     /* its okay for ll_item to be null: hash_next will detect it */
1276*b89261baSDavid van Moolenbroek     pos->ll_item = pos->ll_last;
1277*b89261baSDavid van Moolenbroek 
1278*b89261baSDavid van Moolenbroek     return ans;
1279*b89261baSDavid van Moolenbroek }
1280*b89261baSDavid van Moolenbroek 
1281*b89261baSDavid van Moolenbroek 
1282*b89261baSDavid van Moolenbroek 
1283*b89261baSDavid van Moolenbroek /*
1284*b89261baSDavid van Moolenbroek  * void hash_add_pidthr(hash_table *ht, pidthr_t key, void *value)
1285*b89261baSDavid van Moolenbroek  *
1286*b89261baSDavid van Moolenbroek  * Add an element to table "ht".  The element is described by
1287*b89261baSDavid van Moolenbroek  * "key" and "value".  Return NULL on success.  If the key
1288*b89261baSDavid van Moolenbroek  * already exists in the table, then no action is taken and
1289*b89261baSDavid van Moolenbroek  * the data for the existing element is returned.
1290*b89261baSDavid van Moolenbroek  * Key type is pidthr_t
1291*b89261baSDavid van Moolenbroek  */
1292*b89261baSDavid van Moolenbroek 
1293*b89261baSDavid van Moolenbroek void *
hash_add_pidthr(hash_table * ht,pidthr_t key,void * value)1294*b89261baSDavid van Moolenbroek hash_add_pidthr(hash_table *ht, pidthr_t key, void *value)
1295*b89261baSDavid van Moolenbroek 
1296*b89261baSDavid van Moolenbroek {
1297*b89261baSDavid van Moolenbroek     bucket_t *bucket;
1298*b89261baSDavid van Moolenbroek     hash_item_pidthr *hi;
1299*b89261baSDavid van Moolenbroek     hash_item_pidthr *h;
1300*b89261baSDavid van Moolenbroek     llist *ll;
1301*b89261baSDavid van Moolenbroek     llistitem *li;
1302*b89261baSDavid van Moolenbroek     llistitem *newli;
1303*b89261baSDavid van Moolenbroek     pidthr_t k1;
1304*b89261baSDavid van Moolenbroek 
1305*b89261baSDavid van Moolenbroek     /* allocate the space we will need */
1306*b89261baSDavid van Moolenbroek     newli = ll_newitem(sizeof(hash_item_pidthr));
1307*b89261baSDavid van Moolenbroek     hi = (hash_item_pidthr *)newli->datum;
1308*b89261baSDavid van Moolenbroek 
1309*b89261baSDavid van Moolenbroek     /* fill in the values */
1310*b89261baSDavid van Moolenbroek     hi->key = key;
1311*b89261baSDavid van Moolenbroek     hi->value = value;
1312*b89261baSDavid van Moolenbroek 
1313*b89261baSDavid van Moolenbroek     /* hash to the bucket */
1314*b89261baSDavid van Moolenbroek     bucket = &(ht->buckets[((key.k_thr * 10000 + key.k_pid) % ht->num_buckets)]);
1315*b89261baSDavid van Moolenbroek 
1316*b89261baSDavid van Moolenbroek     /* walk the list to make sure we do not have a duplicate */
1317*b89261baSDavid van Moolenbroek     ll = &(bucket->list);
1318*b89261baSDavid van Moolenbroek     li = LL_FIRST(ll);
1319*b89261baSDavid van Moolenbroek     while (li != NULL)
1320*b89261baSDavid van Moolenbroek     {
1321*b89261baSDavid van Moolenbroek 	h = (hash_item_pidthr *)li->datum;
1322*b89261baSDavid van Moolenbroek 	k1 = h->key;
1323*b89261baSDavid van Moolenbroek 	if ((key.k_pid == k1.k_pid && key.k_thr == k1.k_thr))
1324*b89261baSDavid van Moolenbroek 	{
1325*b89261baSDavid van Moolenbroek 	    /* found one */
1326*b89261baSDavid van Moolenbroek 	    break;
1327*b89261baSDavid van Moolenbroek 	}
1328*b89261baSDavid van Moolenbroek 	li = LL_NEXT(ll, li);
1329*b89261baSDavid van Moolenbroek     }
1330*b89261baSDavid van Moolenbroek     li = NULL;
1331*b89261baSDavid van Moolenbroek 
1332*b89261baSDavid van Moolenbroek     /* is there already one there? */
1333*b89261baSDavid van Moolenbroek     if (li == NULL)
1334*b89261baSDavid van Moolenbroek     {
1335*b89261baSDavid van Moolenbroek 	/* add the unique element to the buckets list */
1336*b89261baSDavid van Moolenbroek 	ll_add(&(bucket->list), newli);
1337*b89261baSDavid van Moolenbroek 	return NULL;
1338*b89261baSDavid van Moolenbroek     }
1339*b89261baSDavid van Moolenbroek     else
1340*b89261baSDavid van Moolenbroek     {
1341*b89261baSDavid van Moolenbroek 	/* free the stuff we just allocated */
1342*b89261baSDavid van Moolenbroek 	ll_freeitem(newli);
1343*b89261baSDavid van Moolenbroek 	return ((hash_item_pidthr *)(li->datum))->value;
1344*b89261baSDavid van Moolenbroek     }
1345*b89261baSDavid van Moolenbroek }
1346*b89261baSDavid van Moolenbroek 
1347*b89261baSDavid van Moolenbroek /*
1348*b89261baSDavid van Moolenbroek  * void *hash_replace_pidthr(hash_table *ht, pidthr_t key, void *value)
1349*b89261baSDavid van Moolenbroek  *
1350*b89261baSDavid van Moolenbroek  * Replace an existing value in the hash table with a new one and
1351*b89261baSDavid van Moolenbroek  * return the old value.  If the key does not already exist in
1352*b89261baSDavid van Moolenbroek  * the hash table, add a new element and return NULL.
1353*b89261baSDavid van Moolenbroek  * Key type is pidthr_t
1354*b89261baSDavid van Moolenbroek  */
1355*b89261baSDavid van Moolenbroek 
1356*b89261baSDavid van Moolenbroek void *
hash_replace_pidthr(hash_table * ht,pidthr_t key,void * value)1357*b89261baSDavid van Moolenbroek hash_replace_pidthr(hash_table *ht, pidthr_t key, void *value)
1358*b89261baSDavid van Moolenbroek 
1359*b89261baSDavid van Moolenbroek {
1360*b89261baSDavid van Moolenbroek     bucket_t *bucket;
1361*b89261baSDavid van Moolenbroek     hash_item_pidthr *hi;
1362*b89261baSDavid van Moolenbroek     llist *ll;
1363*b89261baSDavid van Moolenbroek     llistitem *li;
1364*b89261baSDavid van Moolenbroek     void *result = NULL;
1365*b89261baSDavid van Moolenbroek     pidthr_t k1;
1366*b89261baSDavid van Moolenbroek 
1367*b89261baSDavid van Moolenbroek     /* find the bucket */
1368*b89261baSDavid van Moolenbroek     bucket = &(ht->buckets[((key.k_thr * 10000 + key.k_pid) % ht->num_buckets)]);
1369*b89261baSDavid van Moolenbroek 
1370*b89261baSDavid van Moolenbroek     /* walk the list until we find the existing item */
1371*b89261baSDavid van Moolenbroek     ll = &(bucket->list);
1372*b89261baSDavid van Moolenbroek     li = LL_FIRST(ll);
1373*b89261baSDavid van Moolenbroek     while (li != NULL)
1374*b89261baSDavid van Moolenbroek     {
1375*b89261baSDavid van Moolenbroek 	hi = (hash_item_pidthr *)li->datum;
1376*b89261baSDavid van Moolenbroek 	k1 = hi->key;
1377*b89261baSDavid van Moolenbroek 	if ((key.k_pid == k1.k_pid && key.k_thr == k1.k_thr))
1378*b89261baSDavid van Moolenbroek 	{
1379*b89261baSDavid van Moolenbroek 	    /* found it: now replace the value with the new one */
1380*b89261baSDavid van Moolenbroek 	    result = hi->value;
1381*b89261baSDavid van Moolenbroek 	    hi->value = value;
1382*b89261baSDavid van Moolenbroek 	    break;
1383*b89261baSDavid van Moolenbroek 	}
1384*b89261baSDavid van Moolenbroek 	li = LL_NEXT(ll, li);
1385*b89261baSDavid van Moolenbroek     }
1386*b89261baSDavid van Moolenbroek 
1387*b89261baSDavid van Moolenbroek     /* if the element wasnt found, add it */
1388*b89261baSDavid van Moolenbroek     if (result == NULL)
1389*b89261baSDavid van Moolenbroek     {
1390*b89261baSDavid van Moolenbroek 	li = ll_newitem(sizeof(hash_item_pidthr));
1391*b89261baSDavid van Moolenbroek 	hi = (hash_item_pidthr *)li->datum;
1392*b89261baSDavid van Moolenbroek 	hi->key = key;
1393*b89261baSDavid van Moolenbroek 	hi->value = value;
1394*b89261baSDavid van Moolenbroek 	ll_add(&(bucket->list), li);
1395*b89261baSDavid van Moolenbroek     }
1396*b89261baSDavid van Moolenbroek 
1397*b89261baSDavid van Moolenbroek     /* return the old value (so it can be freed) */
1398*b89261baSDavid van Moolenbroek     return result;
1399*b89261baSDavid van Moolenbroek }
1400*b89261baSDavid van Moolenbroek 
1401*b89261baSDavid van Moolenbroek /*
1402*b89261baSDavid van Moolenbroek  * void *hash_lookup_pidthr(hash_table *ht, pidthr_t key)
1403*b89261baSDavid van Moolenbroek  *
1404*b89261baSDavid van Moolenbroek  * Look up "key" in "ht" and return the associated value.  If "key"
1405*b89261baSDavid van Moolenbroek  * is not found, return NULL.  Key type is pidthr_t
1406*b89261baSDavid van Moolenbroek  */
1407*b89261baSDavid van Moolenbroek 
1408*b89261baSDavid van Moolenbroek void *
hash_lookup_pidthr(hash_table * ht,pidthr_t key)1409*b89261baSDavid van Moolenbroek hash_lookup_pidthr(hash_table *ht, pidthr_t key)
1410*b89261baSDavid van Moolenbroek 
1411*b89261baSDavid van Moolenbroek {
1412*b89261baSDavid van Moolenbroek     bucket_t *bucket;
1413*b89261baSDavid van Moolenbroek     llist *ll;
1414*b89261baSDavid van Moolenbroek     llistitem *li;
1415*b89261baSDavid van Moolenbroek     hash_item_pidthr *h;
1416*b89261baSDavid van Moolenbroek     void *result;
1417*b89261baSDavid van Moolenbroek     pidthr_t k1;
1418*b89261baSDavid van Moolenbroek 
1419*b89261baSDavid van Moolenbroek     result = NULL;
1420*b89261baSDavid van Moolenbroek     if ((bucket = &(ht->buckets[((key.k_thr * 10000 + key.k_pid) % ht->num_buckets)])) != NULL)
1421*b89261baSDavid van Moolenbroek     {
1422*b89261baSDavid van Moolenbroek 	ll = &(bucket->list);
1423*b89261baSDavid van Moolenbroek 	li = LL_FIRST(ll);
1424*b89261baSDavid van Moolenbroek 	while (li != NULL)
1425*b89261baSDavid van Moolenbroek 	{
1426*b89261baSDavid van Moolenbroek 	    h = (hash_item_pidthr *)li->datum;
1427*b89261baSDavid van Moolenbroek 	    k1 = h->key;
1428*b89261baSDavid van Moolenbroek 	    if ((key.k_pid == k1.k_pid && key.k_thr == k1.k_thr))
1429*b89261baSDavid van Moolenbroek 	    {
1430*b89261baSDavid van Moolenbroek 		result = h->value;
1431*b89261baSDavid van Moolenbroek 		break;
1432*b89261baSDavid van Moolenbroek 	    }
1433*b89261baSDavid van Moolenbroek 	    li = LL_NEXT(ll, li);
1434*b89261baSDavid van Moolenbroek 	}
1435*b89261baSDavid van Moolenbroek     }
1436*b89261baSDavid van Moolenbroek     return result;
1437*b89261baSDavid van Moolenbroek }
1438*b89261baSDavid van Moolenbroek 
1439*b89261baSDavid van Moolenbroek /*
1440*b89261baSDavid van Moolenbroek  * void *hash_remove_pidthr(hash_table *ht, pidthr_t key)
1441*b89261baSDavid van Moolenbroek  *
1442*b89261baSDavid van Moolenbroek  * Remove the element associated with "key" from the hash table
1443*b89261baSDavid van Moolenbroek  * "ht".  Return the value or NULL if the key was not found.
1444*b89261baSDavid van Moolenbroek  */
1445*b89261baSDavid van Moolenbroek 
1446*b89261baSDavid van Moolenbroek void *
hash_remove_pidthr(hash_table * ht,pidthr_t key)1447*b89261baSDavid van Moolenbroek hash_remove_pidthr(hash_table *ht, pidthr_t key)
1448*b89261baSDavid van Moolenbroek 
1449*b89261baSDavid van Moolenbroek {
1450*b89261baSDavid van Moolenbroek     bucket_t *bucket;
1451*b89261baSDavid van Moolenbroek     llist *ll;
1452*b89261baSDavid van Moolenbroek     llistitem *li;
1453*b89261baSDavid van Moolenbroek     llistitem *lilast;
1454*b89261baSDavid van Moolenbroek     hash_item_pidthr *hi;
1455*b89261baSDavid van Moolenbroek     void *result;
1456*b89261baSDavid van Moolenbroek     pidthr_t k1;
1457*b89261baSDavid van Moolenbroek 
1458*b89261baSDavid van Moolenbroek     result = NULL;
1459*b89261baSDavid van Moolenbroek     if ((bucket = &(ht->buckets[((key.k_thr * 10000 + key.k_pid) % ht->num_buckets)])) != NULL)
1460*b89261baSDavid van Moolenbroek     {
1461*b89261baSDavid van Moolenbroek 	ll = &(bucket->list);
1462*b89261baSDavid van Moolenbroek 	li = LL_FIRST(ll);
1463*b89261baSDavid van Moolenbroek 	lilast = NULL;
1464*b89261baSDavid van Moolenbroek 	while (li != NULL)
1465*b89261baSDavid van Moolenbroek 	{
1466*b89261baSDavid van Moolenbroek 	    hi = (hash_item_pidthr *)li->datum;
1467*b89261baSDavid van Moolenbroek 	    k1 = hi->key;
1468*b89261baSDavid van Moolenbroek 	    if ((key.k_pid == k1.k_pid && key.k_thr == k1.k_thr))
1469*b89261baSDavid van Moolenbroek 	    {
1470*b89261baSDavid van Moolenbroek 		ll_extract(ll, li, lilast);
1471*b89261baSDavid van Moolenbroek 		result = hi->value;
1472*b89261baSDavid van Moolenbroek 		key = hi->key;
1473*b89261baSDavid van Moolenbroek 		;
1474*b89261baSDavid van Moolenbroek 		ll_freeitem(li);
1475*b89261baSDavid van Moolenbroek 		break;
1476*b89261baSDavid van Moolenbroek 	    }
1477*b89261baSDavid van Moolenbroek 	    lilast = li;
1478*b89261baSDavid van Moolenbroek 	    li = LL_NEXT(ll, li);
1479*b89261baSDavid van Moolenbroek 	}
1480*b89261baSDavid van Moolenbroek     }
1481*b89261baSDavid van Moolenbroek     return result;
1482*b89261baSDavid van Moolenbroek }
1483*b89261baSDavid van Moolenbroek 
1484*b89261baSDavid van Moolenbroek /*
1485*b89261baSDavid van Moolenbroek  * hash_item_pidthr *hash_first_pidthr(hash_table *ht, hash_pos *pos)
1486*b89261baSDavid van Moolenbroek  *
1487*b89261baSDavid van Moolenbroek  * First function to call when iterating through all items in the hash
1488*b89261baSDavid van Moolenbroek  * table.  Returns the first item in "ht" and initializes "*pos" to track
1489*b89261baSDavid van Moolenbroek  * the current position.
1490*b89261baSDavid van Moolenbroek  */
1491*b89261baSDavid van Moolenbroek 
1492*b89261baSDavid van Moolenbroek hash_item_pidthr *
hash_first_pidthr(hash_table * ht,hash_pos * pos)1493*b89261baSDavid van Moolenbroek hash_first_pidthr(hash_table *ht, hash_pos *pos)
1494*b89261baSDavid van Moolenbroek 
1495*b89261baSDavid van Moolenbroek {
1496*b89261baSDavid van Moolenbroek     /* initialize pos for first item in first bucket */
1497*b89261baSDavid van Moolenbroek     pos->num_buckets = ht->num_buckets;
1498*b89261baSDavid van Moolenbroek     pos->hash_bucket = ht->buckets;
1499*b89261baSDavid van Moolenbroek     pos->curr = 0;
1500*b89261baSDavid van Moolenbroek     pos->ll_last = NULL;
1501*b89261baSDavid van Moolenbroek 
1502*b89261baSDavid van Moolenbroek     /* find the first non-empty bucket */
1503*b89261baSDavid van Moolenbroek     while(pos->hash_bucket->list.count == 0)
1504*b89261baSDavid van Moolenbroek     {
1505*b89261baSDavid van Moolenbroek 	pos->hash_bucket++;
1506*b89261baSDavid van Moolenbroek 	if (++pos->curr >= pos->num_buckets)
1507*b89261baSDavid van Moolenbroek 	{
1508*b89261baSDavid van Moolenbroek 	    return NULL;
1509*b89261baSDavid van Moolenbroek 	}
1510*b89261baSDavid van Moolenbroek     }
1511*b89261baSDavid van Moolenbroek 
1512*b89261baSDavid van Moolenbroek     /* set and return the first item */
1513*b89261baSDavid van Moolenbroek     pos->ll_item = LL_FIRST(&(pos->hash_bucket->list));
1514*b89261baSDavid van Moolenbroek     return (hash_item_pidthr *)pos->ll_item->datum;
1515*b89261baSDavid van Moolenbroek }
1516*b89261baSDavid van Moolenbroek 
1517*b89261baSDavid van Moolenbroek 
1518*b89261baSDavid van Moolenbroek /*
1519*b89261baSDavid van Moolenbroek  * hash_item_pidthr *hash_next_pidthr(hash_pos *pos)
1520*b89261baSDavid van Moolenbroek  *
1521*b89261baSDavid van Moolenbroek  * Return the next item in the hash table, using "pos" as a description
1522*b89261baSDavid van Moolenbroek  * of the present position in the hash table.  "pos" also identifies the
1523*b89261baSDavid van Moolenbroek  * specific hash table.  Return NULL if there are no more elements.
1524*b89261baSDavid van Moolenbroek  */
1525*b89261baSDavid van Moolenbroek 
1526*b89261baSDavid van Moolenbroek hash_item_pidthr *
hash_next_pidthr(hash_pos * pos)1527*b89261baSDavid van Moolenbroek hash_next_pidthr(hash_pos *pos)
1528*b89261baSDavid van Moolenbroek 
1529*b89261baSDavid van Moolenbroek {
1530*b89261baSDavid van Moolenbroek     llistitem *li;
1531*b89261baSDavid van Moolenbroek 
1532*b89261baSDavid van Moolenbroek     /* move item to last and check for NULL */
1533*b89261baSDavid van Moolenbroek     if ((pos->ll_last = pos->ll_item) == NULL)
1534*b89261baSDavid van Moolenbroek     {
1535*b89261baSDavid van Moolenbroek 	/* are we really at the end of the hash table? */
1536*b89261baSDavid van Moolenbroek 	if (pos->curr >= pos->num_buckets)
1537*b89261baSDavid van Moolenbroek 	{
1538*b89261baSDavid van Moolenbroek 	    /* yes: return NULL */
1539*b89261baSDavid van Moolenbroek 	    return NULL;
1540*b89261baSDavid van Moolenbroek 	}
1541*b89261baSDavid van Moolenbroek 	/* no: regrab first item in current bucket list (might be NULL) */
1542*b89261baSDavid van Moolenbroek 	li = LL_FIRST(&(pos->hash_bucket->list));
1543*b89261baSDavid van Moolenbroek     }
1544*b89261baSDavid van Moolenbroek     else
1545*b89261baSDavid van Moolenbroek     {
1546*b89261baSDavid van Moolenbroek 	/* get the next item in the llist */
1547*b89261baSDavid van Moolenbroek 	li = LL_NEXT(&(pos->hash_bucket->list), pos->ll_item);
1548*b89261baSDavid van Moolenbroek     }
1549*b89261baSDavid van Moolenbroek 
1550*b89261baSDavid van Moolenbroek     /* if its NULL we have to find another bucket */
1551*b89261baSDavid van Moolenbroek     while (li == NULL)
1552*b89261baSDavid van Moolenbroek     {
1553*b89261baSDavid van Moolenbroek 	/* locate another bucket */
1554*b89261baSDavid van Moolenbroek 	pos->ll_last = NULL;
1555*b89261baSDavid van Moolenbroek 
1556*b89261baSDavid van Moolenbroek 	/* move to the next one */
1557*b89261baSDavid van Moolenbroek 	pos->hash_bucket++;
1558*b89261baSDavid van Moolenbroek 	if (++pos->curr >= pos->num_buckets)
1559*b89261baSDavid van Moolenbroek 	{
1560*b89261baSDavid van Moolenbroek 	    /* at the end of the hash table */
1561*b89261baSDavid van Moolenbroek 	    pos->ll_item = NULL;
1562*b89261baSDavid van Moolenbroek 	    return NULL;
1563*b89261baSDavid van Moolenbroek 	}
1564*b89261baSDavid van Moolenbroek 
1565*b89261baSDavid van Moolenbroek 	/* get the first element (might be NULL) */
1566*b89261baSDavid van Moolenbroek 	li = LL_FIRST(&(pos->hash_bucket->list));
1567*b89261baSDavid van Moolenbroek     }
1568*b89261baSDavid van Moolenbroek 
1569*b89261baSDavid van Moolenbroek     /* li is the next element to dish out */
1570*b89261baSDavid van Moolenbroek     pos->ll_item = li;
1571*b89261baSDavid van Moolenbroek     return (hash_item_pidthr *)li->datum;
1572*b89261baSDavid van Moolenbroek }
1573*b89261baSDavid van Moolenbroek 
1574*b89261baSDavid van Moolenbroek /*
1575*b89261baSDavid van Moolenbroek  * void *hash_remove_pos_pidthr(hash_pos *pos)
1576*b89261baSDavid van Moolenbroek  *
1577*b89261baSDavid van Moolenbroek  * Remove the hash table entry pointed to by position marker "pos".
1578*b89261baSDavid van Moolenbroek  * The data from the entry is returned upon success, otherwise NULL.
1579*b89261baSDavid van Moolenbroek  */
1580*b89261baSDavid van Moolenbroek 
1581*b89261baSDavid van Moolenbroek 
1582*b89261baSDavid van Moolenbroek void *
hash_remove_pos_pidthr(hash_pos * pos)1583*b89261baSDavid van Moolenbroek hash_remove_pos_pidthr(hash_pos *pos)
1584*b89261baSDavid van Moolenbroek 
1585*b89261baSDavid van Moolenbroek {
1586*b89261baSDavid van Moolenbroek     llistitem *li;
1587*b89261baSDavid van Moolenbroek     void *ans;
1588*b89261baSDavid van Moolenbroek     hash_item_pidthr *hi;
1589*b89261baSDavid van Moolenbroek 
1590*b89261baSDavid van Moolenbroek     /* sanity checks */
1591*b89261baSDavid van Moolenbroek     if (pos == NULL || pos->ll_last == pos->ll_item)
1592*b89261baSDavid van Moolenbroek     {
1593*b89261baSDavid van Moolenbroek 	return NULL;
1594*b89261baSDavid van Moolenbroek     }
1595*b89261baSDavid van Moolenbroek 
1596*b89261baSDavid van Moolenbroek     /* at this point pos contains the item to remove (ll_item)
1597*b89261baSDavid van Moolenbroek        and its predecesor (ll_last) */
1598*b89261baSDavid van Moolenbroek     /* extract the item from the llist */
1599*b89261baSDavid van Moolenbroek     li = pos->ll_item;
1600*b89261baSDavid van Moolenbroek     ll_extract(&(pos->hash_bucket->list), li, pos->ll_last);
1601*b89261baSDavid van Moolenbroek 
1602*b89261baSDavid van Moolenbroek     /* retain the data */
1603*b89261baSDavid van Moolenbroek     hi = (hash_item_pidthr *)li->datum;
1604*b89261baSDavid van Moolenbroek     ans = hi->value;
1605*b89261baSDavid van Moolenbroek 
1606*b89261baSDavid van Moolenbroek     /* free up the space */
1607*b89261baSDavid van Moolenbroek     ll_freeitem(li);
1608*b89261baSDavid van Moolenbroek 
1609*b89261baSDavid van Moolenbroek     /* back up to previous item */
1610*b89261baSDavid van Moolenbroek     /* its okay for ll_item to be null: hash_next will detect it */
1611*b89261baSDavid van Moolenbroek     pos->ll_item = pos->ll_last;
1612*b89261baSDavid van Moolenbroek 
1613*b89261baSDavid van Moolenbroek     return ans;
1614*b89261baSDavid van Moolenbroek }
1615*b89261baSDavid van Moolenbroek 
1616*b89261baSDavid van Moolenbroek #if HAVE_LWPID_T
1617*b89261baSDavid van Moolenbroek 
1618*b89261baSDavid van Moolenbroek 
1619*b89261baSDavid van Moolenbroek /*
1620*b89261baSDavid van Moolenbroek  * void hash_add_lwpid(hash_table *ht, lwpid_t key, void *value)
1621*b89261baSDavid van Moolenbroek  *
1622*b89261baSDavid van Moolenbroek  * Add an element to table "ht".  The element is described by
1623*b89261baSDavid van Moolenbroek  * "key" and "value".  Return NULL on success.  If the key
1624*b89261baSDavid van Moolenbroek  * already exists in the table, then no action is taken and
1625*b89261baSDavid van Moolenbroek  * the data for the existing element is returned.
1626*b89261baSDavid van Moolenbroek  * Key type is lwpid_t
1627*b89261baSDavid van Moolenbroek  */
1628*b89261baSDavid van Moolenbroek 
1629*b89261baSDavid van Moolenbroek void *
hash_add_lwpid(hash_table * ht,lwpid_t key,void * value)1630*b89261baSDavid van Moolenbroek hash_add_lwpid(hash_table *ht, lwpid_t key, void *value)
1631*b89261baSDavid van Moolenbroek 
1632*b89261baSDavid van Moolenbroek {
1633*b89261baSDavid van Moolenbroek     bucket_t *bucket;
1634*b89261baSDavid van Moolenbroek     hash_item_lwpid *hi;
1635*b89261baSDavid van Moolenbroek     hash_item_lwpid *h;
1636*b89261baSDavid van Moolenbroek     llist *ll;
1637*b89261baSDavid van Moolenbroek     llistitem *li;
1638*b89261baSDavid van Moolenbroek     llistitem *newli;
1639*b89261baSDavid van Moolenbroek     lwpid_t k1;
1640*b89261baSDavid van Moolenbroek 
1641*b89261baSDavid van Moolenbroek     /* allocate the space we will need */
1642*b89261baSDavid van Moolenbroek     newli = ll_newitem(sizeof(hash_item_lwpid));
1643*b89261baSDavid van Moolenbroek     hi = (hash_item_lwpid *)newli->datum;
1644*b89261baSDavid van Moolenbroek 
1645*b89261baSDavid van Moolenbroek     /* fill in the values */
1646*b89261baSDavid van Moolenbroek     hi->key = key;
1647*b89261baSDavid van Moolenbroek     hi->value = value;
1648*b89261baSDavid van Moolenbroek 
1649*b89261baSDavid van Moolenbroek     /* hash to the bucket */
1650*b89261baSDavid van Moolenbroek     bucket = &(ht->buckets[(key % ht->num_buckets)]);
1651*b89261baSDavid van Moolenbroek 
1652*b89261baSDavid van Moolenbroek     /* walk the list to make sure we do not have a duplicate */
1653*b89261baSDavid van Moolenbroek     ll = &(bucket->list);
1654*b89261baSDavid van Moolenbroek     li = LL_FIRST(ll);
1655*b89261baSDavid van Moolenbroek     while (li != NULL)
1656*b89261baSDavid van Moolenbroek     {
1657*b89261baSDavid van Moolenbroek 	h = (hash_item_lwpid *)li->datum;
1658*b89261baSDavid van Moolenbroek 	k1 = h->key;
1659*b89261baSDavid van Moolenbroek 	if (key == k1)
1660*b89261baSDavid van Moolenbroek 	{
1661*b89261baSDavid van Moolenbroek 	    /* found one */
1662*b89261baSDavid van Moolenbroek 	    break;
1663*b89261baSDavid van Moolenbroek 	}
1664*b89261baSDavid van Moolenbroek 	li = LL_NEXT(ll, li);
1665*b89261baSDavid van Moolenbroek     }
1666*b89261baSDavid van Moolenbroek     li = NULL;
1667*b89261baSDavid van Moolenbroek 
1668*b89261baSDavid van Moolenbroek     /* is there already one there? */
1669*b89261baSDavid van Moolenbroek     if (li == NULL)
1670*b89261baSDavid van Moolenbroek     {
1671*b89261baSDavid van Moolenbroek 	/* add the unique element to the buckets list */
1672*b89261baSDavid van Moolenbroek 	ll_add(&(bucket->list), newli);
1673*b89261baSDavid van Moolenbroek 	return NULL;
1674*b89261baSDavid van Moolenbroek     }
1675*b89261baSDavid van Moolenbroek     else
1676*b89261baSDavid van Moolenbroek     {
1677*b89261baSDavid van Moolenbroek 	/* free the stuff we just allocated */
1678*b89261baSDavid van Moolenbroek 	ll_freeitem(newli);
1679*b89261baSDavid van Moolenbroek 	return ((hash_item_lwpid *)(li->datum))->value;
1680*b89261baSDavid van Moolenbroek     }
1681*b89261baSDavid van Moolenbroek }
1682*b89261baSDavid van Moolenbroek 
1683*b89261baSDavid van Moolenbroek /*
1684*b89261baSDavid van Moolenbroek  * void *hash_replace_lwpid(hash_table *ht, lwpid_t key, void *value)
1685*b89261baSDavid van Moolenbroek  *
1686*b89261baSDavid van Moolenbroek  * Replace an existing value in the hash table with a new one and
1687*b89261baSDavid van Moolenbroek  * return the old value.  If the key does not already exist in
1688*b89261baSDavid van Moolenbroek  * the hash table, add a new element and return NULL.
1689*b89261baSDavid van Moolenbroek  * Key type is lwpid_t
1690*b89261baSDavid van Moolenbroek  */
1691*b89261baSDavid van Moolenbroek 
1692*b89261baSDavid van Moolenbroek void *
hash_replace_lwpid(hash_table * ht,lwpid_t key,void * value)1693*b89261baSDavid van Moolenbroek hash_replace_lwpid(hash_table *ht, lwpid_t key, void *value)
1694*b89261baSDavid van Moolenbroek 
1695*b89261baSDavid van Moolenbroek {
1696*b89261baSDavid van Moolenbroek     bucket_t *bucket;
1697*b89261baSDavid van Moolenbroek     hash_item_lwpid *hi;
1698*b89261baSDavid van Moolenbroek     llist *ll;
1699*b89261baSDavid van Moolenbroek     llistitem *li;
1700*b89261baSDavid van Moolenbroek     void *result = NULL;
1701*b89261baSDavid van Moolenbroek     lwpid_t k1;
1702*b89261baSDavid van Moolenbroek 
1703*b89261baSDavid van Moolenbroek     /* find the bucket */
1704*b89261baSDavid van Moolenbroek     bucket = &(ht->buckets[(key % ht->num_buckets)]);
1705*b89261baSDavid van Moolenbroek 
1706*b89261baSDavid van Moolenbroek     /* walk the list until we find the existing item */
1707*b89261baSDavid van Moolenbroek     ll = &(bucket->list);
1708*b89261baSDavid van Moolenbroek     li = LL_FIRST(ll);
1709*b89261baSDavid van Moolenbroek     while (li != NULL)
1710*b89261baSDavid van Moolenbroek     {
1711*b89261baSDavid van Moolenbroek 	hi = (hash_item_lwpid *)li->datum;
1712*b89261baSDavid van Moolenbroek 	k1 = hi->key;
1713*b89261baSDavid van Moolenbroek 	if (key == k1)
1714*b89261baSDavid van Moolenbroek 	{
1715*b89261baSDavid van Moolenbroek 	    /* found it: now replace the value with the new one */
1716*b89261baSDavid van Moolenbroek 	    result = hi->value;
1717*b89261baSDavid van Moolenbroek 	    hi->value = value;
1718*b89261baSDavid van Moolenbroek 	    break;
1719*b89261baSDavid van Moolenbroek 	}
1720*b89261baSDavid van Moolenbroek 	li = LL_NEXT(ll, li);
1721*b89261baSDavid van Moolenbroek     }
1722*b89261baSDavid van Moolenbroek 
1723*b89261baSDavid van Moolenbroek     /* if the element wasnt found, add it */
1724*b89261baSDavid van Moolenbroek     if (result == NULL)
1725*b89261baSDavid van Moolenbroek     {
1726*b89261baSDavid van Moolenbroek 	li = ll_newitem(sizeof(hash_item_lwpid));
1727*b89261baSDavid van Moolenbroek 	hi = (hash_item_lwpid *)li->datum;
1728*b89261baSDavid van Moolenbroek 	hi->key = key;
1729*b89261baSDavid van Moolenbroek 	hi->value = value;
1730*b89261baSDavid van Moolenbroek 	ll_add(&(bucket->list), li);
1731*b89261baSDavid van Moolenbroek     }
1732*b89261baSDavid van Moolenbroek 
1733*b89261baSDavid van Moolenbroek     /* return the old value (so it can be freed) */
1734*b89261baSDavid van Moolenbroek     return result;
1735*b89261baSDavid van Moolenbroek }
1736*b89261baSDavid van Moolenbroek 
1737*b89261baSDavid van Moolenbroek /*
1738*b89261baSDavid van Moolenbroek  * void *hash_lookup_lwpid(hash_table *ht, lwpid_t key)
1739*b89261baSDavid van Moolenbroek  *
1740*b89261baSDavid van Moolenbroek  * Look up "key" in "ht" and return the associated value.  If "key"
1741*b89261baSDavid van Moolenbroek  * is not found, return NULL.  Key type is lwpid_t
1742*b89261baSDavid van Moolenbroek  */
1743*b89261baSDavid van Moolenbroek 
1744*b89261baSDavid van Moolenbroek void *
hash_lookup_lwpid(hash_table * ht,lwpid_t key)1745*b89261baSDavid van Moolenbroek hash_lookup_lwpid(hash_table *ht, lwpid_t key)
1746*b89261baSDavid van Moolenbroek 
1747*b89261baSDavid van Moolenbroek {
1748*b89261baSDavid van Moolenbroek     bucket_t *bucket;
1749*b89261baSDavid van Moolenbroek     llist *ll;
1750*b89261baSDavid van Moolenbroek     llistitem *li;
1751*b89261baSDavid van Moolenbroek     hash_item_lwpid *h;
1752*b89261baSDavid van Moolenbroek     void *result;
1753*b89261baSDavid van Moolenbroek     lwpid_t k1;
1754*b89261baSDavid van Moolenbroek 
1755*b89261baSDavid van Moolenbroek     result = NULL;
1756*b89261baSDavid van Moolenbroek     if ((bucket = &(ht->buckets[(key % ht->num_buckets)])) != NULL)
1757*b89261baSDavid van Moolenbroek     {
1758*b89261baSDavid van Moolenbroek 	ll = &(bucket->list);
1759*b89261baSDavid van Moolenbroek 	li = LL_FIRST(ll);
1760*b89261baSDavid van Moolenbroek 	while (li != NULL)
1761*b89261baSDavid van Moolenbroek 	{
1762*b89261baSDavid van Moolenbroek 	    h = (hash_item_lwpid *)li->datum;
1763*b89261baSDavid van Moolenbroek 	    k1 = h->key;
1764*b89261baSDavid van Moolenbroek 	    if (key == k1)
1765*b89261baSDavid van Moolenbroek 	    {
1766*b89261baSDavid van Moolenbroek 		result = h->value;
1767*b89261baSDavid van Moolenbroek 		break;
1768*b89261baSDavid van Moolenbroek 	    }
1769*b89261baSDavid van Moolenbroek 	    li = LL_NEXT(ll, li);
1770*b89261baSDavid van Moolenbroek 	}
1771*b89261baSDavid van Moolenbroek     }
1772*b89261baSDavid van Moolenbroek     return result;
1773*b89261baSDavid van Moolenbroek }
1774*b89261baSDavid van Moolenbroek 
1775*b89261baSDavid van Moolenbroek /*
1776*b89261baSDavid van Moolenbroek  * void *hash_remove_lwpid(hash_table *ht, lwpid_t key)
1777*b89261baSDavid van Moolenbroek  *
1778*b89261baSDavid van Moolenbroek  * Remove the element associated with "key" from the hash table
1779*b89261baSDavid van Moolenbroek  * "ht".  Return the value or NULL if the key was not found.
1780*b89261baSDavid van Moolenbroek  */
1781*b89261baSDavid van Moolenbroek 
1782*b89261baSDavid van Moolenbroek void *
hash_remove_lwpid(hash_table * ht,lwpid_t key)1783*b89261baSDavid van Moolenbroek hash_remove_lwpid(hash_table *ht, lwpid_t key)
1784*b89261baSDavid van Moolenbroek 
1785*b89261baSDavid van Moolenbroek {
1786*b89261baSDavid van Moolenbroek     bucket_t *bucket;
1787*b89261baSDavid van Moolenbroek     llist *ll;
1788*b89261baSDavid van Moolenbroek     llistitem *li;
1789*b89261baSDavid van Moolenbroek     llistitem *lilast;
1790*b89261baSDavid van Moolenbroek     hash_item_lwpid *hi;
1791*b89261baSDavid van Moolenbroek     void *result;
1792*b89261baSDavid van Moolenbroek     lwpid_t k1;
1793*b89261baSDavid van Moolenbroek 
1794*b89261baSDavid van Moolenbroek     result = NULL;
1795*b89261baSDavid van Moolenbroek     if ((bucket = &(ht->buckets[(key % ht->num_buckets)])) != NULL)
1796*b89261baSDavid van Moolenbroek     {
1797*b89261baSDavid van Moolenbroek 	ll = &(bucket->list);
1798*b89261baSDavid van Moolenbroek 	li = LL_FIRST(ll);
1799*b89261baSDavid van Moolenbroek 	lilast = NULL;
1800*b89261baSDavid van Moolenbroek 	while (li != NULL)
1801*b89261baSDavid van Moolenbroek 	{
1802*b89261baSDavid van Moolenbroek 	    hi = (hash_item_lwpid *)li->datum;
1803*b89261baSDavid van Moolenbroek 	    k1 = hi->key;
1804*b89261baSDavid van Moolenbroek 	    if (key == k1)
1805*b89261baSDavid van Moolenbroek 	    {
1806*b89261baSDavid van Moolenbroek 		ll_extract(ll, li, lilast);
1807*b89261baSDavid van Moolenbroek 		result = hi->value;
1808*b89261baSDavid van Moolenbroek 		key = hi->key;
1809*b89261baSDavid van Moolenbroek 		;
1810*b89261baSDavid van Moolenbroek 		ll_freeitem(li);
1811*b89261baSDavid van Moolenbroek 		break;
1812*b89261baSDavid van Moolenbroek 	    }
1813*b89261baSDavid van Moolenbroek 	    lilast = li;
1814*b89261baSDavid van Moolenbroek 	    li = LL_NEXT(ll, li);
1815*b89261baSDavid van Moolenbroek 	}
1816*b89261baSDavid van Moolenbroek     }
1817*b89261baSDavid van Moolenbroek     return result;
1818*b89261baSDavid van Moolenbroek }
1819*b89261baSDavid van Moolenbroek 
1820*b89261baSDavid van Moolenbroek /*
1821*b89261baSDavid van Moolenbroek  * hash_item_lwpid *hash_first_lwpid(hash_table *ht, hash_pos *pos)
1822*b89261baSDavid van Moolenbroek  *
1823*b89261baSDavid van Moolenbroek  * First function to call when iterating through all items in the hash
1824*b89261baSDavid van Moolenbroek  * table.  Returns the first item in "ht" and initializes "*pos" to track
1825*b89261baSDavid van Moolenbroek  * the current position.
1826*b89261baSDavid van Moolenbroek  */
1827*b89261baSDavid van Moolenbroek 
1828*b89261baSDavid van Moolenbroek hash_item_lwpid *
hash_first_lwpid(hash_table * ht,hash_pos * pos)1829*b89261baSDavid van Moolenbroek hash_first_lwpid(hash_table *ht, hash_pos *pos)
1830*b89261baSDavid van Moolenbroek 
1831*b89261baSDavid van Moolenbroek {
1832*b89261baSDavid van Moolenbroek     /* initialize pos for first item in first bucket */
1833*b89261baSDavid van Moolenbroek     pos->num_buckets = ht->num_buckets;
1834*b89261baSDavid van Moolenbroek     pos->hash_bucket = ht->buckets;
1835*b89261baSDavid van Moolenbroek     pos->curr = 0;
1836*b89261baSDavid van Moolenbroek     pos->ll_last = NULL;
1837*b89261baSDavid van Moolenbroek 
1838*b89261baSDavid van Moolenbroek     /* find the first non-empty bucket */
1839*b89261baSDavid van Moolenbroek     while(pos->hash_bucket->list.count == 0)
1840*b89261baSDavid van Moolenbroek     {
1841*b89261baSDavid van Moolenbroek 	pos->hash_bucket++;
1842*b89261baSDavid van Moolenbroek 	if (++pos->curr >= pos->num_buckets)
1843*b89261baSDavid van Moolenbroek 	{
1844*b89261baSDavid van Moolenbroek 	    return NULL;
1845*b89261baSDavid van Moolenbroek 	}
1846*b89261baSDavid van Moolenbroek     }
1847*b89261baSDavid van Moolenbroek 
1848*b89261baSDavid van Moolenbroek     /* set and return the first item */
1849*b89261baSDavid van Moolenbroek     pos->ll_item = LL_FIRST(&(pos->hash_bucket->list));
1850*b89261baSDavid van Moolenbroek     return (hash_item_lwpid *)pos->ll_item->datum;
1851*b89261baSDavid van Moolenbroek }
1852*b89261baSDavid van Moolenbroek 
1853*b89261baSDavid van Moolenbroek 
1854*b89261baSDavid van Moolenbroek /*
1855*b89261baSDavid van Moolenbroek  * hash_item_lwpid *hash_next_lwpid(hash_pos *pos)
1856*b89261baSDavid van Moolenbroek  *
1857*b89261baSDavid van Moolenbroek  * Return the next item in the hash table, using "pos" as a description
1858*b89261baSDavid van Moolenbroek  * of the present position in the hash table.  "pos" also identifies the
1859*b89261baSDavid van Moolenbroek  * specific hash table.  Return NULL if there are no more elements.
1860*b89261baSDavid van Moolenbroek  */
1861*b89261baSDavid van Moolenbroek 
1862*b89261baSDavid van Moolenbroek hash_item_lwpid *
hash_next_lwpid(hash_pos * pos)1863*b89261baSDavid van Moolenbroek hash_next_lwpid(hash_pos *pos)
1864*b89261baSDavid van Moolenbroek 
1865*b89261baSDavid van Moolenbroek {
1866*b89261baSDavid van Moolenbroek     llistitem *li;
1867*b89261baSDavid van Moolenbroek 
1868*b89261baSDavid van Moolenbroek     /* move item to last and check for NULL */
1869*b89261baSDavid van Moolenbroek     if ((pos->ll_last = pos->ll_item) == NULL)
1870*b89261baSDavid van Moolenbroek     {
1871*b89261baSDavid van Moolenbroek 	/* are we really at the end of the hash table? */
1872*b89261baSDavid van Moolenbroek 	if (pos->curr >= pos->num_buckets)
1873*b89261baSDavid van Moolenbroek 	{
1874*b89261baSDavid van Moolenbroek 	    /* yes: return NULL */
1875*b89261baSDavid van Moolenbroek 	    return NULL;
1876*b89261baSDavid van Moolenbroek 	}
1877*b89261baSDavid van Moolenbroek 	/* no: regrab first item in current bucket list (might be NULL) */
1878*b89261baSDavid van Moolenbroek 	li = LL_FIRST(&(pos->hash_bucket->list));
1879*b89261baSDavid van Moolenbroek     }
1880*b89261baSDavid van Moolenbroek     else
1881*b89261baSDavid van Moolenbroek     {
1882*b89261baSDavid van Moolenbroek 	/* get the next item in the llist */
1883*b89261baSDavid van Moolenbroek 	li = LL_NEXT(&(pos->hash_bucket->list), pos->ll_item);
1884*b89261baSDavid van Moolenbroek     }
1885*b89261baSDavid van Moolenbroek 
1886*b89261baSDavid van Moolenbroek     /* if its NULL we have to find another bucket */
1887*b89261baSDavid van Moolenbroek     while (li == NULL)
1888*b89261baSDavid van Moolenbroek     {
1889*b89261baSDavid van Moolenbroek 	/* locate another bucket */
1890*b89261baSDavid van Moolenbroek 	pos->ll_last = NULL;
1891*b89261baSDavid van Moolenbroek 
1892*b89261baSDavid van Moolenbroek 	/* move to the next one */
1893*b89261baSDavid van Moolenbroek 	pos->hash_bucket++;
1894*b89261baSDavid van Moolenbroek 	if (++pos->curr >= pos->num_buckets)
1895*b89261baSDavid van Moolenbroek 	{
1896*b89261baSDavid van Moolenbroek 	    /* at the end of the hash table */
1897*b89261baSDavid van Moolenbroek 	    pos->ll_item = NULL;
1898*b89261baSDavid van Moolenbroek 	    return NULL;
1899*b89261baSDavid van Moolenbroek 	}
1900*b89261baSDavid van Moolenbroek 
1901*b89261baSDavid van Moolenbroek 	/* get the first element (might be NULL) */
1902*b89261baSDavid van Moolenbroek 	li = LL_FIRST(&(pos->hash_bucket->list));
1903*b89261baSDavid van Moolenbroek     }
1904*b89261baSDavid van Moolenbroek 
1905*b89261baSDavid van Moolenbroek     /* li is the next element to dish out */
1906*b89261baSDavid van Moolenbroek     pos->ll_item = li;
1907*b89261baSDavid van Moolenbroek     return (hash_item_lwpid *)li->datum;
1908*b89261baSDavid van Moolenbroek }
1909*b89261baSDavid van Moolenbroek 
1910*b89261baSDavid van Moolenbroek /*
1911*b89261baSDavid van Moolenbroek  * void *hash_remove_pos_lwpid(hash_pos *pos)
1912*b89261baSDavid van Moolenbroek  *
1913*b89261baSDavid van Moolenbroek  * Remove the hash table entry pointed to by position marker "pos".
1914*b89261baSDavid van Moolenbroek  * The data from the entry is returned upon success, otherwise NULL.
1915*b89261baSDavid van Moolenbroek  */
1916*b89261baSDavid van Moolenbroek 
1917*b89261baSDavid van Moolenbroek 
1918*b89261baSDavid van Moolenbroek void *
hash_remove_pos_lwpid(hash_pos * pos)1919*b89261baSDavid van Moolenbroek hash_remove_pos_lwpid(hash_pos *pos)
1920*b89261baSDavid van Moolenbroek 
1921*b89261baSDavid van Moolenbroek {
1922*b89261baSDavid van Moolenbroek     llistitem *li;
1923*b89261baSDavid van Moolenbroek     void *ans;
1924*b89261baSDavid van Moolenbroek     hash_item_lwpid *hi;
1925*b89261baSDavid van Moolenbroek 
1926*b89261baSDavid van Moolenbroek     /* sanity checks */
1927*b89261baSDavid van Moolenbroek     if (pos == NULL || pos->ll_last == pos->ll_item)
1928*b89261baSDavid van Moolenbroek     {
1929*b89261baSDavid van Moolenbroek 	return NULL;
1930*b89261baSDavid van Moolenbroek     }
1931*b89261baSDavid van Moolenbroek 
1932*b89261baSDavid van Moolenbroek     /* at this point pos contains the item to remove (ll_item)
1933*b89261baSDavid van Moolenbroek        and its predecesor (ll_last) */
1934*b89261baSDavid van Moolenbroek     /* extract the item from the llist */
1935*b89261baSDavid van Moolenbroek     li = pos->ll_item;
1936*b89261baSDavid van Moolenbroek     ll_extract(&(pos->hash_bucket->list), li, pos->ll_last);
1937*b89261baSDavid van Moolenbroek 
1938*b89261baSDavid van Moolenbroek     /* retain the data */
1939*b89261baSDavid van Moolenbroek     hi = (hash_item_lwpid *)li->datum;
1940*b89261baSDavid van Moolenbroek     ans = hi->value;
1941*b89261baSDavid van Moolenbroek 
1942*b89261baSDavid van Moolenbroek     /* free up the space */
1943*b89261baSDavid van Moolenbroek     ll_freeitem(li);
1944*b89261baSDavid van Moolenbroek 
1945*b89261baSDavid van Moolenbroek     /* back up to previous item */
1946*b89261baSDavid van Moolenbroek     /* its okay for ll_item to be null: hash_next will detect it */
1947*b89261baSDavid van Moolenbroek     pos->ll_item = pos->ll_last;
1948*b89261baSDavid van Moolenbroek 
1949*b89261baSDavid van Moolenbroek     return ans;
1950*b89261baSDavid van Moolenbroek }
1951*b89261baSDavid van Moolenbroek 
1952*b89261baSDavid van Moolenbroek #endif
1953