2 * Copyright 2001-2003 The OpenLDAP Foundation, Redwood City, California, USA
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted only as authorized by the OpenLDAP
7 * Public License. A copy of this license is available at
8 * http://www.OpenLDAP.org/license.html or in file LICENSE in the
9 * top-level directory of the distribution.
11 /* stolen from FreeBSD for use in OpenLDAP */
14 * Copyright (c) 1991, 1993
15 * The Regents of the University of California. All rights reserved.
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions
20 * 1. Redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer.
22 * 2. Redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution.
25 * 3. All advertising materials mentioning features or use of this software
26 * must display the following acknowledgement:
27 * This product includes software developed by the University of
28 * California, Berkeley and its contributors.
29 * 4. Neither the name of the University nor the names of its contributors
30 * may be used to endorse or promote products derived from this software
31 * without specific prior written permission.
33 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
34 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
35 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
36 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
37 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
38 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
39 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
41 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
42 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
45 * @(#)queue.h 8.5 (Berkeley) 8/20/94
46 * $FreeBSD: src/sys/sys/queue.h,v 1.32.2.5 2001/09/30 21:12:54 luigi Exp $
49 #ifndef _LDAP_QUEUE_H_
50 #define _LDAP_QUEUE_H_
53 * This file defines five types of data structures: singly-linked lists,
54 * singly-linked tail queues, lists, tail queues, and circular queues.
56 * A singly-linked list is headed by a single forward pointer. The elements
57 * are singly linked for minimum space and pointer manipulation overhead at
58 * the expense of O(n) removal for arbitrary elements. New elements can be
59 * added to the list after an existing element or at the head of the list.
60 * Elements being removed from the head of the list should use the explicit
61 * macro for this purpose for optimum efficiency. A singly-linked list may
62 * only be traversed in the forward direction. Singly-linked lists are ideal
63 * for applications with large datasets and few or no removals or for
64 * implementing a LIFO queue.
66 * A singly-linked tail queue is headed by a pair of pointers, one to the
67 * head of the list and the other to the tail of the list. The elements are
68 * singly linked for minimum space and pointer manipulation overhead at the
69 * expense of O(n) removal for arbitrary elements. New elements can be added
70 * to the list after an existing element, at the head of the list, or at the
71 * end of the list. Elements being removed from the head of the tail queue
72 * should use the explicit macro for this purpose for optimum efficiency.
73 * A singly-linked tail queue may only be traversed in the forward direction.
74 * Singly-linked tail queues are ideal for applications with large datasets
75 * and few or no removals or for implementing a FIFO queue.
77 * A list is headed by a single forward pointer (or an array of forward
78 * pointers for a hash table header). The elements are doubly linked
79 * so that an arbitrary element can be removed without a need to
80 * traverse the list. New elements can be added to the list before
81 * or after an existing element or at the head of the list. A list
82 * may only be traversed in the forward direction.
84 * A tail queue is headed by a pair of pointers, one to the head of the
85 * list and the other to the tail of the list. The elements are doubly
86 * linked so that an arbitrary element can be removed without a need to
87 * traverse the list. New elements can be added to the list before or
88 * after an existing element, at the head of the list, or at the end of
89 * the list. A tail queue may be traversed in either direction.
91 * A circle queue is headed by a pair of pointers, one to the head of the
92 * list and the other to the tail of the list. The elements are doubly
93 * linked so that an arbitrary element can be removed without a need to
94 * traverse the list. New elements can be added to the list before or after
95 * an existing element, at the head of the list, or at the end of the list.
96 * A circle queue may be traversed in either direction, but has a more
97 * complex end of list detection.
99 * For details on the use of these macros, see the queue(3) manual page.
100 * All macros are prefixed with LDAP_.
102 * SLIST_ LIST_ STAILQ_ TAILQ_ CIRCLEQ_
112 * _FOREACH_REVERSE - - - + +
113 * _INSERT_HEAD + + + + +
114 * _INSERT_BEFORE - + - + +
115 * _INSERT_AFTER + + + + +
116 * _INSERT_TAIL - - + + +
117 * _REMOVE_HEAD + - + - -
123 * Singly-linked List definitions.
125 #define LDAP_SLIST_HEAD(name, type) \
127 struct type *slh_first; /* first element */ \
130 #define LDAP_SLIST_HEAD_INITIALIZER(head) \
133 #define LDAP_SLIST_ENTRY(type) \
135 struct type *sle_next; /* next element */ \
139 * Singly-linked List functions.
141 #define LDAP_SLIST_EMPTY(head) ((head)->slh_first == NULL)
143 #define LDAP_SLIST_FIRST(head) ((head)->slh_first)
145 #define LDAP_SLIST_FOREACH(var, head, field) \
146 for((var) = (head)->slh_first; (var); (var) = (var)->field.sle_next)
148 #define LDAP_SLIST_INIT(head) { \
149 (head)->slh_first = NULL; \
152 #define LDAP_SLIST_INSERT_AFTER(slistelm, elm, field) do { \
153 (elm)->field.sle_next = (slistelm)->field.sle_next; \
154 (slistelm)->field.sle_next = (elm); \
157 #define LDAP_SLIST_INSERT_HEAD(head, elm, field) do { \
158 (elm)->field.sle_next = (head)->slh_first; \
159 (head)->slh_first = (elm); \
162 #define LDAP_SLIST_NEXT(elm, field) ((elm)->field.sle_next)
164 #define LDAP_SLIST_REMOVE_HEAD(head, field) do { \
165 (head)->slh_first = (head)->slh_first->field.sle_next; \
168 #define LDAP_SLIST_REMOVE(head, elm, type, field) do { \
169 if ((head)->slh_first == (elm)) { \
170 LDAP_SLIST_REMOVE_HEAD((head), field); \
173 struct type *curelm = (head)->slh_first; \
174 while( curelm->field.sle_next != (elm) ) \
175 curelm = curelm->field.sle_next; \
176 curelm->field.sle_next = \
177 curelm->field.sle_next->field.sle_next; \
182 * Singly-linked Tail queue definitions.
184 #define LDAP_STAILQ_HEAD(name, type) \
186 struct type *stqh_first;/* first element */ \
187 struct type **stqh_last;/* addr of last next element */ \
190 #define LDAP_STAILQ_HEAD_INITIALIZER(head) \
191 { NULL, &(head).stqh_first }
193 #define LDAP_STAILQ_ENTRY(type) \
195 struct type *stqe_next; /* next element */ \
199 * Singly-linked Tail queue functions.
201 #define LDAP_STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
203 #define LDAP_STAILQ_INIT(head) do { \
204 (head)->stqh_first = NULL; \
205 (head)->stqh_last = &(head)->stqh_first; \
208 #define LDAP_STAILQ_FIRST(head) ((head)->stqh_first)
210 #define LDAP_STAILQ_LAST(head, type, field) \
211 (LDAP_STAILQ_EMPTY(head) ? \
214 ((char *)((head)->stqh_last) - offsetof(struct type, field))))
216 #define LDAP_STAILQ_FOREACH(var, head, field) \
217 for((var) = (head)->stqh_first; (var); (var) = (var)->field.stqe_next)
219 #define LDAP_STAILQ_INSERT_HEAD(head, elm, field) do { \
220 if (((elm)->field.stqe_next = (head)->stqh_first) == NULL) \
221 (head)->stqh_last = &(elm)->field.stqe_next; \
222 (head)->stqh_first = (elm); \
225 #define LDAP_STAILQ_INSERT_TAIL(head, elm, field) do { \
226 (elm)->field.stqe_next = NULL; \
227 *(head)->stqh_last = (elm); \
228 (head)->stqh_last = &(elm)->field.stqe_next; \
231 #define LDAP_STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \
232 if (((elm)->field.stqe_next = (tqelm)->field.stqe_next) == NULL)\
233 (head)->stqh_last = &(elm)->field.stqe_next; \
234 (tqelm)->field.stqe_next = (elm); \
237 #define LDAP_STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
239 #define LDAP_STAILQ_REMOVE_HEAD(head, field) do { \
240 if (((head)->stqh_first = \
241 (head)->stqh_first->field.stqe_next) == NULL) \
242 (head)->stqh_last = &(head)->stqh_first; \
245 #define LDAP_STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do { \
246 if (((head)->stqh_first = (elm)->field.stqe_next) == NULL) \
247 (head)->stqh_last = &(head)->stqh_first; \
250 #define LDAP_STAILQ_REMOVE(head, elm, type, field) do { \
251 if ((head)->stqh_first == (elm)) { \
252 LDAP_STAILQ_REMOVE_HEAD(head, field); \
255 struct type *curelm = (head)->stqh_first; \
256 while( curelm->field.stqe_next != (elm) ) \
257 curelm = curelm->field.stqe_next; \
258 if((curelm->field.stqe_next = \
259 curelm->field.stqe_next->field.stqe_next) == NULL) \
260 (head)->stqh_last = &(curelm)->field.stqe_next; \
267 #define LDAP_LIST_HEAD(name, type) \
269 struct type *lh_first; /* first element */ \
272 #define LDAP_LIST_HEAD_INITIALIZER(head) \
275 #define LDAP_LIST_ENTRY(type) \
277 struct type *le_next; /* next element */ \
278 struct type **le_prev; /* address of previous next element */ \
285 #define LDAP_LIST_EMPTY(head) ((head)->lh_first == NULL)
287 #define LDAP_LIST_FIRST(head) ((head)->lh_first)
289 #define LDAP_LIST_FOREACH(var, head, field) \
290 for((var) = (head)->lh_first; (var); (var) = (var)->field.le_next)
292 #define LDAP_LIST_INIT(head) do { \
293 (head)->lh_first = NULL; \
296 #define LDAP_LIST_INSERT_AFTER(listelm, elm, field) do { \
297 if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \
298 (listelm)->field.le_next->field.le_prev = \
299 &(elm)->field.le_next; \
300 (listelm)->field.le_next = (elm); \
301 (elm)->field.le_prev = &(listelm)->field.le_next; \
304 #define LDAP_LIST_INSERT_BEFORE(listelm, elm, field) do { \
305 (elm)->field.le_prev = (listelm)->field.le_prev; \
306 (elm)->field.le_next = (listelm); \
307 *(listelm)->field.le_prev = (elm); \
308 (listelm)->field.le_prev = &(elm)->field.le_next; \
311 #define LDAP_LIST_INSERT_HEAD(head, elm, field) do { \
312 if (((elm)->field.le_next = (head)->lh_first) != NULL) \
313 (head)->lh_first->field.le_prev = &(elm)->field.le_next;\
314 (head)->lh_first = (elm); \
315 (elm)->field.le_prev = &(head)->lh_first; \
318 #define LDAP_LIST_NEXT(elm, field) ((elm)->field.le_next)
320 #define LDAP_LIST_REMOVE(elm, field) do { \
321 if ((elm)->field.le_next != NULL) \
322 (elm)->field.le_next->field.le_prev = \
323 (elm)->field.le_prev; \
324 *(elm)->field.le_prev = (elm)->field.le_next; \
328 * Tail queue definitions.
330 #define LDAP_TAILQ_HEAD(name, type) \
332 struct type *tqh_first; /* first element */ \
333 struct type **tqh_last; /* addr of last next element */ \
336 #define LDAP_TAILQ_HEAD_INITIALIZER(head) \
337 { NULL, &(head).tqh_first }
339 #define LDAP_TAILQ_ENTRY(type) \
341 struct type *tqe_next; /* next element */ \
342 struct type **tqe_prev; /* address of previous next element */ \
346 * Tail queue functions.
348 #define LDAP_TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
350 #define LDAP_TAILQ_FOREACH(var, head, field) \
351 for (var = LDAP_TAILQ_FIRST(head); var; var = TAILQ_NEXT(var, field))
353 #define LDAP_TAILQ_FOREACH_REVERSE(var, head, type, field) \
354 for ((var) = LDAP_TAILQ_LAST((head), type, field); \
356 (var) = LDAP_TAILQ_PREV((var), head, type, field))
358 #define LDAP_TAILQ_FIRST(head) ((head)->tqh_first)
360 #define LDAP_TAILQ_LAST(head, type, field) \
361 (LDAP_TAILQ_EMPTY(head) ? \
364 ((char *)((head)->tqh_last) - offsetof(struct type, field))))
366 #define LDAP_TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
368 #define LDAP_TAILQ_PREV(elm, head, type, field) \
369 ((struct type *)((elm)->field.tqe_prev) == LDAP_TAILQ_FIRST(head) ? \
372 ((char *)((elm)->field.tqe_prev) - offsetof(struct type, field))))
374 #define LDAP_TAILQ_INIT(head) do { \
375 (head)->tqh_first = NULL; \
376 (head)->tqh_last = &(head)->tqh_first; \
379 #define LDAP_TAILQ_INSERT_HEAD(head, elm, field) do { \
380 if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \
381 (head)->tqh_first->field.tqe_prev = \
382 &(elm)->field.tqe_next; \
384 (head)->tqh_last = &(elm)->field.tqe_next; \
385 (head)->tqh_first = (elm); \
386 (elm)->field.tqe_prev = &(head)->tqh_first; \
389 #define LDAP_TAILQ_INSERT_TAIL(head, elm, field) do { \
390 (elm)->field.tqe_next = NULL; \
391 (elm)->field.tqe_prev = (head)->tqh_last; \
392 *(head)->tqh_last = (elm); \
393 (head)->tqh_last = &(elm)->field.tqe_next; \
396 #define LDAP_TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
397 if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
398 (elm)->field.tqe_next->field.tqe_prev = \
399 &(elm)->field.tqe_next; \
401 (head)->tqh_last = &(elm)->field.tqe_next; \
402 (listelm)->field.tqe_next = (elm); \
403 (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
406 #define LDAP_TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
407 (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
408 (elm)->field.tqe_next = (listelm); \
409 *(listelm)->field.tqe_prev = (elm); \
410 (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
413 #define LDAP_TAILQ_REMOVE(head, elm, field) do { \
414 if (((elm)->field.tqe_next) != NULL) \
415 (elm)->field.tqe_next->field.tqe_prev = \
416 (elm)->field.tqe_prev; \
418 (head)->tqh_last = (elm)->field.tqe_prev; \
419 *(elm)->field.tqe_prev = (elm)->field.tqe_next; \
423 * Circular queue definitions.
425 #define LDAP_CIRCLEQ_HEAD(name, type) \
427 struct type *cqh_first; /* first element */ \
428 struct type *cqh_last; /* last element */ \
431 #define LDAP_CIRCLEQ_ENTRY(type) \
433 struct type *cqe_next; /* next element */ \
434 struct type *cqe_prev; /* previous element */ \
438 * Circular queue functions.
440 #define LDAP_CIRCLEQ_EMPTY(head) ((head)->cqh_first == (void *)(head))
442 #define LDAP_CIRCLEQ_FIRST(head) ((head)->cqh_first)
444 #define LDAP_CIRCLEQ_FOREACH(var, head, field) \
445 for((var) = (head)->cqh_first; \
446 (var) != (void *)(head); \
447 (var) = (var)->field.cqe_next)
449 #define LDAP_CIRCLEQ_FOREACH_REVERSE(var, head, field) \
450 for((var) = (head)->cqh_last; \
451 (var) != (void *)(head); \
452 (var) = (var)->field.cqe_prev)
454 #define LDAP_CIRCLEQ_INIT(head) do { \
455 (head)->cqh_first = (void *)(head); \
456 (head)->cqh_last = (void *)(head); \
459 #define LDAP_CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
460 (elm)->field.cqe_next = (listelm)->field.cqe_next; \
461 (elm)->field.cqe_prev = (listelm); \
462 if ((listelm)->field.cqe_next == (void *)(head)) \
463 (head)->cqh_last = (elm); \
465 (listelm)->field.cqe_next->field.cqe_prev = (elm); \
466 (listelm)->field.cqe_next = (elm); \
469 #define LDAP_CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \
470 (elm)->field.cqe_next = (listelm); \
471 (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \
472 if ((listelm)->field.cqe_prev == (void *)(head)) \
473 (head)->cqh_first = (elm); \
475 (listelm)->field.cqe_prev->field.cqe_next = (elm); \
476 (listelm)->field.cqe_prev = (elm); \
479 #define LDAP_CIRCLEQ_INSERT_HEAD(head, elm, field) do { \
480 (elm)->field.cqe_next = (head)->cqh_first; \
481 (elm)->field.cqe_prev = (void *)(head); \
482 if ((head)->cqh_last == (void *)(head)) \
483 (head)->cqh_last = (elm); \
485 (head)->cqh_first->field.cqe_prev = (elm); \
486 (head)->cqh_first = (elm); \
489 #define LDAP_CIRCLEQ_INSERT_TAIL(head, elm, field) do { \
490 (elm)->field.cqe_next = (void *)(head); \
491 (elm)->field.cqe_prev = (head)->cqh_last; \
492 if ((head)->cqh_first == (void *)(head)) \
493 (head)->cqh_first = (elm); \
495 (head)->cqh_last->field.cqe_next = (elm); \
496 (head)->cqh_last = (elm); \
499 #define LDAP_CIRCLEQ_LAST(head) ((head)->cqh_last)
501 #define LDAP_CIRCLEQ_NEXT(elm,field) ((elm)->field.cqe_next)
503 #define LDAP_CIRCLEQ_PREV(elm,field) ((elm)->field.cqe_prev)
505 #define LDAP_CIRCLEQ_REMOVE(head, elm, field) do { \
506 if ((elm)->field.cqe_next == (void *)(head)) \
507 (head)->cqh_last = (elm)->field.cqe_prev; \
509 (elm)->field.cqe_next->field.cqe_prev = \
510 (elm)->field.cqe_prev; \
511 if ((elm)->field.cqe_prev == (void *)(head)) \
512 (head)->cqh_first = (elm)->field.cqe_next; \
514 (elm)->field.cqe_prev->field.cqe_next = \
515 (elm)->field.cqe_next; \
518 #endif /* !_LDAP_QUEUE_H_ */