Skip to content

Linked list

include/structures/list.h View source View on GitHub
struct list_node (1 field) source

Circular doubly linked list.

We use two different types here since a unified list_head proved problematic for readability and semantics. It’s largely symbolic and for type safety.

struct list_node is the link struct list_head is the head/anchor of the list.

list_head_* operations take the list_head, list_node_* operations a list_node, list_root_* operations technically take a list_node, but this is meant to be the list_head’s root member, and is used as convenience.

Thus, swapping arguments like list_add(&parent->node, &child->node); is not possible and fails to compile.

§ struct list_node *next
struct list_head (1 field) source
§ struct list_node root
struct slist_node (1 field) source
§ struct slist_node *next
struct slist_head (2 fields) source
§ struct slist_node *first
§ struct slist_node *last
typedef int (*list_cmp_fn)(struct list_node * *, struct list_node * *)
source
void list_add_check(
    const struct list_node *new,
    const struct list_node *prev,
    const struct list_node *next
)
source
void list_del_check(const struct list_node *entry)
source
void list_splice_check(
    const struct list_node *list,
    const struct list_node *prev,
    const struct list_node *next
)
source
void list_add_check(
    const struct list_node *new,
    const struct list_node *prev,
    const struct list_node *next
)
source
void list_del_check(const struct list_node *entry)
source
void list_splice_check(
    const struct list_node *list,
    const struct list_node *prev,
    const struct list_node *next
)
source
void list_node_init(struct list_node *n)
source
void list_head_init(struct list_head *h)
source
bool list_node_is_linked(const struct list_node *n)
source
struct list_node * list_node_next(const struct list_node *n)
source
struct list_node * list_node_prev(const struct list_node *n)
source
struct list_node * list_head_sentinel(struct list_head *h)
source
struct list_head * list_node_as_head(struct list_node *n)
source

Treat a node as if it’s the head. Should only be used in headless lists where one of the middle members is also the anchor

void list_node_link_between(
    struct list_node *new,
    struct list_node *prev,
    struct list_node *next
)
source
void list_node_unlink_between(
    struct list_node *prev,
    struct list_node *next
)
source
void list_node_insert_after(
    struct list_node *pos,
    struct list_node *n
)
source
void list_node_insert_before(
    struct list_node *pos,
    struct list_node *n
)
source
void list_node_delete(struct list_node *n)
source
void list_node_delete_init(struct list_node *n)
source
bool list_head_empty(const struct list_head *h)
source
void list_head_push_front(struct list_head *h, struct list_node *n)
source
void list_head_push_back(struct list_head *h, struct list_node *n)
source
struct list_node * list_root_pop_front(struct list_node *root)
source

root_*, For direct sentinel manipulation

struct list_node * list_root_pop_back(struct list_node *root)
source
struct list_node * list_head_peek_front(struct list_head *h)
source
struct list_node * list_head_peek_back(struct list_head *h)
source
struct list_node * list_head_pop_front(struct list_head *h)
source
struct list_node * list_head_pop_back(struct list_head *h)
source
struct list_node * list_head_pop_front_init(struct list_head *h)
source
struct list_node * list_head_pop_back_init(struct list_head *h)
source
void list_splice_between(
    const struct list_node *list,
    struct list_node *prev,
    struct list_node *next
)
source
void list_head_splice_front_init(
    struct list_head *dst,
    struct list_head *src
)
source

Move everyone from src to the front of dst

void list_head_splice_back_init(
    struct list_head *dst,
    struct list_head *src
)
source

Move everyone from src to the back of dst

void list_root_sort(struct list_node *root, list_cmp_fn cmp)
source
void list_head_sort(struct list_head *h, list_cmp_fn cmp)
source
void slist_head_init(struct slist_head *h)
source
int slist_empty(const struct slist_head *h)
source
void slist_push_head(struct slist_head *h, struct slist_node *n)
source
void slist_push_tail(struct slist_head *h, struct slist_node *n)
source
struct slist_node * slist_pop_head(struct slist_head *h)
source
void slist_remove_node_after(
    struct slist_head *h,
    struct slist_node *prev,
    struct slist_node *target
)
source
#define LIST_NODE_INIT(name)
source
Expansion
#define LIST_NODE_INIT(name) {&(name), &(name)}
#define LIST_HEAD_INIT(name)
source
Expansion
#define LIST_HEAD_INIT(name) \
    { \
        .root = { &(name).root, &(name).root } \
    }
