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