1*64eba9a2Syasuoka /* $OpenBSD: hash.c,v 1.6 2024/02/26 08:25:51 yasuoka Exp $ */
20fbf3537Syasuoka /*-
30fbf3537Syasuoka * Copyright (c) 2009 Internet Initiative Japan Inc.
40fbf3537Syasuoka * All rights reserved.
50fbf3537Syasuoka *
60fbf3537Syasuoka * Redistribution and use in source and binary forms, with or without
70fbf3537Syasuoka * modification, are permitted provided that the following conditions
80fbf3537Syasuoka * are met:
90fbf3537Syasuoka * 1. Redistributions of source code must retain the above copyright
100fbf3537Syasuoka * notice, this list of conditions and the following disclaimer.
110fbf3537Syasuoka * 2. Redistributions in binary form must reproduce the above copyright
120fbf3537Syasuoka * notice, this list of conditions and the following disclaimer in the
130fbf3537Syasuoka * documentation and/or other materials provided with the distribution.
140fbf3537Syasuoka *
150fbf3537Syasuoka * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
160fbf3537Syasuoka * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
170fbf3537Syasuoka * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
180fbf3537Syasuoka * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
190fbf3537Syasuoka * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
200fbf3537Syasuoka * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
210fbf3537Syasuoka * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
220fbf3537Syasuoka * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
230fbf3537Syasuoka * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
240fbf3537Syasuoka * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
250fbf3537Syasuoka * SUCH DAMAGE.
260fbf3537Syasuoka */
270fbf3537Syasuoka #include <sys/types.h>
280fbf3537Syasuoka #include <stdio.h>
290fbf3537Syasuoka #include <stdlib.h>
300fbf3537Syasuoka #include <string.h>
310fbf3537Syasuoka
320fbf3537Syasuoka #include "hash.h"
330fbf3537Syasuoka
340fbf3537Syasuoka /* hash_create - Create a new hash table.
350fbf3537Syasuoka * Returns a pointer of new hash_table on success. Otherwise returns
360fbf3537Syasuoka * NULL.
370fbf3537Syasuoka */
380fbf3537Syasuoka hash_table *
hash_create(int (* cmp_func)(const void *,const void *),uint32_t (* hash_func)(const void *,int),int hsz)39*64eba9a2Syasuoka hash_create(int (*cmp_func) (const void *, const void *),
40*64eba9a2Syasuoka uint32_t (*hash_func) (const void *, int), int hsz)
410fbf3537Syasuoka {
420fbf3537Syasuoka hash_table *htbl;
430fbf3537Syasuoka
4474590bb3Sderaadt htbl = malloc(sizeof(hash_table));
450fbf3537Syasuoka if (htbl == NULL)
460fbf3537Syasuoka return NULL;
470fbf3537Syasuoka
480fbf3537Syasuoka if (hsz < 1)
490fbf3537Syasuoka htbl->size = HASH_SIZE;
500fbf3537Syasuoka else
510fbf3537Syasuoka htbl->size = hsz;
520fbf3537Syasuoka
530fbf3537Syasuoka htbl->bucket = calloc(htbl->size, sizeof(hash_link *));
540fbf3537Syasuoka htbl->cmp = cmp_func;
550fbf3537Syasuoka htbl->hash = hash_func;
560fbf3537Syasuoka htbl->cur = 0;
570fbf3537Syasuoka htbl->bucket_cur = NULL;
580fbf3537Syasuoka
590fbf3537Syasuoka return htbl;
600fbf3537Syasuoka }
610fbf3537Syasuoka
620fbf3537Syasuoka /* hash_first - Get first item from hash table.
630fbf3537Syasuoka * Returns a pointer of first bucket on success. Otherwise returns
640fbf3537Syasuoka * NULL.
650fbf3537Syasuoka */
660fbf3537Syasuoka hash_link *
hash_first(hash_table * htbl)67*64eba9a2Syasuoka hash_first(hash_table *htbl)
680fbf3537Syasuoka {
690fbf3537Syasuoka htbl->cur = 0;
700fbf3537Syasuoka htbl->bucket_cur = NULL;
710fbf3537Syasuoka return hash_next(htbl);
720fbf3537Syasuoka }
730fbf3537Syasuoka
740fbf3537Syasuoka /* hash_next - Get next item from hash table.
750fbf3537Syasuoka * Returns a pointer of next bucket on success. Otherwise returns
760fbf3537Syasuoka * NULL.
770fbf3537Syasuoka */
780fbf3537Syasuoka hash_link *
hash_next(hash_table * htbl)79*64eba9a2Syasuoka hash_next(hash_table *htbl)
800fbf3537Syasuoka {
810fbf3537Syasuoka hash_link *hlink;
820fbf3537Syasuoka
830fbf3537Syasuoka if (htbl->bucket_cur != NULL) {
840fbf3537Syasuoka hlink = htbl->bucket_cur;
850fbf3537Syasuoka htbl->bucket_cur = hlink->next;
860fbf3537Syasuoka return hlink;
870fbf3537Syasuoka }
880fbf3537Syasuoka while (htbl->cur < htbl->size) {
890fbf3537Syasuoka if (htbl->bucket[htbl->cur] != NULL) {
900fbf3537Syasuoka hlink = htbl->bucket[htbl->cur++];
910fbf3537Syasuoka htbl->bucket_cur = hlink->next;
920fbf3537Syasuoka return hlink;
930fbf3537Syasuoka }
940fbf3537Syasuoka htbl->cur++;
950fbf3537Syasuoka }
960fbf3537Syasuoka return NULL;
970fbf3537Syasuoka }
980fbf3537Syasuoka
990fbf3537Syasuoka /* hash_lookup - Lookup item under the key in hash table.
1000fbf3537Syasuoka * Return a pointer of the bucket on success. Otherwise returns
1010fbf3537Syasuoka * NULL
1020fbf3537Syasuoka */
1030fbf3537Syasuoka hash_link *
hash_lookup(hash_table * htbl,const void * k)104*64eba9a2Syasuoka hash_lookup(hash_table *htbl, const void *k)
1050fbf3537Syasuoka {
1060fbf3537Syasuoka int c;
1070fbf3537Syasuoka hash_link *w;
1080fbf3537Syasuoka
1090fbf3537Syasuoka if (htbl == NULL || k == NULL)
1100fbf3537Syasuoka return NULL;
1110fbf3537Syasuoka c = (htbl->hash) (k, (int)htbl->size);
1120fbf3537Syasuoka for (w = htbl->bucket[c]; w != NULL; w = w->next)
1130fbf3537Syasuoka if (htbl->cmp(w->key, k) == 0)
1140fbf3537Syasuoka return w;
1150fbf3537Syasuoka return NULL;
1160fbf3537Syasuoka }
1170fbf3537Syasuoka
1180fbf3537Syasuoka /* hash_insert - Insert a item into hash table.
1190fbf3537Syasuoka * Return 0 on success. Return -1 on failure.
1200fbf3537Syasuoka */
1210fbf3537Syasuoka int
hash_insert(hash_table * htbl,const void * k,void * i)122*64eba9a2Syasuoka hash_insert(hash_table *htbl, const void *k, void *i)
1230fbf3537Syasuoka {
1240fbf3537Syasuoka int c;
1250fbf3537Syasuoka hash_link *n;
1260fbf3537Syasuoka
1270fbf3537Syasuoka if (htbl == NULL || k == NULL)
1280fbf3537Syasuoka return -1;
1290fbf3537Syasuoka
13074590bb3Sderaadt if ((n = malloc(sizeof(hash_link))) == NULL) {
1310fbf3537Syasuoka return -1;
1320fbf3537Syasuoka }
1330fbf3537Syasuoka
1340fbf3537Syasuoka c = (htbl->hash) (k, (int)htbl->size);
1350fbf3537Syasuoka
1360fbf3537Syasuoka n->item = i;
1370fbf3537Syasuoka n->key = k;
1380fbf3537Syasuoka n->next = htbl->bucket[c];
1390fbf3537Syasuoka htbl->bucket[c] = n;
1400fbf3537Syasuoka
1410fbf3537Syasuoka return 0;
1420fbf3537Syasuoka }
1430fbf3537Syasuoka
1440fbf3537Syasuoka /* hash_delete - Remove a item from hash table.
1450fbf3537Syasuoka * If memfree then free the item. Return 0 on success. Return -1
1460fbf3537Syasuoka * on failure.
1470fbf3537Syasuoka */
1480fbf3537Syasuoka int
hash_delete(hash_table * htbl,const void * k,int memfree)149*64eba9a2Syasuoka hash_delete(hash_table *htbl, const void *k, int memfree)
1500fbf3537Syasuoka {
1510fbf3537Syasuoka int i;
1520fbf3537Syasuoka hash_link *b, *w;
1530fbf3537Syasuoka
1540fbf3537Syasuoka if (htbl == NULL || k == NULL)
1550fbf3537Syasuoka return -1;
1560fbf3537Syasuoka
1570fbf3537Syasuoka i = (htbl->hash) (k, (int)htbl->size);
1580fbf3537Syasuoka
1590fbf3537Syasuoka for (w = htbl->bucket[i], b = NULL; w != NULL; w = w->next) {
1600fbf3537Syasuoka if (htbl->cmp(w->key, k) == 0) {
1610fbf3537Syasuoka if (b != NULL)
1620fbf3537Syasuoka b->next = w->next;
1630fbf3537Syasuoka else
1640fbf3537Syasuoka htbl->bucket[i] = w->next;
1650fbf3537Syasuoka
1660fbf3537Syasuoka if (htbl->bucket_cur == w)
1670fbf3537Syasuoka htbl->bucket_cur = w->next;
1680fbf3537Syasuoka
1690fbf3537Syasuoka if (w->item != NULL && memfree) {
1700fbf3537Syasuoka free(w->item);
1710fbf3537Syasuoka }
1720fbf3537Syasuoka free(w);
1730fbf3537Syasuoka return 0;
1740fbf3537Syasuoka }
1750fbf3537Syasuoka b = w;
1760fbf3537Syasuoka }
1770fbf3537Syasuoka return -1;
1780fbf3537Syasuoka }
1790fbf3537Syasuoka
1800fbf3537Syasuoka /*
1810fbf3537Syasuoka * delete all items from this hash_table.
1820fbf3537Syasuoka * If memfree != 0 then free items.
1830fbf3537Syasuoka */
1840fbf3537Syasuoka void
hash_delete_all(hash_table * htbl,int memfree)185*64eba9a2Syasuoka hash_delete_all(hash_table *htbl, int memfree)
1860fbf3537Syasuoka {
1870fbf3537Syasuoka int i;
1880fbf3537Syasuoka hash_link *w, *hl;
1890fbf3537Syasuoka
1900fbf3537Syasuoka for (i = 0; i < htbl->size; i++) {
1910fbf3537Syasuoka hl = htbl->bucket[i];
1920fbf3537Syasuoka htbl->bucket[i] = NULL;
1930fbf3537Syasuoka while (hl != NULL) {
1940fbf3537Syasuoka w = hl;
1950fbf3537Syasuoka hl = hl->next;
1960fbf3537Syasuoka if (memfree && w->item != NULL)
1970fbf3537Syasuoka free(w->item);
1980fbf3537Syasuoka free(w);
1990fbf3537Syasuoka }
2000fbf3537Syasuoka }
2010fbf3537Syasuoka }
2020fbf3537Syasuoka
2030fbf3537Syasuoka /* hash_free - Free hash table and all buckets.
2040fbf3537Syasuoka */
2050fbf3537Syasuoka void
hash_free(hash_table * htbl)206*64eba9a2Syasuoka hash_free(hash_table *htbl)
2070fbf3537Syasuoka {
2080fbf3537Syasuoka if (htbl != NULL) {
2090fbf3537Syasuoka free(htbl->bucket);
2100fbf3537Syasuoka free(htbl);
2110fbf3537Syasuoka }
2120fbf3537Syasuoka }
213