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