]> git.ipfire.org Git - thirdparty/kmod.git/blob - libkmod/libkmod-list.c
5b5899c5b886a7c1a1d6114e46bb29ce6fc4ad67
[thirdparty/kmod.git] / libkmod / libkmod-list.c
1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 /*
3 * Copyright (C) 2011-2013 ProFUSION embedded systems
4 */
5
6 #include <stdlib.h>
7
8 #include "libkmod.h"
9 #include "libkmod-internal.h"
10
11 static inline struct list_node *list_node_init(struct list_node *node)
12 {
13 node->next = node;
14 node->prev = node;
15
16 return node;
17 }
18
19 static inline void list_node_append(struct list_node *list, struct list_node *node)
20 {
21 if (list == NULL) {
22 list_node_init(node);
23 return;
24 }
25
26 node->prev = list->prev;
27 list->prev->next = node;
28 list->prev = node;
29 node->next = list;
30 }
31
32 static inline struct list_node *list_node_remove(struct list_node *node)
33 {
34 if (node->prev == node || node->next == node)
35 return NULL;
36
37 node->prev->next = node->next;
38 node->next->prev = node->prev;
39
40 return node->next;
41 }
42
43 static inline void list_node_insert_after(struct list_node *list, struct list_node *node)
44 {
45 if (list == NULL) {
46 list_node_init(node);
47 return;
48 }
49
50 node->prev = list;
51 node->next = list->next;
52 list->next->prev = node;
53 list->next = node;
54 }
55
56 static inline void list_node_insert_before(struct list_node *list, struct list_node *node)
57 {
58 if (list == NULL) {
59 list_node_init(node);
60 return;
61 }
62
63 node->next = list;
64 node->prev = list->prev;
65 list->prev->next = node;
66 list->prev = node;
67 }
68
69 static inline void list_node_append_list(struct list_node *list1, struct list_node *list2)
70 {
71 struct list_node *list1_last;
72
73 if (list1 == NULL) {
74 list_node_init(list2);
75 return;
76 }
77
78 list1->prev->next = list2;
79 list2->prev->next = list1;
80
81 /* cache the last, because we will lose the pointer */
82 list1_last = list1->prev;
83
84 list1->prev = list2->prev;
85 list2->prev = list1_last;
86 }
87
88 struct kmod_list *kmod_list_append(struct kmod_list *list, const void *data)
89 {
90 struct kmod_list *new;
91
92 new = malloc(sizeof(*new));
93 if (new == NULL)
94 return NULL;
95
96 new->data = (void *)data;
97 list_node_append(list ? &list->node : NULL, &new->node);
98
99 return list ? list : new;
100 }
101
102 struct kmod_list *kmod_list_insert_after(struct kmod_list *list, const void *data)
103 {
104 struct kmod_list *new;
105
106 if (list == NULL)
107 return kmod_list_append(list, data);
108
109 new = malloc(sizeof(*new));
110 if (new == NULL)
111 return NULL;
112
113 new->data = (void *)data;
114 list_node_insert_after(&list->node, &new->node);
115
116 return list;
117 }
118
119 struct kmod_list *kmod_list_insert_before(struct kmod_list *list, const void *data)
120 {
121 struct kmod_list *new;
122
123 if (list == NULL)
124 return kmod_list_append(list, data);
125
126 new = malloc(sizeof(*new));
127 if (new == NULL)
128 return NULL;
129
130 new->data = (void *)data;
131 list_node_insert_before(&list->node, &new->node);
132
133 return new;
134 }
135
136 struct kmod_list *kmod_list_append_list(struct kmod_list *list1, struct kmod_list *list2)
137 {
138 if (list1 == NULL)
139 return list2;
140
141 if (list2 == NULL)
142 return list1;
143
144 list_node_append_list(&list1->node, &list2->node);
145
146 return list1;
147 }
148
149 struct kmod_list *kmod_list_prepend(struct kmod_list *list, const void *data)
150 {
151 struct kmod_list *new;
152
153 new = malloc(sizeof(*new));
154 if (new == NULL)
155 return NULL;
156
157 new->data = (void *)data;
158 list_node_append(list ? &list->node : NULL, &new->node);
159
160 return new;
161 }
162
163 struct kmod_list *kmod_list_remove(struct kmod_list *list)
164 {
165 struct list_node *node;
166
167 if (list == NULL)
168 return NULL;
169
170 node = list_node_remove(&list->node);
171 free(list);
172
173 if (node == NULL)
174 return NULL;
175
176 return container_of(node, struct kmod_list, node);
177 }
178
179 struct kmod_list *kmod_list_remove_data(struct kmod_list *list, const void *data)
180 {
181 struct kmod_list *itr;
182 struct list_node *node;
183
184 for (itr = list; itr != NULL; itr = kmod_list_next(list, itr)) {
185 if (itr->data == data)
186 break;
187 }
188
189 if (itr == NULL)
190 return list;
191
192 node = list_node_remove(&itr->node);
193 free(itr);
194
195 if (node == NULL)
196 return NULL;
197
198 return container_of(node, struct kmod_list, node);
199 }
200
201 KMOD_EXPORT struct kmod_list *kmod_list_prev(const struct kmod_list *list,
202 const struct kmod_list *curr)
203 {
204 if (list == NULL || curr == NULL)
205 return NULL;
206
207 if (list == curr)
208 return NULL;
209
210 return container_of(curr->node.prev, struct kmod_list, node);
211 }
212
213 KMOD_EXPORT struct kmod_list *kmod_list_next(const struct kmod_list *list,
214 const struct kmod_list *curr)
215 {
216 if (list == NULL || curr == NULL)
217 return NULL;
218
219 if (curr->node.next == &list->node)
220 return NULL;
221
222 return container_of(curr->node.next, struct kmod_list, node);
223 }
224
225 KMOD_EXPORT struct kmod_list *kmod_list_last(const struct kmod_list *list)
226 {
227 if (list == NULL)
228 return NULL;
229 return container_of(list->node.prev, struct kmod_list, node);
230 }