X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=include%2Fwimlib%2Flist.h;h=d556a56c6a142ddfaf2a732db3e4a4cb2912913b;hp=d6bd55c11013b54dadb2d0e615882058ace32e64;hb=719a063c87e3abab99b0fb53ebc80223fbf33123;hpb=8e5d4209c12a7436488d9a3d1f8d59383c5c48f2 diff --git a/include/wimlib/list.h b/include/wimlib/list.h index d6bd55c1..d556a56c 100644 --- a/include/wimlib/list.h +++ b/include/wimlib/list.h @@ -3,42 +3,27 @@ * This file is based on include/linux/list.h in the Linux kernel source code. */ -#ifndef _LINUX_LIST_H -#define _LINUX_LIST_H +#ifndef _WIMLIB_LIST_H +#define _WIMLIB_LIST_H +#include #include -struct list_head { - struct list_head *next, *prev; -}; -struct hlist_head { - struct hlist_node *first; -}; +/* Simple doubly linked list implementation. */ -struct hlist_node { - struct hlist_node *next, **pprev; +struct list_head { + struct list_head *next; + struct list_head *prev; }; -/* - * Simple doubly linked list implementation. - * - * Some of the internal functions ("__xxx") are useful when - * manipulating whole lists rather than single entries, as - * sometimes we already know the next/prev entries and we can - * generate better code by using them directly rather than - * using the generic single-entry routines. - */ #define LIST_HEAD_INIT(name) { &(name), &(name) } -#ifdef LIST_HEAD /* BSD sys/queue.h defines this... */ -# undef LIST_HEAD -#endif +#undef LIST_HEAD /* BSD sys/queue.h defines this... */ +#define LIST_HEAD(name) struct list_head name = LIST_HEAD_INIT(name) -#define LIST_HEAD(name) \ - struct list_head name = LIST_HEAD_INIT(name) - -static inline void INIT_LIST_HEAD(struct list_head *list) +static inline void +INIT_LIST_HEAD(struct list_head *list) { list->next = list; list->prev = list; @@ -50,9 +35,8 @@ static inline void INIT_LIST_HEAD(struct list_head *list) * This is only for internal list manipulation where we know * the prev/next entries already! */ -static inline void __list_add(struct list_head *new, - struct list_head *prev, - struct list_head *next) +static inline void +__list_add(struct list_head *new, struct list_head *prev, struct list_head *next) { next->prev = new; new->next = next; @@ -68,7 +52,8 @@ static inline void __list_add(struct list_head *new, * Insert a new entry after the specified head. * This is good for implementing stacks. */ -static inline void list_add(struct list_head *new, struct list_head *head) +static inline void +list_add(struct list_head *new, struct list_head *head) { __list_add(new, head, head->next); } @@ -81,22 +66,26 @@ static inline void list_add(struct list_head *new, struct list_head *head) * Insert a new entry before the specified head. * This is useful for implementing queues. */ -static inline void list_add_tail(struct list_head *new, struct list_head *head) +static inline void +list_add_tail(struct list_head *new, struct list_head *head) { __list_add(new, head->prev, head); } -/* - * Delete a list entry by making the prev/next entries - * point to each other. +/** + * list_replace - replace old entry by new one + * @old : the element to be replaced + * @new : the new element to insert * - * This is only for internal list manipulation where we know - * the prev/next entries already! + * If @old was empty, it will be overwritten. */ -static inline void __list_del(struct list_head * prev, struct list_head * next) +static inline void +list_replace(struct list_head *old, struct list_head *new) { - next->prev = prev; - prev->next = next; + new->next = old->next; + new->next->prev = new; + new->prev = old->prev; + new->prev->next = new; } /** @@ -105,42 +94,29 @@ static inline void __list_del(struct list_head * prev, struct list_head * next) * Note: list_empty() on entry does not return true after this, the entry is * in an undefined state. */ -static inline void list_del(struct list_head *entry) +static inline void +list_del(struct list_head *entry) { - __list_del(entry->prev, entry->next); -} + struct list_head *prev = entry->prev; + struct list_head *next = 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); + prev->next = next; + next->prev = prev; } /** * list_empty - tests whether a list is empty * @head: the list to test. */ -static inline int list_empty(const struct list_head *head) +static inline bool +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) +static inline void +__list_splice(const struct list_head *list, + struct list_head *prev, struct list_head *next) { struct list_head *first = list->next; struct list_head *last = list->prev; @@ -157,37 +133,20 @@ static inline void __list_splice(const struct list_head *list, * @list: the new list to add. * @head: the place to add it in the first list. */ -static inline void list_splice(const struct list_head *list, - struct list_head *head) +static inline void +list_splice(const struct list_head *list, struct list_head *head) { if (!list_empty(list)) __list_splice(list, head, head->next); } -/* Move the entire list @old to the list @new, overwriting it. */ -static inline void list_transfer(struct list_head *old, - struct list_head *new) -{ - struct list_head *prev, *next; - - if (list_empty(old)) { - INIT_LIST_HEAD(new); - } else { - prev = old->prev; - next = old->next; - new->next = next; - new->prev = prev; - prev->next = new; - next->prev = new; - } -} - /** * list_move - delete from one list and add as another's head * @list: the entry to move * @head: the head that will precede our entry */ -static inline void list_move(struct list_head *list, struct list_head *head) +static inline void +list_move(struct list_head *list, struct list_head *head) { list_del(list); list_add(list, head); @@ -198,8 +157,8 @@ static inline void list_move(struct list_head *list, struct list_head *head) * @list: the entry to move * @head: the head that will follow our entry */ -static inline void list_move_tail(struct list_head *list, - struct list_head *head) +static inline void +list_move_tail(struct list_head *list, struct list_head *head) { list_del(list); list_add_tail(list, head); @@ -210,8 +169,8 @@ static inline void list_move_tail(struct list_head *list, * @list: the new list to add. * @head: the place to add it in the first list. */ -static inline void list_splice_tail(struct list_head *list, - struct list_head *head) +static inline void +list_splice_tail(struct list_head *list, struct list_head *head) { if (!list_empty(list)) __list_splice(list, head->prev, head); @@ -226,6 +185,45 @@ 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_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. @@ -235,25 +233,26 @@ static inline void list_splice_tail(struct list_head *list, for (pos = (head)->next; pos != (head); pos = pos->next) /** - * 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 + * 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_struct within the struct. */ -#define list_for_each_safe(pos, n, head) \ - for (pos = (head)->next, n = pos->next; pos != (head); \ - pos = n, n = pos->next) +#define list_for_each_entry(pos, head, member) \ + for (pos = list_first_entry(head, typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_next_entry(pos, member)) /** - * list_for_each_entry - iterate over list of given type + * 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(pos, head, member) \ - for (pos = list_entry((head)->next, typeof(*pos), member); \ - &pos->member != (head); \ - pos = list_entry(pos->member.next, typeof(*pos), member)) +#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 @@ -265,7 +264,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)) /* @@ -275,26 +274,35 @@ static inline void list_splice_tail(struct list_head *list, * You lose the ability to access the tail in O(1). */ -#define HLIST_HEAD_INIT { .first = NULL } -#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL } -#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL) -static inline void INIT_HLIST_NODE(struct hlist_node *h) +struct hlist_head { + struct hlist_node *first; +}; + +struct hlist_node { + struct hlist_node *next; + struct hlist_node **pprev; +}; + +static inline void +INIT_HLIST_HEAD(struct hlist_head *h) { - h->next = NULL; - h->pprev = NULL; + h->first = NULL; } -static inline int hlist_unhashed(const struct hlist_node *h) +static inline bool +hlist_unhashed(const struct hlist_node *h) { return !h->pprev; } -static inline int hlist_empty(const struct hlist_head *h) +static inline bool +hlist_empty(const struct hlist_head *h) { return !h->first; } -static inline void __hlist_del(struct hlist_node *n) +static inline void +hlist_del(struct hlist_node *n) { struct hlist_node *next = n->next; struct hlist_node **pprev = n->pprev; @@ -303,24 +311,8 @@ 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) +static inline void +hlist_add_head(struct hlist_node *n, struct hlist_head *h) { struct hlist_node *first = h->first; n->next = first; @@ -332,38 +324,32 @@ static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h) #define hlist_entry(ptr, type, member) container_of(ptr,type,member) -#define hlist_for_each(pos, head) \ - for (pos = (head)->first; pos ; pos = pos->next) - -#define hlist_for_each_safe(pos, n, head) \ - for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \ - pos = n) +#define hlist_entry_safe(ptr, type, member) \ + ({ typeof(ptr) ____ptr = (ptr); \ + ____ptr ? hlist_entry(____ptr, type, member) : NULL; \ + }) /** * hlist_for_each_entry - iterate over list of given type - * @tpos: the type * to use as a loop cursor. - * @pos: the &struct hlist_node to use as a loop cursor. + * @pos: the type * to use as a loop cursor. * @head: the head for your list. * @member: the name of the hlist_node within the struct. */ -#define hlist_for_each_entry(tpos, pos, head, member) \ - for (pos = (head)->first; \ - pos && \ - ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ - pos = pos->next) +#define hlist_for_each_entry(pos, head, member) \ + for (pos = hlist_entry_safe((head)->first, typeof(*(pos)), member);\ + pos; \ + pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member)) /** * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry - * @tpos: the type * to use as a loop cursor. - * @pos: the &struct hlist_node to use as a loop cursor. + * @pos: the type * to use as a loop cursor. * @n: another &struct hlist_node to use as temporary storage * @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) \ - for (pos = (head)->first; \ - pos && ({ n = pos->next; 1; }) && \ - ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ - pos = n) +#define hlist_for_each_entry_safe(pos, n, head, member) \ + for (pos = hlist_entry_safe((head)->first, typeof(*pos), member);\ + pos && ({ n = pos->member.next; 1; }); \ + pos = hlist_entry_safe(n, typeof(*pos), member)) -#endif +#endif /* _WIMLIB_LIST_H */