/*
* Copyright (c) 2003, 2004 Sendmail, Inc. and its suppliers.
* All rights reserved.
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the sendmail distribution.
*
* $Id: ringhd.h,v 1.7 2006/12/26 23:43:36 ca Exp $
*/
#ifndef SM_RINGHD_H
#define SM_RINGHD_H 1
#include "sm/generic.h"
#include "sm/types.h"
#include "sm/assert.h"
#include "sm/ring.h"
/*
** Define a ring with a head (see sm/ring.h about rings).
** The head points to one element in a ring.
** Special precautions must be taken:
** - for append/prepend if the ring is empty (hd == NULL)
** - for delete if the ring has only one element
**
** hd: head of ring: pointer to a structure that has a ring embedded
** entry: pointer to a structure that has a ring embedded
** entry_ring: pointer to ring
** ring_member: name of field that is the ring in structure
**
** append(hd, entry) makes entry the last element in the list,
** i.e., it prepend entry to the element that hd points to.
** prepend(hd, entry) makes entry the first element in the list,
** i.e., it prepend entry to the element that hd points to and
** hd points afterwards to entry.
**
** Note: it is possible to perform operations on the ring itself,
** especially walking through the entries, and even adding entries.
** However, deleting entries will cause problems if:
** - the ring becomes empty
** - the entry to which the head points is removed.
** Be careful!
**
** example:
struct entry_S {
some e_types;
sm_ring_T e_ring;
};
struct head_S {
some hd_types;
entry_P hd_entry;
};
entry_P entry;
head_P hd;
SM_RINGHD_INIT(hd->hd_entry);
SM_RINGHD_APPEND(hd, entry, e_ring);
SM_RINGHD_DELETE(hd, &(entry->e_ring));
*/
#ifndef SM_RINGHD_INLINE
# define SM_RINGHD_INLINE 0
#endif
#define SM_RINGHD_INIT(hd_entry) (hd_entry) = NULLPTR
#define SM_RINGHD_APPEND(hd, entry, ring_member) \
do { \
if ((hd) == NULLPTR) { \
(hd) = (entry); \
SM_RING_INIT(&((entry)->ring_member)); \
} \
else { \
SM_RING_PREPEND(&((hd)->ring_member), \
&((entry)->ring_member)); \
} \
} while (0)
#define SM_RINGHD_PREPEND(hd, entry, ring_member) \
do { \
if ((hd) == NULLPTR) { \
SM_RING_INIT(&((entry)->ring_member)); \
} \
else { \
SM_RING_PREPEND(&((hd)->ring_member), \
&((entry)->ring_member)); \
} \
(hd) = (entry); \
} while (0)
#define SM_RINGHD_DELENTRY(hd, entry_ring) \
do { \
sm_ring_P succ, pred; \
\
SM_REQUIRE((hd) != NULLPTR); \
succ = (entry_ring)->sm_rg_succ; \
pred = (entry_ring)->sm_rg_pred; \
if ((succ == NULL && pred == NULL) \
|| (succ == (entry_ring) && pred == (entry_ring))) \
(hd) = NULLPTR; \
else { \
pred->sm_rg_succ = succ; \
succ->sm_rg_pred = pred; \
(entry_ring)->sm_rg_succ = \
(entry_ring)->sm_rg_pred = NULL; \
} \
} while (0)
#endif /* SM_RINGHD_H */
syntax highlighted by Code2HTML, v. 0.9.1