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 **
nsc_create_hash()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
nsc_insert_node(hash_node_t ** hash,void * data,const char * key)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 *
nsc_lookup(hash_node_t ** hash,const char * key)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 *
nsc_remove_node(hash_node_t ** hash,char * key)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
nsc_remove_all(hash_node_t ** hash,void (* callback)(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
calc_hash(const char * key)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