1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* 30*7c478bd9Sstevel@tonic-gate * Routines for manipulating linked lists 31*7c478bd9Sstevel@tonic-gate */ 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate #include <stdio.h> 34*7c478bd9Sstevel@tonic-gate #include <assert.h> 35*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 36*7c478bd9Sstevel@tonic-gate 37*7c478bd9Sstevel@tonic-gate #include "list.h" 38*7c478bd9Sstevel@tonic-gate #include "memory.h" 39*7c478bd9Sstevel@tonic-gate 40*7c478bd9Sstevel@tonic-gate struct list { 41*7c478bd9Sstevel@tonic-gate void *l_data; 42*7c478bd9Sstevel@tonic-gate struct list *l_next; 43*7c478bd9Sstevel@tonic-gate }; 44*7c478bd9Sstevel@tonic-gate 45*7c478bd9Sstevel@tonic-gate /* Add an element to a list */ 46*7c478bd9Sstevel@tonic-gate void 47*7c478bd9Sstevel@tonic-gate list_add(list_t **list, void *data) 48*7c478bd9Sstevel@tonic-gate { 49*7c478bd9Sstevel@tonic-gate list_t *le; 50*7c478bd9Sstevel@tonic-gate 51*7c478bd9Sstevel@tonic-gate le = xmalloc(sizeof (list_t)); 52*7c478bd9Sstevel@tonic-gate le->l_data = data; 53*7c478bd9Sstevel@tonic-gate le->l_next = *list; 54*7c478bd9Sstevel@tonic-gate *list = le; 55*7c478bd9Sstevel@tonic-gate } 56*7c478bd9Sstevel@tonic-gate 57*7c478bd9Sstevel@tonic-gate /* Add an element to a sorted list */ 58*7c478bd9Sstevel@tonic-gate void 59*7c478bd9Sstevel@tonic-gate slist_add(list_t **list, void *data, int (*cmp)(void *, void *)) 60*7c478bd9Sstevel@tonic-gate { 61*7c478bd9Sstevel@tonic-gate list_t **nextp; 62*7c478bd9Sstevel@tonic-gate 63*7c478bd9Sstevel@tonic-gate for (nextp = list; *nextp; nextp = &((*nextp)->l_next)) { 64*7c478bd9Sstevel@tonic-gate if (cmp((*nextp)->l_data, data) > 0) 65*7c478bd9Sstevel@tonic-gate break; 66*7c478bd9Sstevel@tonic-gate } 67*7c478bd9Sstevel@tonic-gate 68*7c478bd9Sstevel@tonic-gate list_add(nextp, data); 69*7c478bd9Sstevel@tonic-gate } 70*7c478bd9Sstevel@tonic-gate 71*7c478bd9Sstevel@tonic-gate /*ARGSUSED2*/ 72*7c478bd9Sstevel@tonic-gate static int 73*7c478bd9Sstevel@tonic-gate list_defcmp(void *d1, void *d2, void *private) 74*7c478bd9Sstevel@tonic-gate { 75*7c478bd9Sstevel@tonic-gate return (d1 != d2); 76*7c478bd9Sstevel@tonic-gate } 77*7c478bd9Sstevel@tonic-gate 78*7c478bd9Sstevel@tonic-gate void * 79*7c478bd9Sstevel@tonic-gate list_remove(list_t **list, void *data, int (*cmp)(void *, void *, void *), 80*7c478bd9Sstevel@tonic-gate void *private) 81*7c478bd9Sstevel@tonic-gate { 82*7c478bd9Sstevel@tonic-gate list_t *le, **le2; 83*7c478bd9Sstevel@tonic-gate void *led; 84*7c478bd9Sstevel@tonic-gate 85*7c478bd9Sstevel@tonic-gate if (!cmp) 86*7c478bd9Sstevel@tonic-gate cmp = list_defcmp; 87*7c478bd9Sstevel@tonic-gate 88*7c478bd9Sstevel@tonic-gate for (le = *list, le2 = list; le; le2 = &le->l_next, le = le->l_next) { 89*7c478bd9Sstevel@tonic-gate if (cmp(le->l_data, data, private) == 0) { 90*7c478bd9Sstevel@tonic-gate *le2 = le->l_next; 91*7c478bd9Sstevel@tonic-gate led = le->l_data; 92*7c478bd9Sstevel@tonic-gate free(le); 93*7c478bd9Sstevel@tonic-gate return (led); 94*7c478bd9Sstevel@tonic-gate } 95*7c478bd9Sstevel@tonic-gate } 96*7c478bd9Sstevel@tonic-gate 97*7c478bd9Sstevel@tonic-gate return (NULL); 98*7c478bd9Sstevel@tonic-gate } 99*7c478bd9Sstevel@tonic-gate 100*7c478bd9Sstevel@tonic-gate void 101*7c478bd9Sstevel@tonic-gate list_free(list_t *list, void (*datafree)(void *, void *), void *private) 102*7c478bd9Sstevel@tonic-gate { 103*7c478bd9Sstevel@tonic-gate list_t *le; 104*7c478bd9Sstevel@tonic-gate 105*7c478bd9Sstevel@tonic-gate while (list) { 106*7c478bd9Sstevel@tonic-gate le = list; 107*7c478bd9Sstevel@tonic-gate list = list->l_next; 108*7c478bd9Sstevel@tonic-gate if (le->l_data && datafree) 109*7c478bd9Sstevel@tonic-gate datafree(le->l_data, private); 110*7c478bd9Sstevel@tonic-gate free(le); 111*7c478bd9Sstevel@tonic-gate } 112*7c478bd9Sstevel@tonic-gate } 113*7c478bd9Sstevel@tonic-gate 114*7c478bd9Sstevel@tonic-gate /* 115*7c478bd9Sstevel@tonic-gate * This iterator is specifically designed to tolerate the deletion of the 116*7c478bd9Sstevel@tonic-gate * node being iterated over. 117*7c478bd9Sstevel@tonic-gate */ 118*7c478bd9Sstevel@tonic-gate int 119*7c478bd9Sstevel@tonic-gate list_iter(list_t *list, int (*func)(void *, void *), void *private) 120*7c478bd9Sstevel@tonic-gate { 121*7c478bd9Sstevel@tonic-gate list_t *lnext; 122*7c478bd9Sstevel@tonic-gate int cumrc = 0; 123*7c478bd9Sstevel@tonic-gate int cbrc; 124*7c478bd9Sstevel@tonic-gate 125*7c478bd9Sstevel@tonic-gate while (list) { 126*7c478bd9Sstevel@tonic-gate lnext = list->l_next; 127*7c478bd9Sstevel@tonic-gate if ((cbrc = func(list->l_data, private)) < 0) 128*7c478bd9Sstevel@tonic-gate return (cbrc); 129*7c478bd9Sstevel@tonic-gate cumrc += cbrc; 130*7c478bd9Sstevel@tonic-gate list = lnext; 131*7c478bd9Sstevel@tonic-gate } 132*7c478bd9Sstevel@tonic-gate 133*7c478bd9Sstevel@tonic-gate return (cumrc); 134*7c478bd9Sstevel@tonic-gate } 135*7c478bd9Sstevel@tonic-gate 136*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 137*7c478bd9Sstevel@tonic-gate static int 138*7c478bd9Sstevel@tonic-gate list_count_cb(void *data, void *private) 139*7c478bd9Sstevel@tonic-gate { 140*7c478bd9Sstevel@tonic-gate return (1); 141*7c478bd9Sstevel@tonic-gate } 142*7c478bd9Sstevel@tonic-gate 143*7c478bd9Sstevel@tonic-gate int 144*7c478bd9Sstevel@tonic-gate list_count(list_t *list) 145*7c478bd9Sstevel@tonic-gate { 146*7c478bd9Sstevel@tonic-gate return (list_iter(list, list_count_cb, NULL)); 147*7c478bd9Sstevel@tonic-gate } 148*7c478bd9Sstevel@tonic-gate 149*7c478bd9Sstevel@tonic-gate int 150*7c478bd9Sstevel@tonic-gate list_empty(list_t *list) 151*7c478bd9Sstevel@tonic-gate { 152*7c478bd9Sstevel@tonic-gate return (list == NULL); 153*7c478bd9Sstevel@tonic-gate } 154*7c478bd9Sstevel@tonic-gate 155*7c478bd9Sstevel@tonic-gate void * 156*7c478bd9Sstevel@tonic-gate list_find(list_t *list, void *tmpl, int (*cmp)(void *, void *)) 157*7c478bd9Sstevel@tonic-gate { 158*7c478bd9Sstevel@tonic-gate for (; list; list = list->l_next) { 159*7c478bd9Sstevel@tonic-gate if (cmp(list->l_data, tmpl) == 0) 160*7c478bd9Sstevel@tonic-gate return (list->l_data); 161*7c478bd9Sstevel@tonic-gate } 162*7c478bd9Sstevel@tonic-gate 163*7c478bd9Sstevel@tonic-gate return (NULL); 164*7c478bd9Sstevel@tonic-gate } 165*7c478bd9Sstevel@tonic-gate 166*7c478bd9Sstevel@tonic-gate void * 167*7c478bd9Sstevel@tonic-gate list_first(list_t *list) 168*7c478bd9Sstevel@tonic-gate { 169*7c478bd9Sstevel@tonic-gate return (list ? list->l_data : NULL); 170*7c478bd9Sstevel@tonic-gate } 171*7c478bd9Sstevel@tonic-gate 172*7c478bd9Sstevel@tonic-gate void 173*7c478bd9Sstevel@tonic-gate list_concat(list_t **list1, list_t *list2) 174*7c478bd9Sstevel@tonic-gate { 175*7c478bd9Sstevel@tonic-gate list_t *l, *last; 176*7c478bd9Sstevel@tonic-gate 177*7c478bd9Sstevel@tonic-gate for (l = *list1, last = NULL; l; last = l, l = l->l_next) 178*7c478bd9Sstevel@tonic-gate continue; 179*7c478bd9Sstevel@tonic-gate 180*7c478bd9Sstevel@tonic-gate if (last == NULL) 181*7c478bd9Sstevel@tonic-gate *list1 = list2; 182*7c478bd9Sstevel@tonic-gate else 183*7c478bd9Sstevel@tonic-gate last->l_next = list2; 184*7c478bd9Sstevel@tonic-gate } 185*7c478bd9Sstevel@tonic-gate 186*7c478bd9Sstevel@tonic-gate /* 187*7c478bd9Sstevel@tonic-gate * Merges two sorted lists. Equal nodes (as determined by cmp) are retained. 188*7c478bd9Sstevel@tonic-gate */ 189*7c478bd9Sstevel@tonic-gate void 190*7c478bd9Sstevel@tonic-gate slist_merge(list_t **list1p, list_t *list2, int (*cmp)(void *, void *)) 191*7c478bd9Sstevel@tonic-gate { 192*7c478bd9Sstevel@tonic-gate list_t *list1, *next2; 193*7c478bd9Sstevel@tonic-gate list_t *last1 = NULL; 194*7c478bd9Sstevel@tonic-gate 195*7c478bd9Sstevel@tonic-gate if (*list1p == NULL) { 196*7c478bd9Sstevel@tonic-gate *list1p = list2; 197*7c478bd9Sstevel@tonic-gate return; 198*7c478bd9Sstevel@tonic-gate } 199*7c478bd9Sstevel@tonic-gate 200*7c478bd9Sstevel@tonic-gate list1 = *list1p; 201*7c478bd9Sstevel@tonic-gate while (list2 != NULL) { 202*7c478bd9Sstevel@tonic-gate if (cmp(list1->l_data, list2->l_data) > 0) { 203*7c478bd9Sstevel@tonic-gate next2 = list2->l_next; 204*7c478bd9Sstevel@tonic-gate 205*7c478bd9Sstevel@tonic-gate if (last1 == NULL) { 206*7c478bd9Sstevel@tonic-gate /* Insert at beginning */ 207*7c478bd9Sstevel@tonic-gate *list1p = last1 = list2; 208*7c478bd9Sstevel@tonic-gate list2->l_next = list1; 209*7c478bd9Sstevel@tonic-gate } else { 210*7c478bd9Sstevel@tonic-gate list2->l_next = list1; 211*7c478bd9Sstevel@tonic-gate last1->l_next = list2; 212*7c478bd9Sstevel@tonic-gate last1 = list2; 213*7c478bd9Sstevel@tonic-gate } 214*7c478bd9Sstevel@tonic-gate 215*7c478bd9Sstevel@tonic-gate list2 = next2; 216*7c478bd9Sstevel@tonic-gate } else { 217*7c478bd9Sstevel@tonic-gate 218*7c478bd9Sstevel@tonic-gate last1 = list1; 219*7c478bd9Sstevel@tonic-gate list1 = list1->l_next; 220*7c478bd9Sstevel@tonic-gate 221*7c478bd9Sstevel@tonic-gate if (list1 == NULL) { 222*7c478bd9Sstevel@tonic-gate /* Add the rest to the end of list1 */ 223*7c478bd9Sstevel@tonic-gate last1->l_next = list2; 224*7c478bd9Sstevel@tonic-gate list2 = NULL; 225*7c478bd9Sstevel@tonic-gate } 226*7c478bd9Sstevel@tonic-gate } 227*7c478bd9Sstevel@tonic-gate } 228*7c478bd9Sstevel@tonic-gate } 229