ossp-pkg/act/act_chain.h
/*
** OSSP act - Abstract Container Types
** Copyright (c) 1999-2003 Ralf S. Engelschall <rse@engelschall.com>
** Copyright (c) 1999-2003 The OSSP Project <http://www.ossp.org/>
**
** This file is part of OSSP act, an abstract container type library
** which can be found at http://www.ossp.org/pkg/lib/act/.
**
** Permission to use, copy, modify, and distribute this software for
** any purpose with or without fee is hereby granted, provided that
** the above copyright notice and this permission notice appear in all
** copies.
**
** THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
** USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
** OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
** SUCH DAMAGE.
**
** act_chain.h: basic chained data structures (implementation)
*/
#ifndef __ACT_CHAIN_H__
#define __ACT_CHAIN_H__
/*
* Macro set for implementing single-linked lists.
*/
/* declaration:
* typedef struct {
* ACT_LIST_ELEM(foo_t) next;
* } foo_t;
* ACT_LIST_HEAD(foo_t) head;
*/
#define ACT_LIST_HEAD(type)\
struct { type *first; }
#define ACT_LIST_ELEM(type) \
struct { type *next; }
/* initialization */
#define ACT_LIST_INITIALIZER \
{ NULL }
#define ACT_LIST_INIT(hp) \
ACT_LIST_FIRST((hp)) = NULL
#define ACT_LIST_ELEM_INIT(ep, field) \
ACT_LIST_NEXT((ep), field) = NULL
/* direct access */
#define ACT_LIST_FIRST(hp) \
((hp)->first)
#define ACT_LIST_NEXT(ep, field) \
((ep)->field.next)
/* empty check */
#define ACT_LIST_EMPTY(hp) \
(ACT_LIST_FIRST((hp)) == NULL)
/* insert */
#define ACT_LIST_INSERT_HEAD(hp, ep, field) \
do { ACT_LIST_NEXT((ep), field) = ACT_LIST_FIRST((hp)); \
ACT_LIST_FIRST((hp)) = (ep); } while (0)
#define ACT_LIST_INSERT_AFTER(ap, ep, field) \
do { ACT_LIST_NEXT((ep), field) = ACT_LIST_NEXT((ap), field); \
ACT_LIST_NEXT((ap), field) = (ep); } while (0)
/* remove */
#define ACT_LIST_REMOVE_HEAD(hp, field) \
ACT_LIST_FIRST((hp)) = \
ACT_LIST_NEXT(ACT_LIST_FIRST((hp)), field)
#define ACT_LIST_REMOVE(hp, ep, field, type) \
do { \
if (ACT_LIST_FIRST((hp)) == (ep)) \
ACT_LIST_REMOVE_HEAD((hp), field); \
else { \
type *cep = ACT_LIST_FIRST((hp)); \
while (ACT_LIST_NEXT(cep, field) != (ep)) \
cep = ACT_LIST_NEXT(cep, field); \
ACT_LIST_NEXT(cep, field) = \
ACT_LIST_NEXT(ACT_LIST_NEXT(cep, field), field); \
} \
} while (0)
/* iteration */
#define ACT_LIST_FOREACH(hp, ep, field) \
for ((ep) = ACT_LIST_FIRST((hp)); \
(ep) != NULL; \
(ep) = ACT_LIST_NEXT((ep), field))
/*
* Macro set for implementing double-linked rings.
*/
/* declaration */
#define ACT_RING_HEAD(type) \
struct { type *next; type *prev; }
#define ACT_RING_ELEM(type) \
struct { type *next; type *prev; }
/* initialization */
#define ACT_RING_INITIALIZER \
{ NULL, NULL }
#define ACT_RING_SENTINEL(hp, type, field) \
(type *)((char *)(hp) - ((size_t)(&((type *)0)->field)))
#define ACT_RING_INIT(hp, type, field) \
do { ACT_RING_FIRST((hp)) = ACT_RING_SENTINEL((hp), type, field); \
ACT_RING_LAST((hp)) = ACT_RING_SENTINEL((hp), type, field); } while (0)
#define ACT_RING_ELEM_INIT(ep, field) \
do { ACT_RING_NEXT((ep), field) = (ep); \
ACT_RING_PREV((ep), field) = (ep); } while (0)
/* direct access */
#define ACT_RING_FIRST(hp) \
((hp)->next)
#define ACT_RING_LAST(hp) \
((hp)->prev)
#define ACT_RING_NEXT(ep, field) \
((ep)->field.next)
#define ACT_RING_PREV(ep, field) \
((ep)->field.prev)
/* empty check */
#define ACT_RING_EMPTY(hp, type, field) \
(ACT_RING_FIRST((hp)) == ACT_RING_SENTINEL((hp), type, field))
/* insert */
#define ACT_RING_SPLICE_BEFORE(lep, ep1, epN, field) \
do { \
ACT_RING_NEXT((epN), field) = (lep); \
ACT_RING_PREV((ep1), field) = ACT_RING_PREV((lep), field); \
ACT_RING_NEXT(ACT_RING_PREV((lep), field), field) = (ep1); \
ACT_RING_PREV((lep), field) = (epN); \
} while (0)
#define ACT_RING_SPLICE_AFTER(lep, ep1, epN, field) \
do { \
ACT_RING_PREV((ep1), field) = (lep); \
ACT_RING_NEXT((epN), field) = ACT_RING_NEXT((lep), field); \
ACT_RING_PREV(ACT_RING_NEXT((lep), field), field) = (epN); \
ACT_RING_NEXT((lep), field) = (ep1); \
} while (0)
#define ACT_RING_SPLICE_HEAD(hp, ep1, epN, type, field) \
ACT_RING_SPLICE_AFTER(ACT_RING_SENTINEL((hp), type, field), (ep1), (epN), field)
#define ACT_RING_SPLICE_TAIL(hp, ep1, epN, type, field) \
ACT_RING_SPLICE_BEFORE(ACT_RING_SENTINEL((hp), type, field), (ep1), (epN), field)
#define ACT_RING_INSERT_BEFORE(lep, nep, field) \
ACT_RING_SPLICE_BEFORE((lep), (nep), (nep), field)
#define ACT_RING_INSERT_AFTER(lep, nep, field) \
ACT_RING_SPLICE_AFTER((lep), (nep), (nep), field)
#define ACT_RING_INSERT_HEAD(hp, nep, type, field) \
ACT_RING_SPLICE_HEAD((hp), (nep), (nep), type, field)
#define ACT_RING_INSERT_TAIL(hp, nep, type, field) \
ACT_RING_SPLICE_TAIL((hp), (nep), (nep), type, field)
/* remove */
#define ACT_RING_UNSPLICE(ep1, epN, field) \
do { \
ACT_RING_NEXT(ACT_RING_PREV((ep1), field), field) = \
ACT_RING_NEXT((epN), field); \
ACT_RING_PREV(ACT_RING_NEXT((epN), field), field) = \
ACT_RING_PREV((ep1), field); \
} while (0)
#define ACT_RING_REMOVE(ep, field) \
ACT_RING_UNSPLICE((ep), (ep), field)
/* concatenation */
#define ACT_RING_CONCAT(h1, h2, type, field) \
do { \
if (!ACT_RING_EMPTY((h2), type, field)) { \
ACT_RING_SPLICE_BEFORE(ACT_RING_SENTINEL((h1), type, field), \
ACT_RING_FIRST((h2)), \
ACT_RING_LAST((h2)), field); \
ACT_RING_INIT((h2), type, field); \
} \
} while (0)
/* iteration */
#define ACT_RING_FOREACH(ep, hp, type, field) \
for ((ep) = ACT_RING_FIRST((hp)); \
(ep) != ACT_RING_SENTINEL((hp), type, field); \
(ep) = ACT_RING_NEXT((ep), field))
#define ACT_RING_FOREACH_REVERSE(ep, hp, type, field) \
for ((ep) = ACT_RING_LAST((hp)); \
(ep) != ACT_RING_SENTINEL((hp), type, field); \
(ep) = ACT_RING_PREV((ep), field))
#endif /* __ACT_CHAIN_H__*/