1 /* $NetBSD: ldap_queue.h,v 1.8 2021/08/14 16:14:55 christos Exp $ */ 2 3 /* ldap_queue.h -- queue macros */ 4 /* $OpenLDAP$ */ 5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 6 * 7 * Copyright 2001-2021 The OpenLDAP Foundation. 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted only as authorized by the OpenLDAP 12 * Public License. 13 * 14 * A copy of this license is available in file LICENSE in the 15 * top-level directory of the distribution or, alternatively, at 16 * <http://www.OpenLDAP.org/license.html>. 17 */ 18 /* Copyright (c) 1991, 1993 19 * The Regents of the University of California. All rights reserved. 20 * 21 * Redistribution and use in source and binary forms, with or without 22 * modification, are permitted provided that the following conditions 23 * are met: 24 * 1. Redistributions of source code must retain the above copyright 25 * notice, this list of conditions and the following disclaimer. 26 * 2. Redistributions in binary form must reproduce the above copyright 27 * notice, this list of conditions and the following disclaimer in the 28 * documentation and/or other materials provided with the distribution. 29 * 3. All advertising materials mentioning features or use of this software 30 * must display the following acknowledgement: 31 * This product includes software developed by the University of 32 * California, Berkeley and its contributors. 33 * 4. Neither the name of the University nor the names of its contributors 34 * may be used to endorse or promote products derived from this software 35 * without specific prior written permission. 36 * 37 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 38 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 39 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 40 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 41 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 42 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 43 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 44 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 45 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 46 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 47 * SUCH DAMAGE. 48 * 49 * @(#)queue.h 8.5 (Berkeley) 8/20/94 50 * $FreeBSD: src/sys/sys/queue.h,v 1.32.2.5 2001/09/30 21:12:54 luigi Exp $ 51 * 52 * See also: ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change 53 */ 54 /* ACKNOWLEDGEMENTS: 55 * This work is derived from FreeBSD queue.h work. Adapted for use in 56 * OpenLDAP Software by Kurt D. Zeilenga. 57 */ 58 59 #ifndef _LDAP_QUEUE_H_ 60 #define _LDAP_QUEUE_H_ 61 62 /* 63 * This file defines five types of data structures: singly-linked lists, 64 * singly-linked tail queues, lists, tail queues, and circular queues. 65 * 66 * A singly-linked list is headed by a single forward pointer. The elements 67 * are singly linked for minimum space and pointer manipulation overhead at 68 * the expense of O(n) removal for arbitrary elements. New elements can be 69 * added to the list after an existing element or at the head of the list. 70 * Elements being removed from the head of the list should use the explicit 71 * macro for this purpose for optimum efficiency. A singly-linked list may 72 * only be traversed in the forward direction. Singly-linked lists are ideal 73 * for applications with large datasets and few or no removals or for 74 * implementing a LIFO queue. 75 * 76 * A singly-linked tail queue is headed by a pair of pointers, one to the 77 * head of the list and the other to the tail of the list. The elements are 78 * singly linked for minimum space and pointer manipulation overhead at the 79 * expense of O(n) removal for arbitrary elements. New elements can be added 80 * to the list after an existing element, at the head of the list, or at the 81 * end of the list. Elements being removed from the head of the tail queue 82 * should use the explicit macro for this purpose for optimum efficiency. 83 * A singly-linked tail queue may only be traversed in the forward direction. 84 * Singly-linked tail queues are ideal for applications with large datasets 85 * and few or no removals or for implementing a FIFO queue. 86 * 87 * A list is headed by a single forward pointer (or an array of forward 88 * pointers for a hash table header). The elements are doubly linked 89 * so that an arbitrary element can be removed without a need to 90 * traverse the list. New elements can be added to the list before 91 * or after an existing element or at the head of the list. A list 92 * may only be traversed in the forward direction. 93 * 94 * A tail queue is headed by a pair of pointers, one to the head of the 95 * list and the other to the tail of the list. The elements are doubly 96 * linked so that an arbitrary element can be removed without a need to 97 * traverse the list. New elements can be added to the list before or 98 * after an existing element, at the head of the list, or at the end of 99 * the list. A tail queue may be traversed in either direction. 100 * 101 * A circle queue is headed by a pair of pointers, one to the head of the 102 * list and the other to the tail of the list. The elements are doubly 103 * linked so that an arbitrary element can be removed without a need to 104 * traverse the list. New elements can be added to the list before or after 105 * an existing element, at the head of the list, or at the end of the list. 106 * A circle queue may be traversed in either direction, but has a more 107 * complex end of list detection. Also, it is possible to rotate the queue, 108 * rejoining the ends and splitting it so that a given element becomes the 109 * new head or tail. 110 * 111 * For details on the use of these macros, see the queue(3) manual page. 112 * All macros are prefixed with LDAP_. 113 * 114 * SLIST_ LIST_ STAILQ_ TAILQ_ 115 * _HEAD + + + + 116 * _ENTRY + + + + 117 * _INIT + + + + 118 * _ENTRY_INIT + + + + 119 * _EMPTY + + + + 120 * _FIRST + + + + 121 * _NEXT + + + + 122 * _PREV - - - + 123 * _LAST - - + + 124 * _FOREACH + + + + 125 * _FOREACH_REVERSE - - - + 126 * _INSERT_HEAD + + + + 127 * _INSERT_BEFORE - + - + 128 * _INSERT_AFTER + + + + 129 * _INSERT_TAIL - - + + 130 * _REMOVE_HEAD + - + - 131 * _REMOVE + + + + 132 * 133 */ 134 135 /* 136 * Singly-linked List definitions. 137 */ 138 #define LDAP_SLIST_HEAD(name, type) \ 139 struct name { \ 140 struct type *slh_first; /* first element */ \ 141 } 142 143 #define LDAP_SLIST_HEAD_INITIALIZER(head) \ 144 { NULL } 145 146 #define LDAP_SLIST_ENTRY(type) \ 147 struct { \ 148 struct type *sle_next; /* next element */ \ 149 } 150 151 #define LDAP_SLIST_ENTRY_INITIALIZER(entry) \ 152 { NULL } 153 154 /* 155 * Singly-linked List functions. 156 */ 157 #define LDAP_SLIST_EMPTY(head) ((head)->slh_first == NULL) 158 159 #define LDAP_SLIST_FIRST(head) ((head)->slh_first) 160 161 #define LDAP_SLIST_FOREACH(var, head, field) \ 162 for((var) = (head)->slh_first; (var); (var) = (var)->field.sle_next) 163 164 #define LDAP_SLIST_INIT(head) { \ 165 (head)->slh_first = NULL; \ 166 } 167 168 #define LDAP_SLIST_ENTRY_INIT(var, field) { \ 169 (var)->field.sle_next = NULL; \ 170 } 171 172 #define LDAP_SLIST_INSERT_AFTER(slistelm, elm, field) do { \ 173 (elm)->field.sle_next = (slistelm)->field.sle_next; \ 174 (slistelm)->field.sle_next = (elm); \ 175 } while (0) 176 177 #define LDAP_SLIST_INSERT_HEAD(head, elm, field) do { \ 178 (elm)->field.sle_next = (head)->slh_first; \ 179 (head)->slh_first = (elm); \ 180 } while (0) 181 182 #define LDAP_SLIST_NEXT(elm, field) ((elm)->field.sle_next) 183 184 #define LDAP_SLIST_REMOVE_HEAD(head, field) do { \ 185 (head)->slh_first = (head)->slh_first->field.sle_next; \ 186 } while (0) 187 188 #define LDAP_SLIST_REMOVE(head, elm, type, field) do { \ 189 if ((head)->slh_first == (elm)) { \ 190 LDAP_SLIST_REMOVE_HEAD((head), field); \ 191 } \ 192 else { \ 193 struct type *curelm = (head)->slh_first; \ 194 while( curelm->field.sle_next != (elm) ) \ 195 curelm = curelm->field.sle_next; \ 196 curelm->field.sle_next = \ 197 curelm->field.sle_next->field.sle_next; \ 198 } \ 199 } while (0) 200 201 /* 202 * Singly-linked Tail queue definitions. 203 */ 204 #define LDAP_STAILQ_HEAD(name, type) \ 205 struct name { \ 206 struct type *stqh_first;/* first element */ \ 207 struct type **stqh_last;/* addr of last next element */ \ 208 } 209 210 #define LDAP_STAILQ_HEAD_INITIALIZER(head) \ 211 { NULL, &(head).stqh_first } 212 213 #define LDAP_STAILQ_ENTRY(type) \ 214 struct { \ 215 struct type *stqe_next; /* next element */ \ 216 } 217 218 #define LDAP_STAILQ_ENTRY_INITIALIZER(entry) \ 219 { NULL } 220 221 /* 222 * Singly-linked Tail queue functions. 223 */ 224 #define LDAP_STAILQ_EMPTY(head) ((head)->stqh_first == NULL) 225 226 #define LDAP_STAILQ_INIT(head) do { \ 227 (head)->stqh_first = NULL; \ 228 (head)->stqh_last = &(head)->stqh_first; \ 229 } while (0) 230 231 #define LDAP_STAILQ_ENTRY_INIT(var, field) { \ 232 (var)->field.stqe_next = NULL; \ 233 } 234 235 #define LDAP_STAILQ_FIRST(head) ((head)->stqh_first) 236 237 #define LDAP_STAILQ_LAST(head, type, field) \ 238 (LDAP_STAILQ_EMPTY(head) ? \ 239 NULL : \ 240 ((struct type *) \ 241 ((char *)((head)->stqh_last) - offsetof(struct type, field)))) 242 243 #define LDAP_STAILQ_FOREACH(var, head, field) \ 244 for((var) = (head)->stqh_first; (var); (var) = (var)->field.stqe_next) 245 246 #define LDAP_STAILQ_INSERT_HEAD(head, elm, field) do { \ 247 if (((elm)->field.stqe_next = (head)->stqh_first) == NULL) \ 248 (head)->stqh_last = &(elm)->field.stqe_next; \ 249 (head)->stqh_first = (elm); \ 250 } while (0) 251 252 #define LDAP_STAILQ_INSERT_TAIL(head, elm, field) do { \ 253 (elm)->field.stqe_next = NULL; \ 254 *(head)->stqh_last = (elm); \ 255 (head)->stqh_last = &(elm)->field.stqe_next; \ 256 } while (0) 257 258 #define LDAP_STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \ 259 if (((elm)->field.stqe_next = (tqelm)->field.stqe_next) == NULL)\ 260 (head)->stqh_last = &(elm)->field.stqe_next; \ 261 (tqelm)->field.stqe_next = (elm); \ 262 } while (0) 263 264 #define LDAP_STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) 265 266 #define LDAP_STAILQ_REMOVE_HEAD(head, field) do { \ 267 if (((head)->stqh_first = \ 268 (head)->stqh_first->field.stqe_next) == NULL) \ 269 (head)->stqh_last = &(head)->stqh_first; \ 270 } while (0) 271 272 #define LDAP_STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do { \ 273 if (((head)->stqh_first = (elm)->field.stqe_next) == NULL) \ 274 (head)->stqh_last = &(head)->stqh_first; \ 275 } while (0) 276 277 #define LDAP_STAILQ_REMOVE(head, elm, type, field) do { \ 278 if ((head)->stqh_first == (elm)) { \ 279 LDAP_STAILQ_REMOVE_HEAD(head, field); \ 280 } \ 281 else { \ 282 struct type *curelm = (head)->stqh_first; \ 283 while( curelm->field.stqe_next != (elm) ) \ 284 curelm = curelm->field.stqe_next; \ 285 if((curelm->field.stqe_next = \ 286 curelm->field.stqe_next->field.stqe_next) == NULL) \ 287 (head)->stqh_last = &(curelm)->field.stqe_next; \ 288 } \ 289 } while (0) 290 291 /* 292 * List definitions. 293 */ 294 #define LDAP_LIST_HEAD(name, type) \ 295 struct name { \ 296 struct type *lh_first; /* first element */ \ 297 } 298 299 #define LDAP_LIST_HEAD_INITIALIZER(head) \ 300 { NULL } 301 302 #define LDAP_LIST_ENTRY(type) \ 303 struct { \ 304 struct type *le_next; /* next element */ \ 305 struct type **le_prev; /* address of previous next element */ \ 306 } 307 308 #define LDAP_LIST_ENTRY_INITIALIZER(entry) \ 309 { NULL, NULL } 310 311 /* 312 * List functions. 313 */ 314 315 #define LDAP_LIST_EMPTY(head) ((head)->lh_first == NULL) 316 317 #define LDAP_LIST_FIRST(head) ((head)->lh_first) 318 319 #define LDAP_LIST_FOREACH(var, head, field) \ 320 for((var) = (head)->lh_first; (var); (var) = (var)->field.le_next) 321 322 #define LDAP_LIST_INIT(head) do { \ 323 (head)->lh_first = NULL; \ 324 } while (0) 325 326 #define LDAP_LIST_ENTRY_INIT(var, field) do { \ 327 (var)->field.le_next = NULL; \ 328 (var)->field.le_prev = NULL; \ 329 } while (0) 330 331 #define LDAP_LIST_INSERT_AFTER(listelm, elm, field) do { \ 332 if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \ 333 (listelm)->field.le_next->field.le_prev = \ 334 &(elm)->field.le_next; \ 335 (listelm)->field.le_next = (elm); \ 336 (elm)->field.le_prev = &(listelm)->field.le_next; \ 337 } while (0) 338 339 #define LDAP_LIST_INSERT_BEFORE(listelm, elm, field) do { \ 340 (elm)->field.le_prev = (listelm)->field.le_prev; \ 341 (elm)->field.le_next = (listelm); \ 342 *(listelm)->field.le_prev = (elm); \ 343 (listelm)->field.le_prev = &(elm)->field.le_next; \ 344 } while (0) 345 346 #define LDAP_LIST_INSERT_HEAD(head, elm, field) do { \ 347 if (((elm)->field.le_next = (head)->lh_first) != NULL) \ 348 (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ 349 (head)->lh_first = (elm); \ 350 (elm)->field.le_prev = &(head)->lh_first; \ 351 } while (0) 352 353 #define LDAP_LIST_NEXT(elm, field) ((elm)->field.le_next) 354 355 #define LDAP_LIST_REMOVE(elm, field) do { \ 356 if ((elm)->field.le_next != NULL) \ 357 (elm)->field.le_next->field.le_prev = \ 358 (elm)->field.le_prev; \ 359 *(elm)->field.le_prev = (elm)->field.le_next; \ 360 } while (0) 361 362 /* 363 * Tail queue definitions. 364 */ 365 #define LDAP_TAILQ_HEAD(name, type) \ 366 struct name { \ 367 struct type *tqh_first; /* first element */ \ 368 struct type **tqh_last; /* addr of last next element */ \ 369 } 370 371 #define LDAP_TAILQ_HEAD_INITIALIZER(head) \ 372 { NULL, &(head).tqh_first } 373 374 #define LDAP_TAILQ_ENTRY(type) \ 375 struct { \ 376 struct type *tqe_next; /* next element */ \ 377 struct type **tqe_prev; /* address of previous next element */ \ 378 } 379 380 #define LDAP_TAILQ_ENTRY_INITIALIZER(entry) \ 381 { NULL, NULL } 382 383 /* 384 * Tail queue functions. 385 */ 386 #define LDAP_TAILQ_EMPTY(head) ((head)->tqh_first == NULL) 387 388 #define LDAP_TAILQ_FOREACH(var, head, field) \ 389 for (var = LDAP_TAILQ_FIRST(head); var; var = LDAP_TAILQ_NEXT(var, field)) 390 391 #define LDAP_TAILQ_FOREACH_REVERSE(var, head, headname, field) \ 392 for ((var) = LDAP_TAILQ_LAST((head), headname); \ 393 (var); \ 394 (var) = LDAP_TAILQ_PREV((var), headname, field)) 395 396 #define LDAP_TAILQ_FIRST(head) ((head)->tqh_first) 397 398 #define LDAP_TAILQ_LAST(head, headname) \ 399 (*(((struct headname *)((head)->tqh_last))->tqh_last)) 400 401 #define LDAP_TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) 402 403 #define LDAP_TAILQ_PREV(elm, headname, field) \ 404 (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) 405 406 #define LDAP_TAILQ_INIT(head) do { \ 407 (head)->tqh_first = NULL; \ 408 (head)->tqh_last = &(head)->tqh_first; \ 409 } while (0) 410 411 #define LDAP_TAILQ_ENTRY_INIT(var, field) do { \ 412 (var)->field.tqe_next = NULL; \ 413 (var)->field.tqe_prev = NULL; \ 414 } while (0) 415 416 #define LDAP_TAILQ_INSERT_HEAD(head, elm, field) do { \ 417 if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ 418 (head)->tqh_first->field.tqe_prev = \ 419 &(elm)->field.tqe_next; \ 420 else \ 421 (head)->tqh_last = &(elm)->field.tqe_next; \ 422 (head)->tqh_first = (elm); \ 423 (elm)->field.tqe_prev = &(head)->tqh_first; \ 424 } while (0) 425 426 #define LDAP_TAILQ_INSERT_TAIL(head, elm, field) do { \ 427 (elm)->field.tqe_next = NULL; \ 428 (elm)->field.tqe_prev = (head)->tqh_last; \ 429 *(head)->tqh_last = (elm); \ 430 (head)->tqh_last = &(elm)->field.tqe_next; \ 431 } while (0) 432 433 #define LDAP_TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ 434 if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\ 435 (elm)->field.tqe_next->field.tqe_prev = \ 436 &(elm)->field.tqe_next; \ 437 else \ 438 (head)->tqh_last = &(elm)->field.tqe_next; \ 439 (listelm)->field.tqe_next = (elm); \ 440 (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ 441 } while (0) 442 443 #define LDAP_TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ 444 (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ 445 (elm)->field.tqe_next = (listelm); \ 446 *(listelm)->field.tqe_prev = (elm); \ 447 (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ 448 } while (0) 449 450 #define LDAP_TAILQ_REMOVE(head, elm, field) do { \ 451 if (((elm)->field.tqe_next) != NULL) \ 452 (elm)->field.tqe_next->field.tqe_prev = \ 453 (elm)->field.tqe_prev; \ 454 else \ 455 (head)->tqh_last = (elm)->field.tqe_prev; \ 456 *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ 457 } while (0) 458 459 /* 460 * Circular queue definitions. 461 */ 462 #define LDAP_CIRCLEQ_HEAD(name, type) \ 463 struct name { \ 464 struct type *cqh_first; /* first element */ \ 465 struct type *cqh_last; /* last element */ \ 466 } 467 468 #define LDAP_CIRCLEQ_HEAD_INITIALIZER(head) \ 469 { (void *)&(head), (void *)&(head) } 470 471 #define LDAP_CIRCLEQ_ENTRY(type) \ 472 struct { \ 473 struct type *cqe_next; /* next element */ \ 474 struct type *cqe_prev; /* previous element */ \ 475 } 476 477 /* 478 * Circular queue functions. 479 */ 480 #define LDAP_CIRCLEQ_EMPTY(head) ((head)->cqh_first == (void *)(head)) 481 482 #define LDAP_CIRCLEQ_FIRST(head) ((head)->cqh_first) 483 484 #define LDAP_CIRCLEQ_FOREACH(var, head, field) \ 485 for((var) = (head)->cqh_first; \ 486 (var) != (void *)(head); \ 487 (var) = (var)->field.cqe_next) 488 489 #define LDAP_CIRCLEQ_FOREACH_REVERSE(var, head, field) \ 490 for((var) = (head)->cqh_last; \ 491 (var) != (void *)(head); \ 492 (var) = (var)->field.cqe_prev) 493 494 #define LDAP_CIRCLEQ_INIT(head) do { \ 495 (head)->cqh_first = (void *)(head); \ 496 (head)->cqh_last = (void *)(head); \ 497 } while (0) 498 499 #define LDAP_CIRCLEQ_ENTRY_INIT(var, field) do { \ 500 (var)->field.cqe_next = NULL; \ 501 (var)->field.cqe_prev = NULL; \ 502 } while (0) 503 504 #define LDAP_CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ 505 (elm)->field.cqe_next = (listelm)->field.cqe_next; \ 506 (elm)->field.cqe_prev = (listelm); \ 507 if ((listelm)->field.cqe_next == (void *)(head)) \ 508 (head)->cqh_last = (elm); \ 509 else \ 510 (listelm)->field.cqe_next->field.cqe_prev = (elm); \ 511 (listelm)->field.cqe_next = (elm); \ 512 } while (0) 513 514 #define LDAP_CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \ 515 (elm)->field.cqe_next = (listelm); \ 516 (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \ 517 if ((listelm)->field.cqe_prev == (void *)(head)) \ 518 (head)->cqh_first = (elm); \ 519 else \ 520 (listelm)->field.cqe_prev->field.cqe_next = (elm); \ 521 (listelm)->field.cqe_prev = (elm); \ 522 } while (0) 523 524 #define LDAP_CIRCLEQ_INSERT_HEAD(head, elm, field) do { \ 525 (elm)->field.cqe_next = (head)->cqh_first; \ 526 (elm)->field.cqe_prev = (void *)(head); \ 527 if ((head)->cqh_last == (void *)(head)) \ 528 (head)->cqh_last = (elm); \ 529 else \ 530 (head)->cqh_first->field.cqe_prev = (elm); \ 531 (head)->cqh_first = (elm); \ 532 } while (0) 533 534 #define LDAP_CIRCLEQ_INSERT_TAIL(head, elm, field) do { \ 535 (elm)->field.cqe_next = (void *)(head); \ 536 (elm)->field.cqe_prev = (head)->cqh_last; \ 537 if ((head)->cqh_first == (void *)(head)) \ 538 (head)->cqh_first = (elm); \ 539 else \ 540 (head)->cqh_last->field.cqe_next = (elm); \ 541 (head)->cqh_last = (elm); \ 542 } while (0) 543 544 #define LDAP_CIRCLEQ_LAST(head) ((head)->cqh_last) 545 546 #define LDAP_CIRCLEQ_NEXT(elm,field) ((elm)->field.cqe_next) 547 548 #define LDAP_CIRCLEQ_PREV(elm,field) ((elm)->field.cqe_prev) 549 550 #define LDAP_CIRCLEQ_REMOVE(head, elm, field) do { \ 551 if ((elm)->field.cqe_next == (void *)(head)) \ 552 (head)->cqh_last = (elm)->field.cqe_prev; \ 553 else \ 554 (elm)->field.cqe_next->field.cqe_prev = \ 555 (elm)->field.cqe_prev; \ 556 if ((elm)->field.cqe_prev == (void *)(head)) \ 557 (head)->cqh_first = (elm)->field.cqe_next; \ 558 else \ 559 (elm)->field.cqe_prev->field.cqe_next = \ 560 (elm)->field.cqe_next; \ 561 } while (0) 562 563 #define LDAP_CIRCLEQ_LOOP_NEXT(head, elm, field) \ 564 (((elm)->field.cqe_next == (void *)(head)) \ 565 ? ((head)->cqh_first) \ 566 : ((elm)->field.cqe_next)) 567 568 #define LDAP_CIRCLEQ_LOOP_PREV(head, elm, field) \ 569 (((elm)->field.cqe_prev == (void *)(head)) \ 570 ? ((head)->cqh_last) \ 571 : ((elm)->field.cqe_prev)) 572 573 #define LDAP_CIRCLEQ_MAKE_HEAD(head, elm, field) do { \ 574 if ((elm)->field.cqe_prev != (void *)(head)) { \ 575 (head)->cqh_first->field.cqe_prev = (head)->cqh_last; \ 576 (head)->cqh_last->field.cqe_next = (head)->cqh_first; \ 577 (head)->cqh_first = elm; \ 578 (head)->cqh_last = (elm)->field.cqe_prev; \ 579 (elm)->field.cqe_prev->field.cqe_next = (void *)(head); \ 580 (elm)->field.cqe_prev = (void *)(head); \ 581 } \ 582 } while (0) 583 584 #define LDAP_CIRCLEQ_MAKE_TAIL(head, elm, field) do { \ 585 if ((elm)->field.cqe_next != (void *)(head)) { \ 586 (head)->cqh_first->field.cqe_prev = (head)->cqh_last; \ 587 (head)->cqh_last->field.cqe_next = (head)->cqh_first; \ 588 (head)->cqh_first = (elm)->field.cqe_next; \ 589 (head)->cqh_last = elm; \ 590 (elm)->field.cqe_next->field.cqe_prev = (void *)(head); \ 591 (elm)->field.cqe_next = (void *)(head); \ 592 } \ 593 } while (0) 594 595 #endif /* !_LDAP_QUEUE_H_ */ 596