xref: /onnv-gate/usr/src/lib/libnsctl/common/hash.c (revision 7836:4e95154b5b7a)
1*7836SJohn.Forte@Sun.COM /*
2*7836SJohn.Forte@Sun.COM  * CDDL HEADER START
3*7836SJohn.Forte@Sun.COM  *
4*7836SJohn.Forte@Sun.COM  * The contents of this file are subject to the terms of the
5*7836SJohn.Forte@Sun.COM  * Common Development and Distribution License (the "License").
6*7836SJohn.Forte@Sun.COM  * You may not use this file except in compliance with the License.
7*7836SJohn.Forte@Sun.COM  *
8*7836SJohn.Forte@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*7836SJohn.Forte@Sun.COM  * or http://www.opensolaris.org/os/licensing.
10*7836SJohn.Forte@Sun.COM  * See the License for the specific language governing permissions
11*7836SJohn.Forte@Sun.COM  * and limitations under the License.
12*7836SJohn.Forte@Sun.COM  *
13*7836SJohn.Forte@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*7836SJohn.Forte@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*7836SJohn.Forte@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
16*7836SJohn.Forte@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*7836SJohn.Forte@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*7836SJohn.Forte@Sun.COM  *
19*7836SJohn.Forte@Sun.COM  * CDDL HEADER END
20*7836SJohn.Forte@Sun.COM  */
21*7836SJohn.Forte@Sun.COM /*
22*7836SJohn.Forte@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23*7836SJohn.Forte@Sun.COM  * Use is subject to license terms.
24*7836SJohn.Forte@Sun.COM  */
25*7836SJohn.Forte@Sun.COM 
26*7836SJohn.Forte@Sun.COM #include <string.h>
27*7836SJohn.Forte@Sun.COM #include <stdlib.h>
28*7836SJohn.Forte@Sun.COM #include <sys/nsctl/nsc_hash.h>
29*7836SJohn.Forte@Sun.COM 
30*7836SJohn.Forte@Sun.COM #define	HASH_PRIME 2039
31*7836SJohn.Forte@Sun.COM 
32*7836SJohn.Forte@Sun.COM static int calc_hash(const char *);
33*7836SJohn.Forte@Sun.COM 
34*7836SJohn.Forte@Sun.COM hash_node_t **
nsc_create_hash()35*7836SJohn.Forte@Sun.COM nsc_create_hash()
36*7836SJohn.Forte@Sun.COM {
37*7836SJohn.Forte@Sun.COM 	hash_node_t **hash;
38*7836SJohn.Forte@Sun.COM 
39*7836SJohn.Forte@Sun.COM 	hash = (hash_node_t **)calloc(HASH_PRIME, sizeof (hash_node_t *));
40*7836SJohn.Forte@Sun.COM 	return (hash);
41*7836SJohn.Forte@Sun.COM }
42*7836SJohn.Forte@Sun.COM 
43*7836SJohn.Forte@Sun.COM int
nsc_insert_node(hash_node_t ** hash,void * data,const char * key)44*7836SJohn.Forte@Sun.COM nsc_insert_node(hash_node_t **hash, void *data, const char *key)
45*7836SJohn.Forte@Sun.COM {
46*7836SJohn.Forte@Sun.COM 	int index;
47*7836SJohn.Forte@Sun.COM 	hash_node_t *node;
48*7836SJohn.Forte@Sun.COM 
49*7836SJohn.Forte@Sun.COM 	node = (hash_node_t *)malloc(sizeof (hash_node_t));
50*7836SJohn.Forte@Sun.COM 	if (!node) {
51*7836SJohn.Forte@Sun.COM 		return (-1);
52*7836SJohn.Forte@Sun.COM 	}
53*7836SJohn.Forte@Sun.COM 	node->key = strdup(key);
54*7836SJohn.Forte@Sun.COM 	node->data = data;
55*7836SJohn.Forte@Sun.COM 
56*7836SJohn.Forte@Sun.COM 	/*
57*7836SJohn.Forte@Sun.COM 	 * possible enhancement would be to search
58*7836SJohn.Forte@Sun.COM 	 * in this index for a duplicate
59*7836SJohn.Forte@Sun.COM 	 */
60*7836SJohn.Forte@Sun.COM 	index = calc_hash(key);
61*7836SJohn.Forte@Sun.COM 	node->next = hash[ index ];
62*7836SJohn.Forte@Sun.COM 	hash[ index ] = node;
63*7836SJohn.Forte@Sun.COM 
64*7836SJohn.Forte@Sun.COM 	return (0);
65*7836SJohn.Forte@Sun.COM }
66*7836SJohn.Forte@Sun.COM 
67*7836SJohn.Forte@Sun.COM /*
68*7836SJohn.Forte@Sun.COM  * lookup
69*7836SJohn.Forte@Sun.COM  *
70*7836SJohn.Forte@Sun.COM  * Description:
71*7836SJohn.Forte@Sun.COM  *	Searches the hash to find a node.
72*7836SJohn.Forte@Sun.COM  *
73*7836SJohn.Forte@Sun.COM  * Return values:
74*7836SJohn.Forte@Sun.COM  *	0 if not found.
75*7836SJohn.Forte@Sun.COM  *	pointer to node if found.
76*7836SJohn.Forte@Sun.COM  */
77*7836SJohn.Forte@Sun.COM void *
nsc_lookup(hash_node_t ** hash,const char * key)78*7836SJohn.Forte@Sun.COM nsc_lookup(hash_node_t **hash, const char *key)
79*7836SJohn.Forte@Sun.COM {
80*7836SJohn.Forte@Sun.COM 	int index;
81*7836SJohn.Forte@Sun.COM 	hash_node_t *node;
82*7836SJohn.Forte@Sun.COM 
83*7836SJohn.Forte@Sun.COM 	index = calc_hash(key);
84*7836SJohn.Forte@Sun.COM 	node = hash[ index ];
85*7836SJohn.Forte@Sun.COM 	while (node) {
86*7836SJohn.Forte@Sun.COM 		if (strcmp(node->key, key) == 0)
87*7836SJohn.Forte@Sun.COM 			return (node->data);
88*7836SJohn.Forte@Sun.COM 		node = node->next;
89*7836SJohn.Forte@Sun.COM 	}
90*7836SJohn.Forte@Sun.COM 	return (0);
91*7836SJohn.Forte@Sun.COM }
92*7836SJohn.Forte@Sun.COM 
93*7836SJohn.Forte@Sun.COM void *
nsc_remove_node(hash_node_t ** hash,char * key)94*7836SJohn.Forte@Sun.COM nsc_remove_node(hash_node_t **hash, char *key)
95*7836SJohn.Forte@Sun.COM {
96*7836SJohn.Forte@Sun.COM 	int index;
97*7836SJohn.Forte@Sun.COM 	hash_node_t *node, *prev;
98*7836SJohn.Forte@Sun.COM 	void *retval;
99*7836SJohn.Forte@Sun.COM 
100*7836SJohn.Forte@Sun.COM 	index = calc_hash(key);
101*7836SJohn.Forte@Sun.COM 	if (!hash[ index ]) {
102*7836SJohn.Forte@Sun.COM 		return (0);
103*7836SJohn.Forte@Sun.COM 	}
104*7836SJohn.Forte@Sun.COM 
105*7836SJohn.Forte@Sun.COM 	if (strcmp(hash[ index ]->key, key) == 0) {
106*7836SJohn.Forte@Sun.COM 		node = hash[ index ];
107*7836SJohn.Forte@Sun.COM 		retval = node->data;
108*7836SJohn.Forte@Sun.COM 		hash[ index ] = hash[ index ]->next;
109*7836SJohn.Forte@Sun.COM 		free(node->key);
110*7836SJohn.Forte@Sun.COM 		free(node);
111*7836SJohn.Forte@Sun.COM 		return (retval);
112*7836SJohn.Forte@Sun.COM 	}
113*7836SJohn.Forte@Sun.COM 	prev = hash[ index ];
114*7836SJohn.Forte@Sun.COM 	node = prev->next;
115*7836SJohn.Forte@Sun.COM 	while (node && (strcmp(node->key, key) != 0)) {
116*7836SJohn.Forte@Sun.COM 		prev = node;
117*7836SJohn.Forte@Sun.COM 		node = node->next;
118*7836SJohn.Forte@Sun.COM 	}
119*7836SJohn.Forte@Sun.COM 
120*7836SJohn.Forte@Sun.COM 	/* did we find it? */
121*7836SJohn.Forte@Sun.COM 	if (node) {
122*7836SJohn.Forte@Sun.COM 		prev->next = node->next;
123*7836SJohn.Forte@Sun.COM 		retval = node->data;
124*7836SJohn.Forte@Sun.COM 		free(node->key);
125*7836SJohn.Forte@Sun.COM 		free(node);
126*7836SJohn.Forte@Sun.COM 		return (retval);
127*7836SJohn.Forte@Sun.COM 	}
128*7836SJohn.Forte@Sun.COM 	return (0);
129*7836SJohn.Forte@Sun.COM }
130*7836SJohn.Forte@Sun.COM 
131*7836SJohn.Forte@Sun.COM void
nsc_remove_all(hash_node_t ** hash,void (* callback)(void *))132*7836SJohn.Forte@Sun.COM nsc_remove_all(hash_node_t **hash, void (*callback)(void *))
133*7836SJohn.Forte@Sun.COM {
134*7836SJohn.Forte@Sun.COM 	int i;
135*7836SJohn.Forte@Sun.COM 	hash_node_t *p, *next;
136*7836SJohn.Forte@Sun.COM 
137*7836SJohn.Forte@Sun.COM 	for (i = 0; i < HASH_PRIME; i++) {
138*7836SJohn.Forte@Sun.COM 		p = hash[ i ];
139*7836SJohn.Forte@Sun.COM 		while (p) {
140*7836SJohn.Forte@Sun.COM 			next = p->next;
141*7836SJohn.Forte@Sun.COM 			if (callback) {
142*7836SJohn.Forte@Sun.COM 				callback(p->data);
143*7836SJohn.Forte@Sun.COM 			}
144*7836SJohn.Forte@Sun.COM 			free(p->key);
145*7836SJohn.Forte@Sun.COM 			free(p);
146*7836SJohn.Forte@Sun.COM 			p = next;
147*7836SJohn.Forte@Sun.COM 		}
148*7836SJohn.Forte@Sun.COM 	}
149*7836SJohn.Forte@Sun.COM 	free(hash);
150*7836SJohn.Forte@Sun.COM }
151*7836SJohn.Forte@Sun.COM 
152*7836SJohn.Forte@Sun.COM /* ---------------------------------------------------------------------- */
153*7836SJohn.Forte@Sun.COM 
154*7836SJohn.Forte@Sun.COM /*
155*7836SJohn.Forte@Sun.COM  * Basic rotating hash, as per Knuth.
156*7836SJohn.Forte@Sun.COM  */
157*7836SJohn.Forte@Sun.COM static int
calc_hash(const char * key)158*7836SJohn.Forte@Sun.COM calc_hash(const char *key)
159*7836SJohn.Forte@Sun.COM {
160*7836SJohn.Forte@Sun.COM 	unsigned int hash, i;
161*7836SJohn.Forte@Sun.COM 	int len = strlen(key);
162*7836SJohn.Forte@Sun.COM 	for (hash = len, i = 0; i < len; i++) {
163*7836SJohn.Forte@Sun.COM 		hash = (hash << 5) ^ (hash >> 27) ^ key[ i ];
164*7836SJohn.Forte@Sun.COM 	}
165*7836SJohn.Forte@Sun.COM 	return (hash % HASH_PRIME);
166*7836SJohn.Forte@Sun.COM }
167