blob: 9c1b297aeb605556f78b20e75261f96c3fe2b033 [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.
gdt76398032003-12-22 16:32:15 +000088 *
89 * XXX not sure this is right:
90 * It is currently undefined whether new nodes for which cmp returns 0
91 * should be added before or after any existing nodes.
gdt29760212003-12-22 15:56:00 +000092 */
paul718e3742002-12-13 20:15:29 +000093void
94listnode_add_sort (struct list *list, void *val)
95{
96 struct listnode *n;
97 struct listnode *new;
98
hassoe90fbab2003-12-21 09:51:42 +000099 new = listnode_new ();
100 new->data = val;
paul718e3742002-12-13 20:15:29 +0000101
102 if (list->cmp)
103 {
104 for (n = list->head; n; n = n->next)
105 {
gdt29760212003-12-22 15:56:00 +0000106 /* XXX should an "equal" node be inserted before or after? */
hassoe90fbab2003-12-21 09:51:42 +0000107 if ((*list->cmp) (val, n->data) <= 0)
paul718e3742002-12-13 20:15:29 +0000108 {
109 new->next = n;
110 new->prev = n->prev;
111
112 if (n->prev)
113 n->prev->next = new;
114 else
115 list->head = new;
116 n->prev = new;
117 list->count++;
118 return;
119 }
120 }
121 }
122
123 new->prev = list->tail;
124
125 if (list->tail)
126 list->tail->next = new;
127 else
128 list->head = new;
129
130 list->tail = new;
131 list->count++;
132}
133
134void
135listnode_add_after (struct list *list, struct listnode *pp, void *val)
136{
137 struct listnode *nn;
138
139 nn = listnode_new ();
140 nn->data = val;
141
142 if (pp == NULL)
143 {
144 if (list->head)
145 list->head->prev = nn;
146 else
147 list->tail = nn;
148
149 nn->next = list->head;
150 nn->prev = pp;
151
152 list->head = nn;
153 }
154 else
155 {
156 if (pp->next)
157 pp->next->prev = nn;
158 else
159 list->tail = nn;
160
161 nn->next = pp->next;
162 nn->prev = pp;
163
164 pp->next = nn;
165 }
166}
167
168
169/* Delete specific date pointer from the list. */
170void
171listnode_delete (struct list *list, void *val)
172{
173 struct listnode *node;
174
paulf2c80652002-12-13 21:44:27 +0000175 assert(list);
paul718e3742002-12-13 20:15:29 +0000176 for (node = list->head; node; node = node->next)
177 {
178 if (node->data == val)
179 {
180 if (node->prev)
181 node->prev->next = node->next;
182 else
183 list->head = node->next;
184
185 if (node->next)
186 node->next->prev = node->prev;
187 else
188 list->tail = node->prev;
189
190 list->count--;
191 listnode_free (node);
192 return;
193 }
194 }
195}
196
197/* Return first node's data if it is there. */
198void *
199listnode_head (struct list *list)
200{
201 struct listnode *node;
202
paulf2c80652002-12-13 21:44:27 +0000203 assert(list);
paul718e3742002-12-13 20:15:29 +0000204 node = list->head;
205
206 if (node)
207 return node->data;
208 return NULL;
209}
210
211/* Delete all listnode from the list. */
212void
213list_delete_all_node (struct list *list)
214{
215 struct listnode *node;
216 struct listnode *next;
217
paulf2c80652002-12-13 21:44:27 +0000218 assert(list);
paul718e3742002-12-13 20:15:29 +0000219 for (node = list->head; node; node = next)
220 {
221 next = node->next;
222 if (list->del)
223 (*list->del) (node->data);
224 listnode_free (node);
225 }
226 list->head = list->tail = NULL;
227 list->count = 0;
228}
229
230/* Delete all listnode then free list itself. */
231void
232list_delete (struct list *list)
233{
234 struct listnode *node;
235 struct listnode *next;
236
paulf2c80652002-12-13 21:44:27 +0000237 assert(list);
paul718e3742002-12-13 20:15:29 +0000238 for (node = list->head; node; node = next)
239 {
240 next = node->next;
241 if (list->del)
242 (*list->del) (node->data);
243 listnode_free (node);
244 }
245 list_free (list);
246}
247
248/* Lookup the node which has given data. */
249struct listnode *
250listnode_lookup (struct list *list, void *data)
251{
252 listnode node;
253
paulf2c80652002-12-13 21:44:27 +0000254 assert(list);
paul718e3742002-12-13 20:15:29 +0000255 for (node = list->head; node; nextnode (node))
256 if (data == getdata (node))
257 return node;
258 return NULL;
259}
260
261/* Delete the node from list. For ospfd and ospf6d. */
262void
263list_delete_node (list list, listnode node)
264{
265 if (node->prev)
266 node->prev->next = node->next;
267 else
268 list->head = node->next;
269 if (node->next)
270 node->next->prev = node->prev;
271 else
272 list->tail = node->prev;
273 list->count--;
274 listnode_free (node);
275}
276
277/* ospf_spf.c */
278void
279list_add_node_prev (list list, listnode current, void *val)
280{
281 struct listnode *node;
282
283 node = listnode_new ();
284 node->next = current;
285 node->data = val;
286
287 if (current->prev == NULL)
288 list->head = node;
289 else
290 current->prev->next = node;
291
292 node->prev = current->prev;
293 current->prev = node;
294
295 list->count++;
296}
297
298/* ospf_spf.c */
299void
300list_add_node_next (list list, listnode current, void *val)
301{
302 struct listnode *node;
303
304 node = listnode_new ();
305 node->prev = current;
306 node->data = val;
307
308 if (current->next == NULL)
309 list->tail = node;
310 else
311 current->next->prev = node;
312
313 node->next = current->next;
314 current->next = node;
315
316 list->count++;
317}
318
319/* ospf_spf.c */
320void
321list_add_list (struct list *l, struct list *m)
322{
323 struct listnode *n;
324
325 for (n = listhead (m); n; nextnode (n))
326 listnode_add (l, n->data);
327}