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