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