21
21
#include <stdbool.h>
22
22
#include <stddef.h>
25
/* Doubly linked list head or element. */
27
struct list *prev; /* Previous list element. */
28
struct list *next; /* Next list element. */
31
#define LIST_INITIALIZER(LIST) { LIST, LIST }
33
void list_init(struct list *);
34
void list_poison(struct list *);
24
#include "openvswitch/list.h"
26
static inline void list_init(struct ovs_list *);
27
static inline void list_poison(struct ovs_list *);
36
29
/* List insertion. */
37
void list_insert(struct list *, struct list *);
38
void list_splice(struct list *before, struct list *first, struct list *last);
39
void list_push_front(struct list *, struct list *);
40
void list_push_back(struct list *, struct list *);
41
void list_replace(struct list *, const struct list *);
42
void list_moved(struct list *, const struct list *orig);
43
void list_move(struct list *dst, struct list *src);
30
static inline void list_insert(struct ovs_list *, struct ovs_list *);
31
static inline void list_splice(struct ovs_list *before, struct ovs_list *first,
32
struct ovs_list *last);
33
static inline void list_push_front(struct ovs_list *, struct ovs_list *);
34
static inline void list_push_back(struct ovs_list *, struct ovs_list *);
35
static inline void list_replace(struct ovs_list *, const struct ovs_list *);
36
static inline void list_moved(struct ovs_list *, const struct ovs_list *orig);
37
static inline void list_move(struct ovs_list *dst, struct ovs_list *src);
45
39
/* List removal. */
46
struct list *list_remove(struct list *);
47
struct list *list_pop_front(struct list *);
48
struct list *list_pop_back(struct list *);
40
static inline struct ovs_list *list_remove(struct ovs_list *);
41
static inline struct ovs_list *list_pop_front(struct ovs_list *);
42
static inline struct ovs_list *list_pop_back(struct ovs_list *);
50
44
/* List elements. */
51
struct list *list_front(const struct list *);
52
struct list *list_back(const struct list *);
45
static inline struct ovs_list *list_front(const struct ovs_list *);
46
static inline struct ovs_list *list_back(const struct ovs_list *);
54
48
/* List properties. */
55
size_t list_size(const struct list *);
56
bool list_is_empty(const struct list *);
57
bool list_is_singleton(const struct list *);
58
bool list_is_short(const struct list *);
49
static inline size_t list_size(const struct ovs_list *);
50
static inline bool list_is_empty(const struct ovs_list *);
51
static inline bool list_is_singleton(const struct ovs_list *);
52
static inline bool list_is_short(const struct ovs_list *);
60
54
#define LIST_FOR_EACH(ITER, MEMBER, LIST) \
61
for (ASSIGN_CONTAINER(ITER, (LIST)->next, MEMBER); \
55
for (INIT_CONTAINER(ITER, (LIST)->next, MEMBER); \
62
56
&(ITER)->MEMBER != (LIST); \
63
57
ASSIGN_CONTAINER(ITER, (ITER)->MEMBER.next, MEMBER))
64
58
#define LIST_FOR_EACH_CONTINUE(ITER, MEMBER, LIST) \
65
for (ASSIGN_CONTAINER(ITER, (ITER)->MEMBER.next, MEMBER); \
59
for (INIT_CONTAINER(ITER, (ITER)->MEMBER.next, MEMBER); \
66
60
&(ITER)->MEMBER != (LIST); \
67
61
ASSIGN_CONTAINER(ITER, (ITER)->MEMBER.next, MEMBER))
68
62
#define LIST_FOR_EACH_REVERSE(ITER, MEMBER, LIST) \
69
for (ASSIGN_CONTAINER(ITER, (LIST)->prev, MEMBER); \
63
for (INIT_CONTAINER(ITER, (LIST)->prev, MEMBER); \
70
64
&(ITER)->MEMBER != (LIST); \
71
65
ASSIGN_CONTAINER(ITER, (ITER)->MEMBER.prev, MEMBER))
72
66
#define LIST_FOR_EACH_REVERSE_CONTINUE(ITER, MEMBER, LIST) \
74
68
&(ITER)->MEMBER != (LIST); \
75
69
ASSIGN_CONTAINER(ITER, (ITER)->MEMBER.prev, MEMBER))
76
70
#define LIST_FOR_EACH_SAFE(ITER, NEXT, MEMBER, LIST) \
77
for (ASSIGN_CONTAINER(ITER, (LIST)->next, MEMBER); \
71
for (INIT_CONTAINER(ITER, (LIST)->next, MEMBER); \
78
72
(&(ITER)->MEMBER != (LIST) \
79
? ASSIGN_CONTAINER(NEXT, (ITER)->MEMBER.next, MEMBER), 1 \
73
? INIT_CONTAINER(NEXT, (ITER)->MEMBER.next, MEMBER), 1 \
76
#define LIST_FOR_EACH_POP(ITER, MEMBER, LIST) \
77
while (!list_is_empty(LIST) \
78
&& (INIT_CONTAINER(ITER, list_pop_front(LIST), MEMBER), 1))
80
/* Inline implementations. */
82
/* Initializes 'list' as an empty list. */
84
list_init(struct ovs_list *list)
86
list->next = list->prev = list;
89
/* Initializes 'list' with pointers that will (probably) cause segfaults if
90
* dereferenced and, better yet, show up clearly in a debugger. */
92
list_poison(struct ovs_list *list)
94
memset(list, 0xcc, sizeof *list);
97
/* Inserts 'elem' just before 'before'. */
99
list_insert(struct ovs_list *before, struct ovs_list *elem)
101
elem->prev = before->prev;
103
before->prev->next = elem;
107
/* Removes elements 'first' though 'last' (exclusive) from their current list,
108
then inserts them just before 'before'. */
110
list_splice(struct ovs_list *before, struct ovs_list *first, struct ovs_list *last)
117
/* Cleanly remove 'first'...'last' from its current list. */
118
first->prev->next = last->next;
119
last->next->prev = first->prev;
121
/* Splice 'first'...'last' into new list. */
122
first->prev = before->prev;
124
before->prev->next = first;
128
/* Inserts 'elem' at the beginning of 'list', so that it becomes the front in
131
list_push_front(struct ovs_list *list, struct ovs_list *elem)
133
list_insert(list->next, elem);
136
/* Inserts 'elem' at the end of 'list', so that it becomes the back in
139
list_push_back(struct ovs_list *list, struct ovs_list *elem)
141
list_insert(list, elem);
144
/* Puts 'elem' in the position currently occupied by 'position'.
145
* Afterward, 'position' is not part of a list. */
147
list_replace(struct ovs_list *element, const struct ovs_list *position)
149
element->next = position->next;
150
element->next->prev = element;
151
element->prev = position->prev;
152
element->prev->next = element;
155
/* Adjusts pointers around 'list' to compensate for 'list' having been moved
156
* around in memory (e.g. as a consequence of realloc()), with original
159
* ('orig' likely points to freed memory, but this function does not
160
* dereference 'orig', it only compares it to 'list'. In a very pedantic
161
* language lawyer sense, this still yields undefined behavior, but it works
162
* with actual compilers.) */
164
list_moved(struct ovs_list *list, const struct ovs_list *orig)
166
if (list->next == orig) {
169
list->prev->next = list->next->prev = list;
173
/* Initializes 'dst' with the contents of 'src', compensating for moving it
174
* around in memory. The effect is that, if 'src' was the head of a list, now
175
* 'dst' is the head of a list containing the same elements. */
177
list_move(struct ovs_list *dst, struct ovs_list *src)
180
list_moved(dst, src);
183
/* Removes 'elem' from its list and returns the element that followed it.
184
Undefined behavior if 'elem' is not in a list. */
185
static inline struct ovs_list *
186
list_remove(struct ovs_list *elem)
188
elem->prev->next = elem->next;
189
elem->next->prev = elem->prev;
193
/* Removes the front element from 'list' and returns it. Undefined behavior if
194
'list' is empty before removal. */
195
static inline struct ovs_list *
196
list_pop_front(struct ovs_list *list)
198
struct ovs_list *front = list->next;
204
/* Removes the back element from 'list' and returns it.
205
Undefined behavior if 'list' is empty before removal. */
206
static inline struct ovs_list *
207
list_pop_back(struct ovs_list *list)
209
struct ovs_list *back = list->prev;
215
/* Returns the front element in 'list_'.
216
Undefined behavior if 'list_' is empty. */
217
static inline struct ovs_list *
218
list_front(const struct ovs_list *list_)
220
struct ovs_list *list = CONST_CAST(struct ovs_list *, list_);
222
ovs_assert(!list_is_empty(list));
227
/* Returns the back element in 'list_'.
228
Undefined behavior if 'list_' is empty. */
229
static inline struct ovs_list *
230
list_back(const struct ovs_list *list_)
232
struct ovs_list *list = CONST_CAST(struct ovs_list *, list_);
234
ovs_assert(!list_is_empty(list));
239
/* Returns the number of elements in 'list'.
240
Runs in O(n) in the number of elements. */
242
list_size(const struct ovs_list *list)
244
const struct ovs_list *e;
247
for (e = list->next; e != list; e = e->next) {
253
/* Returns true if 'list' is empty, false otherwise. */
255
list_is_empty(const struct ovs_list *list)
257
return list->next == list;
260
/* Returns true if 'list' has exactly 1 element, false otherwise. */
262
list_is_singleton(const struct ovs_list *list)
264
return list_is_short(list) && !list_is_empty(list);
267
/* Returns true if 'list' has 0 or 1 elements, false otherwise. */
269
list_is_short(const struct ovs_list *list)
271
return list->next == list->prev;
83
274
#endif /* list.h */