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