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