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