1/*
2 * CDDL HEADER START
3 *
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.
7 *
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.
12 *
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]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26#pragma ident	"%Z%%M%	%I%	%E% SMI"
27
28/*LINTLIBRARY*/
29
30#include <stdio.h>
31#include <stdlib.h>
32#include <unistd.h>
33#include <sys/types.h>
34#include <stdarg.h>
35#include <syslog.h>
36#include <stdlib.h>
37#include <strings.h>
38
39#include <list.h>
40
41
42static int _list_increment = 64;  /* just so It can be tuned with adb(1) */
43/*
44 *  list_append() takes in a list (type **) and a pointer to an item to add
45 *	to the list and returns a new list with the new item appended on the
46 *	end.  The list is NULL terminated.  If there was an error, NULL is
47 *	returned.  For reasonable efficiency, the list will be allocated
48 *	in blocks of size _list_increment.
49 */
50void **
51list_append(void **list, void *item)
52{
53#ifdef DEBUG
54	syslog(LOG_DEBUG, "list_append(0x%x, 0x%x)", list, item);
55#endif
56	if (item == NULL)
57		return (list);
58
59	if (list == NULL) {
60		list = (void **)calloc(_list_increment, sizeof (void *));
61		(void) memset(list, NULL, (_list_increment * sizeof (void *)));
62		list[0] = item;
63	} else {
64		int	count;
65
66		for (count = 0; list[count] != NULL; count++);
67
68		if ((count + 1) % _list_increment == 0) { /* increase size */
69			void	**new_list = NULL;
70			int new_size = (((count + 1) / _list_increment) + 1) *
71				_list_increment;
72
73			new_list = (void **)calloc(new_size,
74						sizeof (void *));
75			(void) memset(new_list, NULL,
76			    (new_size * sizeof (void *)));
77			for (count = 0; list[count] != NULL; count++)
78				new_list[count] = list[count];
79			free(list);
80			list = new_list;
81		}
82		list[count] = item;
83	}
84	return (list);
85}
86
87
88void **
89list_append_unique(void **list, void *item, int (*cmp)(void *, void*))
90{
91	if (list_locate(list, cmp, item))
92		return (list);
93
94	list = list_append(list, item);
95	return (list);
96}
97
98
99/*
100 *  list_locate() iterates through the list passed in and uses the comparison
101 *	routine and element passed in to find an element in the list.  It
102 *	returns the first element matched, or NULL if none exists
103 */
104void *
105list_locate(void **list, int (*compair)(void *, void *), void *element)
106{
107	int	current = 0;
108
109#ifdef DEBUG
110	syslog(LOG_DEBUG, "list_locate()");
111#endif
112	if (list != NULL)
113		for (current = 0; list[current] != NULL; current++)
114			if ((compair)(list[current], element) == 0)
115				return (list[current]);
116	return (NULL);
117}
118
119
120/*
121 *  list_concatenate() takes in two NULL terminated lists of items (type **)
122 *	and creates a new list with items from list2 appended on the end of
123 *	the list of items from list1.  The result is a list (type **).  If
124 *	there is a failure, NULL is returned.
125 */
126void **
127list_concatenate(void **list1, void **list2)
128{
129	void	**list = NULL;
130	int	size1 = 0,
131		size2 = 0,
132		new_size = 0;
133#ifdef DEBUG
134	syslog(LOG_DEBUG, "list_concatenate(0x%x, 0x%x)", list1, list2);
135#endif
136	if ((list1 == NULL) || (list2 == NULL))
137		return ((list1 != NULL) ? list1 : list2);
138
139	for (size1 = 0; list1[size1] != NULL; size1++);
140	for (size2 = 0; list2[size2] != NULL; size2++);
141
142	/* list1 + list2 padded to a multiple of _list_increment */
143	new_size = ((size1 + size2)/_list_increment + 2) * _list_increment;
144
145	if ((list = (void **)calloc((new_size), sizeof (void *)))
146				!= NULL) {
147		int count = 0;
148
149		(void) memset(list, NULL, (new_size * sizeof (void *)));
150
151		for (size1 = 0; list1[size1] != NULL; size1++)
152			list[count++] = list1[size1];
153		for (size2 = 0; list2[size2] != NULL; size2++)
154			list[count++] = list2[size2];
155		free(list1);
156	}
157	return (list);
158}
159
160
161/*
162 *  list_iterate() take in a list, pointer to a function, and variable number
163 *	of arguements following.  list_iterate() will iterate through the list
164 *	calling the functions passed in with the first argument being a pointer
165 *	to the current item in the list and the second argument being a va_list
166 *	containing the rest of arguments used to call list_iterate().  The
167 *	calling fuction should be declared: int func(type *, va_list).  The
168 *	return results are all added together and the sum is returned from
169 *	list_iterate().
170 */
171int
172list_iterate(void **list, int (*vfunc)(void *, va_list), ...)
173{
174	int	current = 0,
175		rc = 0;
176
177#ifdef DEBUG
178	syslog(LOG_DEBUG, "list_iterate(0x%x, 0x%x)", list, vfunc);
179#endif
180	if (list != NULL)
181		while (list[current] != NULL) {
182			va_list	ap;
183
184			va_start(ap, (vfunc));
185			rc += (vfunc)(list[current++], ap);
186			va_end(ap);
187		}
188	return (rc);
189}
190