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