xref: /kvm-unit-tests/lib/list.h (revision a7eb7780d525b69a8fcfc8a3cfba85570a321c33)
14fa2b92fSClaudio Imbrenda #ifndef LIST_H
24fa2b92fSClaudio Imbrenda #define LIST_H
34fa2b92fSClaudio Imbrenda 
44fa2b92fSClaudio Imbrenda #include <stdbool.h>
54fa2b92fSClaudio Imbrenda 
64fa2b92fSClaudio Imbrenda /*
74fa2b92fSClaudio Imbrenda  * Circular doubly-linked list. The pointer to the list is a list item itself,
84fa2b92fSClaudio Imbrenda  * like in the kernel implementation.
94fa2b92fSClaudio Imbrenda  */
104fa2b92fSClaudio Imbrenda struct linked_list {
114fa2b92fSClaudio Imbrenda 	struct linked_list *prev;
124fa2b92fSClaudio Imbrenda 	struct linked_list *next;
134fa2b92fSClaudio Imbrenda };
144fa2b92fSClaudio Imbrenda 
154fa2b92fSClaudio Imbrenda /*
164fa2b92fSClaudio Imbrenda  * An empty list is a list item whose prev and next both point to itself.
174fa2b92fSClaudio Imbrenda  * Returns true if the list is empty.
184fa2b92fSClaudio Imbrenda  */
194fa2b92fSClaudio Imbrenda static inline bool is_list_empty(struct linked_list *p)
204fa2b92fSClaudio Imbrenda {
214fa2b92fSClaudio Imbrenda 	return !p->next || !p->prev || p == p->next || p == p->prev;
224fa2b92fSClaudio Imbrenda }
234fa2b92fSClaudio Imbrenda 
244fa2b92fSClaudio Imbrenda /*
254fa2b92fSClaudio Imbrenda  * Remove the given element from the list, if the list is not already empty.
264fa2b92fSClaudio Imbrenda  * The removed element is returned.
274fa2b92fSClaudio Imbrenda  */
284fa2b92fSClaudio Imbrenda static inline struct linked_list *list_remove(struct linked_list *l)
294fa2b92fSClaudio Imbrenda {
304fa2b92fSClaudio Imbrenda 	if (is_list_empty(l))
314fa2b92fSClaudio Imbrenda 		return NULL;
324fa2b92fSClaudio Imbrenda 
334fa2b92fSClaudio Imbrenda 	l->prev->next = l->next;
344fa2b92fSClaudio Imbrenda 	l->next->prev = l->prev;
354fa2b92fSClaudio Imbrenda 	l->prev = l->next = NULL;
364fa2b92fSClaudio Imbrenda 
374fa2b92fSClaudio Imbrenda 	return l;
384fa2b92fSClaudio Imbrenda }
394fa2b92fSClaudio Imbrenda 
404fa2b92fSClaudio Imbrenda /*
414fa2b92fSClaudio Imbrenda  * Add the given element after the given list head.
424fa2b92fSClaudio Imbrenda  */
434fa2b92fSClaudio Imbrenda static inline void list_add(struct linked_list *head, struct linked_list *li)
444fa2b92fSClaudio Imbrenda {
454fa2b92fSClaudio Imbrenda 	assert(li);
464fa2b92fSClaudio Imbrenda 	assert(head);
474fa2b92fSClaudio Imbrenda 	li->prev = head;
484fa2b92fSClaudio Imbrenda 	li->next = head->next;
494fa2b92fSClaudio Imbrenda 	head->next->prev = li;
504fa2b92fSClaudio Imbrenda 	head->next = li;
514fa2b92fSClaudio Imbrenda }
524fa2b92fSClaudio Imbrenda 
53*a7eb7780SClaudio Imbrenda /*
54*a7eb7780SClaudio Imbrenda  * Add the given element before the given list head.
55*a7eb7780SClaudio Imbrenda  */
56*a7eb7780SClaudio Imbrenda static inline void list_add_tail(struct linked_list *head, struct linked_list *li)
57*a7eb7780SClaudio Imbrenda {
58*a7eb7780SClaudio Imbrenda 	assert(head);
59*a7eb7780SClaudio Imbrenda 	list_add(head->prev, li);
60*a7eb7780SClaudio Imbrenda }
61*a7eb7780SClaudio Imbrenda 
624fa2b92fSClaudio Imbrenda #endif
63