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