4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
25 * lut.c -- simple lookup table module
27 * this file contains a very simple lookup table (lut) implementation.
28 * the tables only support insert & lookup, no delete, and can
29 * only be walked in one order. if the key already exists
30 * for something being inserted, the previous entry is simply
34 #pragma ident "%Z%%M% %I% %E% SMI"
44 static struct stats
*Addtotal
;
45 static struct stats
*Lookuptotal
;
46 static struct stats
*Freetotal
;
51 Addtotal
= stats_new_counter("lut.adds", "total adds", 1);
52 Lookuptotal
= stats_new_counter("lut.lookup", "total lookups", 1);
53 Freetotal
= stats_new_counter("lut.frees", "total frees", 1);
59 stats_delete(Addtotal
);
60 stats_delete(Lookuptotal
);
61 stats_delete(Freetotal
);
65 * lut_add -- add an entry to the table
68 * struct lut *root = NULL;
69 * root = lut_add(root, key, value, cmp_func);
71 * the cmp_func can be strcmp(). pass in NULL and instead of
72 * calling a cmp_func the routine will just look at the difference
73 * between key pointers (useful when all strings are kept in a
74 * string table so they are equal if their pointers are equal).
78 lut_add(struct lut
*root
, void *lhs
, void *rhs
, lut_cmp cmp_func
)
81 struct lut
**tmp_hdl
= &root
, *parent
= NULL
, *tmp
= root
;
85 diff
= (*cmp_func
)(tmp
->lut_lhs
, lhs
);
87 diff
= (const char *)lhs
- (const char *)tmp
->lut_lhs
;
90 /* already in tree, replace node */
93 } else if (diff
> 0) {
94 tmp_hdl
= &(tmp
->lut_left
);
98 tmp_hdl
= &(tmp
->lut_right
);
100 tmp
= tmp
->lut_right
;
104 /* either empty tree or not in tree, so create new node */
105 *tmp_hdl
= MALLOC(sizeof (*root
));
106 (*tmp_hdl
)->lut_lhs
= lhs
;
107 (*tmp_hdl
)->lut_rhs
= rhs
;
108 (*tmp_hdl
)->lut_parent
= parent
;
109 (*tmp_hdl
)->lut_left
= (*tmp_hdl
)->lut_right
= NULL
;
110 stats_counter_bump(Addtotal
);
116 lut_lookup(struct lut
*root
, void *lhs
, lut_cmp cmp_func
)
120 stats_counter_bump(Lookuptotal
);
124 diff
= (*cmp_func
)(root
->lut_lhs
, lhs
);
126 diff
= (const char *)lhs
- (const char *)root
->lut_lhs
;
129 return (root
->lut_rhs
);
131 root
= root
->lut_left
;
133 root
= root
->lut_right
;
139 lut_lookup_lhs(struct lut
*root
, void *lhs
, lut_cmp cmp_func
)
143 stats_counter_bump(Lookuptotal
);
147 diff
= (*cmp_func
)(root
->lut_lhs
, lhs
);
149 diff
= (const char *)lhs
- (const char *)root
->lut_lhs
;
152 return (root
->lut_lhs
);
154 root
= root
->lut_left
;
156 root
= root
->lut_right
;
162 * lut_walk -- walk the table in lexical order
165 lut_walk(struct lut
*root
, lut_cb callback
, void *arg
)
167 struct lut
*tmp
= root
;
168 struct lut
*prev_child
= NULL
;
173 while (tmp
->lut_left
!= NULL
)
176 /* do callback on leftmost node */
177 (*callback
)(tmp
->lut_lhs
, tmp
->lut_rhs
, arg
);
180 if (tmp
->lut_right
!= NULL
&& tmp
->lut_right
!= prev_child
) {
181 tmp
= tmp
->lut_right
;
182 while (tmp
->lut_left
!= NULL
)
185 /* do callback on leftmost node */
186 (*callback
)(tmp
->lut_lhs
, tmp
->lut_rhs
, arg
);
187 } else if (tmp
->lut_parent
!= NULL
) {
189 tmp
= tmp
->lut_parent
;
191 * do callback on parent only if we're coming up
194 if (tmp
->lut_right
!= prev_child
)
195 (*callback
)(tmp
->lut_lhs
, tmp
->lut_rhs
, arg
);
202 * lut_free -- free the lut
205 lut_free(struct lut
*root
, lut_cb callback
, void *arg
)
207 struct lut
*tmp
= root
;
208 struct lut
*prev_child
= NULL
;
213 while (tmp
->lut_left
!= NULL
)
216 /* do callback on leftmost node */
218 (*callback
)(tmp
->lut_lhs
, tmp
->lut_rhs
, arg
);
221 if (tmp
->lut_right
!= NULL
&& tmp
->lut_right
!= prev_child
) {
222 tmp
= tmp
->lut_right
;
223 while (tmp
->lut_left
!= NULL
)
226 /* do callback on leftmost node */
228 (*callback
)(tmp
->lut_lhs
, tmp
->lut_rhs
, arg
);
229 } else if (tmp
->lut_parent
!= NULL
) {
231 tmp
= tmp
->lut_parent
;
234 * do callback on parent only if we're coming up
237 if (tmp
->lut_right
!= prev_child
&& callback
)
238 (*callback
)(tmp
->lut_lhs
, tmp
->lut_rhs
, arg
);
241 * free the root node and then we're done