libevl/include/evl/list.h

200 lines
4.8 KiB
C

/*
* SPDX-License-Identifier: MIT
*
* Imported from Xenomai 'list' macros (https://xenomai.org/)
* Copyright (C) 2019 Philippe Gerum <rpm@xenomai.org>
* Relicensed by its author from LGPL 2.1 to MIT.
*/
#ifndef _EVL_LIST_H
#define _EVL_LIST_H
#include <evl/compiler.h>
struct list_head {
struct list_head *next;
struct list_head *prev;
};
#define LIST_HEAD_INITIALIZER(__name) \
{ .next = &(__name), .prev = &(__name) }
#define DEFINE_LIST_HEAD(__name) \
struct list_head __name = LIST_HEAD_INITIALIZER(__name)
static inline void inith(struct list_head *head)
{
head->next = head;
head->prev = head;
}
static inline void ath(struct list_head *head,
struct list_head *e)
{
/* Inserts the new element right after the heading one. */
e->prev = head;
e->next = head->next;
e->next->prev = e;
head->next = e;
}
static inline void dth(struct list_head *e)
{
e->prev->next = e->next;
e->next->prev = e->prev;
}
static inline void list_init(struct list_head *head)
{
inith(head);
}
/*
* XXX: list_init() is mandatory if you later want to use this
* predicate.
*/
static inline int list_is_linked(const struct list_head *e)
{
return !(e->prev == e->next && e->prev == e);
}
static inline void list_prepend(struct list_head *e,
struct list_head *head)
{
ath(head, e);
}
static inline void list_append(struct list_head *e,
struct list_head *head)
{
ath(head->prev, e);
}
static inline void list_insert(struct list_head *next,
struct list_head *prev)
{
ath(prev, next);
}
static inline void list_join(struct list_head *src,
struct list_head *dst)
{
struct list_head *headsrc = src->next;
struct list_head *tailsrc = src->prev;
headsrc->prev->next = tailsrc->next;
tailsrc->next->prev = headsrc->prev;
headsrc->prev = dst;
tailsrc->next = dst->next;
dst->next->prev = tailsrc;
dst->next = headsrc;
}
static inline void list_remove(struct list_head *e)
{
dth(e);
}
static inline void list_remove_init(struct list_head *e)
{
dth(e);
inith(e);
}
static inline int list_empty(const struct list_head *head)
{
return head->next == head;
}
static inline struct list_head *list_pop(struct list_head *head)
{
struct list_head *e = head->next;
list_remove(e);
return e;
}
static inline int list_is_heading(const struct list_head *e,
const struct list_head *head)
{
return head->next == e;
}
#define list_entry(ptr, type, member) \
container_of(ptr, type, member)
#define list_first_entry(head, type, member) \
list_entry((head)->next, type, member)
#define list_last_entry(head, type, member) \
list_entry((head)->prev, type, member)
#define list_prev_entry(pos, head, member) \
({ \
typeof(*pos) *__prev = NULL; \
if ((head)->next != &(pos)->member) \
__prev = list_entry((pos)->member.prev, \
typeof(*pos), member); \
__prev; \
})
#define list_next_entry(pos, head, member) \
({ \
typeof(*pos) *__next = NULL; \
if ((head)->prev != &(pos)->member) \
__next = list_entry((pos)->member.next, \
typeof(*pos), member); \
__next; \
})
#define list_pop_entry(head, type, member) \
({ \
struct list_head *__e = list_pop(head); \
list_entry(__e, type, member); \
})
#define list_for_each(pos, head) \
for (pos = (head)->next; \
pos != (head); pos = (pos)->next)
#define list_for_each_reverse(pos, head) \
for (pos = (head)->prev; \
pos != (head); pos = (pos)->prev)
#define list_for_each_safe(pos, tmp, head) \
for (pos = (head)->next, tmp = (pos)->next; \
pos != (head); pos = tmp, tmp = (pos)->next)
#define list_for_each_entry(pos, head, member) \
for (pos = list_entry((head)->next, \
typeof(*pos), member); \
&(pos)->member != (head); \
pos = list_entry((pos)->member.next, \
typeof(*pos), member))
#define list_for_each_entry_safe(pos, tmp, head, member) \
for (pos = list_entry((head)->next, \
typeof(*pos), member), \
tmp = list_entry((pos)->member.next, \
typeof(*pos), member); \
&(pos)->member != (head); \
pos = tmp, tmp = list_entry((pos)->member.next, \
typeof(*pos), member))
#define list_for_each_entry_reverse(pos, head, member) \
for (pos = list_entry((head)->prev, \
typeof(*pos), member); \
&pos->member != (head); \
pos = list_entry(pos->member.prev, \
typeof(*pos), member))
#define list_for_each_entry_reverse_safe(pos, tmp, head, member) \
for (pos = list_entry((head)->prev, \
typeof(*pos), member), \
tmp = list_entry((pos)->member.prev, \
typeof(*pos), member); \
&(pos)->member != (head); \
pos = tmp, tmp = list_entry((pos)->member.prev, \
typeof(*pos), member))
#endif /* !_EVL_LIST_H */