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