util: Cope with LONG_BIT not being defined on Windows.
[mesa.git] / src / util / list.h
index 191030c47bb4d958a4963bf73a4df546e001944b..b98ce59ff77d6c6344f6147fe13214b022c7a863 100644 (file)
@@ -38,7 +38,9 @@
 #define _UTIL_LIST_H_
 
 
+#include <stdbool.h>
 #include <stddef.h>
+#include <assert.h>
 
 
 struct list_head
@@ -92,6 +94,28 @@ static inline void list_delinit(struct list_head *item)
     item->prev = item;
 }
 
+static inline bool list_empty(struct list_head *list)
+{
+   return list->next == list;
+}
+
+static inline unsigned list_length(struct list_head *list)
+{
+   struct list_head *node;
+   unsigned length = 0;
+   for (node = list->next; node != list; node = node->next)
+      length++;
+   return length;
+}
+
+static inline void list_validate(struct list_head *list)
+{
+   struct list_head *node;
+   assert(list->next->prev == list && list->prev->next == list);
+   for (node = list->next; node != list; node = node->next)
+      assert(node->next->prev == node && node->prev->next == node);
+}
+
 #define LIST_INITHEAD(__item) list_inithead(__item)
 #define LIST_ADD(__item, __list) list_add(__item, __list)
 #define LIST_ADDTAIL(__item, __list) list_addtail(__item, __list)
@@ -116,6 +140,13 @@ static inline void list_delinit(struct list_head *item)
             - ((char *)&(sample)->member - (char *)(sample)))
 #endif
 
+#define list_first_entry(ptr, type, member) \
+        LIST_ENTRY(type, (ptr)->next, member)
+
+#define list_last_entry(ptr, type, member) \
+        LIST_ENTRY(type, (ptr)->prev, member)
+
+
 #define LIST_FOR_EACH_ENTRY(pos, head, member)                         \
    for (pos = NULL, pos = container_of((head)->next, pos, member);     \
        &pos->member != (head);                                         \
@@ -143,4 +174,38 @@ static inline void list_delinit(struct list_head *item)
        &pos->member != (head);                                         \
        pos = container_of(pos->member.prev, pos, member))
 
+#define list_for_each_entry(type, pos, head, member)                    \
+   for (type *pos = LIST_ENTRY(type, (head)->next, member);             \
+       &pos->member != (head);                                         \
+       pos = LIST_ENTRY(type, pos->member.next, member))
+
+#define list_for_each_entry_safe(type, pos, head, member)               \
+   for (type *pos = LIST_ENTRY(type, (head)->next, member),             \
+            *__next = LIST_ENTRY(type, pos->member.next, member);      \
+       &pos->member != (head);                                         \
+       pos = __next,                                                   \
+        __next = LIST_ENTRY(type, __next->member.next, member))
+
+#define list_for_each_entry_rev(type, pos, head, member)                \
+   for (type *pos = LIST_ENTRY(type, (head)->prev, member);             \
+       &pos->member != (head);                                         \
+       pos = LIST_ENTRY(type, pos->member.prev, member))
+
+#define list_for_each_entry_safe_rev(type, pos, head, member)           \
+   for (type *pos = LIST_ENTRY(type, (head)->prev, member),             \
+            *__prev = LIST_ENTRY(type, pos->member.prev, member);      \
+       &pos->member != (head);                                         \
+       pos = __prev,                                                   \
+        __prev = LIST_ENTRY(type, __prev->member.prev, member))
+
+#define list_for_each_entry_from(type, pos, start, head, member)        \
+   for (type *pos = LIST_ENTRY(type, (start), member);                  \
+       &pos->member != (head);                                         \
+       pos = LIST_ENTRY(type, pos->member.next, member))
+
+#define list_for_each_entry_from_rev(type, pos, start, head, member)    \
+   for (type *pos = LIST_ENTRY(type, (start), member);                  \
+       &pos->member != (head);                                         \
+       pos = LIST_ENTRY(type, pos->member.prev, member))
+
 #endif /*_UTIL_LIST_H_*/