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