1 /*
2 * Copyright © 2015 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 *
23 */
24
25 #ifndef IGT_LIST_H
26 #define IGT_LIST_H
27
28 #include <stdbool.h>
29 #include <stddef.h>
30
31 /*
32 * This list data structure is a verbatim copy from wayland-util.h from the
33 * Wayland project; except that wl_ prefix has been removed.
34 */
35
36 struct igt_list {
37 struct igt_list *prev;
38 struct igt_list *next;
39 };
40
41 #define __IGT_INIT_LIST(name) { &(name), &(name) }
42 #define IGT_LIST(name) struct igt_list name = __IGT_INIT_LIST(name)
43
igt_list_init(struct igt_list * list)44 static inline void igt_list_init(struct igt_list *list)
45 {
46 list->prev = list;
47 list->next = list;
48 }
49
__igt_list_add(struct igt_list * list,struct igt_list * prev,struct igt_list * next)50 static inline void __igt_list_add(struct igt_list *list,
51 struct igt_list *prev,
52 struct igt_list *next)
53 {
54 next->prev = list;
55 list->next = next;
56 list->prev = prev;
57 prev->next = list;
58 }
59
igt_list_add(struct igt_list * elm,struct igt_list * list)60 static inline void igt_list_add(struct igt_list *elm, struct igt_list *list)
61 {
62 __igt_list_add(elm, list, list->next);
63 }
64
igt_list_add_tail(struct igt_list * elm,struct igt_list * list)65 static inline void igt_list_add_tail(struct igt_list *elm,
66 struct igt_list *list)
67 {
68 __igt_list_add(elm, list->prev, list);
69 }
70
__igt_list_del(struct igt_list * prev,struct igt_list * next)71 static inline void __igt_list_del(struct igt_list *prev, struct igt_list *next)
72 {
73 next->prev = prev;
74 prev->next = next;
75 }
76
igt_list_del(struct igt_list * elm)77 static inline void igt_list_del(struct igt_list *elm)
78 {
79 __igt_list_del(elm->prev, elm->next);
80 }
81
igt_list_move(struct igt_list * elm,struct igt_list * list)82 static inline void igt_list_move(struct igt_list *elm, struct igt_list *list)
83 {
84 igt_list_del(elm);
85 igt_list_add(elm, list);
86 }
87
igt_list_move_tail(struct igt_list * elm,struct igt_list * list)88 static inline void igt_list_move_tail(struct igt_list *elm,
89 struct igt_list *list)
90 {
91 igt_list_del(elm);
92 igt_list_add_tail(elm, list);
93 }
94
igt_list_empty(const struct igt_list * list)95 static inline bool igt_list_empty(const struct igt_list *list)
96 {
97 return list->next == list;
98 }
99
100 #define container_of(ptr, sample, member) \
101 (typeof(sample))((char *)(ptr) - offsetof(typeof(*sample), member))
102
103 #define igt_list_first_entry(head, pos, member) \
104 container_of((head)->next, (pos), member)
105 #define igt_list_last_entry(head, pos, member) \
106 container_of((head)->prev, (pos), member)
107
108 #define igt_list_next_entry(pos, member) \
109 container_of((pos)->member.next, (pos), member)
110 #define igt_list_prev_entry(pos, member) \
111 container_of((pos)->member.prev, (pos), member)
112
113 #define igt_list_for_each(pos, head, member) \
114 for (pos = igt_list_first_entry(head, pos, member); \
115 &pos->member != (head); \
116 pos = igt_list_next_entry(pos, member))
117
118 #define igt_list_for_each_reverse(pos, head, member) \
119 for (pos = igt_list_last_entry(head, pos, member); \
120 &pos->member != (head); \
121 pos = igt_list_prev_entry(pos, member))
122
123 #define igt_list_for_each_safe(pos, tmp, head, member) \
124 for (pos = igt_list_first_entry(head, pos, member), \
125 tmp = igt_list_next_entry(pos, member); \
126 &pos->member != (head); \
127 pos = tmp, tmp = igt_list_next_entry(pos, member))
128
129 #endif /* IGT_LIST_H */
130