/* Copyright (c) 2010, 2011 * The Regents of the University of Michigan * All Rights Reserved * * Olga Kornievskaia * Casey Bodley * * Permission is granted to use, copy and redistribute this software * for noncommercial education and research purposes, so long as no * fee is charged, and so long as the name of the University of Michigan * is not used in any advertising or publicity pertaining to the use * or distribution of this software without specific, written prior * authorization. Permission to modify or otherwise create derivative * works of this software is not granted. * * This software is provided as is, without representation or warranty * of any kind either express or implied, including without limitation * the implied warranties of merchantability, fitness for a particular * purpose, or noninfringement. The Regents of the University of * Michigan shall not be liable for any damages, including special, * indirect, incidental, or consequential damages, with respect to any * claim arising out of or in connection with the use of the software, * even if it has been or is hereafter advised of the possibility of * such damages. */ #ifndef NFS41_LIST_H #define NFS41_LIST_H /* doubly-linked list */ struct list_entry { struct list_entry *prev; struct list_entry *next; }; #define list_container(entry, type, field) \ ((type*)((const char*)(entry) - (const char*)(&((type*)0)->field))) #define list_for_each(entry, head) \ for (entry = (head)->next; entry != (head); entry = entry->next) #define list_for_each_tmp(entry, tmp, head) \ for (entry = (head)->next, tmp = entry->next; entry != (head); \ entry = tmp, tmp = entry->next) #define list_for_each_reverse(entry, head) \ for (entry = (head)->prev; entry != (head); entry = entry->prev) #define list_for_each_reverse_tmp(entry, tmp, head) \ for (entry = (head)->next, tmp = entry->next; entry != (head); \ entry = tmp, tmp = entry->next) static void list_init( struct list_entry *head) { head->prev = head; head->next = head; } static int list_empty( struct list_entry *head) { return head->next == head; } static void list_add( struct list_entry *entry, struct list_entry *prev, struct list_entry *next) { /* assert(prev->next == next && next->prev == prev); */ entry->prev = prev; entry->next = next; prev->next = entry; next->prev = entry; } static void list_add_head( struct list_entry *head, struct list_entry *entry) { list_add(entry, head, head->next); } static void list_add_tail( struct list_entry *head, struct list_entry *entry) { list_add(entry, head->prev, head); } static void list_remove( struct list_entry *entry) { if (!list_empty(entry)) { entry->next->prev = entry->prev; entry->prev->next = entry->next; list_init(entry); } } typedef int (*list_compare_fn)(const struct list_entry*, const void*); static struct list_entry* list_search( const struct list_entry *head, const void *value, list_compare_fn compare) { struct list_entry *entry; list_for_each(entry, head) if (compare(entry, value) == 0) return entry; return NULL; } #endif /* !NFS41_LIST_H */