1 /**
2  * \file simple_list.h
3  * Simple macros for type-safe, intrusive lists.
4  *
5  *  Intended to work with a list sentinal which is created as an empty
6  *  list.  Insert & delete are O(1).
7  *
8  * \author
9  *  (C) 1997, Keith Whitwell
10  */
11 
12 /*
13  * Mesa 3-D graphics library
14  *
15  * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved.
16  *
17  * Permission is hereby granted, free of charge, to any person obtaining a
18  * copy of this software and associated documentation files (the "Software"),
19  * to deal in the Software without restriction, including without limitation
20  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
21  * and/or sell copies of the Software, and to permit persons to whom the
22  * Software is furnished to do so, subject to the following conditions:
23  *
24  * The above copyright notice and this permission notice shall be included
25  * in all copies or substantial portions of the Software.
26  *
27  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
28  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
30  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
31  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
32  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
33  * OTHER DEALINGS IN THE SOFTWARE.
34  */
35 
36 
37 #ifndef _SIMPLE_LIST_H
38 #define _SIMPLE_LIST_H
39 
40 #ifdef __cplusplus
41 extern "C" {
42 #endif
43 
44 /**
45  * Remove an element from list.
46  *
47  * \param elem element to remove.
48  */
49 #define remove_from_list(elem)			\
50 do {						\
51    (elem)->next->prev = (elem)->prev;		\
52    (elem)->prev->next = (elem)->next;		\
53 } while (0)
54 
55 /**
56  * Insert an element to the list head.
57  *
58  * \param list list.
59  * \param elem element to insert.
60  */
61 #define insert_at_head(list, elem)		\
62 do {						\
63    (elem)->prev = list;				\
64    (elem)->next = (list)->next;			\
65    (list)->next->prev = elem;			\
66    (list)->next = elem;				\
67 } while(0)
68 
69 /**
70  * Insert an element to the list tail.
71  *
72  * \param list list.
73  * \param elem element to insert.
74  */
75 #define insert_at_tail(list, elem)		\
76 do {						\
77    (elem)->next = list;				\
78    (elem)->prev = (list)->prev;			\
79    (list)->prev->next = elem;			\
80    (list)->prev = elem;				\
81 } while(0)
82 
83 /**
84  * Move an element to the list head.
85  *
86  * \param list list.
87  * \param elem element to move.
88  */
89 #define move_to_head(list, elem)		\
90 do {						\
91    remove_from_list(elem);			\
92    insert_at_head(list, elem);			\
93 } while (0)
94 
95 /**
96  * Move an element to the list tail.
97  *
98  * \param list list.
99  * \param elem element to move.
100  */
101 #define move_to_tail(list, elem)		\
102 do {						\
103    remove_from_list(elem);			\
104    insert_at_tail(list, elem);			\
105 } while (0)
106 
107 /**
108  * Make a empty list empty.
109  *
110  * \param sentinal list (sentinal element).
111  */
112 #define make_empty_list(sentinal)		\
113 do {						\
114    (sentinal)->next = sentinal;			\
115    (sentinal)->prev = sentinal;			\
116 } while (0)
117 
118 /**
119  * Get list first element.
120  *
121  * \param list list.
122  *
123  * \return pointer to first element.
124  */
125 #define first_elem(list)       ((list)->next)
126 
127 /**
128  * Get list last element.
129  *
130  * \param list list.
131  *
132  * \return pointer to last element.
133  */
134 #define last_elem(list)        ((list)->prev)
135 
136 /**
137  * Get next element.
138  *
139  * \param elem element.
140  *
141  * \return pointer to next element.
142  */
143 #define next_elem(elem)        ((elem)->next)
144 
145 /**
146  * Get previous element.
147  *
148  * \param elem element.
149  *
150  * \return pointer to previous element.
151  */
152 #define prev_elem(elem)        ((elem)->prev)
153 
154 /**
155  * Test whether element is at end of the list.
156  *
157  * \param list list.
158  * \param elem element.
159  *
160  * \return non-zero if element is at end of list, or zero otherwise.
161  */
162 #define at_end(list, elem)     ((elem) == (list))
163 
164 /**
165  * Test if a list is empty.
166  *
167  * \param list list.
168  *
169  * \return non-zero if list empty, or zero otherwise.
170  */
171 #define is_empty_list(list)    ((list)->next == (list))
172 
173 /**
174  * Walk through the elements of a list.
175  *
176  * \param ptr pointer to the current element.
177  * \param list list.
178  *
179  * \note It should be followed by a { } block or a single statement, as in a \c
180  * for loop.
181  */
182 #define foreach(ptr, list)     \
183         for( ptr=(list)->next ;  ptr!=list ;  ptr=(ptr)->next )
184 
185 /**
186  * Walk through the elements of a list.
187  *
188  * Same as #foreach but lets you unlink the current value during a list
189  * traversal.  Useful for freeing a list, element by element.
190  *
191  * \param ptr pointer to the current element.
192  * \param t temporary pointer.
193  * \param list list.
194  *
195  * \note It should be followed by a { } block or a single statement, as in a \c
196  * for loop.
197  */
198 #define foreach_s(ptr, t, list)   \
199         for(ptr=(list)->next,t=(ptr)->next; list != ptr; ptr=t, t=(t)->next)
200 
201 #ifdef __cplusplus
202 }
203 #endif
204 
205 #endif
206