]>
Commit | Line | Data |
---|---|---|
b5a2cd07 | 1 | // SPDX-License-Identifier: LGPL-2.1-or-later |
6924e47a | 2 | /* |
e6b0e49b | 3 | * Copyright (C) 2011-2013 ProFUSION embedded systems |
6924e47a LDM |
4 | */ |
5 | ||
6 | #include <stdlib.h> | |
7 | ||
8 | #include "libkmod.h" | |
83b855a6 | 9 | #include "libkmod-internal.h" |
6924e47a LDM |
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 | ||
115bcd52 | 19 | static inline void list_node_append(struct list_node *list, struct list_node *node) |
6924e47a LDM |
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 | ||
e16e27f4 | 40 | return node->next; |
6924e47a LDM |
41 | } |
42 | ||
115bcd52 | 43 | static inline void list_node_insert_after(struct list_node *list, struct list_node *node) |
86e87885 LDM |
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 | ||
115bcd52 | 56 | static inline void list_node_insert_before(struct list_node *list, struct list_node *node) |
b91a1c6d LDM |
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 | ||
115bcd52 | 69 | static inline void list_node_append_list(struct list_node *list1, struct list_node *list2) |
1965029c LDM |
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 | ||
1ce08a56 | 88 | struct kmod_list *kmod_list_append(struct kmod_list *list, const void *data) |
6924e47a LDM |
89 | { |
90 | struct kmod_list *new; | |
91 | ||
92 | new = malloc(sizeof(*new)); | |
93 | if (new == NULL) | |
94 | return NULL; | |
95 | ||
1ce08a56 | 96 | new->data = (void *)data; |
6924e47a LDM |
97 | list_node_append(list ? &list->node : NULL, &new->node); |
98 | ||
99 | return list ? list : new; | |
100 | } | |
101 | ||
115bcd52 | 102 | struct kmod_list *kmod_list_insert_after(struct kmod_list *list, const void *data) |
86e87885 LDM |
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 | ||
115bcd52 | 119 | struct kmod_list *kmod_list_insert_before(struct kmod_list *list, const void *data) |
b91a1c6d LDM |
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 | ||
115bcd52 | 136 | struct kmod_list *kmod_list_append_list(struct kmod_list *list1, struct kmod_list *list2) |
1965029c LDM |
137 | { |
138 | if (list1 == NULL) | |
139 | return list2; | |
140 | ||
434f32ca LDM |
141 | if (list2 == NULL) |
142 | return list1; | |
143 | ||
1965029c LDM |
144 | list_node_append_list(&list1->node, &list2->node); |
145 | ||
146 | return list1; | |
147 | } | |
148 | ||
1ce08a56 | 149 | struct kmod_list *kmod_list_prepend(struct kmod_list *list, const void *data) |
6924e47a LDM |
150 | { |
151 | struct kmod_list *new; | |
152 | ||
153 | new = malloc(sizeof(*new)); | |
154 | if (new == NULL) | |
155 | return NULL; | |
156 | ||
1ce08a56 | 157 | new->data = (void *)data; |
6924e47a LDM |
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 | ||
115bcd52 | 179 | struct kmod_list *kmod_list_remove_data(struct kmod_list *list, const void *data) |
6924e47a LDM |
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 | ||
1ce08a56 | 201 | KMOD_EXPORT struct kmod_list *kmod_list_prev(const struct kmod_list *list, |
115bcd52 | 202 | const struct kmod_list *curr) |
79d77111 LDM |
203 | { |
204 | if (list == NULL || curr == NULL) | |
205 | return NULL; | |
206 | ||
2a70a5d4 | 207 | if (list == curr) |
79d77111 LDM |
208 | return NULL; |
209 | ||
210 | return container_of(curr->node.prev, struct kmod_list, node); | |
211 | } | |
212 | ||
1ce08a56 | 213 | KMOD_EXPORT struct kmod_list *kmod_list_next(const struct kmod_list *list, |
115bcd52 | 214 | const struct kmod_list *curr) |
6924e47a LDM |
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 | } | |
d5ec60bc | 224 | |
d5ec60bc GSB |
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 | } |