list.h revision 234010
1135446Strhodes/*
2234010Sdougb * Copyright (C) 2004, 2006, 2007, 2012  Internet Systems Consortium, Inc. ("ISC")
3135446Strhodes * Copyright (C) 1997-2002  Internet Software Consortium.
4135446Strhodes *
5193149Sdougb * Permission to use, copy, modify, and/or distribute this software for any
6135446Strhodes * purpose with or without fee is hereby granted, provided that the above
7135446Strhodes * copyright notice and this permission notice appear in all copies.
8135446Strhodes *
9135446Strhodes * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10135446Strhodes * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11135446Strhodes * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12135446Strhodes * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13135446Strhodes * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14135446Strhodes * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15135446Strhodes * PERFORMANCE OF THIS SOFTWARE.
16135446Strhodes */
17135446Strhodes
18234010Sdougb/* $Id$ */
19135446Strhodes
20135446Strhodes#ifndef ISC_LIST_H
21135446Strhodes#define ISC_LIST_H 1
22135446Strhodes#include <isc/boolean.h>
23135446Strhodes#include <isc/assertions.h>
24135446Strhodes
25135446Strhodes#ifdef ISC_LIST_CHECKINIT
26135446Strhodes#define ISC_LINK_INSIST(x) ISC_INSIST(x)
27135446Strhodes#else
28135446Strhodes#define ISC_LINK_INSIST(x)
29135446Strhodes#endif
30135446Strhodes
31135446Strhodes#define ISC_LIST(type) struct { type *head, *tail; }
32135446Strhodes#define ISC_LIST_INIT(list) \
33135446Strhodes	do { (list).head = NULL; (list).tail = NULL; } while (0)
34135446Strhodes
35135446Strhodes#define ISC_LINK(type) struct { type *prev, *next; }
36135446Strhodes#define ISC_LINK_INIT_TYPE(elt, link, type) \
37135446Strhodes	do { \
38135446Strhodes		(elt)->link.prev = (type *)(-1); \
39135446Strhodes		(elt)->link.next = (type *)(-1); \
40135446Strhodes	} while (0)
41135446Strhodes#define ISC_LINK_INIT(elt, link) \
42135446Strhodes	ISC_LINK_INIT_TYPE(elt, link, void)
43135446Strhodes#define ISC_LINK_LINKED(elt, link) ((void *)((elt)->link.prev) != (void *)(-1))
44135446Strhodes
45135446Strhodes#define ISC_LIST_HEAD(list) ((list).head)
46135446Strhodes#define ISC_LIST_TAIL(list) ((list).tail)
47135446Strhodes#define ISC_LIST_EMPTY(list) ISC_TF((list).head == NULL)
48135446Strhodes
49135446Strhodes#define __ISC_LIST_PREPENDUNSAFE(list, elt, link) \
50135446Strhodes	do { \
51135446Strhodes		if ((list).head != NULL) \
52135446Strhodes			(list).head->link.prev = (elt); \
53135446Strhodes		else \
54135446Strhodes			(list).tail = (elt); \
55135446Strhodes		(elt)->link.prev = NULL; \
56135446Strhodes		(elt)->link.next = (list).head; \
57135446Strhodes		(list).head = (elt); \
58135446Strhodes	} while (0)
59135446Strhodes
60135446Strhodes#define ISC_LIST_PREPEND(list, elt, link) \
61135446Strhodes	do { \
62135446Strhodes		ISC_LINK_INSIST(!ISC_LINK_LINKED(elt, link)); \
63135446Strhodes		__ISC_LIST_PREPENDUNSAFE(list, elt, link); \
64135446Strhodes	} while (0)
65135446Strhodes
66135446Strhodes#define ISC_LIST_INITANDPREPEND(list, elt, link) \
67135446Strhodes		__ISC_LIST_PREPENDUNSAFE(list, elt, link)
68135446Strhodes
69135446Strhodes#define __ISC_LIST_APPENDUNSAFE(list, elt, link) \
70135446Strhodes	do { \
71135446Strhodes		if ((list).tail != NULL) \
72135446Strhodes			(list).tail->link.next = (elt); \
73135446Strhodes		else \
74135446Strhodes			(list).head = (elt); \
75135446Strhodes		(elt)->link.prev = (list).tail; \
76135446Strhodes		(elt)->link.next = NULL; \
77135446Strhodes		(list).tail = (elt); \
78135446Strhodes	} while (0)
79135446Strhodes
80135446Strhodes#define ISC_LIST_APPEND(list, elt, link) \
81135446Strhodes	do { \
82135446Strhodes		ISC_LINK_INSIST(!ISC_LINK_LINKED(elt, link)); \
83135446Strhodes		__ISC_LIST_APPENDUNSAFE(list, elt, link); \
84135446Strhodes	} while (0)
85135446Strhodes
86135446Strhodes#define ISC_LIST_INITANDAPPEND(list, elt, link) \
87135446Strhodes		__ISC_LIST_APPENDUNSAFE(list, elt, link)
88135446Strhodes
89135446Strhodes#define __ISC_LIST_UNLINKUNSAFE_TYPE(list, elt, link, type) \
90135446Strhodes	do { \
91135446Strhodes		if ((elt)->link.next != NULL) \
92135446Strhodes			(elt)->link.next->link.prev = (elt)->link.prev; \
93165071Sdougb		else { \
94165071Sdougb			ISC_INSIST((list).tail == (elt)); \
95135446Strhodes			(list).tail = (elt)->link.prev; \
96165071Sdougb		} \
97135446Strhodes		if ((elt)->link.prev != NULL) \
98135446Strhodes			(elt)->link.prev->link.next = (elt)->link.next; \
99165071Sdougb		else { \
100165071Sdougb			ISC_INSIST((list).head == (elt)); \
101135446Strhodes			(list).head = (elt)->link.next; \
102165071Sdougb		} \
103135446Strhodes		(elt)->link.prev = (type *)(-1); \
104135446Strhodes		(elt)->link.next = (type *)(-1); \
105135446Strhodes	} while (0)
106135446Strhodes
107135446Strhodes#define __ISC_LIST_UNLINKUNSAFE(list, elt, link) \
108135446Strhodes	__ISC_LIST_UNLINKUNSAFE_TYPE(list, elt, link, void)
109135446Strhodes
110135446Strhodes#define ISC_LIST_UNLINK_TYPE(list, elt, link, type) \
111135446Strhodes	do { \
112135446Strhodes		ISC_LINK_INSIST(ISC_LINK_LINKED(elt, link)); \
113135446Strhodes		__ISC_LIST_UNLINKUNSAFE_TYPE(list, elt, link, type); \
114135446Strhodes	} while (0)
115135446Strhodes#define ISC_LIST_UNLINK(list, elt, link) \
116135446Strhodes	ISC_LIST_UNLINK_TYPE(list, elt, link, void)
117135446Strhodes
118135446Strhodes#define ISC_LIST_PREV(elt, link) ((elt)->link.prev)
119135446Strhodes#define ISC_LIST_NEXT(elt, link) ((elt)->link.next)
120135446Strhodes
121135446Strhodes#define __ISC_LIST_INSERTBEFOREUNSAFE(list, before, elt, link) \
122135446Strhodes	do { \
123135446Strhodes		if ((before)->link.prev == NULL) \
124135446Strhodes			ISC_LIST_PREPEND(list, elt, link); \
125135446Strhodes		else { \
126135446Strhodes			(elt)->link.prev = (before)->link.prev; \
127135446Strhodes			(before)->link.prev = (elt); \
128135446Strhodes			(elt)->link.prev->link.next = (elt); \
129135446Strhodes			(elt)->link.next = (before); \
130135446Strhodes		} \
131135446Strhodes	} while (0)
132135446Strhodes
133135446Strhodes#define ISC_LIST_INSERTBEFORE(list, before, elt, link) \
134135446Strhodes	do { \
135135446Strhodes		ISC_LINK_INSIST(ISC_LINK_LINKED(before, link)); \
136135446Strhodes		ISC_LINK_INSIST(!ISC_LINK_LINKED(elt, link)); \
137135446Strhodes		__ISC_LIST_INSERTBEFOREUNSAFE(list, before, elt, link); \
138135446Strhodes	} while (0)
139135446Strhodes
140135446Strhodes#define __ISC_LIST_INSERTAFTERUNSAFE(list, after, elt, link) \
141135446Strhodes	do { \
142135446Strhodes		if ((after)->link.next == NULL) \
143135446Strhodes			ISC_LIST_APPEND(list, elt, link); \
144135446Strhodes		else { \
145135446Strhodes			(elt)->link.next = (after)->link.next; \
146135446Strhodes			(after)->link.next = (elt); \
147135446Strhodes			(elt)->link.next->link.prev = (elt); \
148135446Strhodes			(elt)->link.prev = (after); \
149135446Strhodes		} \
150135446Strhodes	} while (0)
151135446Strhodes
152135446Strhodes#define ISC_LIST_INSERTAFTER(list, after, elt, link) \
153135446Strhodes	do { \
154135446Strhodes		ISC_LINK_INSIST(ISC_LINK_LINKED(after, link)); \
155135446Strhodes		ISC_LINK_INSIST(!ISC_LINK_LINKED(elt, link)); \
156135446Strhodes		__ISC_LIST_INSERTAFTERUNSAFE(list, after, elt, link); \
157135446Strhodes	} while (0)
158135446Strhodes
159135446Strhodes#define ISC_LIST_APPENDLIST(list1, list2, link) \
160135446Strhodes	do { \
161135446Strhodes		if (ISC_LIST_EMPTY(list1)) \
162135446Strhodes			(list1) = (list2); \
163135446Strhodes		else if (!ISC_LIST_EMPTY(list2)) { \
164135446Strhodes			(list1).tail->link.next = (list2).head; \
165135446Strhodes			(list2).head->link.prev = (list1).tail; \
166135446Strhodes			(list1).tail = (list2).tail; \
167135446Strhodes		} \
168135446Strhodes		(list2).head = NULL; \
169135446Strhodes		(list2).tail = NULL; \
170135446Strhodes	} while (0)
171135446Strhodes
172135446Strhodes#define ISC_LIST_ENQUEUE(list, elt, link) ISC_LIST_APPEND(list, elt, link)
173135446Strhodes#define __ISC_LIST_ENQUEUEUNSAFE(list, elt, link) \
174135446Strhodes	__ISC_LIST_APPENDUNSAFE(list, elt, link)
175135446Strhodes#define ISC_LIST_DEQUEUE(list, elt, link) \
176135446Strhodes	 ISC_LIST_UNLINK_TYPE(list, elt, link, void)
177135446Strhodes#define ISC_LIST_DEQUEUE_TYPE(list, elt, link, type) \
178135446Strhodes	 ISC_LIST_UNLINK_TYPE(list, elt, link, type)
179135446Strhodes#define __ISC_LIST_DEQUEUEUNSAFE(list, elt, link) \
180135446Strhodes	__ISC_LIST_UNLINKUNSAFE_TYPE(list, elt, link, void)
181135446Strhodes#define __ISC_LIST_DEQUEUEUNSAFE_TYPE(list, elt, link, type) \
182135446Strhodes	__ISC_LIST_UNLINKUNSAFE_TYPE(list, elt, link, type)
183135446Strhodes
184135446Strhodes#endif /* ISC_LIST_H */
185