-
Notifications
You must be signed in to change notification settings - Fork 33
/
Copy pathlist.h
112 lines (91 loc) · 3.36 KB
/
list.h
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
#ifndef LIST_H
#define LIST_H
#include <stddef.h>
/*
* Represents a single entry in the list. This must be embedded in your linked
* structure.
*/
struct list_head {
struct list_head *blink, /* back link */
*flink; /* front link */
};
/* The first element is a sentinel. Don't access it. */
#define INIT_LIST_HEAD(head) (head)->flink = (head)->blink = (head)
/* Adds a new element to the beginning of a list. Returns the head of the list
* so that calls may be chained. */
static inline struct list_head* list_add_head(struct list_head* restrict new_element,
struct list_head* restrict head)
{
new_element->flink = head->flink;
new_element->blink = head;
new_element->flink->blink = new_element;
new_element->blink->flink = new_element;
return head;
}
/* Adds a new element to the end of a list. Returns the head of the list so that
* calls may be chained. */
static inline struct list_head* list_add_tail(struct list_head* restrict new_element,
struct list_head* restrict head)
{
new_element->flink = head;
new_element->blink = head->blink;
new_element->flink->blink = new_element;
new_element->blink->flink = new_element;
return head;
}
/* Deletes an element from a list. NOTE: This does not free any memory. */
static inline void list_del(struct list_head* loc)
{
loc->flink->blink = loc->blink;
loc->blink->flink = loc->flink;
loc->flink = NULL;
loc->blink = NULL;
}
/* Tests if the list is empty */
#define list_empty(head) ((head)->flink == (head))
/* Gets a pointer to the overall structure from the list member */
#define list_entry(ptr, type, member) \
((type*)((char*)(ptr) - offsetof(type, member)))
/*
* Iterates over all the elements forward. If you modify the list (such as by
* deleting an element), you should use list_for_each_safe instead.
*/
#define list_for_each(pos, head) \
for((pos) = (head)->flink; \
(pos) != (head); \
(pos) = (pos)->flink)
/* The same as list_for_each, except it traverses the list backwards. */
#define list_for_each_reverse(pos, head) \
for((pos) = (head)->blink; \
(pos) != (head); \
(pos) = (pos)->blink)
/*
* Iterates over a list, where `pos' represents the current element, `n'
* represents temporary storage for the next element, and `head' is the start of
* the list.
*
* As opposed to list_for_each, it is safe to remove `pos' from the list.
*/
#define list_for_each_safe(pos, n, head) \
for((pos) = (head)->flink, (n) = (pos)->flink; \
(pos) != (head); \
(pos) = (n), (n) = (pos)->flink)
/* The same as list_for_each_safe, except it traverses the list backwards. */
#define list_for_each_reverse_safe(pos, p, head) \
for((pos) = (head)->blink, (p) = (pos)->blink; \
(pos) != (head); \
(pos) = (p), (p) = (pos)->blink)
/*
* Returns the length of a list. WARNING: Unlike every other function, this runs
* in O(n). Avoid using it as much as possible, as you will have to walk the
* whole list.
*/
static inline size_t list_length(const struct list_head* head)
{
const struct list_head* cursor;
size_t accum = 0;
list_for_each(cursor, head)
accum++;
return accum;
}
#endif