1178481Sjb/*
2178481Sjb * CDDL HEADER START
3178481Sjb *
4178481Sjb * The contents of this file are subject to the terms of the
5178481Sjb * Common Development and Distribution License, Version 1.0 only
6178481Sjb * (the "License").  You may not use this file except in compliance
7178481Sjb * with the License.
8178481Sjb *
9178481Sjb * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10178481Sjb * or http://www.opensolaris.org/os/licensing.
11178481Sjb * See the License for the specific language governing permissions
12178481Sjb * and limitations under the License.
13178481Sjb *
14178481Sjb * When distributing Covered Code, include this CDDL HEADER in each
15178481Sjb * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16178481Sjb * If applicable, add the following below this CDDL HEADER, with the
17178481Sjb * fields enclosed by brackets "[]" replaced with your own identifying
18178481Sjb * information: Portions Copyright [yyyy] [name of copyright owner]
19178481Sjb *
20178481Sjb * CDDL HEADER END
21178481Sjb */
22178481Sjb/*
23178481Sjb * Copyright 2001-2003 Sun Microsystems, Inc.  All rights reserved.
24178481Sjb * Use is subject to license terms.
25178481Sjb */
26178481Sjb
27178481Sjb#pragma ident	"%Z%%M%	%I%	%E% SMI"
28178481Sjb
29178481Sjb/*
30178481Sjb * Create, manage, and destroy association lists.  alists are arrays with
31178481Sjb * arbitrary index types, and are also commonly known as associative arrays.
32178481Sjb */
33178481Sjb
34178481Sjb#include <stdio.h>
35178481Sjb#include <stdlib.h>
36178481Sjb
37178481Sjb#include "alist.h"
38178481Sjb#include "memory.h"
39178481Sjb#include "hash.h"
40178481Sjb
41178481Sjb#define	ALIST_HASH_SIZE	997
42178481Sjb
43178481Sjbstruct alist {
44178481Sjb	hash_t *al_elements;
45178481Sjb	void (*al_namefree)(void *);
46178481Sjb	void (*al_valfree)(void *);
47178481Sjb};
48178481Sjb
49178481Sjbtypedef struct alist_el {
50178481Sjb	void *ale_name;
51178481Sjb	void *ale_value;
52178481Sjb} alist_el_t;
53178481Sjb
54178481Sjbstatic int
55178546Sjbalist_hash(int nbuckets, void *arg)
56178481Sjb{
57178546Sjb	alist_el_t *el = arg;
58178481Sjb	uintptr_t num = (uintptr_t)el->ale_name;
59178481Sjb
60178481Sjb	return (num % nbuckets);
61178481Sjb}
62178481Sjb
63178481Sjbstatic int
64178546Sjbalist_cmp(void *arg1, void *arg2)
65178481Sjb{
66178546Sjb	alist_el_t *el1 = arg1;
67178546Sjb	alist_el_t *el2 = arg2;
68178481Sjb	return ((uintptr_t)el1->ale_name != (uintptr_t)el2->ale_name);
69178481Sjb}
70178481Sjb
71178481Sjbalist_t *
72178481Sjbalist_xnew(int nbuckets, void (*namefree)(void *),
73178481Sjb    void (*valfree)(void *), int (*hashfn)(int, void *),
74178481Sjb    int (*cmpfn)(void *, void *))
75178481Sjb{
76178481Sjb	alist_t *alist;
77178481Sjb
78178481Sjb	alist = xcalloc(sizeof (alist_t));
79178481Sjb	alist->al_elements = hash_new(nbuckets, hashfn, cmpfn);
80178481Sjb	alist->al_namefree = namefree;
81178481Sjb	alist->al_valfree = valfree;
82178481Sjb
83178481Sjb	return (alist);
84178481Sjb}
85178481Sjb
86178481Sjbalist_t *
87178481Sjbalist_new(void (*namefree)(void *), void (*valfree)(void *))
88178481Sjb{
89178481Sjb	return (alist_xnew(ALIST_HASH_SIZE, namefree, valfree,
90178546Sjb	    alist_hash, alist_cmp));
91178481Sjb}
92178481Sjb
93178481Sjbstatic void
94178546Sjbalist_free_cb(void *arg1, void *arg2)
95178481Sjb{
96178546Sjb	alist_el_t *el = arg1;
97178546Sjb	alist_t *alist = arg2;
98178481Sjb	if (alist->al_namefree)
99178481Sjb		alist->al_namefree(el->ale_name);
100178481Sjb	if (alist->al_valfree)
101178481Sjb		alist->al_valfree(el->ale_name);
102178481Sjb	free(el);
103178481Sjb}
104178481Sjb
105178481Sjbvoid
106178481Sjbalist_free(alist_t *alist)
107178481Sjb{
108178546Sjb	hash_free(alist->al_elements, alist_free_cb, alist);
109178481Sjb	free(alist);
110178481Sjb}
111178481Sjb
112178481Sjbvoid
113178481Sjbalist_add(alist_t *alist, void *name, void *value)
114178481Sjb{
115178481Sjb	alist_el_t *el;
116178481Sjb
117178481Sjb	el = xmalloc(sizeof (alist_el_t));
118178481Sjb	el->ale_name = name;
119178481Sjb	el->ale_value = value;
120178481Sjb	hash_add(alist->al_elements, el);
121178481Sjb}
122178481Sjb
123178481Sjbint
124178481Sjbalist_find(alist_t *alist, void *name, void **value)
125178481Sjb{
126178546Sjb	alist_el_t template, *retx;
127178546Sjb	void *ret;
128178481Sjb
129178481Sjb	template.ale_name = name;
130178546Sjb	if (!hash_find(alist->al_elements, &template, &ret))
131178481Sjb		return (0);
132178481Sjb
133178546Sjb	if (value) {
134178546Sjb		retx = ret;
135178546Sjb		*value = retx->ale_value;
136178546Sjb	}
137178481Sjb
138178481Sjb	return (1);
139178481Sjb}
140178481Sjb
141178481Sjbtypedef struct alist_iter_data {
142178481Sjb	int (*aid_func)(void *, void *, void *);
143178481Sjb	void *aid_priv;
144178481Sjb} alist_iter_data_t;
145178481Sjb
146178481Sjbstatic int
147178546Sjbalist_iter_cb(void *arg1, void *arg2)
148178481Sjb{
149178546Sjb	alist_el_t *el = arg1;
150178546Sjb	alist_iter_data_t *aid = arg2;
151178481Sjb	return (aid->aid_func(el->ale_name, el->ale_value, aid->aid_priv));
152178481Sjb}
153178481Sjb
154178481Sjbint
155178481Sjbalist_iter(alist_t *alist, int (*func)(void *, void *, void *), void *private)
156178481Sjb{
157178481Sjb	alist_iter_data_t aid;
158178481Sjb
159178481Sjb	aid.aid_func = func;
160178481Sjb	aid.aid_priv = private;
161178481Sjb
162178546Sjb	return (hash_iter(alist->al_elements, alist_iter_cb, &aid));
163178481Sjb}
164178481Sjb
165178481Sjb/*
166178481Sjb * Debugging support.  Used to print the contents of an alist.
167178481Sjb */
168178481Sjb
169178481Sjbvoid
170178481Sjbalist_stats(alist_t *alist, int verbose)
171178481Sjb{
172178481Sjb	printf("Alist statistics\n");
173178481Sjb	hash_stats(alist->al_elements, verbose);
174178481Sjb}
175178481Sjb
176178481Sjbstatic int alist_def_print_cb_key_int = 1;
177178481Sjbstatic int alist_def_print_cb_value_int = 1;
178178481Sjb
179178481Sjbstatic int
180178481Sjbalist_def_print_cb(void *key, void *value)
181178481Sjb{
182178481Sjb	printf("Key: ");
183178481Sjb	if (alist_def_print_cb_key_int == 1)
184178546Sjb		printf("%5lu ", (ulong_t)key);
185178481Sjb	else
186178481Sjb		printf("%s\n", (char *)key);
187178481Sjb
188178481Sjb	printf("Value: ");
189178481Sjb	if (alist_def_print_cb_value_int == 1)
190178546Sjb		printf("%5lu\n", (ulong_t)value);
191178481Sjb	else
192178481Sjb		printf("%s\n", (char *)key);
193178481Sjb
194178481Sjb	return (1);
195178481Sjb}
196178481Sjb
197178481Sjbstatic int
198178481Sjbalist_dump_cb(void *node, void *private)
199178481Sjb{
200178546Sjb	int (*printer)(void *, void *) = private;
201178481Sjb	alist_el_t *el = node;
202178481Sjb
203178481Sjb	printer(el->ale_name, el->ale_value);
204178481Sjb
205178481Sjb	return (1);
206178481Sjb}
207178481Sjb
208178481Sjbint
209178481Sjbalist_dump(alist_t *alist, int (*printer)(void *, void *))
210178481Sjb{
211178481Sjb	if (!printer)
212178481Sjb		printer = alist_def_print_cb;
213178481Sjb
214178481Sjb	return (hash_iter(alist->al_elements, alist_dump_cb, (void *)printer));
215178481Sjb}
216