blob: 049ab0bb497d4a43943eafa3f5b145be2f6df4b8 [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
paul718e3742002-12-13 20:15:29 +000090
91 if (list->cmp)
92 {
93 for (n = list->head; n; n = n->next)
94 {
paul729606f2003-09-23 23:47:14 +000095 if ((*list->cmp) (val, n->data) == 0)
96 return;
paul718e3742002-12-13 20:15:29 +000097 if ((*list->cmp) (val, n->data) < 0)
98 {
paul729606f2003-09-23 23:47:14 +000099 new = listnode_new ();
100 new->data = val;
paul718e3742002-12-13 20:15:29 +0000101 new->next = n;
102 new->prev = n->prev;
103
104 if (n->prev)
105 n->prev->next = new;
106 else
107 list->head = new;
108 n->prev = new;
109 list->count++;
110 return;
111 }
112 }
113 }
114
paul729606f2003-09-23 23:47:14 +0000115 new = listnode_new ();
116 new->data = val;
paul718e3742002-12-13 20:15:29 +0000117 new->prev = list->tail;
118
119 if (list->tail)
120 list->tail->next = new;
121 else
122 list->head = new;
123
124 list->tail = new;
125 list->count++;
126}
127
128void
129listnode_add_after (struct list *list, struct listnode *pp, void *val)
130{
131 struct listnode *nn;
132
133 nn = listnode_new ();
134 nn->data = val;
135
136 if (pp == NULL)
137 {
138 if (list->head)
139 list->head->prev = nn;
140 else
141 list->tail = nn;
142
143 nn->next = list->head;
144 nn->prev = pp;
145
146 list->head = nn;
147 }
148 else
149 {
150 if (pp->next)
151 pp->next->prev = nn;
152 else
153 list->tail = nn;
154
155 nn->next = pp->next;
156 nn->prev = pp;
157
158 pp->next = nn;
159 }
160}
161
162
163/* Delete specific date pointer from the list. */
164void
165listnode_delete (struct list *list, void *val)
166{
167 struct listnode *node;
168
paulf2c80652002-12-13 21:44:27 +0000169 assert(list);
paul718e3742002-12-13 20:15:29 +0000170 for (node = list->head; node; node = node->next)
171 {
172 if (node->data == val)
173 {
174 if (node->prev)
175 node->prev->next = node->next;
176 else
177 list->head = node->next;
178
179 if (node->next)
180 node->next->prev = node->prev;
181 else
182 list->tail = node->prev;
183
184 list->count--;
185 listnode_free (node);
186 return;
187 }
188 }
189}
190
191/* Return first node's data if it is there. */
192void *
193listnode_head (struct list *list)
194{
195 struct listnode *node;
196
paulf2c80652002-12-13 21:44:27 +0000197 assert(list);
paul718e3742002-12-13 20:15:29 +0000198 node = list->head;
199
200 if (node)
201 return node->data;
202 return NULL;
203}
204
205/* Delete all listnode from the list. */
206void
207list_delete_all_node (struct list *list)
208{
209 struct listnode *node;
210 struct listnode *next;
211
paulf2c80652002-12-13 21:44:27 +0000212 assert(list);
paul718e3742002-12-13 20:15:29 +0000213 for (node = list->head; node; node = next)
214 {
215 next = node->next;
216 if (list->del)
217 (*list->del) (node->data);
218 listnode_free (node);
219 }
220 list->head = list->tail = NULL;
221 list->count = 0;
222}
223
224/* Delete all listnode then free list itself. */
225void
226list_delete (struct list *list)
227{
228 struct listnode *node;
229 struct listnode *next;
230
paulf2c80652002-12-13 21:44:27 +0000231 assert(list);
paul718e3742002-12-13 20:15:29 +0000232 for (node = list->head; node; node = next)
233 {
234 next = node->next;
235 if (list->del)
236 (*list->del) (node->data);
237 listnode_free (node);
238 }
239 list_free (list);
240}
241
242/* Lookup the node which has given data. */
243struct listnode *
244listnode_lookup (struct list *list, void *data)
245{
246 listnode node;
247
paulf2c80652002-12-13 21:44:27 +0000248 assert(list);
paul718e3742002-12-13 20:15:29 +0000249 for (node = list->head; node; nextnode (node))
250 if (data == getdata (node))
251 return node;
252 return NULL;
253}
254
255/* Delete the node from list. For ospfd and ospf6d. */
256void
257list_delete_node (list list, listnode node)
258{
259 if (node->prev)
260 node->prev->next = node->next;
261 else
262 list->head = node->next;
263 if (node->next)
264 node->next->prev = node->prev;
265 else
266 list->tail = node->prev;
267 list->count--;
268 listnode_free (node);
269}
270
271/* ospf_spf.c */
272void
273list_add_node_prev (list list, listnode current, void *val)
274{
275 struct listnode *node;
276
277 node = listnode_new ();
278 node->next = current;
279 node->data = val;
280
281 if (current->prev == NULL)
282 list->head = node;
283 else
284 current->prev->next = node;
285
286 node->prev = current->prev;
287 current->prev = node;
288
289 list->count++;
290}
291
292/* ospf_spf.c */
293void
294list_add_node_next (list list, listnode current, void *val)
295{
296 struct listnode *node;
297
298 node = listnode_new ();
299 node->prev = current;
300 node->data = val;
301
302 if (current->next == NULL)
303 list->tail = node;
304 else
305 current->next->prev = node;
306
307 node->next = current->next;
308 current->next = node;
309
310 list->count++;
311}
312
313/* ospf_spf.c */
314void
315list_add_list (struct list *l, struct list *m)
316{
317 struct listnode *n;
318
319 for (n = listhead (m); n; nextnode (n))
320 listnode_add (l, n->data);
321}