Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

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