1/* 2 Unix SMB/CIFS implementation. 3 some simple double linked list macros 4 Copyright (C) Andrew Tridgell 1998 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software 18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19*/ 20 21/* To use these macros you must have a structure containing a next and 22 prev pointer */ 23 24#ifndef _DLINKLIST_H 25#define _DLINKLIST_H 26 27 28/* hook into the front of the list */ 29#define DLIST_ADD(list, p) \ 30do { \ 31 if (!(list)) { \ 32 (list) = (p); \ 33 (p)->next = (p)->prev = NULL; \ 34 } else { \ 35 (list)->prev = (p); \ 36 (p)->next = (list); \ 37 (p)->prev = NULL; \ 38 (list) = (p); \ 39 }\ 40} while (0) 41 42/* remove an element from a list - element doesn't have to be in list. */ 43#define DLIST_REMOVE(list, p) \ 44do { \ 45 if ((p) == (list)) { \ 46 (list) = (p)->next; \ 47 if (list) (list)->prev = NULL; \ 48 } else { \ 49 if ((p)->prev) (p)->prev->next = (p)->next; \ 50 if ((p)->next) (p)->next->prev = (p)->prev; \ 51 } \ 52 if ((p) != (list)) (p)->next = (p)->prev = NULL; \ 53} while (0) 54 55/* promote an element to the top of the list */ 56#define DLIST_PROMOTE(list, p) \ 57do { \ 58 DLIST_REMOVE(list, p); \ 59 DLIST_ADD(list, p); \ 60} while (0) 61 62/* hook into the end of the list - needs the entry type */ 63#define DLIST_ADD_END(list, p, type) \ 64do { \ 65 if (!(list)) { \ 66 (list) = (p); \ 67 (p)->next = (p)->prev = NULL; \ 68 } else { \ 69 type tmp; \ 70 for (tmp = (list); tmp->next; tmp = tmp->next) ; \ 71 tmp->next = (p); \ 72 (p)->next = NULL; \ 73 (p)->prev = tmp; \ 74 } \ 75} while (0) 76 77/* insert 'p' after the given element 'el' in a list. If el is NULL then 78 this is the same as a DLIST_ADD() */ 79#define DLIST_ADD_AFTER(list, p, el) \ 80do { \ 81 if (!(list) || !(el)) { \ 82 DLIST_ADD(list, p); \ 83 } else { \ 84 p->prev = el; \ 85 p->next = el->next; \ 86 el->next = p; \ 87 if (p->next) p->next->prev = p; \ 88 }\ 89} while (0) 90 91/* demote an element to the end of the list, needs a tmp pointer */ 92#define DLIST_DEMOTE(list, p, tmp) \ 93do { \ 94 DLIST_REMOVE(list, p); \ 95 DLIST_ADD_END(list, p, tmp); \ 96} while (0) 97 98/* concatenate two lists - putting all elements of the 2nd list at the 99 end of the first list */ 100#define DLIST_CONCATENATE(list1, list2, type) \ 101do { \ 102 if (!(list1)) { \ 103 (list1) = (list2); \ 104 } else { \ 105 type tmp; \ 106 for (tmp = (list1); tmp->next; tmp = tmp->next) ; \ 107 tmp->next = (list2); \ 108 if (list2) { \ 109 (list2)->prev = tmp; \ 110 } \ 111 } \ 112} while (0) 113 114#endif /* _DLINKLIST_H */ 115