101 lines
2.8 KiB
C
101 lines
2.8 KiB
C
/* A set of doubly linked list utilities, implemented as macros. */
|
|
/* Copyright 1995, 2000 Graeme W. Gill */
|
|
|
|
#ifndef _LLIST_H_
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/* A doubly link list structure */
|
|
#define LINKSTRUCT(obj) \
|
|
struct { \
|
|
obj *fwd; /* Forward link */ \
|
|
obj *bwd; /* Backwards link */ \
|
|
} _llistp
|
|
|
|
/* Initialize the linked list */
|
|
#define INIT_LIST(head) \
|
|
((head) = NULL)
|
|
|
|
/* test if the list is empty */
|
|
#define IS_LIST_EMPTY(head) \
|
|
((head) == NULL)
|
|
|
|
/* Add an item to the top of a list */
|
|
#define ADD_ITEM_TO_TOP(head,objp) \
|
|
(IS_LIST_EMPTY(head) ? (INIT_LINK(objp), (head) = objp) : \
|
|
(ADD_LINK_BWD((head),(objp)), (head) = objp))
|
|
|
|
/* Add an item to the bottom of a list */
|
|
#define ADD_ITEM_TO_BOT(head,objp) \
|
|
(IS_LIST_EMPTY(head) ? (INIT_LINK(objp), (head) = objp) : \
|
|
(ADD_LINK_BWD((head),(objp))))
|
|
|
|
/* Insert a new item forward of the old one in linked list */
|
|
#define ADD_LINK_FWD(oob,nob) \
|
|
((nob)->_llistp.fwd = (oob)->_llistp.fwd, \
|
|
(nob)->_llistp.bwd = (oob), \
|
|
(oob)->_llistp.fwd->_llistp.bwd = (nob), \
|
|
(oob)->_llistp.fwd = (nob))
|
|
|
|
/* Insert a new item backward of the old one in linked list */
|
|
#define ADD_LINK_BWD(oob,nob) \
|
|
((nob)->_llistp.bwd = (oob)->_llistp.bwd, \
|
|
(nob)->_llistp.fwd = (oob), \
|
|
(oob)->_llistp.bwd->_llistp.fwd = (nob), \
|
|
(oob)->_llistp.bwd = (nob))
|
|
|
|
/* Delete an object from the list. */
|
|
#define DEL_LINK(head,objp) \
|
|
(IS_ONE_ITEM(objp) ? (head) = NULL : \
|
|
((objp) == (head) ? (head) = (head)->_llistp.fwd : 0, \
|
|
(objp)->_llistp.fwd->_llistp.bwd = (objp)->_llistp.bwd, \
|
|
(objp)->_llistp.bwd->_llistp.fwd = (objp)->_llistp.fwd, \
|
|
(objp)->_llistp.fwd = (objp)->_llistp.bwd = (objp)))
|
|
|
|
/* Combine two linked lists. Doesn't fix parent/child stuff */
|
|
/* Breaks lists backward of oob, and forward of nob */
|
|
#define MERGE_LINK(oob,nob) \
|
|
(((nob)->_llistp.fwd)->_llistp.bwd = (oob)->_llistp.bwd, \
|
|
((oob)->_llistp.bwd)->_llistp.fwd = (nob)->_llistp.fwd, \
|
|
(nob)->_llistp.fwd = (oob), \
|
|
(oob)->_llistp.bwd = (nob))
|
|
|
|
|
|
/* Scan through all of the items in a linked list */
|
|
/* (Robust version, copes with deleting the items) */
|
|
#define FOR_ALL_ITEMS(objtype, objp) \
|
|
if (objp != NULL) \
|
|
{ \
|
|
objtype *_end, *_next; \
|
|
_end = objp->_llistp.bwd; \
|
|
_next = objp->_llistp.fwd; \
|
|
do {
|
|
|
|
#define END_FOR_ALL_ITEMS(objp) \
|
|
} while (objp == _end ? 0 : \
|
|
(objp = _next, _next = objp->_llistp.fwd, 1)); \
|
|
}
|
|
|
|
#define NEXT_FWD(objp) \
|
|
(objp == NULL ? NULL : objp->_llistp.fwd)
|
|
|
|
/* ----------------------------- */
|
|
|
|
/* initialise a list to have only one entry */
|
|
#define INIT_LINK(objp) \
|
|
((objp)->_llistp.fwd = (objp)->_llistp.bwd = (objp))
|
|
|
|
/* test if the given object is the only one */
|
|
#define IS_ONE_ITEM(objp) \
|
|
((objp) == (objp)->_llistp.fwd)
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#define _LLIST_H_
|
|
#endif /* _LLIST_H_ */
|
|
|