1178481Sjb/*
2178481Sjb * CDDL HEADER START
3178481Sjb *
4178481Sjb * The contents of this file are subject to the terms of the
5178481Sjb * Common Development and Distribution License, Version 1.0 only
6178481Sjb * (the "License").  You may not use this file except in compliance
7178481Sjb * with the License.
8178481Sjb *
9178481Sjb * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10178481Sjb * or http://www.opensolaris.org/os/licensing.
11178481Sjb * See the License for the specific language governing permissions
12178481Sjb * and limitations under the License.
13178481Sjb *
14178481Sjb * When distributing Covered Code, include this CDDL HEADER in each
15178481Sjb * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16178481Sjb * If applicable, add the following below this CDDL HEADER, with the
17178481Sjb * fields enclosed by brackets "[]" replaced with your own identifying
18178481Sjb * information: Portions Copyright [yyyy] [name of copyright owner]
19178481Sjb *
20178481Sjb * CDDL HEADER END
21178481Sjb */
22178481Sjb/*
23178481Sjb * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24178481Sjb * Use is subject to license terms.
25178481Sjb */
26178481Sjb
27178481Sjb#pragma ident	"%Z%%M%	%I%	%E% SMI"
28178481Sjb
29178481Sjb/*
30178481Sjb * Routines for manipulating linked lists
31178481Sjb */
32178481Sjb
33178481Sjb#include <stdio.h>
34178481Sjb#include <assert.h>
35178481Sjb#include <stdlib.h>
36178481Sjb
37178481Sjb#include "list.h"
38178481Sjb#include "memory.h"
39178481Sjb
40178481Sjbstruct list {
41178481Sjb	void *l_data;
42178481Sjb	struct list *l_next;
43178481Sjb};
44178481Sjb
45178481Sjb/* Add an element to a list */
46178481Sjbvoid
47178481Sjblist_add(list_t **list, void *data)
48178481Sjb{
49178481Sjb	list_t *le;
50178481Sjb
51178481Sjb	le = xmalloc(sizeof (list_t));
52178481Sjb	le->l_data = data;
53178481Sjb	le->l_next = *list;
54178481Sjb	*list = le;
55178481Sjb}
56178481Sjb
57178481Sjb/* Add an element to a sorted list */
58178481Sjbvoid
59178481Sjbslist_add(list_t **list, void *data, int (*cmp)(void *, void *))
60178481Sjb{
61178481Sjb	list_t **nextp;
62178481Sjb
63178481Sjb	for (nextp = list; *nextp; nextp = &((*nextp)->l_next)) {
64178481Sjb		if (cmp((*nextp)->l_data, data) > 0)
65178481Sjb			break;
66178481Sjb	}
67178481Sjb
68178481Sjb	list_add(nextp, data);
69178481Sjb}
70178481Sjb
71178481Sjb/*ARGSUSED2*/
72178481Sjbstatic int
73178546Sjblist_defcmp(void *d1, void *d2, void *private __unused)
74178481Sjb{
75178481Sjb	return (d1 != d2);
76178481Sjb}
77178481Sjb
78178481Sjbvoid *
79178481Sjblist_remove(list_t **list, void *data, int (*cmp)(void *, void *, void *),
80178481Sjb    void *private)
81178481Sjb{
82178481Sjb	list_t *le, **le2;
83178481Sjb	void *led;
84178481Sjb
85178481Sjb	if (!cmp)
86178481Sjb		cmp = list_defcmp;
87178481Sjb
88178481Sjb	for (le = *list, le2 = list; le; le2 = &le->l_next, le = le->l_next) {
89178481Sjb		if (cmp(le->l_data, data, private) == 0) {
90178481Sjb			*le2 = le->l_next;
91178481Sjb			led = le->l_data;
92178481Sjb			free(le);
93178481Sjb			return (led);
94178481Sjb		}
95178481Sjb	}
96178481Sjb
97178481Sjb	return (NULL);
98178481Sjb}
99178481Sjb
100178481Sjbvoid
101178481Sjblist_free(list_t *list, void (*datafree)(void *, void *), void *private)
102178481Sjb{
103178481Sjb	list_t *le;
104178481Sjb
105178481Sjb	while (list) {
106178481Sjb		le = list;
107178481Sjb		list = list->l_next;
108178481Sjb		if (le->l_data && datafree)
109178481Sjb			datafree(le->l_data, private);
110178481Sjb		free(le);
111178481Sjb	}
112178481Sjb}
113178481Sjb
114178481Sjb/*
115178481Sjb * This iterator is specifically designed to tolerate the deletion of the
116178481Sjb * node being iterated over.
117178481Sjb */
118178481Sjbint
119178481Sjblist_iter(list_t *list, int (*func)(void *, void *), void *private)
120178481Sjb{
121178481Sjb	list_t *lnext;
122178481Sjb	int cumrc = 0;
123178481Sjb	int cbrc;
124178481Sjb
125178481Sjb	while (list) {
126178481Sjb		lnext = list->l_next;
127178481Sjb		if ((cbrc = func(list->l_data, private)) < 0)
128178481Sjb			return (cbrc);
129178481Sjb		cumrc += cbrc;
130178481Sjb		list = lnext;
131178481Sjb	}
132178481Sjb
133178481Sjb	return (cumrc);
134178481Sjb}
135178481Sjb
136178481Sjb/*ARGSUSED*/
137178481Sjbstatic int
138178546Sjblist_count_cb(void *data __unused, void *private __unused)
139178481Sjb{
140178481Sjb	return (1);
141178481Sjb}
142178481Sjb
143178481Sjbint
144178481Sjblist_count(list_t *list)
145178481Sjb{
146178481Sjb	return (list_iter(list, list_count_cb, NULL));
147178481Sjb}
148178481Sjb
149178481Sjbint
150178481Sjblist_empty(list_t *list)
151178481Sjb{
152178481Sjb	return (list == NULL);
153178481Sjb}
154178481Sjb
155178481Sjbvoid *
156178481Sjblist_find(list_t *list, void *tmpl, int (*cmp)(void *, void *))
157178481Sjb{
158178481Sjb	for (; list; list = list->l_next) {
159178481Sjb		if (cmp(list->l_data, tmpl) == 0)
160178481Sjb			return (list->l_data);
161178481Sjb	}
162178481Sjb
163178481Sjb	return (NULL);
164178481Sjb}
165178481Sjb
166178481Sjbvoid *
167178481Sjblist_first(list_t *list)
168178481Sjb{
169178481Sjb	return (list ? list->l_data : NULL);
170178481Sjb}
171178481Sjb
172178481Sjbvoid
173178481Sjblist_concat(list_t **list1, list_t *list2)
174178481Sjb{
175178481Sjb	list_t *l, *last;
176178481Sjb
177178481Sjb	for (l = *list1, last = NULL; l; last = l, l = l->l_next)
178178481Sjb		continue;
179178481Sjb
180178481Sjb	if (last == NULL)
181178481Sjb		*list1 = list2;
182178481Sjb	else
183178481Sjb		last->l_next = list2;
184178481Sjb}
185178481Sjb
186178481Sjb/*
187178481Sjb * Merges two sorted lists.  Equal nodes (as determined by cmp) are retained.
188178481Sjb */
189178481Sjbvoid
190178481Sjbslist_merge(list_t **list1p, list_t *list2, int (*cmp)(void *, void *))
191178481Sjb{
192178481Sjb	list_t *list1, *next2;
193178481Sjb	list_t *last1 = NULL;
194178481Sjb
195178481Sjb	if (*list1p == NULL) {
196178481Sjb		*list1p = list2;
197178481Sjb		return;
198178481Sjb	}
199178481Sjb
200178481Sjb	list1 = *list1p;
201178481Sjb	while (list2 != NULL) {
202178481Sjb		if (cmp(list1->l_data, list2->l_data) > 0) {
203178481Sjb			next2 = list2->l_next;
204178481Sjb
205178481Sjb			if (last1 == NULL) {
206178481Sjb				/* Insert at beginning */
207178481Sjb				*list1p = last1 = list2;
208178481Sjb				list2->l_next = list1;
209178481Sjb			} else {
210178481Sjb				list2->l_next = list1;
211178481Sjb				last1->l_next = list2;
212178481Sjb				last1 = list2;
213178481Sjb			}
214178481Sjb
215178481Sjb			list2 = next2;
216178481Sjb		} else {
217178481Sjb
218178481Sjb			last1 = list1;
219178481Sjb			list1 = list1->l_next;
220178481Sjb
221178481Sjb			if (list1 == NULL) {
222178481Sjb				/* Add the rest to the end of list1 */
223178481Sjb				last1->l_next = list2;
224178481Sjb				list2 = NULL;
225178481Sjb			}
226178481Sjb		}
227178481Sjb	}
228178481Sjb}
229