4 * Copyright (C) 2002 Alexandre Julliard
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.
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.
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
21 #ifndef __WINE_SERVER_LIST_H
22 #define __WINE_SERVER_LIST_H
25 #define __WINE_SERVER_LIST_INLINE inline
27 #if defined(__GNUC__) && !defined(__clang__)
28 #define __WINE_SERVER_LIST_INLINE extern __inline__ __attribute__((__always_inline__))
29 #elif defined(_MSC_VER)
30 #define __WINE_SERVER_LIST_INLINE __inline
32 #define __WINE_SERVER_LIST_INLINE static
42 /* Define a list like so:
46 * struct list entry; <-- doesn't have to be the first item in the struct
50 * static struct list global_gadgets = LIST_INIT( global_gadgets );
54 * struct some_global_thing
56 * struct list gadgets;
59 * list_init( &some_global_thing->gadgets );
61 * Manipulate it like this:
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 );
67 * And to iterate over it:
69 * struct gadget *gadget;
70 * LIST_FOR_EACH_ENTRY( gadget, &global_gadgets, struct gadget, entry )
77 /* add an element after the specified one */
78 __WINE_SERVER_LIST_INLINE
void list_add_after( struct list
*elem
, struct list
*to_add
)
80 to_add
->next
= elem
->next
;
82 elem
->next
->prev
= to_add
;
86 /* add an element before the specified one */
87 __WINE_SERVER_LIST_INLINE
void list_add_before( struct list
*elem
, struct list
*to_add
)
90 to_add
->prev
= elem
->prev
;
91 elem
->prev
->next
= to_add
;
95 /* add element at the head of the list */
96 __WINE_SERVER_LIST_INLINE
void list_add_head( struct list
*list
, struct list
*elem
)
98 list_add_after( list
, elem
);
101 /* add element at the tail of the list */
102 __WINE_SERVER_LIST_INLINE
void list_add_tail( struct list
*list
, struct list
*elem
)
104 list_add_before( list
, elem
);
107 /* remove an element from its list */
108 __WINE_SERVER_LIST_INLINE
void list_remove( struct list
*elem
)
110 elem
->next
->prev
= elem
->prev
;
111 elem
->prev
->next
= elem
->next
;
114 /* get the next element */
115 __WINE_SERVER_LIST_INLINE
struct list
*list_next( const struct list
*list
, const struct list
*elem
)
117 struct list
*ret
= elem
->next
;
118 if (elem
->next
== list
) ret
= NULL
;
122 /* get the previous element */
123 __WINE_SERVER_LIST_INLINE
struct list
*list_prev( const struct list
*list
, const struct list
*elem
)
125 struct list
*ret
= elem
->prev
;
126 if (elem
->prev
== list
) ret
= NULL
;
130 /* get the first element */
131 __WINE_SERVER_LIST_INLINE
struct list
*list_head( const struct list
*list
)
133 return list_next( list
, list
);
136 /* get the last element */
137 __WINE_SERVER_LIST_INLINE
struct list
*list_tail( const struct list
*list
)
139 return list_prev( list
, list
);
142 /* check if a list is empty */
143 __WINE_SERVER_LIST_INLINE
int list_empty( const struct list
*list
)
145 return list
->next
== list
;
148 /* initialize a list */
149 __WINE_SERVER_LIST_INLINE
void list_init( struct list
*list
)
151 list
->next
= list
->prev
= list
;
154 /* count the elements of a list */
155 __WINE_SERVER_LIST_INLINE
unsigned int list_count( const struct list
*list
)
158 const struct list
*ptr
;
159 for (ptr
= list
->next
; ptr
!= list
; ptr
= ptr
->next
) count
++;
163 /* move all elements from src to the tail of dst */
164 __WINE_SERVER_LIST_INLINE
void list_move_tail( struct list
*dst
, struct list
*src
)
166 if (list_empty(src
)) return;
168 dst
->prev
->next
= src
->next
;
169 src
->next
->prev
= dst
->prev
;
170 dst
->prev
= src
->prev
;
171 src
->prev
->next
= dst
;
175 /* move all elements from src to the head of dst */
176 __WINE_SERVER_LIST_INLINE
void list_move_head( struct list
*dst
, struct list
*src
)
178 if (list_empty(src
)) return;
180 dst
->next
->prev
= src
->prev
;
181 src
->prev
->next
= dst
->next
;
182 dst
->next
= src
->next
;
183 src
->next
->prev
= dst
;
187 /* iterate through the list */
188 #define LIST_FOR_EACH(cursor,list) \
189 for ((cursor) = (list)->next; (cursor) != (list); (cursor) = (cursor)->next)
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)
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))
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))
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)
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)
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))
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))
235 /* macros for statically initialized lists */
236 #define LIST_INIT(list) { &(list), &(list) }
238 /* get pointer to object containing list element */
240 #define LIST_ENTRY(elem, type, field) \
241 ((type *)((char *)(elem) - (unsigned long long)(&((type *)0)->field)))
243 #define LIST_ENTRY(elem, type, field) \
244 ((type *)((char *)(elem) - (unsigned long)(&((type *)0)->field)))
247 #endif /* __WINE_SERVER_LIST_H */