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