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