ReactOS  0.4.12-dev-918-g6c6e7b8
list.h
Go to the documentation of this file.
1 /*
2  * Linked lists support
3  *
4  * Copyright (C) 2002 Alexandre Julliard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 #ifndef __WINE_SERVER_LIST_H
22 #define __WINE_SERVER_LIST_H
23 
24 #ifdef __cplusplus
25 #define __WINE_SERVER_LIST_INLINE inline
26 #else
27 #if defined(__GNUC__)
28 #define __WINE_SERVER_LIST_INLINE extern __inline__ __attribute__((__always_inline__,__gnu_inline__))
29 #elif defined(_MSC_VER)
30 #define __WINE_SERVER_LIST_INLINE __inline
31 #else
32 #define __WINE_SERVER_LIST_INLINE static
33 #endif
34 #endif
35 
36 struct list
37 {
38  struct list *next;
39  struct list *prev;
40 };
41 
42 /* Define a list like so:
43  *
44  * struct gadget
45  * {
46  * struct list entry; <-- doesn't have to be the first item in the struct
47  * int a, b;
48  * };
49  *
50  * static struct list global_gadgets = LIST_INIT( global_gadgets );
51  *
52  * or
53  *
54  * struct some_global_thing
55  * {
56  * struct list gadgets;
57  * };
58  *
59  * list_init( &some_global_thing->gadgets );
60  *
61  * Manipulate it like this:
62  *
63  * list_add_head( &global_gadgets, &new_gadget->entry );
64  * list_remove( &new_gadget->entry );
65  * list_add_after( &some_random_gadget->entry, &new_gadget->entry );
66  *
67  * And to iterate over it:
68  *
69  * struct gadget *gadget;
70  * LIST_FOR_EACH_ENTRY( gadget, &global_gadgets, struct gadget, entry )
71  * {
72  * ...
73  * }
74  *
75  */
76 
77 /* add an element after the specified one */
78 __WINE_SERVER_LIST_INLINE void list_add_after( struct list *elem, struct list *to_add )
79 {
80  to_add->next = elem->next;
81  to_add->prev = elem;
82  elem->next->prev = to_add;
83  elem->next = to_add;
84 }
85 
86 /* add an element before the specified one */
87 __WINE_SERVER_LIST_INLINE void list_add_before( struct list *elem, struct list *to_add )
88 {
89  to_add->next = elem;
90  to_add->prev = elem->prev;
91  elem->prev->next = to_add;
92  elem->prev = to_add;
93 }
94 
95 /* add element at the head of the list */
97 {
99 }
100 
101 /* add element at the tail of the list */
103 {
105 }
106 
107 /* remove an element from its list */
109 {
110  elem->next->prev = elem->prev;
111  elem->prev->next = elem->next;
112 }
113 
114 /* get the next element */
115 __WINE_SERVER_LIST_INLINE struct list *list_next( const struct list *list, const struct list *elem )
116 {
117  struct list *ret = elem->next;
118  if (elem->next == list) ret = NULL;
119  return ret;
120 }
121 
122 /* get the previous element */
123 __WINE_SERVER_LIST_INLINE struct list *list_prev( const struct list *list, const struct list *elem )
124 {
125  struct list *ret = elem->prev;
126  if (elem->prev == list) ret = NULL;
127  return ret;
128 }
129 
130 /* get the first element */
132 {
133  return list_next( list, list );
134 }
135 
136 /* get the last element */
138 {
139  return list_prev( list, list );
140 }
141 
142 /* check if a list is empty */
144 {
145  return list->next == list;
146 }
147 
148 /* initialize a list */
150 {
151  list->next = list->prev = list;
152 }
153 
154 /* count the elements of a list */
155 __WINE_SERVER_LIST_INLINE unsigned int list_count( const struct list *list )
156 {
157  unsigned count = 0;
158  const struct list *ptr;
159  for (ptr = list->next; ptr != list; ptr = ptr->next) count++;
160  return count;
161 }
162 
163 /* move all elements from src to the tail of dst */
165 {
166  if (list_empty(src)) return;
167 
168  dst->prev->next = src->next;
169  src->next->prev = dst->prev;
170  dst->prev = src->prev;
171  src->prev->next = dst;
172  list_init(src);
173 }
174 
175 /* move all elements from src to the head of dst */
177 {
178  if (list_empty(src)) return;
179 
180  dst->next->prev = src->prev;
181  src->prev->next = dst->next;
182  dst->next = src->next;
183  src->next->prev = dst;
184  list_init(src);
185 }
186 
187 /* iterate through the list */
188 #define LIST_FOR_EACH(cursor,list) \
189  for ((cursor) = (list)->next; (cursor) != (list); (cursor) = (cursor)->next)
190 
191 /* iterate through the list, with safety against removal */
192 #define LIST_FOR_EACH_SAFE(cursor, cursor2, list) \
193  for ((cursor) = (list)->next, (cursor2) = (cursor)->next; \
194  (cursor) != (list); \
195  (cursor) = (cursor2), (cursor2) = (cursor)->next)
196 
197 /* iterate through the list using a list entry */
198 #define LIST_FOR_EACH_ENTRY(elem, list, type, field) \
199  for ((elem) = LIST_ENTRY((list)->next, type, field); \
200  &(elem)->field != (list); \
201  (elem) = LIST_ENTRY((elem)->field.next, type, field))
202 
203 /* iterate through the list using a list entry, with safety against removal */
204 #define LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, list, type, field) \
205  for ((cursor) = LIST_ENTRY((list)->next, type, field), \
206  (cursor2) = LIST_ENTRY((cursor)->field.next, type, field); \
207  &(cursor)->field != (list); \
208  (cursor) = (cursor2), \
209  (cursor2) = LIST_ENTRY((cursor)->field.next, type, field))
210 
211 /* iterate through the list in reverse order */
212 #define LIST_FOR_EACH_REV(cursor,list) \
213  for ((cursor) = (list)->prev; (cursor) != (list); (cursor) = (cursor)->prev)
214 
215 /* iterate through the list in reverse order, with safety against removal */
216 #define LIST_FOR_EACH_SAFE_REV(cursor, cursor2, list) \
217  for ((cursor) = (list)->prev, (cursor2) = (cursor)->prev; \
218  (cursor) != (list); \
219  (cursor) = (cursor2), (cursor2) = (cursor)->prev)
220 
221 /* iterate through the list in reverse order using a list entry */
222 #define LIST_FOR_EACH_ENTRY_REV(elem, list, type, field) \
223  for ((elem) = LIST_ENTRY((list)->prev, type, field); \
224  &(elem)->field != (list); \
225  (elem) = LIST_ENTRY((elem)->field.prev, type, field))
226 
227 /* iterate through the list in reverse order using a list entry, with safety against removal */
228 #define LIST_FOR_EACH_ENTRY_SAFE_REV(cursor, cursor2, list, type, field) \
229  for ((cursor) = LIST_ENTRY((list)->prev, type, field), \
230  (cursor2) = LIST_ENTRY((cursor)->field.prev, type, field); \
231  &(cursor)->field != (list); \
232  (cursor) = (cursor2), \
233  (cursor2) = LIST_ENTRY((cursor)->field.prev, type, field))
234 
235 /* macros for statically initialized lists */
236 #define LIST_INIT(list) { &(list), &(list) }
237 
238 /* get pointer to object containing list element */
239 #ifdef _WIN64
240 #define LIST_ENTRY(elem, type, field) \
241  ((type *)((char *)(elem) - (unsigned long long)(&((type *)0)->field)))
242 #else
243 #define LIST_ENTRY(elem, type, field) \
244  ((type *)((char *)(elem) - (unsigned long)(&((type *)0)->field)))
245 #endif
246 
247 #endif /* __WINE_SERVER_LIST_H */
struct list * prev
Definition: list.h:39
__WINE_SERVER_LIST_INLINE struct list * list_prev(const struct list *list, const struct list *elem)
Definition: list.h:123
__WINE_SERVER_LIST_INLINE void list_add_after(struct list *elem, struct list *to_add)
Definition: list.h:78
GLuint GLuint GLsizei count
Definition: gl.h:1545
__WINE_SERVER_LIST_INLINE void list_add_head(struct list *list, struct list *elem)
Definition: list.h:96
__WINE_SERVER_LIST_INLINE struct list * list_tail(const struct list *list)
Definition: list.h:137
__WINE_SERVER_LIST_INLINE struct list * list_head(const struct list *list)
Definition: list.h:131
__WINE_SERVER_LIST_INLINE void list_add_tail(struct list *list, struct list *elem)
Definition: list.h:102
__WINE_SERVER_LIST_INLINE unsigned int list_count(const struct list *list)
Definition: list.h:155
static size_t elem
Definition: string.c:68
static PVOID ptr
Definition: dispmode.c:27
smooth NULL
Definition: ftsmooth.c:416
__WINE_SERVER_LIST_INLINE void list_remove(struct list *elem)
Definition: list.h:108
__WINE_SERVER_LIST_INLINE void list_move_head(struct list *dst, struct list *src)
Definition: list.h:176
__WINE_SERVER_LIST_INLINE void list_move_tail(struct list *dst, struct list *src)
Definition: list.h:164
struct list * next
Definition: list.h:38
int ret
Definition: _list.h:228
GLenum src
Definition: glext.h:6340
__WINE_SERVER_LIST_INLINE int list_empty(const struct list *list)
Definition: list.h:143
GLenum GLenum dst
Definition: glext.h:6340
#define list
Definition: rosglue.h:35
__WINE_SERVER_LIST_INLINE void list_add_before(struct list *elem, struct list *to_add)
Definition: list.h:87
__WINE_SERVER_LIST_INLINE struct list * list_next(const struct list *list, const struct list *elem)
Definition: list.h:115
__WINE_SERVER_LIST_INLINE void list_init(struct list *list)
Definition: list.h:149
#define __WINE_SERVER_LIST_INLINE
Definition: list.h:32