]>
Commit | Line | Data |
---|---|---|
cc73685d | 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ |
250b1eec | 2 | |
f1a4a029 ÇO |
3 | #ifndef __LXC_LIST_H |
4 | #define __LXC_LIST_H | |
0ad19a3f | 5 | |
1a0e70ac CB |
6 | #include <stdio.h> |
7 | ||
951cc719 | 8 | struct lxc_list { |
0ad19a3f | 9 | void *elem; |
951cc719 DL |
10 | struct lxc_list *next; |
11 | struct lxc_list *prev; | |
0ad19a3f | 12 | }; |
13 | ||
1a0e70ac CB |
14 | #define lxc_init_list(l) \ |
15 | { \ | |
16 | .next = l, .prev = l \ | |
17 | } | |
0ad19a3f | 18 | |
c2613927 CB |
19 | /* |
20 | * Iterate through an lxc list. An example for an idiom would be: | |
21 | * | |
22 | * struct lxc_list *iterator; | |
c2613927 | 23 | * lxc_list_for_each(iterator, list) { |
1a0e70ac | 24 | * type *tmp; |
c2613927 | 25 | * tmp = iterator->elem; |
c2613927 | 26 | * } |
c2613927 | 27 | */ |
1a0e70ac CB |
28 | #define lxc_list_for_each(__iterator, __list) \ |
29 | for (__iterator = (__list)->next; __iterator != __list; \ | |
0ad19a3f | 30 | __iterator = __iterator->next) |
31 | ||
1a0e70ac | 32 | /* Iterate safely through an lxc list. An example for an appropriate use case |
c2613927 CB |
33 | * would be: |
34 | * | |
1a0e70ac CB |
35 | * struct lxc_list *cur, *next; |
36 | * lxc_list_for_each_safe(cur, list, next) { | |
37 | * type *tmp; | |
38 | * tmp = cur->elem; | |
c2613927 | 39 | * } |
c2613927 | 40 | */ |
1a0e70ac CB |
41 | #define lxc_list_for_each_safe(__iterator, __list, __next) \ |
42 | for (__iterator = (__list)->next, __next = __iterator->next; \ | |
43 | __iterator != __list; __iterator = __next, __next = __next->next) | |
9ebb03ad | 44 | |
95db7d8c | 45 | /* Initialize list. */ |
951cc719 | 46 | static inline void lxc_list_init(struct lxc_list *list) |
0ad19a3f | 47 | { |
48 | list->elem = NULL; | |
49 | list->next = list->prev = list; | |
50 | } | |
51 | ||
c2613927 | 52 | /* Add an element to a list. See lxc_list_add() and lxc_list_add_tail() for an |
1a0e70ac CB |
53 | * idiom. |
54 | */ | |
951cc719 | 55 | static inline void lxc_list_add_elem(struct lxc_list *list, void *elem) |
0ad19a3f | 56 | { |
57 | list->elem = elem; | |
58 | } | |
59 | ||
c2613927 | 60 | /* Retrieve first element of list. */ |
facdf925 | 61 | static inline void *lxc_list_first_elem(const struct lxc_list *list) |
0ad19a3f | 62 | { |
63 | return list->next->elem; | |
64 | } | |
65 | ||
c2613927 | 66 | /* Retrieve last element of list. */ |
facdf925 | 67 | static inline void *lxc_list_last_elem(const struct lxc_list *list) |
bac89583 DL |
68 | { |
69 | return list->prev->elem; | |
70 | } | |
71 | ||
c2613927 | 72 | /* Determine if list is empty. */ |
facdf925 | 73 | static inline int lxc_list_empty(const struct lxc_list *list) |
0ad19a3f | 74 | { |
75 | return list == list->next; | |
76 | } | |
77 | ||
c2613927 | 78 | /* Workhorse to be called from lxc_list_add() and lxc_list_add_tail(). */ |
1a0e70ac | 79 | static inline void __lxc_list_add(struct lxc_list *new, struct lxc_list *prev, |
951cc719 | 80 | struct lxc_list *next) |
0ad19a3f | 81 | { |
d028235d SG |
82 | next->prev = new; |
83 | new->next = next; | |
84 | new->prev = prev; | |
85 | prev->next = new; | |
0ad19a3f | 86 | } |
87 | ||
1a0e70ac | 88 | /* Idiom to add an element to the beginning of an lxc list: |
c2613927 CB |
89 | * |
90 | * struct lxc_list *tmp = malloc(sizeof(*tmp)); | |
91 | * if (tmp == NULL) | |
92 | * return 1; | |
93 | * lxc_list_add_elem(tmp, elem); | |
94 | * lxc_list_add(list, tmp); | |
95 | */ | |
951cc719 | 96 | static inline void lxc_list_add(struct lxc_list *head, struct lxc_list *list) |
0ad19a3f | 97 | { |
951cc719 DL |
98 | __lxc_list_add(list, head, head->next); |
99 | } | |
100 | ||
1a0e70ac | 101 | /* Idiom to add an element to the end of an lxc list: |
c2613927 CB |
102 | * |
103 | * struct lxc_list *tmp = malloc(sizeof(*tmp)); | |
104 | * if (tmp == NULL) | |
105 | * return 1; | |
106 | * lxc_list_add_elem(tmp, elem); | |
107 | * lxc_list_add_tail(list, tmp); | |
108 | */ | |
951cc719 DL |
109 | static inline void lxc_list_add_tail(struct lxc_list *head, |
110 | struct lxc_list *list) | |
111 | { | |
112 | __lxc_list_add(list, head->prev, head); | |
113 | } | |
114 | ||
1a0e70ac CB |
115 | /* Idiom to remove an element from a list: |
116 | * struct lxc_list *cur, *next; | |
117 | * lxc_list_for_each_safe(cur, list, next) { | |
118 | * lxc_list_del(cur); | |
119 | * free(cur->elem); | |
120 | * free(cur); | |
c2613927 | 121 | * } |
c2613927 | 122 | */ |
951cc719 DL |
123 | static inline void lxc_list_del(struct lxc_list *list) |
124 | { | |
125 | struct lxc_list *next, *prev; | |
0ad19a3f | 126 | |
127 | next = list->next; | |
128 | prev = list->prev; | |
129 | next->prev = prev; | |
130 | prev->next = next; | |
131 | } | |
132 | ||
c2613927 CB |
133 | /* Return length of the list. */ |
134 | static inline size_t lxc_list_len(struct lxc_list *list) | |
9fc7f8c0 | 135 | { |
ca9a2504 | 136 | size_t i = 0; |
137 | struct lxc_list *iter; | |
1a0e70ac | 138 | |
ca9a2504 | 139 | lxc_list_for_each(iter, list) { |
9fc7f8c0 | 140 | i++; |
ca9a2504 | 141 | } |
9fc7f8c0 | 142 | |
ca9a2504 | 143 | return i; |
9fc7f8c0 TA |
144 | } |
145 | ||
1a0e70ac | 146 | #endif /* __LXC_LIST_H */ |