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 /*
23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  *
26  */
27 
28 /* $Id: list.c 146 2006-03-24 00:26:54Z njacobs $ */
29 
30 #pragma ident	"%Z%%M%	%I%	%E% SMI"
31 
32 /*LINTLIBRARY*/
33 
34 #include <stdlib.h>
35 #include <stdarg.h>
36 #include <errno.h>
37 
38 static int __list_increment = 16;
39 
40 #define	LIST_SIZE(x)	((((x) / __list_increment) + 1) * __list_increment)
41 
42 int
list_append(void *** list,void * item)43 list_append(void ***list, void *item)
44 {
45 	int count;
46 
47 	if ((list == NULL) || (item == NULL)) {
48 		errno = EINVAL;
49 		return (-1);
50 	}
51 
52 	if (item != NULL) {
53 		if (*list == NULL)
54 			*list = (void **)calloc(__list_increment,
55 			    sizeof (void *));
56 
57 		for (count = 0; (*list)[count] != NULL; count++)
58 			;
59 
60 		if ((count + 1) % __list_increment == 0) { /* expand the list */
61 			void **new_list = NULL;
62 			int new_size = LIST_SIZE(count + 1);
63 
64 			new_list = (void **)calloc(new_size, sizeof (void *));
65 			if (new_list == NULL)
66 				return (-1);
67 
68 			for (count = 0; (*list)[count] != NULL; count++)
69 				new_list[count] = (*list)[count];
70 			free(*list);
71 			*list = new_list;
72 		}
73 
74 		(*list)[count] = item;
75 	}
76 
77 	return (0);
78 }
79 
80 /*
81  *  list_concatenate() takes in two NULL terminated lists of items (type **)
82  *      and creates a new list with items from list2 appended on the end of
83  *      the list of items from list1.  The result is a list (type **).  If
84  *      there is a failure, -1 is returned.
85  */
86 int
list_concatenate(void *** result,void ** list2)87 list_concatenate(void ***result, void **list2)
88 {
89 	void    **list1;
90 	int	size1 = 0;
91 	int	size2 = 0;
92 	int	new_size = 0;
93 
94 	if ((result == NULL) || ((*result == NULL) && (list2 == NULL))) {
95 		errno = EINVAL;
96 		return (-1);
97 	}
98 
99 	list1 = *result;
100 
101 	if (list1 != NULL)
102 		for (size1 = 0; list1[size1] != NULL; size1++)
103 			;
104 	if (list2 != NULL)
105 		for (size2 = 0; list2[size2] != NULL; size2++)
106 			;
107 
108 	/* list1 + list2 padded to a multiple of _list_increment */
109 	new_size = LIST_SIZE(size1 + size2);
110 
111 	if ((*result = (void **)calloc((new_size), sizeof (void *))) != NULL) {
112 		int count = 0;
113 
114 		if (list1 != NULL)
115 			for (size1 = 0; list1[size1] != NULL; size1++)
116 				(*result)[count++] = list1[size1];
117 		if (list2 != NULL)
118 			for (size2 = 0; list2[size2] != NULL; size2++)
119 				(*result)[count++] = list2[size2];
120 		free(list1);
121 	}
122 
123 	return (0);
124 }
125 
126 /*
127  *  list_locate() iterates through the list passed in and uses the comparison
128  *      routine and element passed in to find an element in the list.  It
129  *      returns the first element matched, or NULL if none exists
130  */
131 void *
list_locate(void ** list,int (* compare)(void *,void *),void * element)132 list_locate(void **list, int (*compare)(void *, void *), void *element)
133 {
134 	int current = 0;
135 
136 	if ((list != NULL) && (element != NULL))
137 		for (current = 0; list[current] != NULL; current++)
138 			if ((compare)(list[current], element) == 0)
139 				return (list[current]);
140 	return (NULL);
141 }
142 
143 void
list_remove(void *** list,void * item)144 list_remove(void ***list, void *item)
145 {
146 	int i = 0, count;
147 
148 	if ((list == NULL) || (*list == NULL) || (item == NULL))
149 		return;
150 
151 	/* size the original list */
152 	for (count = 0; (*list)[count] != NULL; count++)
153 		if ((*list)[count] == item) {	/* mark the location of item */
154 			i = count;
155 			item = NULL;
156 		}
157 
158 	/* if found, remove it */
159 	if (item == NULL) {
160 		/* shift the list over the item */
161 		for (++i; ((*list)[i] != NULL); i++)
162 			(*list)[i-1] = (*list)[i];
163 		(*list)[i-1] = NULL;
164 	}
165 
166 	/* if found, removed, and list should shrink, shrink it */
167 	if ((item == NULL) && (LIST_SIZE(i) < LIST_SIZE(count))) {
168 		void **tmp = (void **)calloc(LIST_SIZE(i), sizeof (void *));
169 
170 		if (tmp != NULL) {
171 			for (i = 0; (*list)[i] != NULL; i++)
172 				tmp[i] = (*list)[i];
173 			free(*list);
174 			*list = tmp;
175 		}
176 	}
177 }
178