]> wimlib.net Git - wimlib/blobdiff - include/wimlib/list.h
extract.c: Store dentries to extract in list
[wimlib] / include / wimlib / list.h
index ff4074286fb3659600734f255019854d05a19851..6073c23b8088b317baa31cd7649a5860e25c7790 100644 (file)
@@ -86,6 +86,29 @@ static inline void list_add_tail(struct list_head *new, struct list_head *head)
        __list_add(new, head->prev, head);
 }
 
+/**
+ * list_replace - replace old entry by new one
+ * @old : the element to be replaced
+ * @new : the new element to insert
+ *
+ * If @old was empty, it will be overwritten.
+ */
+static inline void list_replace(struct list_head *old,
+                               struct list_head *new)
+{
+       new->next = old->next;
+       new->next->prev = new;
+       new->prev = old->prev;
+       new->prev->next = new;
+}
+
+static inline void list_replace_init(struct list_head *old,
+                                       struct list_head *new)
+{
+       list_replace(old, new);
+       INIT_LIST_HEAD(old);
+}
+
 /*
  * Delete a list entry by making the prev/next entries
  * point to each other.
@@ -110,6 +133,16 @@ static inline void list_del(struct list_head *entry)
        __list_del(entry->prev, entry->next);
 }
 
+/**
+ * list_del_init - deletes entry from list and reinitialize it.
+ * @entry: the element to delete from the list.
+ */
+static inline void list_del_init(struct list_head *entry)
+{
+       list_del(entry);
+       INIT_LIST_HEAD(entry);
+}
+
 /**
  * list_empty - tests whether a list is empty
  * @head: the list to test.
@@ -119,6 +152,15 @@ static inline int list_empty(const struct list_head *head)
        return head->next == head;
 }
 
+/**
+ * list_is_singular - tests whether a list has just one entry.
+ * @head: the list to test.
+ */
+static inline int list_is_singular(const struct list_head *head)
+{
+       return !list_empty(head) && (head->next == head->prev);
+}
+
 static inline void __list_splice(const struct list_head *list,
                                 struct list_head *prev,
                                 struct list_head *next)
@@ -207,6 +249,56 @@ static inline void list_splice_tail(struct list_head *list,
 #define list_entry(ptr, type, member) \
        container_of(ptr, type, member)
 
+/**
+ * list_first_entry - get the first element from a list
+ * @ptr:       the list head to take the element from.
+ * @type:      the type of the struct this is embedded in.
+ * @member:    the name of the list_struct within the struct.
+ *
+ * Note, that list is expected to be not empty.
+ */
+#define list_first_entry(ptr, type, member) \
+       list_entry((ptr)->next, type, member)
+
+/**
+ * list_last_entry - get the last element from a list
+ * @ptr:       the list head to take the element from.
+ * @type:      the type of the struct this is embedded in.
+ * @member:    the name of the list_struct within the struct.
+ *
+ * Note, that list is expected to be not empty.
+ */
+#define list_last_entry(ptr, type, member) \
+       list_entry((ptr)->prev, type, member)
+
+/**
+ * list_first_entry_or_null - get the first element from a list
+ * @ptr:       the list head to take the element from.
+ * @type:      the type of the struct this is embedded in.
+ * @member:    the name of the list_struct within the struct.
+ *
+ * Note that if the list is empty, it returns NULL.
+ */
+#define list_first_entry_or_null(ptr, type, member) \
+       (!list_empty(ptr) ? list_first_entry(ptr, type, member) : NULL)
+
+/**
+ * list_next_entry - get the next element in list
+ * @pos:       the type * to cursor
+ * @member:    the name of the list_struct within the struct.
+ */
+#define list_next_entry(pos, member) \
+       list_entry((pos)->member.next, typeof(*(pos)), member)
+
+/**
+ * list_prev_entry - get the prev element in list
+ * @pos:       the type * to cursor
+ * @member:    the name of the list_struct within the struct.
+ */
+#define list_prev_entry(pos, member) \
+       list_entry((pos)->member.prev, typeof(*(pos)), member)
+
+
 /**
  * list_for_each       -       iterate over a list
  * @pos:       the &struct list_head to use as a loop cursor.
@@ -232,9 +324,20 @@ static inline void list_splice_tail(struct list_head *list,
  * @member:    the name of the list_struct within the struct.
  */
 #define list_for_each_entry(pos, head, member)                         \
-       for (pos = list_entry((head)->next, typeof(*pos), member);      \
-            &pos->member != (head);    \
-            pos = list_entry(pos->member.next, typeof(*pos), member))
+       for (pos = list_first_entry(head, typeof(*pos), member);        \
+            &pos->member != (head);                                    \
+            pos = list_next_entry(pos, member))
+
+/**
+ * list_for_each_entry_reverse - iterate backwards over list of given type.
+ * @pos:       the type * to use as a loop cursor.
+ * @head:      the head for your list.
+ * @member:    the name of the list_struct within the struct.
+ */
+#define list_for_each_entry_reverse(pos, head, member)                 \
+       for (pos = list_last_entry(head, typeof(*pos), member);         \
+            &pos->member != (head);                                    \
+            pos = list_prev_entry(pos, member))
 
 /**
  * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
@@ -246,7 +349,7 @@ static inline void list_splice_tail(struct list_head *list,
 #define list_for_each_entry_safe(pos, n, head, member)                 \
        for (pos = list_entry((head)->next, typeof(*pos), member),      \
                n = list_entry(pos->member.next, typeof(*pos), member); \
-            &pos->member != (head);                                    \
+            &pos->member != (head);                                    \
             pos = n, n = list_entry(n->member.next, typeof(*n), member))
 
 /*
@@ -265,7 +368,17 @@ static inline void INIT_HLIST_NODE(struct hlist_node *h)
        h->pprev = NULL;
 }
 
-static inline void hlist_del(struct hlist_node *n)
+static inline int hlist_unhashed(const struct hlist_node *h)
+{
+       return !h->pprev;
+}
+
+static inline int hlist_empty(const struct hlist_head *h)
+{
+       return !h->first;
+}
+
+static inline void __hlist_del(struct hlist_node *n)
 {
        struct hlist_node *next = n->next;
        struct hlist_node **pprev = n->pprev;
@@ -274,6 +387,23 @@ static inline void hlist_del(struct hlist_node *n)
                next->pprev = pprev;
 }
 
+static inline void hlist_del(struct hlist_node *n)
+{
+       __hlist_del(n);
+#if 0
+       n->next = LIST_POISON1;
+       n->pprev = LIST_POISON2;
+#endif
+}
+
+static inline void hlist_del_init(struct hlist_node *n)
+{
+       if (!hlist_unhashed(n)) {
+               __hlist_del(n);
+               INIT_HLIST_NODE(n);
+       }
+}
+
 static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
 {
        struct hlist_node *first = h->first;
@@ -314,9 +444,9 @@ static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
  * @head:      the head for your list.
  * @member:    the name of the hlist_node within the struct.
  */
-#define hlist_for_each_entry_safe(tpos, pos, n, head, member)           \
+#define hlist_for_each_entry_safe(tpos, pos, n, head, member)           \
        for (pos = (head)->first;                                        \
-            pos && ({ n = pos->next; 1; }) &&                           \
+            pos && ({ n = pos->next; 1; }) &&                           \
                ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
             pos = n)