aboutsummaryrefslogtreecommitdiff
path: root/src/list.h
blob: 2a9df611af1902752ede4fd279e5f5e69a9d834f (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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#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 *prev;
    struct list_head *next;
};

#define LIST_END NULL

#define LIST_EMPTY(list) do {    \
        (list)->next = LIST_END; \
        (list)->prev = LIST_END; \
    } while(0);

#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_head(struct list_head *l)
{
    return l->prev == LIST_END;
}   

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

static inline struct list_head *list_get_head(struct list_head *l)
{
    while(!list_is_head(l)) l = l->prev;
    return l;
}

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

static inline struct list_head *list_add(
    struct list_head *head,
    struct list_head *new)
{
    if(head) {
        new->next = head->next;
        head->next = new;
    }
    new->prev = head;
    return new;
}

static inline struct list_head *list_append(
    struct list_head *head,
    struct list_head *new)
{
    if(head) {
        head->next = new;
    }
    new->prev = head;
    return new;
}

#endif