blob: 8b6a8528262dcad1367ef9e349212c5dcd44cbae [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"
David Lamparter6b0655a2014-06-04 06:53:35 +020026
paul718e3742002-12-13 20:15:29 +000027/* Allocate new list. */
28struct list *
paul8cc41982005-05-06 21:25:49 +000029list_new (void)
paul718e3742002-12-13 20:15:29 +000030{
Stephen Hemminger393deb92008-08-18 14:13:29 -070031 return XCALLOC (MTYPE_LINK_LIST, sizeof (struct list));
paul718e3742002-12-13 20:15:29 +000032}
33
34/* Free list. */
35void
36list_free (struct list *l)
37{
38 XFREE (MTYPE_LINK_LIST, l);
39}
40
41/* Allocate new listnode. Internal use only. */
42static struct listnode *
paul8cc41982005-05-06 21:25:49 +000043listnode_new (void)
paul718e3742002-12-13 20:15:29 +000044{
Stephen Hemminger393deb92008-08-18 14:13:29 -070045 return XCALLOC (MTYPE_LINK_NODE, sizeof (struct listnode));
paul718e3742002-12-13 20:15:29 +000046}
47
48/* Free listnode. */
49static void
50listnode_free (struct listnode *node)
51{
52 XFREE (MTYPE_LINK_NODE, node);
53}
David Lamparter6b0655a2014-06-04 06:53:35 +020054
paul718e3742002-12-13 20:15:29 +000055/* Add new data to the list. */
56void
57listnode_add (struct list *list, void *val)
58{
59 struct listnode *node;
Paul Jakma5f568082008-02-28 00:09:04 +000060
61 assert (val != NULL);
62
paul718e3742002-12-13 20:15:29 +000063 node = listnode_new ();
64
65 node->prev = list->tail;
66 node->data = val;
67
68 if (list->head == NULL)
69 list->head = node;
70 else
71 list->tail->next = node;
72 list->tail = node;
73
74 list->count++;
75}
76
gdt29760212003-12-22 15:56:00 +000077/*
78 * Add a node to the list. If the list was sorted according to the
79 * cmp function, insert a new node with the given val such that the
80 * list remains sorted. The new node is always inserted; there is no
81 * notion of omitting duplicates.
82 */
paul718e3742002-12-13 20:15:29 +000083void
84listnode_add_sort (struct list *list, void *val)
85{
86 struct listnode *n;
87 struct listnode *new;
Paul Jakma5f568082008-02-28 00:09:04 +000088
89 assert (val != NULL);
90
hassoe90fbab2003-12-21 09:51:42 +000091 new = listnode_new ();
92 new->data = val;
paul718e3742002-12-13 20:15:29 +000093
94 if (list->cmp)
95 {
96 for (n = list->head; n; n = n->next)
97 {
hasso47ce02a2003-12-22 16:49:15 +000098 if ((*list->cmp) (val, n->data) < 0)
paul718e3742002-12-13 20:15:29 +000099 {
100 new->next = n;
101 new->prev = n->prev;
102
103 if (n->prev)
104 n->prev->next = new;
105 else
106 list->head = new;
107 n->prev = new;
108 list->count++;
109 return;
110 }
111 }
112 }
113
114 new->prev = list->tail;
115
116 if (list->tail)
117 list->tail->next = new;
118 else
119 list->head = new;
120
121 list->tail = new;
122 list->count++;
123}
124
125void
126listnode_add_after (struct list *list, struct listnode *pp, void *val)
127{
128 struct listnode *nn;
Paul Jakma5f568082008-02-28 00:09:04 +0000129
130 assert (val != NULL);
131
paul718e3742002-12-13 20:15:29 +0000132 nn = listnode_new ();
133 nn->data = val;
134
135 if (pp == NULL)
136 {
137 if (list->head)
138 list->head->prev = nn;
139 else
140 list->tail = nn;
141
142 nn->next = list->head;
143 nn->prev = pp;
144
145 list->head = nn;
146 }
147 else
148 {
149 if (pp->next)
150 pp->next->prev = nn;
151 else
152 list->tail = nn;
153
154 nn->next = pp->next;
155 nn->prev = pp;
156
157 pp->next = nn;
158 }
Denis Ovsienko6ce80bd2007-11-12 14:55:01 +0000159 list->count++;
paul718e3742002-12-13 20:15:29 +0000160}
161
David Lamparter449b29e2016-06-13 17:29:12 +0200162struct listnode *
163listnode_add_before (struct list *list, struct listnode *pp, void *val)
164{
165 struct listnode *nn;
166
167 assert (val != NULL);
168
169 nn = listnode_new ();
170 nn->data = val;
171
172 if (pp == NULL)
173 {
174 if (list->tail)
175 list->tail->next = nn;
176 else
177 list->head = nn;
178
179 nn->prev = list->tail;
180 nn->next = pp;
181
182 list->tail = nn;
183 }
184 else
185 {
186 if (pp->prev)
187 pp->prev->next = nn;
188 else
189 list->head = nn;
190
191 nn->prev = pp->prev;
192 nn->next = pp;
193
194 pp->prev = nn;
195 }
196 list->count++;
197 return nn;
198}
199
Paul Jakma6d831132014-10-09 16:05:15 +0100200/* Move given listnode to tail of the list */
201void
202listnode_move_to_tail (struct list *l, struct listnode *n)
203{
204 LISTNODE_DETACH(l,n);
205 LISTNODE_ATTACH(l,n);
206}
paul718e3742002-12-13 20:15:29 +0000207
208/* Delete specific date pointer from the list. */
209void
210listnode_delete (struct list *list, void *val)
211{
212 struct listnode *node;
213
paulf2c80652002-12-13 21:44:27 +0000214 assert(list);
paul718e3742002-12-13 20:15:29 +0000215 for (node = list->head; node; node = node->next)
216 {
217 if (node->data == val)
218 {
219 if (node->prev)
220 node->prev->next = node->next;
221 else
222 list->head = node->next;
223
224 if (node->next)
225 node->next->prev = node->prev;
226 else
227 list->tail = node->prev;
228
229 list->count--;
230 listnode_free (node);
231 return;
232 }
233 }
234}
235
236/* Return first node's data if it is there. */
237void *
238listnode_head (struct list *list)
239{
240 struct listnode *node;
241
paulf2c80652002-12-13 21:44:27 +0000242 assert(list);
paul718e3742002-12-13 20:15:29 +0000243 node = list->head;
244
245 if (node)
246 return node->data;
247 return NULL;
248}
249
250/* Delete all listnode from the list. */
251void
252list_delete_all_node (struct list *list)
253{
254 struct listnode *node;
255 struct listnode *next;
256
paulf2c80652002-12-13 21:44:27 +0000257 assert(list);
paul718e3742002-12-13 20:15:29 +0000258 for (node = list->head; node; node = next)
259 {
260 next = node->next;
261 if (list->del)
262 (*list->del) (node->data);
263 listnode_free (node);
264 }
265 list->head = list->tail = NULL;
266 list->count = 0;
267}
268
269/* Delete all listnode then free list itself. */
270void
271list_delete (struct list *list)
272{
paulf2c80652002-12-13 21:44:27 +0000273 assert(list);
Paul Jakmac024fd02006-06-15 12:43:09 +0000274 list_delete_all_node (list);
paul718e3742002-12-13 20:15:29 +0000275 list_free (list);
276}
277
278/* Lookup the node which has given data. */
279struct listnode *
280listnode_lookup (struct list *list, void *data)
281{
hasso52dc7ee2004-09-23 19:18:23 +0000282 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000283
paulf2c80652002-12-13 21:44:27 +0000284 assert(list);
paul1eb8ef22005-04-07 07:30:20 +0000285 for (node = listhead(list); node; node = listnextnode (node))
286 if (data == listgetdata (node))
paul718e3742002-12-13 20:15:29 +0000287 return node;
288 return NULL;
289}
David Lamparter6b0655a2014-06-04 06:53:35 +0200290
paul718e3742002-12-13 20:15:29 +0000291/* Delete the node from list. For ospfd and ospf6d. */
292void
hasso52dc7ee2004-09-23 19:18:23 +0000293list_delete_node (struct list *list, struct listnode *node)
paul718e3742002-12-13 20:15:29 +0000294{
295 if (node->prev)
296 node->prev->next = node->next;
297 else
298 list->head = node->next;
299 if (node->next)
300 node->next->prev = node->prev;
301 else
302 list->tail = node->prev;
303 list->count--;
304 listnode_free (node);
305}
David Lamparter6b0655a2014-06-04 06:53:35 +0200306
paul718e3742002-12-13 20:15:29 +0000307/* ospf_spf.c */
308void
hasso52dc7ee2004-09-23 19:18:23 +0000309list_add_node_prev (struct list *list, struct listnode *current, void *val)
paul718e3742002-12-13 20:15:29 +0000310{
311 struct listnode *node;
Paul Jakma5f568082008-02-28 00:09:04 +0000312
313 assert (val != NULL);
314
paul718e3742002-12-13 20:15:29 +0000315 node = listnode_new ();
316 node->next = current;
317 node->data = val;
318
319 if (current->prev == NULL)
320 list->head = node;
321 else
322 current->prev->next = node;
323
324 node->prev = current->prev;
325 current->prev = node;
326
327 list->count++;
328}
329
330/* ospf_spf.c */
331void
hasso52dc7ee2004-09-23 19:18:23 +0000332list_add_node_next (struct list *list, struct listnode *current, void *val)
paul718e3742002-12-13 20:15:29 +0000333{
334 struct listnode *node;
Paul Jakma5f568082008-02-28 00:09:04 +0000335
336 assert (val != NULL);
337
paul718e3742002-12-13 20:15:29 +0000338 node = listnode_new ();
339 node->prev = current;
340 node->data = val;
341
342 if (current->next == NULL)
343 list->tail = node;
344 else
345 current->next->prev = node;
346
347 node->next = current->next;
348 current->next = node;
349
350 list->count++;
351}
352
353/* ospf_spf.c */
354void
355list_add_list (struct list *l, struct list *m)
356{
357 struct listnode *n;
358
paul1eb8ef22005-04-07 07:30:20 +0000359 for (n = listhead (m); n; n = listnextnode (n))
paul718e3742002-12-13 20:15:29 +0000360 listnode_add (l, n->data);
361}