aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYaroslav de la Peña Smirnov <yps@yaroslavps.com>2024-04-15 22:41:17 +0300
committerYaroslav de la Peña Smirnov <yps@yaroslavps.com>2024-04-15 22:41:17 +0300
commit026588af6ac371bb06bef844d7fb021feb926eab (patch)
tree34a714db682c4e18f3c79bce4a0c1f5dd04708ac
parent03e8366b7e11e1b6c971f70d22fef07f7ad32448 (diff)
downloadc-wares-026588af6ac371bb06bef844d7fb021feb926eab.tar.gz
c-wares-026588af6ac371bb06bef844d7fb021feb926eab.zip
list: add some macros and functions from Linux
-rw-r--r--list/list.h164
1 files changed, 133 insertions, 31 deletions
diff --git a/list/list.h b/list/list.h
index e944a0a..7f5a407 100644
--- a/list/list.h
+++ b/list/list.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2002 Free Software Foundation, Inc.
- * (originally part of the GNU C Library and Userspace RCU; extracted from Git)
+ * (originally part of the GNU C Library and Userspace RCU)
* Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
*
* Copyright (C) 2009 Pierre-Marc Fournier
@@ -23,7 +23,7 @@
*/
#ifndef LIST_H
-#define LIST_H 1
+#define LIST_H
#include <stddef.h>
@@ -117,38 +117,21 @@ static inline void list_splice(struct list_head *add, struct list_head *head)
}
}
-/* Get typed element from list at a given position. */
-#define list_entry(ptr, type, member) \
- ((type *)((char *)(ptr)-offsetof(type, member)))
-
-/* Get first entry from a list. */
-#define list_first_entry(ptr, type, member) \
- list_entry((ptr)->next, type, member)
-
-/* Iterate forward over the elements of the list. */
-#define list_for_each(pos, head) \
- for (pos = (head)->next; pos != (head); pos = pos->next)
-
-/*
- * Iterate forward over the elements list. The list elements can be
- * removed from the list while doing this.
+/**
+ * list_is_head - tests whether @list is the list @head
+ * @list: the entry to test
+ * @head: the head of the list
*/
-#define list_for_each_safe(pos, p, head) \
- for (pos = (head)->next, p = pos->next; pos != (head); \
- pos = p, p = pos->next)
-
-/* Iterate backward over the elements of the list. */
-#define list_for_each_prev(pos, head) \
- for (pos = (head)->prev; pos != (head); pos = pos->prev)
+static inline int list_is_head(const struct list_head *list,
+ const struct list_head *head)
+{
+ return list == head;
+}
-/*
- * Iterate backwards over the elements list. The list elements can be
- * removed from the list while doing this.
+/**
+ * list_empty - tests whether a list is empty
+ * @head: the list to test.
*/
-#define list_for_each_prev_safe(pos, p, head) \
- for (pos = (head)->prev, p = pos->prev; pos != (head); \
- pos = p, p = pos->prev)
-
static inline int list_empty(struct list_head *head)
{
return head == head->next;
@@ -164,6 +147,125 @@ static inline void list_replace_init(struct list_head *old,
INIT_LIST_HEAD(old);
}
+/**
+ * list_entry - get the struct for this entry
+ * @ptr: the &struct list_head pointer.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the list_head within the struct.
+ */
+#define list_entry(ptr, type, member) \
+ ((type *)((char *)(ptr)-offsetof(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_head 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_head 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_next_entry - get the next element in list
+ * @pos: the type * to cursor
+ * @member: the name of the list_head within the struct.
+ */
+#define list_next_entry(pos, member) \
+ list_entry((pos)->member.next, typeof(*(pos)), member)
+
+/**
+ * __typed_list_for_each() - macro for making other typed for_each macros.
+ * @Te: list entry type.
+ * @e: entry.
+ * @emember: member of the entry structure that holds list_head.
+ * @l: list head to iterate over.
+ * @lmember: member of the list head structure that holds list_head.
+ */
+#define __typed_list_for_each(Te, e, emember, l, lmember) \
+ for (e = list_first_entry(&(l)->lmember, Te, emember); \
+ &e->emember != &(l)->lmember; \
+ e = list_entry(e->emember.next, Te, emember))
+
+/**
+ * list_for_each - iterate over a list
+ * @pos: the &struct list_head to use as a loop cursor.
+ * @head: the head for your list.
+ */
+#define list_for_each(pos, head) \
+ for (pos = (head)->next; !list_is_head(pos, (head)); pos = pos->next)
+
+/**
+ * list_for_each_prev - iterate over a list backwards
+ * @pos: the &struct list_head to use as a loop cursor.
+ * @head: the head for your list.
+ */
+#define list_for_each_prev(pos, head) \
+ for (pos = (head)->prev; !list_is_head(pos, (head)); pos = pos->prev)
+
+/**
+ * list_for_each_safe - iterate over a list safe against removal of list entry
+ * @pos: the &struct list_head to use as a loop cursor.
+ * @n: another &struct list_head to use as temporary storage
+ * @head: the head for your list.
+ */
+#define list_for_each_safe(pos, n, head) \
+ for (pos = (head)->next, n = pos->next; !list_is_head(pos, (head)); \
+ pos = n, n = pos->next)
+
+/**
+ * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry
+ * @pos: the &struct list_head to use as a loop cursor.
+ * @n: another &struct list_head to use as temporary storage
+ * @head: the head for your list.
+ */
+#define list_for_each_prev_safe(pos, n, head) \
+ for (pos = (head)->prev, n = pos->prev; !list_is_head(pos, (head)); \
+ pos = n, n = pos->prev)
+
+/**
+ * list_entry_is_head - test if the entry points to the head of the list
+ * @pos: the type * to cursor
+ * @head: the head for your list.
+ * @member: the name of the list_head within the struct.
+ */
+#define list_entry_is_head(pos, head, member) (&pos->member == (head))
+
+/**
+ * list_for_each_entry - iterate 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_head within the struct.
+ */
+#define list_for_each_entry(pos, head, member) \
+ for (pos = list_first_entry(head, typeof(*pos), member); \
+ !list_entry_is_head(pos, head, member); \
+ pos = list_next_entry(pos, member))
+
+/**
+ * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
+ * @pos: the type * to use as a loop cursor.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the list_head within the struct.
+ */
+#define list_for_each_entry_safe(pos, n, head, member) \
+ for (pos = list_first_entry(head, typeof(*pos), member), \
+ n = list_next_entry(pos, member); \
+ !list_entry_is_head(pos, head, member); \
+ pos = n, n = list_next_entry(n, member))
+
/*
* This is exactly the same as a normal list_head, except that it can be
* declared volatile (e.g., if you have a list that may be accessed from signal