1 /* @configure_input@ */
4 ** Copyright 1998-2002 University of Illinois Board of Trustees
5 ** Copyright 1998-2002 Mark D. Roth
6 ** All rights reserved.
8 ** @LISTHASH_PREFIX@_hash.c - hash table routines
10 ** Mark D. Roth <roth@uiuc.edu>
11 ** Campus Information Technologies and Educational Services
12 ** University of Illinois at Urbana-Champaign
15 #include <@LISTHASH_PREFIX@/config.h>
16 #include <@LISTHASH_PREFIX@/compat.h>
18 #include <@LISTHASH_PREFIX@/@LISTHASH_PREFIX@_listhash.h>
29 ** @LISTHASH_PREFIX@_hashptr_reset() - reset a hash pointer
32 @LISTHASH_PREFIX@
_hashptr_reset(@LISTHASH_PREFIX@_hashptr_t
*hp
)
34 @LISTHASH_PREFIX@
_listptr_reset(&(hp
->node
));
40 ** @LISTHASH_PREFIX@_hashptr_data() - retrieve the data being pointed to
43 @LISTHASH_PREFIX@
_hashptr_data(@LISTHASH_PREFIX@_hashptr_t
*hp
)
45 return @LISTHASH_PREFIX@
_listptr_data(&(hp
->node
));
50 ** @LISTHASH_PREFIX@_str_hashfunc() - default hash function, optimized for
54 @LISTHASH_PREFIX@
_str_hashfunc(char *key
, unsigned int num_buckets
)
57 register unsigned result
= 0;
63 for (i
= 0; *key
!= '\0' && i
< 32; i
++)
64 result
= result
* 33U + *key
++;
66 return (result
% num_buckets
);
71 return (key
[0] % num_buckets
);
77 ** @LISTHASH_PREFIX@_hash_nents() - return number of elements from hash
80 @LISTHASH_PREFIX@
_hash_nents(@LISTHASH_PREFIX@_hash_t
*h
)
87 ** @LISTHASH_PREFIX@_hash_new() - create a new hash
89 @LISTHASH_PREFIX@_hash_t
*
90 @LISTHASH_PREFIX@
_hash_new(int num
, @LISTHASH_PREFIX@_hashfunc_t hashfunc
)
92 @LISTHASH_PREFIX@_hash_t
*hash
;
94 hash
= (@LISTHASH_PREFIX@_hash_t
*)calloc(1, sizeof(@LISTHASH_PREFIX@_hash_t
));
97 hash
->numbuckets
= num
;
99 hash
->hashfunc
= hashfunc
;
101 hash
->hashfunc
= (@LISTHASH_PREFIX@_hashfunc_t
)@LISTHASH_PREFIX@_str_hashfunc
;
103 hash
->table
= (@LISTHASH_PREFIX@_list_t
**)calloc(num
, sizeof(@LISTHASH_PREFIX@_list_t
*));
104 if (hash
->table
== NULL
)
115 ** @LISTHASH_PREFIX@_hash_next() - get next element in hash
121 @LISTHASH_PREFIX@
_hash_next(@LISTHASH_PREFIX@_hash_t
*h
,
122 @LISTHASH_PREFIX@_hashptr_t
*hp
)
125 printf("==> @LISTHASH_PREFIX@_hash_next(h=0x%lx, hp={%d,0x%lx})\n",
126 h
, hp
->bucket
, hp
->node
);
129 if (hp
->bucket
>= 0 && hp
->node
!= NULL
&&
130 @LISTHASH_PREFIX@
_list_next(h
->table
[hp
->bucket
], &(hp
->node
)) != 0)
133 printf(" @LISTHASH_PREFIX@_hash_next(): found additional "
134 "data in current bucket (%d), returing 1\n",
141 printf(" @LISTHASH_PREFIX@_hash_next(): done with bucket %d\n",
145 for (hp
->bucket
++; hp
->bucket
< h
->numbuckets
; hp
->bucket
++)
148 printf(" @LISTHASH_PREFIX@_hash_next(): "
149 "checking bucket %d\n", hp
->bucket
);
152 if (h
->table
[hp
->bucket
] != NULL
&&
153 @LISTHASH_PREFIX@
_list_next(h
->table
[hp
->bucket
],
157 printf(" @LISTHASH_PREFIX@_hash_next(): "
158 "found data in bucket %d, returing 1\n",
165 if (hp
->bucket
== h
->numbuckets
)
168 printf(" @LISTHASH_PREFIX@_hash_next(): hash pointer "
176 printf("<== @LISTHASH_PREFIX@_hash_next(): no more data, "
184 ** @LISTHASH_PREFIX@_hash_del() - delete an entry from the hash
187 ** -1 (and sets errno) failure
190 @LISTHASH_PREFIX@
_hash_del(@LISTHASH_PREFIX@_hash_t
*h
,
191 @LISTHASH_PREFIX@_hashptr_t
*hp
)
194 || hp
->bucket
>= h
->numbuckets
195 || h
->table
[hp
->bucket
] == NULL
202 @LISTHASH_PREFIX@
_list_del(h
->table
[hp
->bucket
], &(hp
->node
));
209 ** @LISTHASH_PREFIX@_hash_empty() - empty the hash
212 @LISTHASH_PREFIX@
_hash_empty(@LISTHASH_PREFIX@_hash_t
*h
, @LISTHASH_PREFIX@_freefunc_t freefunc
)
216 for (i
= 0; i
< h
->numbuckets
; i
++)
217 if (h
->table
[i
] != NULL
)
218 @LISTHASH_PREFIX@
_list_empty(h
->table
[i
], freefunc
);
225 ** @LISTHASH_PREFIX@_hash_free() - delete all of the nodes in the hash
228 @LISTHASH_PREFIX@
_hash_free(@LISTHASH_PREFIX@_hash_t
*h
, @LISTHASH_PREFIX@_freefunc_t freefunc
)
232 for (i
= 0; i
< h
->numbuckets
; i
++)
233 if (h
->table
[i
] != NULL
)
234 @LISTHASH_PREFIX@
_list_free(h
->table
[i
], freefunc
);
242 ** @LISTHASH_PREFIX@_hash_search() - iterative search for an element in a hash
248 @LISTHASH_PREFIX@
_hash_search(@LISTHASH_PREFIX@_hash_t
*h
,
249 @LISTHASH_PREFIX@_hashptr_t
*hp
, void *data
,
250 @LISTHASH_PREFIX@_matchfunc_t matchfunc
)
252 while (@LISTHASH_PREFIX@
_hash_next(h
, hp
) != 0)
253 if ((*matchfunc
)(data
, @LISTHASH_PREFIX@
_listptr_data(&(hp
->node
))) != 0)
261 ** @LISTHASH_PREFIX@_hash_getkey() - hash-based search for an element in a hash
267 @LISTHASH_PREFIX@
_hash_getkey(@LISTHASH_PREFIX@_hash_t
*h
,
268 @LISTHASH_PREFIX@_hashptr_t
*hp
, void *key
,
269 @LISTHASH_PREFIX@_matchfunc_t matchfunc
)
272 printf("==> @LISTHASH_PREFIX@_hash_getkey(h=0x%lx, hp={%d,0x%lx}, "
273 "key=0x%lx, matchfunc=0x%lx)\n",
274 h
, hp
->bucket
, hp
->node
, key
, matchfunc
);
277 if (hp
->bucket
== -1)
279 hp
->bucket
= (*(h
->hashfunc
))(key
, h
->numbuckets
);
281 printf(" @LISTHASH_PREFIX@_hash_getkey(): hp->bucket "
282 "set to %d\n", hp
->bucket
);
286 if (h
->table
[hp
->bucket
] == NULL
)
289 printf(" @LISTHASH_PREFIX@_hash_getkey(): no list "
290 "for bucket %d, returning 0\n", hp
->bucket
);
297 printf("<== @LISTHASH_PREFIX@_hash_getkey(): "
298 "returning @LISTHASH_PREFIX@_list_search()\n");
300 return @LISTHASH_PREFIX@
_list_search(h
->table
[hp
->bucket
], &(hp
->node
),
306 ** @LISTHASH_PREFIX@_hash_add() - add an element to the hash
309 ** -1 (and sets errno) failure
312 @LISTHASH_PREFIX@
_hash_add(@LISTHASH_PREFIX@_hash_t
*h
, void *data
)
317 printf("==> @LISTHASH_PREFIX@_hash_add(h=0x%lx, data=0x%lx)\n",
321 bucket
= (*(h
->hashfunc
))(data
, h
->numbuckets
);
323 printf(" @LISTHASH_PREFIX@_hash_add(): inserting in bucket %d\n",
326 if (h
->table
[bucket
] == NULL
)
329 printf(" @LISTHASH_PREFIX@_hash_add(): creating new list\n");
331 h
->table
[bucket
] = @LISTHASH_PREFIX@
_list_new(LIST_QUEUE
, NULL
);
335 printf("<== @LISTHASH_PREFIX@_hash_add(): "
336 "returning @LISTHASH_PREFIX@_list_add()\n");
338 i
= @LISTHASH_PREFIX@
_list_add(h
->table
[bucket
], data
);