]>
git.ipfire.org Git - thirdparty/bird.git/blob - lib/lists.c
2 * BIRD Library -- Linked Lists
4 * (c) 1998 Martin Mares <mj@ucw.cz>
6 * Can be freely distributed and used under the terms of the GNU GPL.
12 * The BIRD library provides a set of functions for operating on linked
13 * lists. The lists are internally represented as standard doubly linked
14 * lists with synthetic head and tail which makes all the basic operations
15 * run in constant time and contain no extra end-of-list checks. Each list
16 * is described by a &list structure, nodes can have any format as long
17 * as they start with a &node structure. If you want your nodes to belong
18 * to multiple lists at once, you can embed multiple &node structures in them
19 * and use the SKIP_BACK() macro to calculate a pointer to the start of the
20 * structure from a &node pointer, but beware of obscurity.
22 * There also exist safe linked lists (&slist, &snode and all functions
23 * being prefixed with |s_|) which support asynchronous walking very
24 * similar to that used in the &fib structure.
27 #define _BIRD_LISTS_C_
29 #include "nest/bird.h"
30 #include "lib/lists.h"
33 check_list(list
*l
, node
*n
)
40 do { n
= n
->prev
; } while (n
->prev
);
42 l
= SKIP_BACK(list
, head_node
, n
);
47 ASSERT_DIE(l
->null
== NULL
);
48 ASSERT_DIE(l
->head
!= NULL
);
49 ASSERT_DIE(l
->tail
!= NULL
);
51 node
*prev
= &l
->head_node
, *cur
= l
->head
, *next
= l
->head
->next
;
56 ASSERT_DIE(cur
->prev
== prev
);
62 ASSERT_DIE(cur
== &(l
->tail_node
));
63 ASSERT_DIE(!n
|| (seen
== 1));
69 * add_tail - append a node to a list
73 * add_tail() takes a node @n and appends it at the end of the list @l.
76 add_tail(list
*l
, node
*n
)
78 EXPENSIVE_CHECK(check_list(l
, NULL
));
79 ASSUME(n
->prev
== NULL
);
80 ASSUME(n
->next
== NULL
);
84 n
->next
= &l
->tail_node
;
91 * add_head - prepend a node to a list
95 * add_head() takes a node @n and prepends it at the start of the list @l.
98 add_head(list
*l
, node
*n
)
100 EXPENSIVE_CHECK(check_list(l
, NULL
));
101 ASSUME(n
->prev
== NULL
);
102 ASSUME(n
->next
== NULL
);
107 n
->prev
= &l
->head_node
;
113 * insert_node - insert a node to a list
114 * @n: a new list node
115 * @after: a node of a list
117 * Inserts a node @n to a linked list after an already inserted
121 insert_node(node
*n
, node
*after
)
123 EXPENSIVE_CHECK(check_list(l
, after
));
124 ASSUME(n
->prev
== NULL
);
125 ASSUME(n
->next
== NULL
);
127 node
*z
= after
->next
;
136 * rem_node - remove a node from a list
137 * @n: node to be removed
139 * Removes a node @n from the list it's linked in. Afterwards, node @n is cleared.
144 EXPENSIVE_CHECK(check_list(NULL
, n
));
156 * update_node - update node after calling realloc on it
157 * @n: node to be updated
159 * Fixes neighbor pointers.
164 ASSUME(n
->next
->prev
== n
->prev
->next
);
169 EXPENSIVE_CHECK(check_list(NULL
, n
));
173 * init_list - create an empty list
176 * init_list() takes a &list structure and initializes its
177 * fields, so that it represents an empty list.
182 l
->head
= &l
->tail_node
;
184 l
->tail
= &l
->head_node
;
188 * add_tail_list - concatenate two lists
189 * @to: destination list
192 * This function appends all elements of the list @l to
193 * the list @to in constant time.
196 add_tail_list(list
*to
, list
*l
)
198 EXPENSIVE_CHECK(check_list(to
, NULL
));
199 EXPENSIVE_CHECK(check_list(l
, NULL
));
207 q
->next
= &to
->tail_node
;
210 EXPENSIVE_CHECK(check_list(to
, NULL
));
219 EXPENSIVE_CHECK(check_list(l
, NULL
));