blob: 3cb10caf1703ab7fa65676c6120df47c07a5e227 [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
83/* Add new node with sort function. */
84void
85listnode_add_sort (struct list *list, void *val)
86{
87 struct listnode *n;
88 struct listnode *new;
89
90 new = listnode_new ();
91 new->data = val;
92
93 if (list->cmp)
94 {
95 for (n = list->head; n; n = n->next)
96 {
97 if ((*list->cmp) (val, n->data) < 0)
98 {
99 new->next = n;
100 new->prev = n->prev;
101
102 if (n->prev)
103 n->prev->next = new;
104 else
105 list->head = new;
106 n->prev = new;
107 list->count++;
108 return;
109 }
110 }
111 }
112
113 new->prev = list->tail;
114
115 if (list->tail)
116 list->tail->next = new;
117 else
118 list->head = new;
119
120 list->tail = new;
121 list->count++;
122}
123
124void
125listnode_add_after (struct list *list, struct listnode *pp, void *val)
126{
127 struct listnode *nn;
128
129 nn = listnode_new ();
130 nn->data = val;
131
132 if (pp == NULL)
133 {
134 if (list->head)
135 list->head->prev = nn;
136 else
137 list->tail = nn;
138
139 nn->next = list->head;
140 nn->prev = pp;
141
142 list->head = nn;
143 }
144 else
145 {
146 if (pp->next)
147 pp->next->prev = nn;
148 else
149 list->tail = nn;
150
151 nn->next = pp->next;
152 nn->prev = pp;
153
154 pp->next = nn;
155 }
156}
157
158
159/* Delete specific date pointer from the list. */
160void
161listnode_delete (struct list *list, void *val)
162{
163 struct listnode *node;
164
paulf2c80652002-12-13 21:44:27 +0000165 assert(list);
paul718e3742002-12-13 20:15:29 +0000166 for (node = list->head; node; node = node->next)
167 {
168 if (node->data == val)
169 {
170 if (node->prev)
171 node->prev->next = node->next;
172 else
173 list->head = node->next;
174
175 if (node->next)
176 node->next->prev = node->prev;
177 else
178 list->tail = node->prev;
179
180 list->count--;
181 listnode_free (node);
182 return;
183 }
184 }
185}
186
187/* Return first node's data if it is there. */
188void *
189listnode_head (struct list *list)
190{
191 struct listnode *node;
192
paulf2c80652002-12-13 21:44:27 +0000193 assert(list);
paul718e3742002-12-13 20:15:29 +0000194 node = list->head;
195
196 if (node)
197 return node->data;
198 return NULL;
199}
200
201/* Delete all listnode from the list. */
202void
203list_delete_all_node (struct list *list)
204{
205 struct listnode *node;
206 struct listnode *next;
207
paulf2c80652002-12-13 21:44:27 +0000208 assert(list);
paul718e3742002-12-13 20:15:29 +0000209 for (node = list->head; node; node = next)
210 {
211 next = node->next;
212 if (list->del)
213 (*list->del) (node->data);
214 listnode_free (node);
215 }
216 list->head = list->tail = NULL;
217 list->count = 0;
218}
219
220/* Delete all listnode then free list itself. */
221void
222list_delete (struct list *list)
223{
224 struct listnode *node;
225 struct listnode *next;
226
paulf2c80652002-12-13 21:44:27 +0000227 assert(list);
paul718e3742002-12-13 20:15:29 +0000228 for (node = list->head; node; node = next)
229 {
230 next = node->next;
231 if (list->del)
232 (*list->del) (node->data);
233 listnode_free (node);
234 }
235 list_free (list);
236}
237
238/* Lookup the node which has given data. */
239struct listnode *
240listnode_lookup (struct list *list, void *data)
241{
242 listnode node;
243
paulf2c80652002-12-13 21:44:27 +0000244 assert(list);
paul718e3742002-12-13 20:15:29 +0000245 for (node = list->head; node; nextnode (node))
246 if (data == getdata (node))
247 return node;
248 return NULL;
249}
250
251/* Delete the node from list. For ospfd and ospf6d. */
252void
253list_delete_node (list list, listnode node)
254{
255 if (node->prev)
256 node->prev->next = node->next;
257 else
258 list->head = node->next;
259 if (node->next)
260 node->next->prev = node->prev;
261 else
262 list->tail = node->prev;
263 list->count--;
264 listnode_free (node);
265}
266
267/* ospf_spf.c */
268void
269list_add_node_prev (list list, listnode current, void *val)
270{
271 struct listnode *node;
272
273 node = listnode_new ();
274 node->next = current;
275 node->data = val;
276
277 if (current->prev == NULL)
278 list->head = node;
279 else
280 current->prev->next = node;
281
282 node->prev = current->prev;
283 current->prev = node;
284
285 list->count++;
286}
287
288/* ospf_spf.c */
289void
290list_add_node_next (list list, listnode current, void *val)
291{
292 struct listnode *node;
293
294 node = listnode_new ();
295 node->prev = current;
296 node->data = val;
297
298 if (current->next == NULL)
299 list->tail = node;
300 else
301 current->next->prev = node;
302
303 node->next = current->next;
304 current->next = node;
305
306 list->count++;
307}
308
309/* ospf_spf.c */
310void
311list_add_list (struct list *l, struct list *m)
312{
313 struct listnode *n;
314
315 for (n = listhead (m); n; nextnode (n))
316 listnode_add (l, n->data);
317}