]>
git.ipfire.org Git - thirdparty/kmod.git/blob - libkmod/libkmod-list.c
2 * libkmod - interface to kernel module operations
4 * Copyright (C) 2011-2013 ProFUSION embedded systems
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
23 #include "libkmod-internal.h"
26 * SECTION:libkmod-list
27 * @short_description: general purpose list
30 static inline struct list_node
*list_node_init(struct list_node
*node
)
38 static inline void list_node_append(struct list_node
*list
,
39 struct list_node
*node
)
46 node
->prev
= list
->prev
;
47 list
->prev
->next
= node
;
52 static inline struct list_node
*list_node_remove(struct list_node
*node
)
54 if (node
->prev
== node
|| node
->next
== node
)
57 node
->prev
->next
= node
->next
;
58 node
->next
->prev
= node
->prev
;
63 static inline void list_node_insert_after(struct list_node
*list
,
64 struct list_node
*node
)
72 node
->next
= list
->next
;
73 list
->next
->prev
= node
;
77 static inline void list_node_insert_before(struct list_node
*list
,
78 struct list_node
*node
)
86 node
->prev
= list
->prev
;
87 list
->prev
->next
= node
;
91 static inline void list_node_append_list(struct list_node
*list1
,
92 struct list_node
*list2
)
94 struct list_node
*list1_last
;
97 list_node_init(list2
);
101 list1
->prev
->next
= list2
;
102 list2
->prev
->next
= list1
;
104 /* cache the last, because we will lose the pointer */
105 list1_last
= list1
->prev
;
107 list1
->prev
= list2
->prev
;
108 list2
->prev
= list1_last
;
111 struct kmod_list
*kmod_list_append(struct kmod_list
*list
, const void *data
)
113 struct kmod_list
*new;
115 new = malloc(sizeof(*new));
119 new->data
= (void *)data
;
120 list_node_append(list
? &list
->node
: NULL
, &new->node
);
122 return list
? list
: new;
125 struct kmod_list
*kmod_list_insert_after(struct kmod_list
*list
,
128 struct kmod_list
*new;
131 return kmod_list_append(list
, data
);
133 new = malloc(sizeof(*new));
137 new->data
= (void *)data
;
138 list_node_insert_after(&list
->node
, &new->node
);
143 struct kmod_list
*kmod_list_insert_before(struct kmod_list
*list
,
146 struct kmod_list
*new;
149 return kmod_list_append(list
, data
);
151 new = malloc(sizeof(*new));
155 new->data
= (void *)data
;
156 list_node_insert_before(&list
->node
, &new->node
);
161 struct kmod_list
*kmod_list_append_list(struct kmod_list
*list1
,
162 struct kmod_list
*list2
)
170 list_node_append_list(&list1
->node
, &list2
->node
);
175 struct kmod_list
*kmod_list_prepend(struct kmod_list
*list
, const void *data
)
177 struct kmod_list
*new;
179 new = malloc(sizeof(*new));
183 new->data
= (void *)data
;
184 list_node_append(list
? &list
->node
: NULL
, &new->node
);
189 struct kmod_list
*kmod_list_remove(struct kmod_list
*list
)
191 struct list_node
*node
;
196 node
= list_node_remove(&list
->node
);
202 return container_of(node
, struct kmod_list
, node
);
205 struct kmod_list
*kmod_list_remove_data(struct kmod_list
*list
,
208 struct kmod_list
*itr
;
209 struct list_node
*node
;
211 for (itr
= list
; itr
!= NULL
; itr
= kmod_list_next(list
, itr
)) {
212 if (itr
->data
== data
)
219 node
= list_node_remove(&itr
->node
);
225 return container_of(node
, struct kmod_list
, node
);
229 * n must be greater to or equal the number of elements (we don't check the
232 struct kmod_list
*kmod_list_remove_n_latest(struct kmod_list
*list
,
235 struct kmod_list
*l
= list
;
238 for (i
= 0; i
< n
; i
++) {
239 l
= kmod_list_last(l
);
240 l
= kmod_list_remove(l
);
248 * @list: the head of the list
249 * @curr: the current node in the list
251 * Get the previous node in @list relative to @curr as if @list was not a
252 * circular list. I.e.: the previous of the head is NULL. It can be used to
253 * iterate a list by checking for NULL return to know when all elements were
256 * Returns: node previous to @curr or NULL if either this node is the head of
257 * the list or the list is empty.
259 KMOD_EXPORT
struct kmod_list
*kmod_list_prev(const struct kmod_list
*list
,
260 const struct kmod_list
*curr
)
262 if (list
== NULL
|| curr
== NULL
)
268 return container_of(curr
->node
.prev
, struct kmod_list
, node
);
273 * @list: the head of the list
274 * @curr: the current node in the list
276 * Get the next node in @list relative to @curr as if @list was not a circular
277 * list. I.e. calling this function in the last node of the list returns
278 * NULL.. It can be used to iterate a list by checking for NULL return to know
279 * when all elements were iterated.
281 * Returns: node next to @curr or NULL if either this node is the last of or
284 KMOD_EXPORT
struct kmod_list
*kmod_list_next(const struct kmod_list
*list
,
285 const struct kmod_list
*curr
)
287 if (list
== NULL
|| curr
== NULL
)
290 if (curr
->node
.next
== &list
->node
)
293 return container_of(curr
->node
.next
, struct kmod_list
, node
);
298 * @list: the head of the list
300 * Get the last element of the @list. As @list is a circular list,
301 * this is a cheap operation O(1) with the last element being the
304 * If the list has a single element it will return the list itself (as
305 * expected, and this is what differentiates from kmod_list_prev()).
307 * Returns: last node at @list or NULL if the list is empty.
309 KMOD_EXPORT
struct kmod_list
*kmod_list_last(const struct kmod_list
*list
)
313 return container_of(list
->node
.prev
, struct kmod_list
, node
);