Added autoconf instructions to README
[libtar.git] / listhash / hash.c.in
blob2736f542b295ece5c2450cb67518459a7b236076
1 /* @configure_input@ */
3 /*
4 ** Copyright 1998-2002 University of Illinois Board of Trustees
5 ** Copyright 1998-2002 Mark D. Roth
6 ** All rights reserved.
7 **
8 ** @LISTHASH_PREFIX@_hash.c - hash table routines
9 **
10 ** Mark D. Roth <roth@uiuc.edu>
11 ** Campus Information Technologies and Educational Services
12 ** University of Illinois at Urbana-Champaign
15 #include <config.h>
16 #include <compat.h>
18 #include <@LISTHASH_PREFIX@_listhash.h>
20 #include <stdio.h>
21 #include <errno.h>
23 #ifdef STDC_HEADERS
24 # include <stdlib.h>
25 #endif
29 ** @LISTHASH_PREFIX@_hashptr_reset() - reset a hash pointer
31 void
32 @LISTHASH_PREFIX@_hashptr_reset(@LISTHASH_PREFIX@_hashptr_t *hp)
34 @LISTHASH_PREFIX@_listptr_reset(&(hp->node));
35 hp->bucket = -1;
40 ** @LISTHASH_PREFIX@_hashptr_data() - retrieve the data being pointed to
42 void *
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
51 ** 7-bit strings
53 unsigned int
54 @LISTHASH_PREFIX@_str_hashfunc(char *key, unsigned int num_buckets)
56 #if 0
57 register unsigned result = 0;
58 register int i;
60 if (key == NULL)
61 return 0;
63 for (i = 0; *key != '\0' && i < 32; i++)
64 result = result * 33U + *key++;
66 return (result % num_buckets);
67 #else
68 if (key == NULL)
69 return 0;
71 return (key[0] % num_buckets);
72 #endif
77 ** @LISTHASH_PREFIX@_hash_nents() - return number of elements from hash
79 unsigned int
80 @LISTHASH_PREFIX@_hash_nents(@LISTHASH_PREFIX@_hash_t *h)
82 return h->nents;
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));
95 if (hash == NULL)
96 return NULL;
97 hash->numbuckets = num;
98 if (hashfunc != NULL)
99 hash->hashfunc = hashfunc;
100 else
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)
106 free(hash);
107 return NULL;
110 return hash;
115 ** @LISTHASH_PREFIX@_hash_next() - get next element in hash
116 ** returns:
117 ** 1 data found
118 ** 0 end of list
121 @LISTHASH_PREFIX@_hash_next(@LISTHASH_PREFIX@_hash_t *h,
122 @LISTHASH_PREFIX@_hashptr_t *hp)
124 #ifdef DS_DEBUG
125 printf("==> @LISTHASH_PREFIX@_hash_next(h=0x%lx, hp={%d,0x%lx})\n",
126 h, hp->bucket, hp->node);
127 #endif
129 if (hp->bucket >= 0 && hp->node != NULL &&
130 @LISTHASH_PREFIX@_list_next(h->table[hp->bucket], &(hp->node)) != 0)
132 #ifdef DS_DEBUG
133 printf(" @LISTHASH_PREFIX@_hash_next(): found additional "
134 "data in current bucket (%d), returing 1\n",
135 hp->bucket);
136 #endif
137 return 1;
140 #ifdef DS_DEBUG
141 printf(" @LISTHASH_PREFIX@_hash_next(): done with bucket %d\n",
142 hp->bucket);
143 #endif
145 for (hp->bucket++; hp->bucket < h->numbuckets; hp->bucket++)
147 #ifdef DS_DEBUG
148 printf(" @LISTHASH_PREFIX@_hash_next(): "
149 "checking bucket %d\n", hp->bucket);
150 #endif
151 hp->node = NULL;
152 if (h->table[hp->bucket] != NULL &&
153 @LISTHASH_PREFIX@_list_next(h->table[hp->bucket],
154 &(hp->node)) != 0)
156 #ifdef DS_DEBUG
157 printf(" @LISTHASH_PREFIX@_hash_next(): "
158 "found data in bucket %d, returing 1\n",
159 hp->bucket);
160 #endif
161 return 1;
165 if (hp->bucket == h->numbuckets)
167 #ifdef DS_DEBUG
168 printf(" @LISTHASH_PREFIX@_hash_next(): hash pointer "
169 "wrapped to 0\n");
170 #endif
171 hp->bucket = -1;
172 hp->node = NULL;
175 #ifdef DS_DEBUG
176 printf("<== @LISTHASH_PREFIX@_hash_next(): no more data, "
177 "returning 0\n");
178 #endif
179 return 0;
184 ** @LISTHASH_PREFIX@_hash_del() - delete an entry from the hash
185 ** returns:
186 ** 0 success
187 ** -1 (and sets errno) failure
190 @LISTHASH_PREFIX@_hash_del(@LISTHASH_PREFIX@_hash_t *h,
191 @LISTHASH_PREFIX@_hashptr_t *hp)
193 if (hp->bucket < 0
194 || hp->bucket >= h->numbuckets
195 || h->table[hp->bucket] == NULL
196 || hp->node == NULL)
198 errno = EINVAL;
199 return -1;
202 @LISTHASH_PREFIX@_list_del(h->table[hp->bucket], &(hp->node));
203 h->nents--;
204 return 0;
209 ** @LISTHASH_PREFIX@_hash_empty() - empty the hash
211 void
212 @LISTHASH_PREFIX@_hash_empty(@LISTHASH_PREFIX@_hash_t *h, @LISTHASH_PREFIX@_freefunc_t freefunc)
214 int i;
216 for (i = 0; i < h->numbuckets; i++)
217 if (h->table[i] != NULL)
218 @LISTHASH_PREFIX@_list_empty(h->table[i], freefunc);
220 h->nents = 0;
225 ** @LISTHASH_PREFIX@_hash_free() - delete all of the nodes in the hash
227 void
228 @LISTHASH_PREFIX@_hash_free(@LISTHASH_PREFIX@_hash_t *h, @LISTHASH_PREFIX@_freefunc_t freefunc)
230 int i;
232 for (i = 0; i < h->numbuckets; i++)
233 if (h->table[i] != NULL)
234 @LISTHASH_PREFIX@_list_free(h->table[i], freefunc);
236 free(h->table);
237 free(h);
242 ** @LISTHASH_PREFIX@_hash_search() - iterative search for an element in a hash
243 ** returns:
244 ** 1 match found
245 ** 0 no match
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)
254 return 1;
256 return 0;
261 ** @LISTHASH_PREFIX@_hash_getkey() - hash-based search for an element in a hash
262 ** returns:
263 ** 1 match found
264 ** 0 no match
267 @LISTHASH_PREFIX@_hash_getkey(@LISTHASH_PREFIX@_hash_t *h,
268 @LISTHASH_PREFIX@_hashptr_t *hp, void *key,
269 @LISTHASH_PREFIX@_matchfunc_t matchfunc)
271 #ifdef DS_DEBUG
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);
275 #endif
277 if (hp->bucket == -1)
279 hp->bucket = (*(h->hashfunc))(key, h->numbuckets);
280 #ifdef DS_DEBUG
281 printf(" @LISTHASH_PREFIX@_hash_getkey(): hp->bucket "
282 "set to %d\n", hp->bucket);
283 #endif
286 if (h->table[hp->bucket] == NULL)
288 #ifdef DS_DEBUG
289 printf(" @LISTHASH_PREFIX@_hash_getkey(): no list "
290 "for bucket %d, returning 0\n", hp->bucket);
291 #endif
292 hp->bucket = -1;
293 return 0;
296 #ifdef DS_DEBUG
297 printf("<== @LISTHASH_PREFIX@_hash_getkey(): "
298 "returning @LISTHASH_PREFIX@_list_search()\n");
299 #endif
300 return @LISTHASH_PREFIX@_list_search(h->table[hp->bucket], &(hp->node),
301 key, matchfunc);
306 ** @LISTHASH_PREFIX@_hash_add() - add an element to the hash
307 ** returns:
308 ** 0 success
309 ** -1 (and sets errno) failure
312 @LISTHASH_PREFIX@_hash_add(@LISTHASH_PREFIX@_hash_t *h, void *data)
314 int bucket, i;
316 #ifdef DS_DEBUG
317 printf("==> @LISTHASH_PREFIX@_hash_add(h=0x%lx, data=0x%lx)\n",
318 h, data);
319 #endif
321 bucket = (*(h->hashfunc))(data, h->numbuckets);
322 #ifdef DS_DEBUG
323 printf(" @LISTHASH_PREFIX@_hash_add(): inserting in bucket %d\n",
324 bucket);
325 #endif
326 if (h->table[bucket] == NULL)
328 #ifdef DS_DEBUG
329 printf(" @LISTHASH_PREFIX@_hash_add(): creating new list\n");
330 #endif
331 h->table[bucket] = @LISTHASH_PREFIX@_list_new(LIST_QUEUE, NULL);
334 #ifdef DS_DEBUG
335 printf("<== @LISTHASH_PREFIX@_hash_add(): "
336 "returning @LISTHASH_PREFIX@_list_add()\n");
337 #endif
338 i = @LISTHASH_PREFIX@_list_add(h->table[bucket], data);
339 if (i == 0)
340 h->nents++;
341 return i;