blob: d6eeab4171786ed85624bf682ca10c73aa32471a [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* Generic linked list routine.
2 * Copyright (C) 1997, 2000 Kunihiro Ishiguro
3 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Zebra; see the file COPYING. If not, write to the Free
18 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 * 02111-1307, USA.
20 */
21
22#include <zebra.h>
23
24#include "linklist.h"
25#include "memory.h"
26
27/* Allocate new list. */
28struct list *
29list_new ()
30{
31 struct list *new;
32
33 new = XMALLOC (MTYPE_LINK_LIST, sizeof (struct list));
34 memset (new, 0, sizeof (struct list));
35 return new;
36}
37
38/* Free list. */
39void
40list_free (struct list *l)
41{
42 XFREE (MTYPE_LINK_LIST, l);
43}
44
45/* Allocate new listnode. Internal use only. */
46static struct listnode *
47listnode_new ()
48{
49 struct listnode *node;
50
51 node = XMALLOC (MTYPE_LINK_NODE, sizeof (struct listnode));
52 memset (node, 0, sizeof (struct listnode));
53 return node;
54}
55
56/* Free listnode. */
57static void
58listnode_free (struct listnode *node)
59{
60 XFREE (MTYPE_LINK_NODE, node);
61}
62
63/* Add new data to the list. */
64void
65listnode_add (struct list *list, void *val)
66{
67 struct listnode *node;
68
69 node = listnode_new ();
70
71 node->prev = list->tail;
72 node->data = val;
73
74 if (list->head == NULL)
75 list->head = node;
76 else
77 list->tail->next = node;
78 list->tail = node;
79
80 list->count++;
81}
82
gdt29760212003-12-22 15:56:00 +000083/*
84 * Add a node to the list. If the list was sorted according to the
85 * cmp function, insert a new node with the given val such that the
86 * list remains sorted. The new node is always inserted; there is no
87 * notion of omitting duplicates.
88 */
paul718e3742002-12-13 20:15:29 +000089void
90listnode_add_sort (struct list *list, void *val)
91{
92 struct listnode *n;
93 struct listnode *new;
94
hassoe90fbab2003-12-21 09:51:42 +000095 new = listnode_new ();
96 new->data = val;
paul718e3742002-12-13 20:15:29 +000097
98 if (list->cmp)
99 {
100 for (n = list->head; n; n = n->next)
101 {
gdt29760212003-12-22 15:56:00 +0000102 /* XXX should an "equal" node be inserted before or after? */
hassoe90fbab2003-12-21 09:51:42 +0000103 if ((*list->cmp) (val, n->data) <= 0)
paul718e3742002-12-13 20:15:29 +0000104 {
105 new->next = n;
106 new->prev = n->prev;
107
108 if (n->prev)
109 n->prev->next = new;
110 else
111 list->head = new;
112 n->prev = new;
113 list->count++;
114 return;
115 }
116 }
117 }
118
119 new->prev = list->tail;
120
121 if (list->tail)
122 list->tail->next = new;
123 else
124 list->head = new;
125
126 list->tail = new;
127 list->count++;
128}
129
130void
131listnode_add_after (struct list *list, struct listnode *pp, void *val)
132{
133 struct listnode *nn;
134
135 nn = listnode_new ();
136 nn->data = val;
137
138 if (pp == NULL)
139 {
140 if (list->head)
141 list->head->prev = nn;
142 else
143 list->tail = nn;
144
145 nn->next = list->head;
146 nn->prev = pp;
147
148 list->head = nn;
149 }
150 else
151 {
152 if (pp->next)
153 pp->next->prev = nn;
154 else
155 list->tail = nn;
156
157 nn->next = pp->next;
158 nn->prev = pp;
159
160 pp->next = nn;
161 }
162}
163
164
165/* Delete specific date pointer from the list. */
166void
167listnode_delete (struct list *list, void *val)
168{
169 struct listnode *node;
170
paulf2c80652002-12-13 21:44:27 +0000171 assert(list);
paul718e3742002-12-13 20:15:29 +0000172 for (node = list->head; node; node = node->next)
173 {
174 if (node->data == val)
175 {
176 if (node->prev)
177 node->prev->next = node->next;
178 else
179 list->head = node->next;
180
181 if (node->next)
182 node->next->prev = node->prev;
183 else
184 list->tail = node->prev;
185
186 list->count--;
187 listnode_free (node);
188 return;
189 }
190 }
191}
192
193/* Return first node's data if it is there. */
194void *
195listnode_head (struct list *list)
196{
197 struct listnode *node;
198
paulf2c80652002-12-13 21:44:27 +0000199 assert(list);
paul718e3742002-12-13 20:15:29 +0000200 node = list->head;
201
202 if (node)
203 return node->data;
204 return NULL;
205}
206
207/* Delete all listnode from the list. */
208void
209list_delete_all_node (struct list *list)
210{
211 struct listnode *node;
212 struct listnode *next;
213
paulf2c80652002-12-13 21:44:27 +0000214 assert(list);
paul718e3742002-12-13 20:15:29 +0000215 for (node = list->head; node; node = next)
216 {
217 next = node->next;
218 if (list->del)
219 (*list->del) (node->data);
220 listnode_free (node);
221 }
222 list->head = list->tail = NULL;
223 list->count = 0;
224}
225
226/* Delete all listnode then free list itself. */
227void
228list_delete (struct list *list)
229{
230 struct listnode *node;
231 struct listnode *next;
232
paulf2c80652002-12-13 21:44:27 +0000233 assert(list);
paul718e3742002-12-13 20:15:29 +0000234 for (node = list->head; node; node = next)
235 {
236 next = node->next;
237 if (list->del)
238 (*list->del) (node->data);
239 listnode_free (node);
240 }
241 list_free (list);
242}
243
244/* Lookup the node which has given data. */
245struct listnode *
246listnode_lookup (struct list *list, void *data)
247{
248 listnode node;
249
paulf2c80652002-12-13 21:44:27 +0000250 assert(list);
paul718e3742002-12-13 20:15:29 +0000251 for (node = list->head; node; nextnode (node))
252 if (data == getdata (node))
253 return node;
254 return NULL;
255}
256
257/* Delete the node from list. For ospfd and ospf6d. */
258void
259list_delete_node (list list, listnode node)
260{
261 if (node->prev)
262 node->prev->next = node->next;
263 else
264 list->head = node->next;
265 if (node->next)
266 node->next->prev = node->prev;
267 else
268 list->tail = node->prev;
269 list->count--;
270 listnode_free (node);
271}
272
273/* ospf_spf.c */
274void
275list_add_node_prev (list list, listnode current, void *val)
276{
277 struct listnode *node;
278
279 node = listnode_new ();
280 node->next = current;
281 node->data = val;
282
283 if (current->prev == NULL)
284 list->head = node;
285 else
286 current->prev->next = node;
287
288 node->prev = current->prev;
289 current->prev = node;
290
291 list->count++;
292}
293
294/* ospf_spf.c */
295void
296list_add_node_next (list list, listnode current, void *val)
297{
298 struct listnode *node;
299
300 node = listnode_new ();
301 node->prev = current;
302 node->data = val;
303
304 if (current->next == NULL)
305 list->tail = node;
306 else
307 current->next->prev = node;
308
309 node->next = current->next;
310 current->next = node;
311
312 list->count++;
313}
314
315/* ospf_spf.c */
316void
317list_add_list (struct list *l, struct list *m)
318{
319 struct listnode *n;
320
321 for (n = listhead (m); n; nextnode (n))
322 listnode_add (l, n->data);
323}