2 * UCW Library -- Single-Linked Lists
4 * (c) 2005 Martin Mares <mj@ucw.cz>
5 * (c) 2017 Pavel Charvat <pchar@ucw.cz>
7 * This software may be freely distributed and used according to the terms
8 * of the GNU Lesser General Public License.
14 #ifdef CONFIG_UCW_CLEAN_ABI
15 #define slist_insert_before ucw_slist_insert_before
16 #define slist_prev ucw_slist_prev
17 #define slist_remove ucw_slist_remove
21 * Common header for list nodes.
23 typedef struct snode {
30 typedef struct slist {
31 struct snode head, *last;
35 * Initialize a new single-linked list. Must be called before any other function.
37 static inline void slist_init(slist *l)
39 l->head.next = l->last = NULL;
43 * Return the first node of @l or NULL if @l is empty.
45 static inline void *slist_head(slist *l)
51 * Return the last node of @l or NULL if @l is empty.
53 static inline void *slist_tail(slist *l)
59 * Find the next node to @n or NULL if @n is the last one.
61 static inline void *slist_next(snode *n)
67 * Return a non-zero value iff @l is empty.
69 static inline int slist_empty(slist *l)
75 * Insert a new node in front of all other nodes.
77 static inline void slist_add_head(slist *l, snode *n)
79 n->next = l->head.next;
86 * Insert a new node after all other nodes.
88 static inline void slist_add_tail(slist *l, snode *n)
99 * Insert a new node just after the node @after. To insert a new head, use @slist_add_head() instead.
101 static inline void slist_insert_after(slist *l, snode *what, snode *after)
103 what->next = after->next;
110 * Quickly remove the node next to @after. The node may not exist.
112 static inline void slist_remove_after(slist *l, snode *after)
114 snode *n = after->next;
117 after->next = n->next;
119 l->last = (after == &l->head) ? NULL : after;
124 * Remove the first node in @l. The list can be empty.
126 static inline void *slist_remove_head(slist *l)
128 snode *n = slist_head(l);
130 slist_remove_after(l, &l->head);
137 * Loop over all nodes in the @list and perform the next C statement on them. The current node is stored in @n which must be defined before as pointer to any type.
138 * The list should not be changed during this loop command.
140 #define SLIST_WALK(n,list) for(n=(void*)(list).head.next; (n); (n)=(void*)((snode*)(n))->next)
143 * Same as @SLIST_WALK(), but allows removal of the current node. This macro requires one more variable to store the pointer to the previous node (useful for @slist_remove_after()).
145 #define SLIST_WALK_DELSAFE(n,list,prev) for((prev)=(void*)&(list).head; (n)=(void*)((snode*)prev)->next; (prev)=(((snode*)(prev))->next==(snode*)(n) ? (void*)(n) : (void*)(prev)))
148 * Same as @SLIST_WALK(), but it defines the variable for the current node in place. @type should be a pointer type.
150 #define SLIST_FOR_EACH(type,n,list) for(type n=(void*)(list).head.next; n; n=(void*)((snode*)(n))->next)
152 /* Non-trivial functions */
155 * Find the previous node to @n or NULL if @n is the first one. Beware linear time complexity.
157 void *slist_prev(slist *l, snode *n);
160 * Insert a new node just before the node @before. To insert a new tail, use @slist_add_tail(). Beware linear time complexity.
162 void slist_insert_before(slist *l, snode *what, snode *before);
165 * Remove node @n. Beware linear time complexity.
167 void slist_remove(slist *l, snode *n);
170 * Remove the last node in @l. The list can be empty.
172 static inline void slist_remove_tail(slist *l)
174 slist_remove(l, l->last);
178 * Merge two lists by inserting the list @what in front of all other nodes in a different list @l.
179 * The first list is then cleared.
181 static inline void slist_add_list_head(slist *l, slist *what)
183 if (!slist_empty(what))
186 what->last->next = l->head.next;
188 l->last = what->last;
189 l->head.next = what->head.next;
195 * Merge two lists by inserting the list @what after all other nodes in a different list @l.
196 * The first list is then cleared.
198 static inline void slist_add_list_tail(slist *l, slist *what)
200 if (!slist_empty(what))
203 l->last->next = what->head.next;
205 l->head.next = what->head.next;
206 l->last = what->last;
212 * Move all items from a source list to a destination list. The source list
213 * becomes empty, the original contents of the destination list are destroyed.
215 static inline void slist_move(slist *to, slist *from)
217 to->head.next = from->head.next;
218 to->last = from->last;
223 * Compute the number of nodes in @l. Beware linear time complexity.
225 static inline uint slist_size(slist *l)
228 SLIST_FOR_EACH(snode *, n, *l)