1/*	$NetBSD: list.h,v 1.5 2009/04/12 17:07:16 christos Exp $	*/
2
3/*
4 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (c) 1997,1999 by Internet Software Consortium.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
17 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#ifndef LIST_H
21#define LIST_H 1
22#include <isc/assertions.h>
23
24#define LIST(type) struct { type *head, *tail; }
25#define INIT_LIST(list) \
26	do { (list).head = NULL; (list).tail = NULL; } while (/*CONSTCOND*/0)
27
28#define LINK(type) struct { type *prev, *next; }
29#define INIT_LINK_TYPE(elt, link, type) \
30	do { \
31		(elt)->link.prev = (type *)(-1); \
32		(elt)->link.next = (type *)(-1); \
33	} while (/*CONSTCOND*/0)
34#define INIT_LINK(elt, link) \
35	INIT_LINK_TYPE(elt, link, void)
36#define LINKED(elt, link) ((void *)((elt)->link.prev) != (void *)(-1) && \
37			   (void *)((elt)->link.next) != (void *)(-1))
38
39#define HEAD(list) ((list).head)
40#define TAIL(list) ((list).tail)
41#define EMPTY(list) ((list).head == NULL)
42
43#define PREPEND(list, elt, link) \
44	do { \
45		INSIST(!LINKED(elt, link));\
46		if ((list).head != NULL) \
47			(list).head->link.prev = (elt); \
48		else \
49			(list).tail = (elt); \
50		(elt)->link.prev = NULL; \
51		(elt)->link.next = (list).head; \
52		(list).head = (elt); \
53	} while (/*CONSTCOND*/0)
54
55#define APPEND(list, elt, link) \
56	do { \
57		INSIST(!LINKED(elt, link));\
58		if ((list).tail != NULL) \
59			(list).tail->link.next = (elt); \
60		else \
61			(list).head = (elt); \
62		(elt)->link.prev = (list).tail; \
63		(elt)->link.next = NULL; \
64		(list).tail = (elt); \
65	} while (/*CONSTCOND*/0)
66
67#define UNLINK_TYPE(list, elt, link, type) \
68	do { \
69		INSIST(LINKED(elt, link));\
70		if ((elt)->link.next != NULL) \
71			(elt)->link.next->link.prev = (elt)->link.prev; \
72		else { \
73			INSIST((list).tail == (elt)); \
74			(list).tail = (elt)->link.prev; \
75		} \
76		if ((elt)->link.prev != NULL) \
77			(elt)->link.prev->link.next = (elt)->link.next; \
78		else { \
79			INSIST((list).head == (elt)); \
80			(list).head = (elt)->link.next; \
81		} \
82		INIT_LINK_TYPE(elt, link, type); \
83	} while (/*CONSTCOND*/0)
84#define UNLINK(list, elt, link) \
85	UNLINK_TYPE(list, elt, link, void)
86
87#define PREV(elt, link) ((elt)->link.prev)
88#define NEXT(elt, link) ((elt)->link.next)
89
90#define INSERT_BEFORE(list, before, elt, link) \
91	do { \
92		INSIST(!LINKED(elt, link));\
93		if ((before)->link.prev == NULL) \
94			PREPEND(list, elt, link); \
95		else { \
96			(elt)->link.prev = (before)->link.prev; \
97			(before)->link.prev = (elt); \
98			(elt)->link.prev->link.next = (elt); \
99			(elt)->link.next = (before); \
100		} \
101	} while (/*CONSTCOND*/0)
102
103#define INSERT_AFTER(list, after, elt, link) \
104	do { \
105		INSIST(!LINKED(elt, link));\
106		if ((after)->link.next == NULL) \
107			APPEND(list, elt, link); \
108		else { \
109			(elt)->link.next = (after)->link.next; \
110			(after)->link.next = (elt); \
111			(elt)->link.next->link.prev = (elt); \
112			(elt)->link.prev = (after); \
113		} \
114	} while (/*CONSTCOND*/0)
115
116#define ENQUEUE(list, elt, link) APPEND(list, elt, link)
117#define DEQUEUE(list, elt, link) UNLINK(list, elt, link)
118
119#endif /* LIST_H */
120/*! \file */
121