xref: /freebsd-src/cddl/contrib/opensolaris/tools/ctf/common/list.c (revision 4cc75139b96639698b4e96da3b60cd3d81e9a959)
11673e404SJohn Birrell /*
21673e404SJohn Birrell  * CDDL HEADER START
31673e404SJohn Birrell  *
41673e404SJohn Birrell  * The contents of this file are subject to the terms of the
51673e404SJohn Birrell  * Common Development and Distribution License, Version 1.0 only
61673e404SJohn Birrell  * (the "License").  You may not use this file except in compliance
71673e404SJohn Birrell  * with the License.
81673e404SJohn Birrell  *
91673e404SJohn Birrell  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
101673e404SJohn Birrell  * or http://www.opensolaris.org/os/licensing.
111673e404SJohn Birrell  * See the License for the specific language governing permissions
121673e404SJohn Birrell  * and limitations under the License.
131673e404SJohn Birrell  *
141673e404SJohn Birrell  * When distributing Covered Code, include this CDDL HEADER in each
151673e404SJohn Birrell  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
161673e404SJohn Birrell  * If applicable, add the following below this CDDL HEADER, with the
171673e404SJohn Birrell  * fields enclosed by brackets "[]" replaced with your own identifying
181673e404SJohn Birrell  * information: Portions Copyright [yyyy] [name of copyright owner]
191673e404SJohn Birrell  *
201673e404SJohn Birrell  * CDDL HEADER END
211673e404SJohn Birrell  */
221673e404SJohn Birrell /*
231673e404SJohn Birrell  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
241673e404SJohn Birrell  * Use is subject to license terms.
251673e404SJohn Birrell  */
261673e404SJohn Birrell 
271673e404SJohn Birrell #pragma ident	"%Z%%M%	%I%	%E% SMI"
281673e404SJohn Birrell 
291673e404SJohn Birrell /*
301673e404SJohn Birrell  * Routines for manipulating linked lists
311673e404SJohn Birrell  */
321673e404SJohn Birrell 
331673e404SJohn Birrell #include <stdio.h>
341673e404SJohn Birrell #include <assert.h>
351673e404SJohn Birrell #include <stdlib.h>
361673e404SJohn Birrell 
371673e404SJohn Birrell #include "list.h"
381673e404SJohn Birrell #include "memory.h"
391673e404SJohn Birrell 
401673e404SJohn Birrell struct list {
411673e404SJohn Birrell 	void *l_data;
421673e404SJohn Birrell 	struct list *l_next;
431673e404SJohn Birrell };
441673e404SJohn Birrell 
451673e404SJohn Birrell /* Add an element to a list */
461673e404SJohn Birrell void
list_add(list_t ** list,void * data)471673e404SJohn Birrell list_add(list_t **list, void *data)
481673e404SJohn Birrell {
491673e404SJohn Birrell 	list_t *le;
501673e404SJohn Birrell 
511673e404SJohn Birrell 	le = xmalloc(sizeof (list_t));
521673e404SJohn Birrell 	le->l_data = data;
531673e404SJohn Birrell 	le->l_next = *list;
541673e404SJohn Birrell 	*list = le;
551673e404SJohn Birrell }
561673e404SJohn Birrell 
571673e404SJohn Birrell /* Add an element to a sorted list */
581673e404SJohn Birrell void
slist_add(list_t ** list,void * data,int (* cmp)(void *,void *))591673e404SJohn Birrell slist_add(list_t **list, void *data, int (*cmp)(void *, void *))
601673e404SJohn Birrell {
611673e404SJohn Birrell 	list_t **nextp;
621673e404SJohn Birrell 
631673e404SJohn Birrell 	for (nextp = list; *nextp; nextp = &((*nextp)->l_next)) {
641673e404SJohn Birrell 		if (cmp((*nextp)->l_data, data) > 0)
651673e404SJohn Birrell 			break;
661673e404SJohn Birrell 	}
671673e404SJohn Birrell 
681673e404SJohn Birrell 	list_add(nextp, data);
691673e404SJohn Birrell }
701673e404SJohn Birrell 
711673e404SJohn Birrell /*ARGSUSED2*/
721673e404SJohn Birrell static int
list_defcmp(void * d1,void * d2,void * private __unused)73*4cc75139SJohn Birrell list_defcmp(void *d1, void *d2, void *private __unused)
741673e404SJohn Birrell {
751673e404SJohn Birrell 	return (d1 != d2);
761673e404SJohn Birrell }
771673e404SJohn Birrell 
781673e404SJohn Birrell void *
list_remove(list_t ** list,void * data,int (* cmp)(void *,void *,void *),void * private)791673e404SJohn Birrell list_remove(list_t **list, void *data, int (*cmp)(void *, void *, void *),
801673e404SJohn Birrell     void *private)
811673e404SJohn Birrell {
821673e404SJohn Birrell 	list_t *le, **le2;
831673e404SJohn Birrell 	void *led;
841673e404SJohn Birrell 
851673e404SJohn Birrell 	if (!cmp)
861673e404SJohn Birrell 		cmp = list_defcmp;
871673e404SJohn Birrell 
881673e404SJohn Birrell 	for (le = *list, le2 = list; le; le2 = &le->l_next, le = le->l_next) {
891673e404SJohn Birrell 		if (cmp(le->l_data, data, private) == 0) {
901673e404SJohn Birrell 			*le2 = le->l_next;
911673e404SJohn Birrell 			led = le->l_data;
921673e404SJohn Birrell 			free(le);
931673e404SJohn Birrell 			return (led);
941673e404SJohn Birrell 		}
951673e404SJohn Birrell 	}
961673e404SJohn Birrell 
971673e404SJohn Birrell 	return (NULL);
981673e404SJohn Birrell }
991673e404SJohn Birrell 
1001673e404SJohn Birrell void
list_free(list_t * list,void (* datafree)(void *,void *),void * private)1011673e404SJohn Birrell list_free(list_t *list, void (*datafree)(void *, void *), void *private)
1021673e404SJohn Birrell {
1031673e404SJohn Birrell 	list_t *le;
1041673e404SJohn Birrell 
1051673e404SJohn Birrell 	while (list) {
1061673e404SJohn Birrell 		le = list;
1071673e404SJohn Birrell 		list = list->l_next;
1081673e404SJohn Birrell 		if (le->l_data && datafree)
1091673e404SJohn Birrell 			datafree(le->l_data, private);
1101673e404SJohn Birrell 		free(le);
1111673e404SJohn Birrell 	}
1121673e404SJohn Birrell }
1131673e404SJohn Birrell 
1141673e404SJohn Birrell /*
1151673e404SJohn Birrell  * This iterator is specifically designed to tolerate the deletion of the
1161673e404SJohn Birrell  * node being iterated over.
1171673e404SJohn Birrell  */
1181673e404SJohn Birrell int
list_iter(list_t * list,int (* func)(void *,void *),void * private)1191673e404SJohn Birrell list_iter(list_t *list, int (*func)(void *, void *), void *private)
1201673e404SJohn Birrell {
1211673e404SJohn Birrell 	list_t *lnext;
1221673e404SJohn Birrell 	int cumrc = 0;
1231673e404SJohn Birrell 	int cbrc;
1241673e404SJohn Birrell 
1251673e404SJohn Birrell 	while (list) {
1261673e404SJohn Birrell 		lnext = list->l_next;
1271673e404SJohn Birrell 		if ((cbrc = func(list->l_data, private)) < 0)
1281673e404SJohn Birrell 			return (cbrc);
1291673e404SJohn Birrell 		cumrc += cbrc;
1301673e404SJohn Birrell 		list = lnext;
1311673e404SJohn Birrell 	}
1321673e404SJohn Birrell 
1331673e404SJohn Birrell 	return (cumrc);
1341673e404SJohn Birrell }
1351673e404SJohn Birrell 
1361673e404SJohn Birrell /*ARGSUSED*/
1371673e404SJohn Birrell static int
list_count_cb(void * data __unused,void * private __unused)138*4cc75139SJohn Birrell list_count_cb(void *data __unused, void *private __unused)
1391673e404SJohn Birrell {
1401673e404SJohn Birrell 	return (1);
1411673e404SJohn Birrell }
1421673e404SJohn Birrell 
1431673e404SJohn Birrell int
list_count(list_t * list)1441673e404SJohn Birrell list_count(list_t *list)
1451673e404SJohn Birrell {
1461673e404SJohn Birrell 	return (list_iter(list, list_count_cb, NULL));
1471673e404SJohn Birrell }
1481673e404SJohn Birrell 
1491673e404SJohn Birrell int
list_empty(list_t * list)1501673e404SJohn Birrell list_empty(list_t *list)
1511673e404SJohn Birrell {
1521673e404SJohn Birrell 	return (list == NULL);
1531673e404SJohn Birrell }
1541673e404SJohn Birrell 
1551673e404SJohn Birrell void *
list_find(list_t * list,void * tmpl,int (* cmp)(void *,void *))1561673e404SJohn Birrell list_find(list_t *list, void *tmpl, int (*cmp)(void *, void *))
1571673e404SJohn Birrell {
1581673e404SJohn Birrell 	for (; list; list = list->l_next) {
1591673e404SJohn Birrell 		if (cmp(list->l_data, tmpl) == 0)
1601673e404SJohn Birrell 			return (list->l_data);
1611673e404SJohn Birrell 	}
1621673e404SJohn Birrell 
1631673e404SJohn Birrell 	return (NULL);
1641673e404SJohn Birrell }
1651673e404SJohn Birrell 
1661673e404SJohn Birrell void *
list_first(list_t * list)1671673e404SJohn Birrell list_first(list_t *list)
1681673e404SJohn Birrell {
1691673e404SJohn Birrell 	return (list ? list->l_data : NULL);
1701673e404SJohn Birrell }
1711673e404SJohn Birrell 
1721673e404SJohn Birrell void
list_concat(list_t ** list1,list_t * list2)1731673e404SJohn Birrell list_concat(list_t **list1, list_t *list2)
1741673e404SJohn Birrell {
1751673e404SJohn Birrell 	list_t *l, *last;
1761673e404SJohn Birrell 
1771673e404SJohn Birrell 	for (l = *list1, last = NULL; l; last = l, l = l->l_next)
1781673e404SJohn Birrell 		continue;
1791673e404SJohn Birrell 
1801673e404SJohn Birrell 	if (last == NULL)
1811673e404SJohn Birrell 		*list1 = list2;
1821673e404SJohn Birrell 	else
1831673e404SJohn Birrell 		last->l_next = list2;
1841673e404SJohn Birrell }
1851673e404SJohn Birrell 
1861673e404SJohn Birrell /*
1871673e404SJohn Birrell  * Merges two sorted lists.  Equal nodes (as determined by cmp) are retained.
1881673e404SJohn Birrell  */
1891673e404SJohn Birrell void
slist_merge(list_t ** list1p,list_t * list2,int (* cmp)(void *,void *))1901673e404SJohn Birrell slist_merge(list_t **list1p, list_t *list2, int (*cmp)(void *, void *))
1911673e404SJohn Birrell {
1921673e404SJohn Birrell 	list_t *list1, *next2;
1931673e404SJohn Birrell 	list_t *last1 = NULL;
1941673e404SJohn Birrell 
1951673e404SJohn Birrell 	if (*list1p == NULL) {
1961673e404SJohn Birrell 		*list1p = list2;
1971673e404SJohn Birrell 		return;
1981673e404SJohn Birrell 	}
1991673e404SJohn Birrell 
2001673e404SJohn Birrell 	list1 = *list1p;
2011673e404SJohn Birrell 	while (list2 != NULL) {
2021673e404SJohn Birrell 		if (cmp(list1->l_data, list2->l_data) > 0) {
2031673e404SJohn Birrell 			next2 = list2->l_next;
2041673e404SJohn Birrell 
2051673e404SJohn Birrell 			if (last1 == NULL) {
2061673e404SJohn Birrell 				/* Insert at beginning */
2071673e404SJohn Birrell 				*list1p = last1 = list2;
2081673e404SJohn Birrell 				list2->l_next = list1;
2091673e404SJohn Birrell 			} else {
2101673e404SJohn Birrell 				list2->l_next = list1;
2111673e404SJohn Birrell 				last1->l_next = list2;
2121673e404SJohn Birrell 				last1 = list2;
2131673e404SJohn Birrell 			}
2141673e404SJohn Birrell 
2151673e404SJohn Birrell 			list2 = next2;
2161673e404SJohn Birrell 		} else {
2171673e404SJohn Birrell 
2181673e404SJohn Birrell 			last1 = list1;
2191673e404SJohn Birrell 			list1 = list1->l_next;
2201673e404SJohn Birrell 
2211673e404SJohn Birrell 			if (list1 == NULL) {
2221673e404SJohn Birrell 				/* Add the rest to the end of list1 */
2231673e404SJohn Birrell 				last1->l_next = list2;
2241673e404SJohn Birrell 				list2 = NULL;
2251673e404SJohn Birrell 			}
2261673e404SJohn Birrell 		}
2271673e404SJohn Birrell 	}
2281673e404SJohn Birrell }
229