101e04c3fSmrg/**
201e04c3fSmrg * \file simple_list.h
301e04c3fSmrg * Simple macros for type-safe, intrusive lists.
401e04c3fSmrg *
501e04c3fSmrg *  Intended to work with a list sentinal which is created as an empty
601e04c3fSmrg *  list.  Insert & delete are O(1).
701e04c3fSmrg *
801e04c3fSmrg * \author
901e04c3fSmrg *  (C) 1997, Keith Whitwell
1001e04c3fSmrg */
1101e04c3fSmrg
1201e04c3fSmrg/*
1301e04c3fSmrg * Mesa 3-D graphics library
1401e04c3fSmrg *
1501e04c3fSmrg * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved.
1601e04c3fSmrg *
1701e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a
1801e04c3fSmrg * copy of this software and associated documentation files (the "Software"),
1901e04c3fSmrg * to deal in the Software without restriction, including without limitation
2001e04c3fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
2101e04c3fSmrg * and/or sell copies of the Software, and to permit persons to whom the
2201e04c3fSmrg * Software is furnished to do so, subject to the following conditions:
2301e04c3fSmrg *
2401e04c3fSmrg * The above copyright notice and this permission notice shall be included
2501e04c3fSmrg * in all copies or substantial portions of the Software.
2601e04c3fSmrg *
2701e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
2801e04c3fSmrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2901e04c3fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
3001e04c3fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
3101e04c3fSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
3201e04c3fSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
3301e04c3fSmrg * OTHER DEALINGS IN THE SOFTWARE.
3401e04c3fSmrg */
3501e04c3fSmrg
3601e04c3fSmrg
3701e04c3fSmrg#ifndef _SIMPLE_LIST_H
3801e04c3fSmrg#define _SIMPLE_LIST_H
3901e04c3fSmrg
4001e04c3fSmrg#ifdef __cplusplus
4101e04c3fSmrgextern "C" {
4201e04c3fSmrg#endif
4301e04c3fSmrg
4401e04c3fSmrgstruct simple_node {
4501e04c3fSmrg   struct simple_node *next;
4601e04c3fSmrg   struct simple_node *prev;
4701e04c3fSmrg};
4801e04c3fSmrg
4901e04c3fSmrg/**
5001e04c3fSmrg * Remove an element from list.
5101e04c3fSmrg *
5201e04c3fSmrg * \param elem element to remove.
5301e04c3fSmrg */
5401e04c3fSmrg#define remove_from_list(elem)			\
5501e04c3fSmrgdo {						\
5601e04c3fSmrg   (elem)->next->prev = (elem)->prev;		\
5701e04c3fSmrg   (elem)->prev->next = (elem)->next;		\
5801e04c3fSmrg   make_empty_list(elem);			\
5901e04c3fSmrg} while (0)
6001e04c3fSmrg
6101e04c3fSmrg/**
6201e04c3fSmrg * Insert an element to the list head.
6301e04c3fSmrg *
6401e04c3fSmrg * \param list list.
6501e04c3fSmrg * \param elem element to insert.
6601e04c3fSmrg */
6701e04c3fSmrg#define insert_at_head(list, elem)		\
6801e04c3fSmrgdo {						\
6901e04c3fSmrg   (elem)->prev = list;				\
7001e04c3fSmrg   (elem)->next = (list)->next;			\
7101e04c3fSmrg   (list)->next->prev = elem;			\
7201e04c3fSmrg   (list)->next = elem;				\
7301e04c3fSmrg} while(0)
7401e04c3fSmrg
7501e04c3fSmrg/**
7601e04c3fSmrg * Insert an element to the list tail.
7701e04c3fSmrg *
7801e04c3fSmrg * \param list list.
7901e04c3fSmrg * \param elem element to insert.
8001e04c3fSmrg */
8101e04c3fSmrg#define insert_at_tail(list, elem)		\
8201e04c3fSmrgdo {						\
8301e04c3fSmrg   (elem)->next = list;				\
8401e04c3fSmrg   (elem)->prev = (list)->prev;			\
8501e04c3fSmrg   (list)->prev->next = elem;			\
8601e04c3fSmrg   (list)->prev = elem;				\
8701e04c3fSmrg} while(0)
8801e04c3fSmrg
8901e04c3fSmrg/**
9001e04c3fSmrg * Move an element to the list head.
9101e04c3fSmrg *
9201e04c3fSmrg * \param list list.
9301e04c3fSmrg * \param elem element to move.
9401e04c3fSmrg */
9501e04c3fSmrg#define move_to_head(list, elem)		\
9601e04c3fSmrgdo {						\
9701e04c3fSmrg   remove_from_list(elem);			\
9801e04c3fSmrg   insert_at_head(list, elem);			\
9901e04c3fSmrg} while (0)
10001e04c3fSmrg
10101e04c3fSmrg/**
10201e04c3fSmrg * Move an element to the list tail.
10301e04c3fSmrg *
10401e04c3fSmrg * \param list list.
10501e04c3fSmrg * \param elem element to move.
10601e04c3fSmrg */
10701e04c3fSmrg#define move_to_tail(list, elem)		\
10801e04c3fSmrgdo {						\
10901e04c3fSmrg   remove_from_list(elem);			\
11001e04c3fSmrg   insert_at_tail(list, elem);			\
11101e04c3fSmrg} while (0)
11201e04c3fSmrg
11301e04c3fSmrg/**
11401e04c3fSmrg * Make a empty list empty.
11501e04c3fSmrg *
11601e04c3fSmrg * \param sentinal list (sentinal element).
11701e04c3fSmrg */
11801e04c3fSmrg#define make_empty_list(sentinal)		\
11901e04c3fSmrgdo {						\
12001e04c3fSmrg   (sentinal)->next = sentinal;			\
12101e04c3fSmrg   (sentinal)->prev = sentinal;			\
12201e04c3fSmrg} while (0)
12301e04c3fSmrg
12401e04c3fSmrg/**
12501e04c3fSmrg * Get list first element.
12601e04c3fSmrg *
12701e04c3fSmrg * \param list list.
12801e04c3fSmrg *
12901e04c3fSmrg * \return pointer to first element.
13001e04c3fSmrg */
13101e04c3fSmrg#define first_elem(list)       ((list)->next)
13201e04c3fSmrg
13301e04c3fSmrg/**
13401e04c3fSmrg * Get list last element.
13501e04c3fSmrg *
13601e04c3fSmrg * \param list list.
13701e04c3fSmrg *
13801e04c3fSmrg * \return pointer to last element.
13901e04c3fSmrg */
14001e04c3fSmrg#define last_elem(list)        ((list)->prev)
14101e04c3fSmrg
14201e04c3fSmrg/**
14301e04c3fSmrg * Get next element.
14401e04c3fSmrg *
14501e04c3fSmrg * \param elem element.
14601e04c3fSmrg *
14701e04c3fSmrg * \return pointer to next element.
14801e04c3fSmrg */
14901e04c3fSmrg#define next_elem(elem)        ((elem)->next)
15001e04c3fSmrg
15101e04c3fSmrg/**
15201e04c3fSmrg * Get previous element.
15301e04c3fSmrg *
15401e04c3fSmrg * \param elem element.
15501e04c3fSmrg *
15601e04c3fSmrg * \return pointer to previous element.
15701e04c3fSmrg */
15801e04c3fSmrg#define prev_elem(elem)        ((elem)->prev)
15901e04c3fSmrg
16001e04c3fSmrg/**
16101e04c3fSmrg * Test whether element is at end of the list.
16201e04c3fSmrg *
16301e04c3fSmrg * \param list list.
16401e04c3fSmrg * \param elem element.
16501e04c3fSmrg *
16601e04c3fSmrg * \return non-zero if element is at end of list, or zero otherwise.
16701e04c3fSmrg */
16801e04c3fSmrg#define at_end(list, elem)     ((elem) == (list))
16901e04c3fSmrg
17001e04c3fSmrg/**
17101e04c3fSmrg * Test if a list is empty.
17201e04c3fSmrg *
17301e04c3fSmrg * \param list list.
17401e04c3fSmrg *
17501e04c3fSmrg * \return non-zero if list empty, or zero otherwise.
17601e04c3fSmrg */
17701e04c3fSmrg#define is_empty_list(list)    ((list)->next == (list))
17801e04c3fSmrg
17901e04c3fSmrg/**
18001e04c3fSmrg * Walk through the elements of a list.
18101e04c3fSmrg *
18201e04c3fSmrg * \param ptr pointer to the current element.
18301e04c3fSmrg * \param list list.
18401e04c3fSmrg *
18501e04c3fSmrg * \note It should be followed by a { } block or a single statement, as in a \c
18601e04c3fSmrg * for loop.
18701e04c3fSmrg */
18801e04c3fSmrg#define foreach(ptr, list)     \
18901e04c3fSmrg        for( ptr=(list)->next ;  ptr!=list ;  ptr=(ptr)->next )
19001e04c3fSmrg
19101e04c3fSmrg/**
19201e04c3fSmrg * Walk through the elements of a list.
19301e04c3fSmrg *
19401e04c3fSmrg * Same as #foreach but lets you unlink the current value during a list
19501e04c3fSmrg * traversal.  Useful for freeing a list, element by element.
19601e04c3fSmrg *
19701e04c3fSmrg * \param ptr pointer to the current element.
19801e04c3fSmrg * \param t temporary pointer.
19901e04c3fSmrg * \param list list.
20001e04c3fSmrg *
20101e04c3fSmrg * \note It should be followed by a { } block or a single statement, as in a \c
20201e04c3fSmrg * for loop.
20301e04c3fSmrg */
20401e04c3fSmrg#define foreach_s(ptr, t, list)   \
20501e04c3fSmrg        for(ptr=(list)->next,t=(ptr)->next; list != ptr; ptr=t, t=(t)->next)
20601e04c3fSmrg
20701e04c3fSmrg#ifdef __cplusplus
20801e04c3fSmrg}
20901e04c3fSmrg#endif
21001e04c3fSmrg
21101e04c3fSmrg#endif
212