1 /*- 2 * Copyright (c) 2001, 2003 Allan Saddi <allan@saddi.com> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY ALLAN SADDI AND HIS CONTRIBUTORS ``AS IS'' 15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL ALLAN SADDI OR HIS CONTRIBUTORS BE 18 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 * POSSIBILITY OF SUCH DAMAGE. 25 * 26 * $Id: dlist.h 308 2003-02-20 10:39:37Z asaddi $ 27 */ 28 29 #ifndef _APS_DLIST_H 30 #define _APS_DLIST_H 31 32 /* Structures */ 33 #define DLIST(name, type) struct name { struct type *head, *dummy, *tail; } 34 #define DLIST_NODE(name, type) struct name { struct type *next, *prev; } 35 36 /* Internal macros */ 37 #define DLIST_OFFSETOF(type, field) (char *) &((struct type *) 0)->field 38 #define DLIST_LIST_HEAD(listp, type, field) (struct type *) ((char *) &(listp)->head - DLIST_OFFSETOF(type, field)) 39 #define DLIST_LIST_TAIL(listp, type, field) (struct type *) ((char *) &(listp)->dummy - DLIST_OFFSETOF(type, field)) 40 41 /* Initialization */ 42 #define DLIST_INIT(listp, type, field) do { \ 43 (listp)->head = DLIST_LIST_TAIL(listp, type, field); \ 44 (listp)->dummy = 0; \ 45 (listp)->tail = DLIST_LIST_HEAD(listp, type, field); \ 46 } while (0) 47 48 /* Insertion macros */ 49 #define DLIST_INSERT_BEFORE(beforep, nodep, field) do { \ 50 void **temp; \ 51 (nodep)->field.next = beforep; \ 52 (nodep)->field.prev = (beforep)->field.prev; \ 53 temp = (void **) &(beforep)->field.prev; \ 54 (beforep)->field.prev->field.next = nodep; \ 55 *temp = nodep; \ 56 } while (0) 57 58 #define DLIST_INSERT_AFTER(afterp, nodep, field) do { \ 59 void **temp; \ 60 (nodep)->field.next = (afterp)->field.next; \ 61 (nodep)->field.prev = afterp; \ 62 temp = (void **) &(afterp)->field.next; \ 63 (afterp)->field.next->field.prev = nodep; \ 64 *temp = nodep; \ 65 } while (0) 66 67 #define DLIST_ADD_HEAD(listp, nodep, field) DLIST_INSERT_BEFORE((listp)->head, nodep, field) 68 69 #define DLIST_ADD_TAIL(listp, nodep, field) DLIST_INSERT_AFTER((listp)->tail, nodep, field) 70 71 /* Removal */ 72 #define DLIST_REMOVE(nodep, field) do { \ 73 (nodep)->field.prev->field.next = (nodep)->field.next; \ 74 (nodep)->field.next->field.prev = (nodep)->field.prev; \ 75 } while (0) 76 77 /* Testing/expressions */ 78 #define DLIST_EMPTY(listp, field) !((listp)->head->field.next) 79 80 #define DLIST_HEAD(listp, field) ((listp)->head->field.next ? (listp)->head : 0) 81 82 #define DLIST_TAIL(listp, field) ((listp)->tail->field.prev ? (listp)->tail : 0) 83 84 #define DLIST_NEXT(nodep, field) (nodep)->field.next 85 #define DLIST_PREV(nodep, field) (nodep)->field.prev 86 87 /* Iteration macros */ 88 #define DLIST_FOREACH(listp, nodep, field) \ 89 for ((nodep) = (listp)->head; \ 90 (nodep)->field.next; \ 91 (nodep) = (nodep)->field.next) 92 93 #define DLIST_FOREACH_REVERSE(listp, nodep, field) \ 94 for ((nodep) = (listp)->tail; \ 95 (nodep)->field.prev; \ 96 (nodep) = (nodep)->field.prev) 97 98 #endif /* !_APS_DLIST_H */ 99