diff options
author | Yaroslav de la Peña Smirnov <yps@yaroslavps.com> | 2024-04-15 22:41:17 +0300 |
---|---|---|
committer | Yaroslav de la Peña Smirnov <yps@yaroslavps.com> | 2024-04-15 22:41:17 +0300 |
commit | 026588af6ac371bb06bef844d7fb021feb926eab (patch) | |
tree | 34a714db682c4e18f3c79bce4a0c1f5dd04708ac | |
parent | 03e8366b7e11e1b6c971f70d22fef07f7ad32448 (diff) | |
download | c-wares-026588af6ac371bb06bef844d7fb021feb926eab.tar.gz c-wares-026588af6ac371bb06bef844d7fb021feb926eab.zip |
list: add some macros and functions from Linux
-rw-r--r-- | list/list.h | 164 |
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 |