xref: /illumos-gate/usr/src/lib/print/libprint/common/list.c (revision d2ec54f7875f7e05edd56195adbeb593c947763f)
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 
42 static 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  */
50 void **
51 list_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 
88 void **
89 list_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  */
104 void *
105 list_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  */
126 void **
127 list_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  */
171 int
172 list_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