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 2006 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 int
41 list_append(void ***list, void *item)
42 {
43 	int count;
44 
45 	if ((list == NULL) || (item == NULL)) {
46 		errno = EINVAL;
47 		return (-1);
48 	}
49 
50 	if (item != NULL) {
51 		if (*list == NULL)
52 			*list = (void **)calloc(__list_increment,
53 						sizeof (void *));
54 
55 		for (count = 0; (*list)[count] != NULL; count++);
56 
57 		if ((count + 1) % __list_increment == 0) { /* expand the list */
58 			void **new_list = NULL;
59 			int new_size = (((count + 1) / __list_increment) + 1) *
60 				__list_increment;
61 
62 			new_list = (void **)calloc(new_size, sizeof (void *));
63 
64 			for (count = 0; (*list)[count] != NULL; count++)
65 				new_list[count] = (*list)[count];
66 			free(*list);
67 			*list = new_list;
68 		}
69 
70 		(*list)[count] = item;
71 	}
72 
73 	return (0);
74 }
75 
76 /*
77  *  list_concatenate() takes in two NULL terminated lists of items (type **)
78  *      and creates a new list with items from list2 appended on the end of
79  *      the list of items from list1.  The result is a list (type **).  If
80  *      there is a failure, -1 is returned.
81  */
82 int
83 list_concatenate(void ***result, void **list2)
84 {
85 	void    **list1;
86 	int	size1 = 0,
87 		size2 = 0,
88 		new_size = 0;
89 
90 	if ((result == NULL) || ((*result == NULL) && (list2 == NULL))) {
91 		errno = EINVAL;
92 		return (-1);
93 	}
94 
95 	list1 = *result;
96 
97 	if (list1 != NULL)
98 		for (size1 = 0; list1[size1] != NULL; size1++);
99 	if (list2 != NULL)
100 		for (size2 = 0; list2[size2] != NULL; size2++);
101 
102 	/* list1 + list2 padded to a multiple of _list_increment */
103 	new_size = ((size1 + size2)/__list_increment + 2) * __list_increment;
104 
105 	if ((*result = (void **)calloc((new_size), sizeof (void *)))
106 				!= NULL) {
107 		int count = 0;
108 
109 		if (list1 != NULL)
110 			for (size1 = 0; list1[size1] != NULL; size1++)
111 				(*result)[count++] = list1[size1];
112 		if (list2 != NULL)
113 			for (size2 = 0; list2[size2] != NULL; size2++)
114 				(*result)[count++] = list2[size2];
115 		free(list1);
116 	}
117 
118 	return (0);
119 }
120 
121 /*
122  *  list_locate() iterates through the list passed in and uses the comparison
123  *      routine and element passed in to find an element in the list.  It
124  *      returns the first element matched, or NULL if none exists
125  */
126 void *
127 list_locate(void **list, int (*compare)(void *, void *), void *element)
128 {
129 	int current = 0;
130 
131 	if ((list != NULL) && (element != NULL))
132 		for (current = 0; list[current] != NULL; current++)
133 			if ((compare)(list[current], element) == 0)
134 				return (list[current]);
135 	return (NULL);
136 }
137 
138 void
139 list_remove(void **list, void *item)
140 {
141 	int i, last;
142 
143 	if ((list == NULL) || (*list == NULL) || (item == NULL))
144 		return;
145 
146 	for (last = 0; list[last] != NULL; last++)
147 		;
148 	--last;
149 
150 	/*
151 	 * This doesn't preserve order, and doesn't shrink the allocation if we
152 	 * go below % __list_increment == 0.  <shrug>
153 	 */
154 	for (i = 0; list[i] != NULL; i++) {
155 		if (list[i] == item) {
156 			list[i] = list[last];
157 			list[last] = NULL;
158 			break;
159 		}
160 	}
161 }
162