aboutsummaryrefslogtreecommitdiff
path: root/util/list.h
blob: 73eb9004d00b35ee6af0e4356b5a9eaba3149a4a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#ifndef LIST_H
#define LIST_H

// #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#define container_of(ptr, type, member) ((type *)((char *)(ptr) - offsetof(type, member)))

struct list_head {
    struct list_head *next;
};

#define LIST_END NULL

#define LIST_EMPTY(list) (list)->next = LIST_END
#define LIST_INIT_EMPTY() (struct list_head){.next = NULL}

#define list_entry(ptr, type, member) \
	container_of(ptr, type, member)

#define list_next_entry(entry, type, member) \
    list_entry(entry->member.next, type, member)

#define list_for_each(pos, start)                               \
	for(struct list_head *pos = start; pos; pos = pos->next)
#define list_for_each_entry(type, entry, member, start)         \
	for(type *entry = list_entry((start), type, member);        \
        entry;                                                  \
        entry = (entry->member.next == LIST_END ? NULL :        \
                 list_next_entry(entry, type, member)))

#define list_for_each_safe(pos, start)                          \
	for(struct list_head *pos = (start), *__next = LIST_END;    \
        pos && (__next = pos->next,1);                          \
        pos = __next)

static inline int list_is_tail(struct list_head *l)
{
    return l->next == LIST_END;
}

static inline struct list_head *list_get_tail(struct list_head *l)
{
    while(!list_is_tail(l)) l = l->next;
    return l;
}

static inline size_t list_len(struct list_head *head)
{
    size_t n = 0;
    list_for_each(pos, head) n++;
    return n;
}

#endif