/* list.h - libtf single and double linked list macros * * Copyright (C) 2009 Timo Teräs * All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 or later as * published by the Free Software Foundation. * * See http://www.gnu.org/ for details. * * This based to some degree to the code in the linux kernel. This is subset * of the functionality, and tf_list has separate head and node types. */ #ifndef TF_LIST_H #define TF_LIST_H #include struct tf_hlist_head { struct tf_hlist_node *first; }; struct tf_hlist_node { struct tf_hlist_node *next; struct tf_hlist_node **pprev; }; static inline int tf_hlist_empty(const struct tf_hlist_head *h) { return !h->first; } static inline int tf_hlist_hashed(const struct tf_hlist_node *n) { return n->pprev != NULL; } static inline void tf_hlist_del(struct tf_hlist_node *n) { *n->pprev = n->next; n->next = NULL; n->pprev = NULL; } static inline void tf_hlist_add_head(struct tf_hlist_node *n, struct tf_hlist_head *h) { struct tf_hlist_node *first = h->first; n->next = first; n->pprev = &h->first; h->first = n; } static inline void tf_hlist_add_after(struct tf_hlist_node *n, struct tf_hlist_node *prev) { n->next = prev->next; n->pprev = &prev->next; prev->next = n; } static inline struct tf_hlist_node **tf_hlist_tail_ptr(struct tf_hlist_head *h) { struct tf_hlist_node *n = h->first; if (n == NULL) return &h->first; while (n->next != NULL) n = n->next; return &n->next; } #define tf_hlist_entry(ptr, type, member) container_of(ptr,type,member) #define tf_hlist_for_each(pos, head) \ for (pos = (head)->first; pos; pos = pos->next) #define tf_hlist_for_each_safe(pos, n, head) \ for (pos = (head)->first; pos && ({ n = pos->next; 1; }); pos = n) #define tf_hlist_for_each_entry(tpos, pos, head, member) \ for (pos = (head)->first; pos && \ ({ tpos = tf_hlist_entry(pos, typeof(*tpos), member); 1;}); \ pos = pos->next) #define tf_hlist_for_each_entry_safe(tpos, pos, n, head, member) \ for (pos = (head)->first; \ pos && ({ n = pos->next; 1; }) && \ ({ tpos = tf_hlist_entry(pos, typeof(*tpos), member); 1;}); \ pos = n) struct tf_list_node { struct tf_list_node *next, *prev; }; struct tf_list_head { struct tf_list_node node; }; #define TF_LIST_INITIALIZER(l) { .next = &l, .prev = &l } #define TF_LIST_HEAD_INITIALIZER(l) { .node = TF_LIST_INITIALIZER((l).node) } static inline void tf_list_init(struct tf_list_node *list) { list->next = list; list->prev = list; } static inline void tf_list_init_head(struct tf_list_head *head) { tf_list_init(&head->node); } static inline void __tf_list_add(struct tf_list_node *new, struct tf_list_node *prev, struct tf_list_node *next) { next->prev = new; new->next = next; new->prev = prev; prev->next = new; } static inline void tf_list_add_after(struct tf_list_node *new, struct tf_list_node *head) { __tf_list_add(new, head, head->next); } static inline void tf_list_add_before(struct tf_list_node *new, struct tf_list_node *head) { __tf_list_add(new, head->prev, head); } static inline void tf_list_add_head(struct tf_list_node *new, struct tf_list_head *head) { tf_list_add_after(new, &head->node); } static inline void tf_list_add_tail(struct tf_list_node *new, struct tf_list_head *head) { tf_list_add_before(new, &head->node); } static inline void __tf_list_del(struct tf_list_node * prev, struct tf_list_node *next) { next->prev = prev; prev->next = next; } static inline void tf_list_del(struct tf_list_node *entry) { __tf_list_del(entry->prev, entry->next); entry->next = NULL; entry->prev = NULL; } static inline int tf_list_hashed(const struct tf_list_node *n) { return n->next != n && n->next != NULL; } static inline int tf_list_empty(const struct tf_list_head *h) { return !tf_list_hashed(&h->node); } #define tf_list_next(ptr, type, member) \ (tf_list_hashed(ptr) ? container_of((ptr)->next,type,member) : NULL) #define tf_list_first(head, type, member) \ tf_list_next(&((head)->node), type, member) #define tf_list_entry(ptr, type, member) container_of(ptr,type,member) #define tf_list_for_each(pos, head) \ for (pos = (head)->next; pos != (head); pos = pos->next) #define tf_list_for_each_safe(pos, n, head) \ for (pos = (head)->next, n = pos->next; pos != (head); \ pos = n, n = pos->next) #define tf_list_for_each_entry(pos, head, member) \ for (pos = tf_list_entry((head)->next, typeof(*pos), member); \ &pos->member != (head); \ pos = tf_list_entry(pos->member.next, typeof(*pos), member)) #define tf_list_for_each_entry_safe(pos, n, head, member) \ for (pos = tf_list_entry((head)->next, typeof(*pos), member), \ n = tf_list_entry(pos->member.next, typeof(*pos), member); \ &pos->member != (head); \ pos = n, n = tf_list_entry(n->member.next, typeof(*n), member)) #endif