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