xref: /kvm-unit-tests/lib/list.h (revision 9f0ae3012430ed7072d04247fb674125c616a6b4)
1*9f0ae301SCornelia Huck #ifndef _LIST_H_
2*9f0ae301SCornelia Huck #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  */
is_list_empty(struct linked_list * p)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  */
list_remove(struct linked_list * l)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  */
list_add(struct linked_list * head,struct linked_list * li)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 
53a7eb7780SClaudio Imbrenda /*
54a7eb7780SClaudio Imbrenda  * Add the given element before the given list head.
55a7eb7780SClaudio Imbrenda  */
list_add_tail(struct linked_list * head,struct linked_list * li)56a7eb7780SClaudio Imbrenda static inline void list_add_tail(struct linked_list *head, struct linked_list *li)
57a7eb7780SClaudio Imbrenda {
58a7eb7780SClaudio Imbrenda 	assert(head);
59a7eb7780SClaudio Imbrenda 	list_add(head->prev, li);
60a7eb7780SClaudio Imbrenda }
61a7eb7780SClaudio Imbrenda 
624fa2b92fSClaudio Imbrenda #endif
63