1/*
2 * ntp_lists.h - singly-linked lists common code
3 *
4 * These macros implement a simple singly-linked list template.  Both
5 * the listhead and per-entry next fields are declared as pointers to
6 * the list entry struct type.  Initialization to NULL is typically
7 * implicit (for globals and statics) or handled by zeroing of the
8 * containing structure.
9 *
10 * The name of the next link field is passed as an argument to allow
11 * membership in several lists at once using multiple next link fields.
12 *
13 * When possible, placing the link field first in the entry structure
14 * allows slightly smaller code to be generated on some platforms.
15 *
16 * LINK_SLIST(listhead, pentry, nextlink)
17 *	add entry at head
18 *
19 * LINK_TAIL_SLIST(listhead, pentry, nextlink, entrytype)
20 *	add entry at tail
21 *
22 * UNLINK_HEAD_SLIST(punlinked, listhead, nextlink)
23 *	unlink first entry and point punlinked to it, or set punlinked
24 *	to NULL if the list is empty.
25 *
26 * UNLINK_SLIST(punlinked, listhead, ptounlink, nextlink, entrytype)
27 *	unlink entry pointed to by ptounlink.  punlinked is set to NULL
28 *	if the entry is not found on the list, otherwise it is set to
29 *	ptounlink.
30 *
31 * UNLINK_EXPR_SLIST(punlinked, listhead, expr, nextlink, entrytype)
32 *	unlink entry where expression expr is nonzero.  expr can refer
33 *	to the entry being tested using UNLINK_EXPR_SLIST_CURRENT().
34 *	See the	implementation of UNLINK_SLIST() below for an example.
35 *	punlinked is pointed to the removed entry or NULL if none
36 *	satisfy expr.
37 */
38#ifndef NTP_LISTS_H
39#define NTP_LISTS_H
40
41#ifdef HAVE_CONFIG_H
42# include <config.h>
43#endif
44
45#include <isc/list.h>
46
47
48#define LINK_SLIST(listhead, pentry, nextlink)			\
49do {								\
50	(pentry)->nextlink = (listhead);			\
51	(listhead) = (pentry);					\
52} while (0)
53
54#define LINK_TAIL_SLIST(listhead, pentry, nextlink, entrytype)	\
55do {								\
56	entrytype **pptail;					\
57								\
58	pptail = &(listhead);					\
59	while (*pptail != NULL)					\
60		pptail = &((*pptail)->nextlink);		\
61								\
62	(pentry)->nextlink = NULL;				\
63	*pptail = (pentry);					\
64} while (0)
65
66#define UNLINK_HEAD_SLIST(punlinked, listhead, nextlink)	\
67do {								\
68	(punlinked) = (listhead);				\
69	if (NULL != (punlinked)) {				\
70		(listhead) = (punlinked)->nextlink;		\
71		(punlinked)->nextlink = NULL;			\
72	}							\
73} while (0)
74
75#define UNLINK_EXPR_SLIST(punlinked, listhead, expr, nextlink,	\
76			  entrytype)				\
77do {								\
78	entrytype **ppentry;					\
79								\
80	ppentry = &(listhead);					\
81								\
82	while (!(expr))						\
83		if ((*ppentry)->nextlink != NULL)		\
84			ppentry = &((*ppentry)->nextlink);	\
85		else {						\
86			ppentry = NULL;				\
87			break;					\
88		}						\
89								\
90	if (ppentry != NULL) {					\
91		(punlinked) = *ppentry;				\
92		*ppentry = (punlinked)->nextlink;		\
93		(punlinked)->nextlink = NULL;			\
94	} else							\
95		(punlinked) = NULL;				\
96} while (0)
97#define UNLINK_EXPR_SLIST_CURRENT()	(*ppentry)
98
99#define UNLINK_SLIST(punlinked, listhead, ptounlink, nextlink,	\
100		     entrytype)					\
101	UNLINK_EXPR_SLIST(punlinked, listhead, (ptounlink) ==	\
102	    UNLINK_EXPR_SLIST_CURRENT(), nextlink, entrytype)
103
104#endif	/* NTP_LISTS_H */
105