aboutsummaryrefslogtreecommitdiffstats
path: root/klippy/chelper/list.h
blob: 12fe2b038e3510e18575916f4439011e6e7263e9 (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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#ifndef __LIST_H
#define __LIST_H

#define container_of(ptr, type, member) ({                      \
        const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
        (type *)( (char *)__mptr - offsetof(type,member) );})


/****************************************************************
 * list - Double linked lists
 ****************************************************************/

struct list_node {
    struct list_node *next, *prev;
};

struct list_head {
    struct list_node root;
};

static inline void
list_init(struct list_head *h)
{
    h->root.prev = h->root.next = &h->root;
}

static inline int
list_empty(const struct list_head *h)
{
    return h->root.next == &h->root;
}

static inline int
list_is_first(const struct list_node *n, const struct list_head *h)
{
    return n->prev == &h->root;
}

static inline int
list_is_last(const struct list_node *n, const struct list_head *h)
{
    return n->next == &h->root;
}

static inline void
list_del(struct list_node *n)
{
    struct list_node *prev = n->prev;
    struct list_node *next = n->next;
    next->prev = prev;
    prev->next = next;
}

static inline void
__list_add(struct list_node *n, struct list_node *prev, struct list_node *next)
{
    next->prev = n;
    n->next = next;
    n->prev = prev;
    prev->next = n;
}

static inline void
list_add_after(struct list_node *n, struct list_node *prev)
{
    __list_add(n, prev, prev->next);
}

static inline void
list_add_before(struct list_node *n, struct list_node *next)
{
    __list_add(n, next->prev, next);
}

static inline void
list_add_head(struct list_node *n, struct list_head *h)
{
    list_add_after(n, &h->root);
}

static inline void
list_add_tail(struct list_node *n, struct list_head *h)
{
    list_add_before(n, &h->root);
}

static inline void
list_join_tail(struct list_head *add, struct list_head *h)
{
    if (!list_empty(add)) {
        struct list_node *prev = h->root.prev;
        struct list_node *next = &h->root;
        struct list_node *first = add->root.next;
        struct list_node *last = add->root.prev;
        first->prev = prev;
        prev->next = first;
        last->next = next;
        next->prev = last;
    }
}

#define list_next_entry(pos, member)                            \
    container_of((pos)->member.next, typeof(*pos), member)

#define list_prev_entry(pos, member)                            \
    container_of((pos)->member.prev, typeof(*pos), member)

#define list_first_entry(head, type, member)                    \
    container_of((head)->root.next, type, member)

#define list_last_entry(head, type, member)                     \
    container_of((head)->root.prev, type, member)

#define list_for_each_entry(pos, head, member)                  \
    for (pos = list_first_entry((head), typeof(*pos), member)   \
         ; &pos->member != &(head)->root                        \
         ; pos = list_next_entry(pos, member))

#define list_for_each_entry_safe(pos, n, head, member)          \
    for (pos = list_first_entry((head), typeof(*pos), member)   \
          , n = list_next_entry(pos, member)                    \
         ; &pos->member != &(head)->root                        \
         ; pos = n, n = list_next_entry(n, member))


#endif // list.h