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