xref: /openbsd-src/usr.sbin/npppd/common/hash.c (revision 64eba9a26c6e9236e866b97e2b18e0edb144b187)
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