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 struct simple_node {
45    struct simple_node *next;
46    struct simple_node *prev;
47 };
48 
49 /**
50  * Remove an element from list.
51  *
52  * \param elem element to remove.
53  */
54 #define remove_from_list(elem)			\
55 do {						\
56    (elem)->next->prev = (elem)->prev;		\
57    (elem)->prev->next = (elem)->next;		\
58    make_empty_list(elem);			\
59 } while (0)
60 
61 /**
62  * Insert an element to the list head.
63  *
64  * \param list list.
65  * \param elem element to insert.
66  */
67 #define insert_at_head(list, elem)		\
68 do {						\
69    (elem)->prev = list;				\
70    (elem)->next = (list)->next;			\
71    (list)->next->prev = elem;			\
72    (list)->next = elem;				\
73 } while(0)
74 
75 /**
76  * Insert an element to the list tail.
77  *
78  * \param list list.
79  * \param elem element to insert.
80  */
81 #define insert_at_tail(list, elem)		\
82 do {						\
83    (elem)->next = list;				\
84    (elem)->prev = (list)->prev;			\
85    (list)->prev->next = elem;			\
86    (list)->prev = elem;				\
87 } while(0)
88 
89 /**
90  * Move an element to the list head.
91  *
92  * \param list list.
93  * \param elem element to move.
94  */
95 #define move_to_head(list, elem)		\
96 do {						\
97    remove_from_list(elem);			\
98    insert_at_head(list, elem);			\
99 } while (0)
100 
101 /**
102  * Move an element to the list tail.
103  *
104  * \param list list.
105  * \param elem element to move.
106  */
107 #define move_to_tail(list, elem)		\
108 do {						\
109    remove_from_list(elem);			\
110    insert_at_tail(list, elem);			\
111 } while (0)
112 
113 /**
114  * Make a empty list empty.
115  *
116  * \param sentinal list (sentinal element).
117  */
118 #define make_empty_list(sentinal)		\
119 do {						\
120    (sentinal)->next = sentinal;			\
121    (sentinal)->prev = sentinal;			\
122 } while (0)
123 
124 /**
125  * Get list first element.
126  *
127  * \param list list.
128  *
129  * \return pointer to first element.
130  */
131 #define first_elem(list)       ((list)->next)
132 
133 /**
134  * Get list last element.
135  *
136  * \param list list.
137  *
138  * \return pointer to last element.
139  */
140 #define last_elem(list)        ((list)->prev)
141 
142 /**
143  * Get next element.
144  *
145  * \param elem element.
146  *
147  * \return pointer to next element.
148  */
149 #define next_elem(elem)        ((elem)->next)
150 
151 /**
152  * Get previous element.
153  *
154  * \param elem element.
155  *
156  * \return pointer to previous element.
157  */
158 #define prev_elem(elem)        ((elem)->prev)
159 
160 /**
161  * Test whether element is at end of the list.
162  *
163  * \param list list.
164  * \param elem element.
165  *
166  * \return non-zero if element is at end of list, or zero otherwise.
167  */
168 #define at_end(list, elem)     ((elem) == (list))
169 
170 /**
171  * Test if a list is empty.
172  *
173  * \param list list.
174  *
175  * \return non-zero if list empty, or zero otherwise.
176  */
177 #define is_empty_list(list)    ((list)->next == (list))
178 
179 /**
180  * Walk through the elements of a list.
181  *
182  * \param ptr pointer to the current element.
183  * \param list list.
184  *
185  * \note It should be followed by a { } block or a single statement, as in a \c
186  * for loop.
187  */
188 #define foreach(ptr, list)     \
189         for( ptr=(list)->next ;  ptr!=list ;  ptr=(ptr)->next )
190 
191 /**
192  * Walk through the elements of a list.
193  *
194  * Same as #foreach but lets you unlink the current value during a list
195  * traversal.  Useful for freeing a list, element by element.
196  *
197  * \param ptr pointer to the current element.
198  * \param t temporary pointer.
199  * \param list list.
200  *
201  * \note It should be followed by a { } block or a single statement, as in a \c
202  * for loop.
203  */
204 #define foreach_s(ptr, t, list)   \
205         for(ptr=(list)->next,t=(ptr)->next; list != ptr; ptr=t, t=(t)->next)
206 
207 #ifdef __cplusplus
208 }
209 #endif
210 
211 #endif
212