#define LIST_HEAD(name)
source
Expansion
#define LIST_HEAD(name) struct list_head name = LIST_HEAD_INIT(name)
#define list_root(h)
source
Expansion
#define list_root(h) (&(h)->root)
#define list_entry(ptr, type, member)
source
Expansion
#define list_entry(ptr, type, member) container_of(ptr, type, member)
#define list_entry_safe(ptr, type, member)
source
Expansion
#define list_entry_safe(ptr, type, member) \
    ({ \
        __auto_type __list_ptr = (ptr); \
        __list_ptr ? list_entry(__list_ptr, type, member) : NULL; \
    })
#define list_for_each(pos, head)
source
Expansion
#define list_for_each(pos, head) \
    for (pos = list_root(head)->next; pos != list_root(head); pos = pos->next)
#define list_for_each_rev(pos, head)
source
Expansion
#define list_for_each_rev(pos, head) \
    for (pos = list_root(head)->prev; pos != list_root(head); pos = pos->prev)
#define list_for_each_safe(pos, n, head)
source
Expansion
#define list_for_each_safe(pos, n, head) \
    for (pos = list_root(head)->next, n = pos->next; pos != list_root(head); \
         pos = n, n = pos->next)
#define list_for_each_rev_safe(pos, n, head)
source
Expansion
#define list_for_each_rev_safe(pos, n, head) \
    for (pos = list_root(head)->prev, n = pos->prev; pos != list_root(head); \
         pos = n, n = pos->prev)
#define list_for_each_entry(pos, head, member)
source
Expansion
#define list_for_each_entry(pos, head, member) \
    for (pos = list_entry(list_root(head)->next, typeof(*pos), member); \
         &pos->member != list_root(head); \
         pos = list_entry(pos->member.next, typeof(*pos), member))
#define list_for_each_entry_rev(pos, head, member)
source
Expansion
#define list_for_each_entry_rev(pos, head, member) \
    for (pos = list_entry(list_root(head)->prev, typeof(*pos), member); \
         &pos->member != list_root(head); \
         pos = list_entry(pos->member.prev, typeof(*pos), member))
#define list_first_entry(ptr, type, member)
source
Expansion
#define list_first_entry(ptr, type, member) \
    list_entry(list_root(ptr)->next, type, member)
#define list_last_entry(ptr, type, member)
source
Expansion
#define list_last_entry(ptr, type, member) \
    list_entry(list_root(ptr)->prev, type, member)
#define list_for_each_entry_safe(pos, n, head, member)
source
Expansion
#define list_for_each_entry_safe(pos, n, head, member) \
    for (pos = list_entry(list_root(head)->next, typeof(*pos), member), \
        n = list_entry(pos->member.next, typeof(*pos), member); \
         &pos->member != list_root(head); \
         pos = n, n = list_entry(n->member.next, typeof(*n), member))
#define list_for_each_entry_safe_rev(pos, n, head, member)
source
Expansion
#define list_for_each_entry_safe_rev(pos, n, head, member) \
    for (pos = list_entry(list_root(head)->prev, typeof(*pos), member), \
        n = list_entry(pos->member.prev, typeof(*pos), member); \
         &pos->member != list_root(head); \
         pos = n, n = list_entry(n->member.prev, typeof(*n), member))
#define list_for_each_entry_safe_continue(pos, n, head, member)
source
Expansion
#define list_for_each_entry_safe_continue(pos, n, head, member) \
    for (pos = list_entry(pos->member.next, typeof(*pos), member), \
        n = list_entry(pos->member.next, typeof(*pos), member); \
         &pos->member != list_root(head); \
         pos = n, n = list_entry(n->member.next, typeof(*n), member))
#define list_for_each_entry_safe_continue_rev(pos, n, head, member)
source
Expansion
#define list_for_each_entry_safe_continue_rev(pos, n, head, member) \
    for (pos = list_entry(pos->member.prev, typeof(*pos), member), \
        n = list_entry(pos->member.prev, typeof(*pos), member); \
         &pos->member != list_root(head); \
         pos = n, n = list_entry(n->member.prev, typeof(*n), member))