Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2006 VMware, Inc., Bismarck, ND. USA.
  4.  * All Rights Reserved.
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a
  7.  * copy of this software and associated documentation files (the
  8.  * "Software"), to deal in the Software without restriction, including
  9.  * without limitation the rights to use, copy, modify, merge, publish,
  10.  * distribute, sub license, and/or sell copies of the Software, and to
  11.  * permit persons to whom the Software is furnished to do so, subject to
  12.  * the following conditions:
  13.  *
  14.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16.  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
  17.  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
  18.  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  19.  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  20.  * USE OR OTHER DEALINGS IN THE SOFTWARE.
  21.  *
  22.  * The above copyright notice and this permission notice (including the
  23.  * next paragraph) shall be included in all copies or substantial portions
  24.  * of the Software.
  25.  *
  26.  **************************************************************************/
  27.  
  28. /**
  29.  * \file
  30.  * List macros heavily inspired by the Linux kernel
  31.  * list handling. No list looping yet.
  32.  *
  33.  * Is not threadsafe, so common operations need to
  34.  * be protected using an external mutex.
  35.  */
  36.  
  37. #ifndef _UTIL_LIST_H_
  38. #define _UTIL_LIST_H_
  39.  
  40.  
  41. #include <stdbool.h>
  42. #include <stddef.h>
  43. #include <assert.h>
  44.  
  45.  
  46. struct list_head
  47. {
  48.     struct list_head *prev;
  49.     struct list_head *next;
  50. };
  51.  
  52. static inline void list_inithead(struct list_head *item)
  53. {
  54.     item->prev = item;
  55.     item->next = item;
  56. }
  57.  
  58. static inline void list_add(struct list_head *item, struct list_head *list)
  59. {
  60.     item->prev = list;
  61.     item->next = list->next;
  62.     list->next->prev = item;
  63.     list->next = item;
  64. }
  65.  
  66. static inline void list_addtail(struct list_head *item, struct list_head *list)
  67. {
  68.     item->next = list;
  69.     item->prev = list->prev;
  70.     list->prev->next = item;
  71.     list->prev = item;
  72. }
  73.  
  74. static inline void list_replace(struct list_head *from, struct list_head *to)
  75. {
  76.     to->prev = from->prev;
  77.     to->next = from->next;
  78.     from->next->prev = to;
  79.     from->prev->next = to;
  80. }
  81.  
  82. static inline void list_del(struct list_head *item)
  83. {
  84.     item->prev->next = item->next;
  85.     item->next->prev = item->prev;
  86.     item->prev = item->next = NULL;
  87. }
  88.  
  89. static inline void list_delinit(struct list_head *item)
  90. {
  91.     item->prev->next = item->next;
  92.     item->next->prev = item->prev;
  93.     item->next = item;
  94.     item->prev = item;
  95. }
  96.  
  97. static inline bool list_empty(struct list_head *list)
  98. {
  99.    return list->next == list;
  100. }
  101.  
  102. static inline unsigned list_length(struct list_head *list)
  103. {
  104.    struct list_head *node;
  105.    unsigned length = 0;
  106.    for (node = list->next; node != list; node = node->next)
  107.       length++;
  108.    return length;
  109. }
  110.  
  111. static inline void list_validate(struct list_head *list)
  112. {
  113.    struct list_head *node;
  114.    assert(list->next->prev == list && list->prev->next == list);
  115.    for (node = list->next; node != list; node = node->next)
  116.       assert(node->next->prev == node && node->prev->next == node);
  117. }
  118.  
  119. #define LIST_INITHEAD(__item) list_inithead(__item)
  120. #define LIST_ADD(__item, __list) list_add(__item, __list)
  121. #define LIST_ADDTAIL(__item, __list) list_addtail(__item, __list)
  122. #define LIST_REPLACE(__from, __to) list_replace(__from, __to)
  123. #define LIST_DEL(__item) list_del(__item)
  124. #define LIST_DELINIT(__item) list_delinit(__item)
  125.  
  126. #define LIST_ENTRY(__type, __item, __field)   \
  127.     ((__type *)(((char *)(__item)) - offsetof(__type, __field)))
  128.  
  129. #define LIST_IS_EMPTY(__list)                   \
  130.     ((__list)->next == (__list))
  131.  
  132. /**
  133.  * Cast from a pointer to a member of a struct back to the containing struct.
  134.  *
  135.  * 'sample' MUST be initialized, or else the result is undefined!
  136.  */
  137. #ifndef container_of
  138. #define container_of(ptr, sample, member)                               \
  139.     (void *)((char *)(ptr)                                              \
  140.              - ((char *)&(sample)->member - (char *)(sample)))
  141. #endif
  142.  
  143. #define LIST_FOR_EACH_ENTRY(pos, head, member)                          \
  144.    for (pos = NULL, pos = container_of((head)->next, pos, member);      \
  145.         &pos->member != (head);                                         \
  146.         pos = container_of(pos->member.next, pos, member))
  147.  
  148. #define LIST_FOR_EACH_ENTRY_SAFE(pos, storage, head, member)    \
  149.    for (pos = NULL, pos = container_of((head)->next, pos, member),      \
  150.         storage = container_of(pos->member.next, pos, member);  \
  151.         &pos->member != (head);                                         \
  152.         pos = storage, storage = container_of(storage->member.next, storage, member))
  153.  
  154. #define LIST_FOR_EACH_ENTRY_SAFE_REV(pos, storage, head, member)        \
  155.    for (pos = NULL, pos = container_of((head)->prev, pos, member),      \
  156.         storage = container_of(pos->member.prev, pos, member);          \
  157.         &pos->member != (head);                                         \
  158.         pos = storage, storage = container_of(storage->member.prev, storage, member))
  159.  
  160. #define LIST_FOR_EACH_ENTRY_FROM(pos, start, head, member)              \
  161.    for (pos = NULL, pos = container_of((start), pos, member);           \
  162.         &pos->member != (head);                                         \
  163.         pos = container_of(pos->member.next, pos, member))
  164.  
  165. #define LIST_FOR_EACH_ENTRY_FROM_REV(pos, start, head, member)          \
  166.    for (pos = NULL, pos = container_of((start), pos, member);           \
  167.         &pos->member != (head);                                         \
  168.         pos = container_of(pos->member.prev, pos, member))
  169.  
  170. #define list_for_each_entry(type, pos, head, member)                    \
  171.    for (type *pos = LIST_ENTRY(type, (head)->next, member);             \
  172.         &pos->member != (head);                                         \
  173.         pos = LIST_ENTRY(type, pos->member.next, member))
  174.  
  175. #define list_for_each_entry_safe(type, pos, head, member)               \
  176.    for (type *pos = LIST_ENTRY(type, (head)->next, member),             \
  177.              *__next = LIST_ENTRY(type, pos->member.next, member);      \
  178.         &pos->member != (head);                                         \
  179.         pos = __next,                                                   \
  180.         __next = LIST_ENTRY(type, __next->member.next, member))
  181.  
  182. #define list_for_each_entry_rev(type, pos, head, member)                \
  183.    for (type *pos = LIST_ENTRY(type, (head)->prev, member);             \
  184.         &pos->member != (head);                                         \
  185.         pos = LIST_ENTRY(type, pos->member.prev, member))
  186.  
  187. #define list_for_each_entry_safe_rev(type, pos, head, member)           \
  188.    for (type *pos = LIST_ENTRY(type, (head)->prev, member),             \
  189.              *__prev = LIST_ENTRY(type, pos->member.prev, member);      \
  190.         &pos->member != (head);                                         \
  191.         pos = __prev,                                                   \
  192.         __prev = LIST_ENTRY(type, __prev->member.prev, member))
  193.  
  194. #define list_for_each_entry_from(type, pos, start, head, member)        \
  195.    for (type *pos = LIST_ENTRY(type, (start), member);                  \
  196.         &pos->member != (head);                                         \
  197.         pos = LIST_ENTRY(type, pos->member.next, member))
  198.  
  199. #define list_for_each_entry_from_rev(type, pos, start, head, member)    \
  200.    for (type *pos = LIST_ENTRY(type, (start), member);                  \
  201.         &pos->member != (head);                                         \
  202.         pos = LIST_ENTRY(type, pos->member.prev, member))
  203.  
  204. #endif /*_UTIL_LIST_H_*/
  205.