/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
- * Copyright 2001-2015 The OpenLDAP Foundation.
+ * Copyright 2001-2018 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* traverse the list. New elements can be added to the list before or after
* an existing element, at the head of the list, or at the end of the list.
* A circle queue may be traversed in either direction, but has a more
- * complex end of list detection.
+ * complex end of list detection. Also, it is possible to rotate the queue,
+ * rejoining the ends and splitting it so that a given element becomes the
+ * new head or tail.
*
* For details on the use of these macros, see the queue(3) manual page.
* All macros are prefixed with LDAP_.
} while (0)
#define LDAP_STAILQ_ENTRY_INIT(var, field) { \
- (entry)->field.stqe_next = NULL; \
+ (var)->field.stqe_next = NULL; \
}
#define LDAP_STAILQ_FIRST(head) ((head)->stqh_first)
#define LDAP_TAILQ_FOREACH(var, head, field) \
for (var = LDAP_TAILQ_FIRST(head); var; var = LDAP_TAILQ_NEXT(var, field))
-#define LDAP_TAILQ_FOREACH_REVERSE(var, head, type, field) \
- for ((var) = LDAP_TAILQ_LAST((head), type, field); \
+#define LDAP_TAILQ_FOREACH_REVERSE(var, head, headname, field) \
+ for ((var) = LDAP_TAILQ_LAST((head), headname); \
(var); \
- (var) = LDAP_TAILQ_PREV((var), head, type, field))
+ (var) = LDAP_TAILQ_PREV((var), headname, field))
#define LDAP_TAILQ_FIRST(head) ((head)->tqh_first)
-#define LDAP_TAILQ_LAST(head, type, field) \
- (LDAP_TAILQ_EMPTY(head) ? \
- NULL : \
- ((struct type *) \
- ((char *)((head)->tqh_last) - offsetof(struct type, field))))
+#define LDAP_TAILQ_LAST(head, headname) \
+ (*(((struct headname *)((head)->tqh_last))->tqh_last))
#define LDAP_TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
-#define LDAP_TAILQ_PREV(elm, head, type, field) \
- ((struct type *)((elm)->field.tqe_prev) == LDAP_TAILQ_FIRST(head) ? \
- NULL : \
- ((struct type *) \
- ((char *)((elm)->field.tqe_prev) - offsetof(struct type, field))))
+#define LDAP_TAILQ_PREV(elm, headname, field) \
+ (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
#define LDAP_TAILQ_INIT(head) do { \
(head)->tqh_first = NULL; \
struct type *cqh_last; /* last element */ \
}
+#define LDAP_CIRCLEQ_HEAD_INITIALIZER(head) \
+ { (void *)&(head), (void *)&(head) }
+
#define LDAP_CIRCLEQ_ENTRY(type) \
struct { \
struct type *cqe_next; /* next element */ \
(elm)->field.cqe_next; \
} while (0)
+#define LDAP_CIRCLEQ_LOOP_NEXT(head, elm, field) \
+ (((elm)->field.cqe_next == (void *)(head)) \
+ ? ((head)->cqh_first) \
+ : ((elm)->field.cqe_next))
+
+#define LDAP_CIRCLEQ_LOOP_PREV(head, elm, field) \
+ (((elm)->field.cqe_prev == (void *)(head)) \
+ ? ((head)->cqh_last) \
+ : ((elm)->field.cqe_prev))
+
+#define LDAP_CIRCLEQ_MAKE_HEAD(head, elm, field) do { \
+ if ((elm)->field.cqe_prev != (void *)(head)) { \
+ (head)->cqh_first->field.cqe_prev = (head)->cqh_last; \
+ (head)->cqh_last->field.cqe_next = (head)->cqh_first; \
+ (head)->cqh_first = elm; \
+ (head)->cqh_last = (elm)->field.cqe_prev; \
+ (elm)->field.cqe_prev->field.cqe_next = (void *)(head); \
+ (elm)->field.cqe_prev = (void *)(head); \
+ } \
+} while (0)
+
+#define LDAP_CIRCLEQ_MAKE_TAIL(head, elm, field) do { \
+ if ((elm)->field.cqe_next != (void *)(head)) { \
+ (head)->cqh_first->field.cqe_prev = (head)->cqh_last; \
+ (head)->cqh_last->field.cqe_next = (head)->cqh_first; \
+ (head)->cqh_first = (elm)->field.cqe_next; \
+ (head)->cqh_last = elm; \
+ (elm)->field.cqe_next->field.cqe_prev = (void *)(head); \
+ (elm)->field.cqe_next = (void *)(head); \
+ } \
+} while (0)
+
#endif /* !_LDAP_QUEUE_H_ */