xref: /netbsd-src/external/bsd/openldap/dist/include/ldap_queue.h (revision 549b59ed3ccf0d36d3097190a0db27b770f3a839)
1*549b59edSchristos /*	$NetBSD: ldap_queue.h,v 1.8 2021/08/14 16:14:55 christos Exp $	*/
24e6df137Slukem 
32de962bdSlukem /* ldap_queue.h -- queue macros */
4cb54be06Stron /* $OpenLDAP$ */
52de962bdSlukem /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
62de962bdSlukem  *
7*549b59edSchristos  * Copyright 2001-2021 The OpenLDAP Foundation.
82de962bdSlukem  * All rights reserved.
92de962bdSlukem  *
102de962bdSlukem  * Redistribution and use in source and binary forms, with or without
112de962bdSlukem  * modification, are permitted only as authorized by the OpenLDAP
122de962bdSlukem  * Public License.
132de962bdSlukem  *
142de962bdSlukem  * A copy of this license is available in file LICENSE in the
152de962bdSlukem  * top-level directory of the distribution or, alternatively, at
162de962bdSlukem  * <http://www.OpenLDAP.org/license.html>.
172de962bdSlukem  */
182de962bdSlukem /* Copyright (c) 1991, 1993
192de962bdSlukem  *	The Regents of the University of California.  All rights reserved.
202de962bdSlukem  *
212de962bdSlukem  * Redistribution and use in source and binary forms, with or without
222de962bdSlukem  * modification, are permitted provided that the following conditions
232de962bdSlukem  * are met:
242de962bdSlukem  * 1. Redistributions of source code must retain the above copyright
252de962bdSlukem  *    notice, this list of conditions and the following disclaimer.
262de962bdSlukem  * 2. Redistributions in binary form must reproduce the above copyright
272de962bdSlukem  *    notice, this list of conditions and the following disclaimer in the
282de962bdSlukem  *    documentation and/or other materials provided with the distribution.
292de962bdSlukem  * 3. All advertising materials mentioning features or use of this software
302de962bdSlukem  *    must display the following acknowledgement:
312de962bdSlukem  *	This product includes software developed by the University of
322de962bdSlukem  *	California, Berkeley and its contributors.
332de962bdSlukem  * 4. Neither the name of the University nor the names of its contributors
342de962bdSlukem  *    may be used to endorse or promote products derived from this software
352de962bdSlukem  *    without specific prior written permission.
362de962bdSlukem  *
372de962bdSlukem  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
382de962bdSlukem  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
392de962bdSlukem  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
402de962bdSlukem  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
412de962bdSlukem  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
422de962bdSlukem  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
432de962bdSlukem  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
442de962bdSlukem  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
452de962bdSlukem  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
462de962bdSlukem  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
472de962bdSlukem  * SUCH DAMAGE.
482de962bdSlukem  *
492de962bdSlukem  *	@(#)queue.h	8.5 (Berkeley) 8/20/94
50cb54be06Stron  * $FreeBSD: src/sys/sys/queue.h,v 1.32.2.5 2001/09/30 21:12:54 luigi Exp $
512de962bdSlukem  *
522de962bdSlukem  * See also: ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change
532de962bdSlukem  */
542de962bdSlukem /* ACKNOWLEDGEMENTS:
552de962bdSlukem  * This work is derived from FreeBSD queue.h work.  Adapted for use in
562de962bdSlukem  * OpenLDAP Software by Kurt D. Zeilenga.
572de962bdSlukem  */
582de962bdSlukem 
592de962bdSlukem #ifndef _LDAP_QUEUE_H_
602de962bdSlukem #define	_LDAP_QUEUE_H_
612de962bdSlukem 
622de962bdSlukem /*
632de962bdSlukem  * This file defines five types of data structures: singly-linked lists,
642de962bdSlukem  * singly-linked tail queues, lists, tail queues, and circular queues.
652de962bdSlukem  *
662de962bdSlukem  * A singly-linked list is headed by a single forward pointer. The elements
672de962bdSlukem  * are singly linked for minimum space and pointer manipulation overhead at
682de962bdSlukem  * the expense of O(n) removal for arbitrary elements. New elements can be
692de962bdSlukem  * added to the list after an existing element or at the head of the list.
702de962bdSlukem  * Elements being removed from the head of the list should use the explicit
712de962bdSlukem  * macro for this purpose for optimum efficiency. A singly-linked list may
722de962bdSlukem  * only be traversed in the forward direction.  Singly-linked lists are ideal
732de962bdSlukem  * for applications with large datasets and few or no removals or for
742de962bdSlukem  * implementing a LIFO queue.
752de962bdSlukem  *
762de962bdSlukem  * A singly-linked tail queue is headed by a pair of pointers, one to the
772de962bdSlukem  * head of the list and the other to the tail of the list. The elements are
782de962bdSlukem  * singly linked for minimum space and pointer manipulation overhead at the
792de962bdSlukem  * expense of O(n) removal for arbitrary elements. New elements can be added
802de962bdSlukem  * to the list after an existing element, at the head of the list, or at the
812de962bdSlukem  * end of the list. Elements being removed from the head of the tail queue
822de962bdSlukem  * should use the explicit macro for this purpose for optimum efficiency.
832de962bdSlukem  * A singly-linked tail queue may only be traversed in the forward direction.
842de962bdSlukem  * Singly-linked tail queues are ideal for applications with large datasets
852de962bdSlukem  * and few or no removals or for implementing a FIFO queue.
862de962bdSlukem  *
872de962bdSlukem  * A list is headed by a single forward pointer (or an array of forward
882de962bdSlukem  * pointers for a hash table header). The elements are doubly linked
892de962bdSlukem  * so that an arbitrary element can be removed without a need to
902de962bdSlukem  * traverse the list. New elements can be added to the list before
912de962bdSlukem  * or after an existing element or at the head of the list. A list
922de962bdSlukem  * may only be traversed in the forward direction.
932de962bdSlukem  *
942de962bdSlukem  * A tail queue is headed by a pair of pointers, one to the head of the
952de962bdSlukem  * list and the other to the tail of the list. The elements are doubly
962de962bdSlukem  * linked so that an arbitrary element can be removed without a need to
972de962bdSlukem  * traverse the list. New elements can be added to the list before or
982de962bdSlukem  * after an existing element, at the head of the list, or at the end of
992de962bdSlukem  * the list. A tail queue may be traversed in either direction.
1002de962bdSlukem  *
1012de962bdSlukem  * A circle queue is headed by a pair of pointers, one to the head of the
1022de962bdSlukem  * list and the other to the tail of the list. The elements are doubly
1032de962bdSlukem  * linked so that an arbitrary element can be removed without a need to
1042de962bdSlukem  * traverse the list. New elements can be added to the list before or after
1052de962bdSlukem  * an existing element, at the head of the list, or at the end of the list.
1062de962bdSlukem  * A circle queue may be traversed in either direction, but has a more
107*549b59edSchristos  * complex end of list detection. Also, it is possible to rotate the queue,
108*549b59edSchristos  * rejoining the ends and splitting it so that a given element becomes the
109*549b59edSchristos  * new head or tail.
1102de962bdSlukem  *
1112de962bdSlukem  * For details on the use of these macros, see the queue(3) manual page.
1122de962bdSlukem  * All macros are prefixed with LDAP_.
1132de962bdSlukem  *
1145bdc0023Schristos  *			SLIST_	LIST_	STAILQ_	TAILQ_
1155bdc0023Schristos  * _HEAD		+	+	+	+
1165bdc0023Schristos  * _ENTRY		+	+	+	+
1175bdc0023Schristos  * _INIT		+	+	+	+
1185bdc0023Schristos  * _ENTRY_INIT		+	+	+	+
1195bdc0023Schristos  * _EMPTY		+	+	+	+
1205bdc0023Schristos  * _FIRST		+	+	+	+
1215bdc0023Schristos  * _NEXT		+	+	+	+
1225bdc0023Schristos  * _PREV		-	-	-	+
1235bdc0023Schristos  * _LAST		-	-	+	+
1245bdc0023Schristos  * _FOREACH		+	+	+	+
1255bdc0023Schristos  * _FOREACH_REVERSE	-	-	-	+
1265bdc0023Schristos  * _INSERT_HEAD		+	+	+	+
1275bdc0023Schristos  * _INSERT_BEFORE	-	+	-	+
1285bdc0023Schristos  * _INSERT_AFTER	+	+	+	+
1295bdc0023Schristos  * _INSERT_TAIL		-	-	+	+
1305bdc0023Schristos  * _REMOVE_HEAD		+	-	+	-
1315bdc0023Schristos  * _REMOVE		+	+	+	+
1322de962bdSlukem  *
1332de962bdSlukem  */
1342de962bdSlukem 
1352de962bdSlukem /*
1362de962bdSlukem  * Singly-linked List definitions.
1372de962bdSlukem  */
1382de962bdSlukem #define LDAP_SLIST_HEAD(name, type)					\
1392de962bdSlukem struct name {								\
1402de962bdSlukem 	struct type *slh_first;	/* first element */			\
1412de962bdSlukem }
1422de962bdSlukem 
1432de962bdSlukem #define LDAP_SLIST_HEAD_INITIALIZER(head)				\
1442de962bdSlukem 	{ NULL }
1452de962bdSlukem 
1462de962bdSlukem #define LDAP_SLIST_ENTRY(type)						\
1472de962bdSlukem struct {								\
1482de962bdSlukem 	struct type *sle_next;	/* next element */			\
1492de962bdSlukem }
1502de962bdSlukem 
1512de962bdSlukem #define LDAP_SLIST_ENTRY_INITIALIZER(entry)				\
1522de962bdSlukem 	{ NULL }
1532de962bdSlukem 
1542de962bdSlukem /*
1552de962bdSlukem  * Singly-linked List functions.
1562de962bdSlukem  */
1572de962bdSlukem #define	LDAP_SLIST_EMPTY(head)	((head)->slh_first == NULL)
1582de962bdSlukem 
1592de962bdSlukem #define	LDAP_SLIST_FIRST(head)	((head)->slh_first)
1602de962bdSlukem 
1612de962bdSlukem #define LDAP_SLIST_FOREACH(var, head, field)				\
1622de962bdSlukem 	for((var) = (head)->slh_first; (var); (var) = (var)->field.sle_next)
1632de962bdSlukem 
1642de962bdSlukem #define LDAP_SLIST_INIT(head) {						\
1652de962bdSlukem 	(head)->slh_first = NULL;					\
1662de962bdSlukem }
1672de962bdSlukem 
1682de962bdSlukem #define LDAP_SLIST_ENTRY_INIT(var, field) {				\
1692de962bdSlukem 	(var)->field.sle_next = NULL;					\
1702de962bdSlukem }
1712de962bdSlukem 
1722de962bdSlukem #define LDAP_SLIST_INSERT_AFTER(slistelm, elm, field) do {		\
1732de962bdSlukem 	(elm)->field.sle_next = (slistelm)->field.sle_next;		\
1742de962bdSlukem 	(slistelm)->field.sle_next = (elm);				\
1752de962bdSlukem } while (0)
1762de962bdSlukem 
1772de962bdSlukem #define LDAP_SLIST_INSERT_HEAD(head, elm, field) do {			\
1782de962bdSlukem 	(elm)->field.sle_next = (head)->slh_first;			\
1792de962bdSlukem 	(head)->slh_first = (elm);					\
1802de962bdSlukem } while (0)
1812de962bdSlukem 
1822de962bdSlukem #define LDAP_SLIST_NEXT(elm, field)	((elm)->field.sle_next)
1832de962bdSlukem 
1842de962bdSlukem #define LDAP_SLIST_REMOVE_HEAD(head, field) do {			\
1852de962bdSlukem 	(head)->slh_first = (head)->slh_first->field.sle_next;		\
1862de962bdSlukem } while (0)
1872de962bdSlukem 
1882de962bdSlukem #define LDAP_SLIST_REMOVE(head, elm, type, field) do {			\
1892de962bdSlukem 	if ((head)->slh_first == (elm)) {				\
1902de962bdSlukem 		LDAP_SLIST_REMOVE_HEAD((head), field);			\
1912de962bdSlukem 	}								\
1922de962bdSlukem 	else {								\
1932de962bdSlukem 		struct type *curelm = (head)->slh_first;		\
1942de962bdSlukem 		while( curelm->field.sle_next != (elm) )		\
1952de962bdSlukem 			curelm = curelm->field.sle_next;		\
1962de962bdSlukem 		curelm->field.sle_next =				\
1972de962bdSlukem 		    curelm->field.sle_next->field.sle_next;		\
1982de962bdSlukem 	}								\
1992de962bdSlukem } while (0)
2002de962bdSlukem 
2012de962bdSlukem /*
2022de962bdSlukem  * Singly-linked Tail queue definitions.
2032de962bdSlukem  */
2042de962bdSlukem #define LDAP_STAILQ_HEAD(name, type)					\
2052de962bdSlukem struct name {								\
2062de962bdSlukem 	struct type *stqh_first;/* first element */			\
2072de962bdSlukem 	struct type **stqh_last;/* addr of last next element */		\
2082de962bdSlukem }
2092de962bdSlukem 
2102de962bdSlukem #define LDAP_STAILQ_HEAD_INITIALIZER(head)				\
2112de962bdSlukem 	{ NULL, &(head).stqh_first }
2122de962bdSlukem 
2132de962bdSlukem #define LDAP_STAILQ_ENTRY(type)						\
2142de962bdSlukem struct {								\
2152de962bdSlukem 	struct type *stqe_next;	/* next element */			\
2162de962bdSlukem }
2172de962bdSlukem 
2182de962bdSlukem #define LDAP_STAILQ_ENTRY_INITIALIZER(entry)				\
2192de962bdSlukem 	{ NULL }
2202de962bdSlukem 
2212de962bdSlukem /*
2222de962bdSlukem  * Singly-linked Tail queue functions.
2232de962bdSlukem  */
2242de962bdSlukem #define LDAP_STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
2252de962bdSlukem 
2262de962bdSlukem #define	LDAP_STAILQ_INIT(head) do {					\
2272de962bdSlukem 	(head)->stqh_first = NULL;					\
2282de962bdSlukem 	(head)->stqh_last = &(head)->stqh_first;			\
2292de962bdSlukem } while (0)
2302de962bdSlukem 
2312de962bdSlukem #define LDAP_STAILQ_ENTRY_INIT(var, field) {				\
232fbfb70adSchristos 	(var)->field.stqe_next = NULL;					\
2332de962bdSlukem }
2342de962bdSlukem 
2352de962bdSlukem #define LDAP_STAILQ_FIRST(head)	((head)->stqh_first)
2362de962bdSlukem 
2372de962bdSlukem #define	LDAP_STAILQ_LAST(head, type, field)				\
2382de962bdSlukem 	(LDAP_STAILQ_EMPTY(head) ?					\
2392de962bdSlukem 		NULL :							\
2402de962bdSlukem 	        ((struct type *)					\
2412de962bdSlukem 		((char *)((head)->stqh_last) - offsetof(struct type, field))))
2422de962bdSlukem 
2432de962bdSlukem #define LDAP_STAILQ_FOREACH(var, head, field)				\
2442de962bdSlukem 	for((var) = (head)->stqh_first; (var); (var) = (var)->field.stqe_next)
2452de962bdSlukem 
2462de962bdSlukem #define LDAP_STAILQ_INSERT_HEAD(head, elm, field) do {			\
2472de962bdSlukem 	if (((elm)->field.stqe_next = (head)->stqh_first) == NULL)	\
2482de962bdSlukem 		(head)->stqh_last = &(elm)->field.stqe_next;		\
2492de962bdSlukem 	(head)->stqh_first = (elm);					\
2502de962bdSlukem } while (0)
2512de962bdSlukem 
2522de962bdSlukem #define LDAP_STAILQ_INSERT_TAIL(head, elm, field) do {			\
2532de962bdSlukem 	(elm)->field.stqe_next = NULL;					\
2542de962bdSlukem 	*(head)->stqh_last = (elm);					\
2552de962bdSlukem 	(head)->stqh_last = &(elm)->field.stqe_next;			\
2562de962bdSlukem } while (0)
2572de962bdSlukem 
2582de962bdSlukem #define LDAP_STAILQ_INSERT_AFTER(head, tqelm, elm, field) do {		\
2592de962bdSlukem 	if (((elm)->field.stqe_next = (tqelm)->field.stqe_next) == NULL)\
2602de962bdSlukem 		(head)->stqh_last = &(elm)->field.stqe_next;		\
2612de962bdSlukem 	(tqelm)->field.stqe_next = (elm);				\
2622de962bdSlukem } while (0)
2632de962bdSlukem 
2642de962bdSlukem #define LDAP_STAILQ_NEXT(elm, field)	((elm)->field.stqe_next)
2652de962bdSlukem 
2662de962bdSlukem #define LDAP_STAILQ_REMOVE_HEAD(head, field) do {			\
2672de962bdSlukem 	if (((head)->stqh_first =					\
2682de962bdSlukem 	     (head)->stqh_first->field.stqe_next) == NULL)		\
2692de962bdSlukem 		(head)->stqh_last = &(head)->stqh_first;		\
2702de962bdSlukem } while (0)
2712de962bdSlukem 
2722de962bdSlukem #define LDAP_STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do {		\
2732de962bdSlukem 	if (((head)->stqh_first = (elm)->field.stqe_next) == NULL)	\
2742de962bdSlukem 		(head)->stqh_last = &(head)->stqh_first;		\
2752de962bdSlukem } while (0)
2762de962bdSlukem 
2772de962bdSlukem #define LDAP_STAILQ_REMOVE(head, elm, type, field) do {			\
2782de962bdSlukem 	if ((head)->stqh_first == (elm)) {				\
2792de962bdSlukem 		LDAP_STAILQ_REMOVE_HEAD(head, field);			\
2802de962bdSlukem 	}								\
2812de962bdSlukem 	else {								\
2822de962bdSlukem 		struct type *curelm = (head)->stqh_first;		\
2832de962bdSlukem 		while( curelm->field.stqe_next != (elm) )		\
2842de962bdSlukem 			curelm = curelm->field.stqe_next;		\
2852de962bdSlukem 		if((curelm->field.stqe_next =				\
2862de962bdSlukem 		    curelm->field.stqe_next->field.stqe_next) == NULL)	\
2872de962bdSlukem 			(head)->stqh_last = &(curelm)->field.stqe_next;	\
2882de962bdSlukem 	}								\
2892de962bdSlukem } while (0)
2902de962bdSlukem 
2912de962bdSlukem /*
2922de962bdSlukem  * List definitions.
2932de962bdSlukem  */
2942de962bdSlukem #define LDAP_LIST_HEAD(name, type)					\
2952de962bdSlukem struct name {								\
2962de962bdSlukem 	struct type *lh_first;	/* first element */			\
2972de962bdSlukem }
2982de962bdSlukem 
2992de962bdSlukem #define LDAP_LIST_HEAD_INITIALIZER(head)				\
3002de962bdSlukem 	{ NULL }
3012de962bdSlukem 
3022de962bdSlukem #define LDAP_LIST_ENTRY(type)						\
3032de962bdSlukem struct {								\
3042de962bdSlukem 	struct type *le_next;	/* next element */			\
3052de962bdSlukem 	struct type **le_prev;	/* address of previous next element */	\
3062de962bdSlukem }
3072de962bdSlukem 
3082de962bdSlukem #define LDAP_LIST_ENTRY_INITIALIZER(entry)			\
3092de962bdSlukem 	{ NULL, NULL }
3102de962bdSlukem 
3112de962bdSlukem /*
3122de962bdSlukem  * List functions.
3132de962bdSlukem  */
3142de962bdSlukem 
3152de962bdSlukem #define	LDAP_LIST_EMPTY(head) ((head)->lh_first == NULL)
3162de962bdSlukem 
3172de962bdSlukem #define LDAP_LIST_FIRST(head)	((head)->lh_first)
3182de962bdSlukem 
3192de962bdSlukem #define LDAP_LIST_FOREACH(var, head, field)				\
3202de962bdSlukem 	for((var) = (head)->lh_first; (var); (var) = (var)->field.le_next)
3212de962bdSlukem 
3222de962bdSlukem #define	LDAP_LIST_INIT(head) do {					\
3232de962bdSlukem 	(head)->lh_first = NULL;					\
3242de962bdSlukem } while (0)
3252de962bdSlukem 
3262de962bdSlukem #define LDAP_LIST_ENTRY_INIT(var, field) do {				\
3272de962bdSlukem 	(var)->field.le_next = NULL;					\
3282de962bdSlukem 	(var)->field.le_prev = NULL;					\
3292de962bdSlukem } while (0)
3302de962bdSlukem 
3312de962bdSlukem #define LDAP_LIST_INSERT_AFTER(listelm, elm, field) do {		\
3322de962bdSlukem 	if (((elm)->field.le_next = (listelm)->field.le_next) != NULL)	\
3332de962bdSlukem 		(listelm)->field.le_next->field.le_prev =		\
3342de962bdSlukem 		    &(elm)->field.le_next;				\
3352de962bdSlukem 	(listelm)->field.le_next = (elm);				\
3362de962bdSlukem 	(elm)->field.le_prev = &(listelm)->field.le_next;		\
3372de962bdSlukem } while (0)
3382de962bdSlukem 
3392de962bdSlukem #define LDAP_LIST_INSERT_BEFORE(listelm, elm, field) do {		\
3402de962bdSlukem 	(elm)->field.le_prev = (listelm)->field.le_prev;		\
3412de962bdSlukem 	(elm)->field.le_next = (listelm);				\
3422de962bdSlukem 	*(listelm)->field.le_prev = (elm);				\
3432de962bdSlukem 	(listelm)->field.le_prev = &(elm)->field.le_next;		\
3442de962bdSlukem } while (0)
3452de962bdSlukem 
3462de962bdSlukem #define LDAP_LIST_INSERT_HEAD(head, elm, field) do {			\
3472de962bdSlukem 	if (((elm)->field.le_next = (head)->lh_first) != NULL)		\
3482de962bdSlukem 		(head)->lh_first->field.le_prev = &(elm)->field.le_next;\
3492de962bdSlukem 	(head)->lh_first = (elm);					\
3502de962bdSlukem 	(elm)->field.le_prev = &(head)->lh_first;			\
3512de962bdSlukem } while (0)
3522de962bdSlukem 
3532de962bdSlukem #define LDAP_LIST_NEXT(elm, field)	((elm)->field.le_next)
3542de962bdSlukem 
3552de962bdSlukem #define LDAP_LIST_REMOVE(elm, field) do {				\
3562de962bdSlukem 	if ((elm)->field.le_next != NULL)				\
3572de962bdSlukem 		(elm)->field.le_next->field.le_prev = 			\
3582de962bdSlukem 		    (elm)->field.le_prev;				\
3592de962bdSlukem 	*(elm)->field.le_prev = (elm)->field.le_next;			\
3602de962bdSlukem } while (0)
3612de962bdSlukem 
3622de962bdSlukem /*
3632de962bdSlukem  * Tail queue definitions.
3642de962bdSlukem  */
3652de962bdSlukem #define LDAP_TAILQ_HEAD(name, type)					\
3662de962bdSlukem struct name {								\
3672de962bdSlukem 	struct type *tqh_first;	/* first element */			\
3682de962bdSlukem 	struct type **tqh_last;	/* addr of last next element */		\
3692de962bdSlukem }
3702de962bdSlukem 
3712de962bdSlukem #define LDAP_TAILQ_HEAD_INITIALIZER(head)				\
3722de962bdSlukem 	{ NULL, &(head).tqh_first }
3732de962bdSlukem 
3742de962bdSlukem #define LDAP_TAILQ_ENTRY(type)						\
3752de962bdSlukem struct {								\
3762de962bdSlukem 	struct type *tqe_next;	/* next element */			\
3772de962bdSlukem 	struct type **tqe_prev;	/* address of previous next element */	\
3782de962bdSlukem }
3792de962bdSlukem 
3802de962bdSlukem #define LDAP_TAILQ_ENTRY_INITIALIZER(entry)				\
3812de962bdSlukem 	{ NULL, NULL }
3822de962bdSlukem 
3832de962bdSlukem /*
3842de962bdSlukem  * Tail queue functions.
3852de962bdSlukem  */
3862de962bdSlukem #define	LDAP_TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
3872de962bdSlukem 
3882de962bdSlukem #define LDAP_TAILQ_FOREACH(var, head, field)				\
3892de962bdSlukem 	for (var = LDAP_TAILQ_FIRST(head); var; var = LDAP_TAILQ_NEXT(var, field))
3902de962bdSlukem 
391fbfb70adSchristos #define LDAP_TAILQ_FOREACH_REVERSE(var, head, headname, field)		\
392fbfb70adSchristos 	for ((var) = LDAP_TAILQ_LAST((head), headname);			\
3932de962bdSlukem 	     (var);							\
394fbfb70adSchristos 	     (var) = LDAP_TAILQ_PREV((var), headname, field))
3952de962bdSlukem 
3962de962bdSlukem #define	LDAP_TAILQ_FIRST(head) ((head)->tqh_first)
3972de962bdSlukem 
398fbfb70adSchristos #define	LDAP_TAILQ_LAST(head, headname) \
399fbfb70adSchristos 	(*(((struct headname *)((head)->tqh_last))->tqh_last))
4002de962bdSlukem 
4012de962bdSlukem #define	LDAP_TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
4022de962bdSlukem 
403fbfb70adSchristos #define LDAP_TAILQ_PREV(elm, headname, field) \
404fbfb70adSchristos 	(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
4052de962bdSlukem 
4062de962bdSlukem #define	LDAP_TAILQ_INIT(head) do {					\
4072de962bdSlukem 	(head)->tqh_first = NULL;					\
4082de962bdSlukem 	(head)->tqh_last = &(head)->tqh_first;				\
4092de962bdSlukem } while (0)
4102de962bdSlukem 
4112de962bdSlukem #define LDAP_TAILQ_ENTRY_INIT(var, field) do {				\
4122de962bdSlukem 	(var)->field.tqe_next = NULL;					\
4132de962bdSlukem 	(var)->field.tqe_prev = NULL;					\
4142de962bdSlukem } while (0)
4152de962bdSlukem 
4162de962bdSlukem #define LDAP_TAILQ_INSERT_HEAD(head, elm, field) do {			\
4172de962bdSlukem 	if (((elm)->field.tqe_next = (head)->tqh_first) != NULL)	\
4182de962bdSlukem 		(head)->tqh_first->field.tqe_prev =			\
4192de962bdSlukem 		    &(elm)->field.tqe_next;				\
4202de962bdSlukem 	else								\
4212de962bdSlukem 		(head)->tqh_last = &(elm)->field.tqe_next;		\
4222de962bdSlukem 	(head)->tqh_first = (elm);					\
4232de962bdSlukem 	(elm)->field.tqe_prev = &(head)->tqh_first;			\
4242de962bdSlukem } while (0)
4252de962bdSlukem 
4262de962bdSlukem #define LDAP_TAILQ_INSERT_TAIL(head, elm, field) do {			\
4272de962bdSlukem 	(elm)->field.tqe_next = NULL;					\
4282de962bdSlukem 	(elm)->field.tqe_prev = (head)->tqh_last;			\
4292de962bdSlukem 	*(head)->tqh_last = (elm);					\
4302de962bdSlukem 	(head)->tqh_last = &(elm)->field.tqe_next;			\
4312de962bdSlukem } while (0)
4322de962bdSlukem 
4332de962bdSlukem #define LDAP_TAILQ_INSERT_AFTER(head, listelm, elm, field) do {		\
4342de962bdSlukem 	if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
4352de962bdSlukem 		(elm)->field.tqe_next->field.tqe_prev = 		\
4362de962bdSlukem 		    &(elm)->field.tqe_next;				\
4372de962bdSlukem 	else								\
4382de962bdSlukem 		(head)->tqh_last = &(elm)->field.tqe_next;		\
4392de962bdSlukem 	(listelm)->field.tqe_next = (elm);				\
4402de962bdSlukem 	(elm)->field.tqe_prev = &(listelm)->field.tqe_next;		\
4412de962bdSlukem } while (0)
4422de962bdSlukem 
4432de962bdSlukem #define LDAP_TAILQ_INSERT_BEFORE(listelm, elm, field) do {		\
4442de962bdSlukem 	(elm)->field.tqe_prev = (listelm)->field.tqe_prev;		\
4452de962bdSlukem 	(elm)->field.tqe_next = (listelm);				\
4462de962bdSlukem 	*(listelm)->field.tqe_prev = (elm);				\
4472de962bdSlukem 	(listelm)->field.tqe_prev = &(elm)->field.tqe_next;		\
4482de962bdSlukem } while (0)
4492de962bdSlukem 
4502de962bdSlukem #define LDAP_TAILQ_REMOVE(head, elm, field) do {			\
4512de962bdSlukem 	if (((elm)->field.tqe_next) != NULL)				\
4522de962bdSlukem 		(elm)->field.tqe_next->field.tqe_prev = 		\
4532de962bdSlukem 		    (elm)->field.tqe_prev;				\
4542de962bdSlukem 	else								\
4552de962bdSlukem 		(head)->tqh_last = (elm)->field.tqe_prev;		\
4562de962bdSlukem 	*(elm)->field.tqe_prev = (elm)->field.tqe_next;			\
4572de962bdSlukem } while (0)
4582de962bdSlukem 
459*549b59edSchristos /*
460*549b59edSchristos  * Circular queue definitions.
461*549b59edSchristos  */
462*549b59edSchristos #define LDAP_CIRCLEQ_HEAD(name, type)					\
463*549b59edSchristos struct name {								\
464*549b59edSchristos 	struct type *cqh_first;		/* first element */		\
465*549b59edSchristos 	struct type *cqh_last;		/* last element */		\
466*549b59edSchristos }
467*549b59edSchristos 
468*549b59edSchristos #define LDAP_CIRCLEQ_HEAD_INITIALIZER(head)				\
469*549b59edSchristos 	{ (void *)&(head), (void *)&(head) }
470*549b59edSchristos 
471*549b59edSchristos #define LDAP_CIRCLEQ_ENTRY(type)					\
472*549b59edSchristos struct {								\
473*549b59edSchristos 	struct type *cqe_next;		/* next element */		\
474*549b59edSchristos 	struct type *cqe_prev;		/* previous element */		\
475*549b59edSchristos }
476*549b59edSchristos 
477*549b59edSchristos /*
478*549b59edSchristos  * Circular queue functions.
479*549b59edSchristos  */
480*549b59edSchristos #define LDAP_CIRCLEQ_EMPTY(head) ((head)->cqh_first == (void *)(head))
481*549b59edSchristos 
482*549b59edSchristos #define LDAP_CIRCLEQ_FIRST(head) ((head)->cqh_first)
483*549b59edSchristos 
484*549b59edSchristos #define LDAP_CIRCLEQ_FOREACH(var, head, field)				\
485*549b59edSchristos 	for((var) = (head)->cqh_first;					\
486*549b59edSchristos 	    (var) != (void *)(head);					\
487*549b59edSchristos 	    (var) = (var)->field.cqe_next)
488*549b59edSchristos 
489*549b59edSchristos #define LDAP_CIRCLEQ_FOREACH_REVERSE(var, head, field)			\
490*549b59edSchristos 	for((var) = (head)->cqh_last;					\
491*549b59edSchristos 	    (var) != (void *)(head);					\
492*549b59edSchristos 	    (var) = (var)->field.cqe_prev)
493*549b59edSchristos 
494*549b59edSchristos #define	LDAP_CIRCLEQ_INIT(head) do {					\
495*549b59edSchristos 	(head)->cqh_first = (void *)(head);				\
496*549b59edSchristos 	(head)->cqh_last = (void *)(head);				\
497*549b59edSchristos } while (0)
498*549b59edSchristos 
499*549b59edSchristos #define LDAP_CIRCLEQ_ENTRY_INIT(var, field) do {			\
500*549b59edSchristos 	(var)->field.cqe_next = NULL;					\
501*549b59edSchristos 	(var)->field.cqe_prev = NULL;					\
502*549b59edSchristos } while (0)
503*549b59edSchristos 
504*549b59edSchristos #define LDAP_CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do {	\
505*549b59edSchristos 	(elm)->field.cqe_next = (listelm)->field.cqe_next;		\
506*549b59edSchristos 	(elm)->field.cqe_prev = (listelm);				\
507*549b59edSchristos 	if ((listelm)->field.cqe_next == (void *)(head))		\
508*549b59edSchristos 		(head)->cqh_last = (elm);				\
509*549b59edSchristos 	else								\
510*549b59edSchristos 		(listelm)->field.cqe_next->field.cqe_prev = (elm);	\
511*549b59edSchristos 	(listelm)->field.cqe_next = (elm);				\
512*549b59edSchristos } while (0)
513*549b59edSchristos 
514*549b59edSchristos #define LDAP_CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do {	\
515*549b59edSchristos 	(elm)->field.cqe_next = (listelm);				\
516*549b59edSchristos 	(elm)->field.cqe_prev = (listelm)->field.cqe_prev;		\
517*549b59edSchristos 	if ((listelm)->field.cqe_prev == (void *)(head))		\
518*549b59edSchristos 		(head)->cqh_first = (elm);				\
519*549b59edSchristos 	else								\
520*549b59edSchristos 		(listelm)->field.cqe_prev->field.cqe_next = (elm);	\
521*549b59edSchristos 	(listelm)->field.cqe_prev = (elm);				\
522*549b59edSchristos } while (0)
523*549b59edSchristos 
524*549b59edSchristos #define LDAP_CIRCLEQ_INSERT_HEAD(head, elm, field) do {			\
525*549b59edSchristos 	(elm)->field.cqe_next = (head)->cqh_first;			\
526*549b59edSchristos 	(elm)->field.cqe_prev = (void *)(head);				\
527*549b59edSchristos 	if ((head)->cqh_last == (void *)(head))				\
528*549b59edSchristos 		(head)->cqh_last = (elm);				\
529*549b59edSchristos 	else								\
530*549b59edSchristos 		(head)->cqh_first->field.cqe_prev = (elm);		\
531*549b59edSchristos 	(head)->cqh_first = (elm);					\
532*549b59edSchristos } while (0)
533*549b59edSchristos 
534*549b59edSchristos #define LDAP_CIRCLEQ_INSERT_TAIL(head, elm, field) do {			\
535*549b59edSchristos 	(elm)->field.cqe_next = (void *)(head);				\
536*549b59edSchristos 	(elm)->field.cqe_prev = (head)->cqh_last;			\
537*549b59edSchristos 	if ((head)->cqh_first == (void *)(head))			\
538*549b59edSchristos 		(head)->cqh_first = (elm);				\
539*549b59edSchristos 	else								\
540*549b59edSchristos 		(head)->cqh_last->field.cqe_next = (elm);		\
541*549b59edSchristos 	(head)->cqh_last = (elm);					\
542*549b59edSchristos } while (0)
543*549b59edSchristos 
544*549b59edSchristos #define LDAP_CIRCLEQ_LAST(head) ((head)->cqh_last)
545*549b59edSchristos 
546*549b59edSchristos #define LDAP_CIRCLEQ_NEXT(elm,field) ((elm)->field.cqe_next)
547*549b59edSchristos 
548*549b59edSchristos #define LDAP_CIRCLEQ_PREV(elm,field) ((elm)->field.cqe_prev)
549*549b59edSchristos 
550*549b59edSchristos #define	LDAP_CIRCLEQ_REMOVE(head, elm, field) do {			\
551*549b59edSchristos 	if ((elm)->field.cqe_next == (void *)(head))			\
552*549b59edSchristos 		(head)->cqh_last = (elm)->field.cqe_prev;		\
553*549b59edSchristos 	else								\
554*549b59edSchristos 		(elm)->field.cqe_next->field.cqe_prev =			\
555*549b59edSchristos 		    (elm)->field.cqe_prev;				\
556*549b59edSchristos 	if ((elm)->field.cqe_prev == (void *)(head))			\
557*549b59edSchristos 		(head)->cqh_first = (elm)->field.cqe_next;		\
558*549b59edSchristos 	else								\
559*549b59edSchristos 		(elm)->field.cqe_prev->field.cqe_next =			\
560*549b59edSchristos 		    (elm)->field.cqe_next;				\
561*549b59edSchristos } while (0)
562*549b59edSchristos 
563*549b59edSchristos #define LDAP_CIRCLEQ_LOOP_NEXT(head, elm, field)			\
564*549b59edSchristos 	(((elm)->field.cqe_next == (void *)(head))			\
565*549b59edSchristos 		? ((head)->cqh_first)					\
566*549b59edSchristos 		: ((elm)->field.cqe_next))
567*549b59edSchristos 
568*549b59edSchristos #define LDAP_CIRCLEQ_LOOP_PREV(head, elm, field)			\
569*549b59edSchristos 	(((elm)->field.cqe_prev == (void *)(head))			\
570*549b59edSchristos 		? ((head)->cqh_last)					\
571*549b59edSchristos 		: ((elm)->field.cqe_prev))
572*549b59edSchristos 
573*549b59edSchristos #define LDAP_CIRCLEQ_MAKE_HEAD(head, elm, field) do {			\
574*549b59edSchristos 	if ((elm)->field.cqe_prev != (void *)(head)) {			\
575*549b59edSchristos 		(head)->cqh_first->field.cqe_prev = (head)->cqh_last;	\
576*549b59edSchristos 		(head)->cqh_last->field.cqe_next = (head)->cqh_first;	\
577*549b59edSchristos 		(head)->cqh_first = elm;				\
578*549b59edSchristos 		(head)->cqh_last = (elm)->field.cqe_prev;		\
579*549b59edSchristos 		(elm)->field.cqe_prev->field.cqe_next = (void *)(head);	\
580*549b59edSchristos 		(elm)->field.cqe_prev = (void *)(head);			\
581*549b59edSchristos 	}								\
582*549b59edSchristos } while (0)
583*549b59edSchristos 
584*549b59edSchristos #define LDAP_CIRCLEQ_MAKE_TAIL(head, elm, field) do {			\
585*549b59edSchristos 	if ((elm)->field.cqe_next != (void *)(head)) {			\
586*549b59edSchristos 		(head)->cqh_first->field.cqe_prev = (head)->cqh_last;	\
587*549b59edSchristos 		(head)->cqh_last->field.cqe_next = (head)->cqh_first;	\
588*549b59edSchristos 		(head)->cqh_first = (elm)->field.cqe_next;		\
589*549b59edSchristos 		(head)->cqh_last = elm;					\
590*549b59edSchristos 		(elm)->field.cqe_next->field.cqe_prev = (void *)(head);	\
591*549b59edSchristos 		(elm)->field.cqe_next = (void *)(head);			\
592*549b59edSchristos 	}								\
593*549b59edSchristos } while (0)
594*549b59edSchristos 
5952de962bdSlukem #endif /* !_LDAP_QUEUE_H_ */
596