list.h

Go to the documentation of this file.
00001 
00041 #ifndef MWARE_LIST_H
00042 #define MWARE_LIST_H
00043 
00044 #include <cfg/compiler.h> /* INLINE */
00045 #include <cfg/debug.h> /* ASSERT() */
00046 
00053 typedef struct _Node
00054 {
00055     struct _Node *succ;
00056     struct _Node *pred;
00057 } Node;
00058 
00068 typedef struct _List
00069 {
00070     Node head;
00071     Node tail;
00072 } List;
00073 
00077 typedef struct _PriNode
00078 {
00079     Node link;
00080     int  pri;
00081 } PriNode;
00082 
00083 
00114 #define DECLARE_NODE_ANON(T) \
00115     T *succ; T *pred;
00116 
00118 #define DECLARE_NODE_TYPE(T) \
00119     typedef struct T##Node { T *succ; T *pred; } T##Node
00120 
00122 #define DECLARE_LIST_TYPE(T) \
00123     DECLARE_NODE_TYPE(T); \
00124     typedef struct T##List { \
00125          T##Node head; \
00126          T##Node tail; \
00127     } T##List
00128 
00129 #define NODE_TYPE(T) T##Node
00130 #define LIST_TYPE(T) T##List
00131 
00137 #define LIST_HEAD(l) ((l)->head.succ)
00138 
00144 #define LIST_TAIL(l) ((l)->tail.pred)
00145 
00146 // TODO: move in compiler.h
00147 #if COMPILER_TYPEOF
00148     #define TYPEOF_OR_VOIDPTR(type) typeof(type)
00149 #else
00150     #define TYPEOF_OR_VOIDPTR(type) void *
00151 #endif
00152 
00160 #define FOREACH_NODE(n, l) \
00161     for( \
00162         (n) = (TYPEOF_OR_VOIDPTR(n))LIST_HEAD(l); \
00163         ((Node *)(n))->succ; \
00164         (n) = (TYPEOF_OR_VOIDPTR(n))(((Node *)(n))->succ) \
00165     )
00166 
00174 #define REVERSE_FOREACH_NODE(n, l) \
00175     for( \
00176         (n) = (TYPEOF_OR_VOIDPTR(n))LIST_TAIL(l); \
00177         ((Node *)(n))->pred; \
00178         (n) = (TYPEOF_OR_VOIDPTR(n))(((Node *)(n))->pred) \
00179     )
00180 
00182 #define LIST_INIT(l) \
00183     do { \
00184         (l)->head.succ = (TYPEOF_OR_VOIDPTR((l)->head.succ)) &(l)->tail; \
00185         (l)->head.pred = NULL; \
00186         (l)->tail.succ = NULL; \
00187         (l)->tail.pred = (TYPEOF_OR_VOIDPTR((l)->tail.pred)) &(l)->head; \
00188     } while (0)
00189 
00190 #ifdef _DEBUG
00191 
00192     #define LIST_ASSERT_VALID(l) \
00193         do { \
00194             Node *n, *pred; \
00195             ASSERT((l)->head.succ != NULL); \
00196             ASSERT((l)->head.pred == NULL); \
00197             ASSERT((l)->tail.succ == NULL); \
00198             ASSERT((l)->tail.pred != NULL); \
00199             pred = &(l)->head; \
00200             FOREACH_NODE(n, l) \
00201             { \
00202                 ASSERT(n->pred == pred); \
00203                 pred = n; \
00204             } \
00205             ASSERT(n == &(l)->tail); \
00206         } while (0)
00207 
00208     #define INVALIDATE_NODE(n) ((n)->succ = (n)->pred = NULL)
00209 #else
00210     #define LIST_ASSERT_VALID(l) do {} while (0)
00211     #define INVALIDATE_NODE(n) do {} while (0)
00212 #endif
00213 
00215 #define ADDHEAD(l,n) \
00216     do { \
00217         ASSERT(l); \
00218         ASSERT(n); \
00219         (n)->succ = (l)->head.succ; \
00220         (n)->pred = (l)->head.succ->pred; \
00221         (n)->succ->pred = (n); \
00222         (n)->pred->succ = (n); \
00223     } while (0)
00224 
00226 #define ADDTAIL(l,n) \
00227     do { \
00228         ASSERT(l); \
00229         ASSERT(n); \
00230         (n)->succ = &(l)->tail; \
00231         (n)->pred = (l)->tail.pred; \
00232         (n)->pred->succ = (n); \
00233         (l)->tail.pred = (n); \
00234     } while (0)
00235 
00242 #define INSERT_BEFORE(n,ln) \
00243     do { \
00244         (n)->succ = (ln); \
00245         (n)->pred = (ln)->pred; \
00246         (ln)->pred->succ = (n); \
00247         (ln)->pred = (n); \
00248     } while (0)
00249 
00256 #define REMOVE(n) \
00257     do { \
00258         (n)->pred->succ = (n)->succ; \
00259         (n)->succ->pred = (n)->pred; \
00260         INVALIDATE_NODE(n); \
00261     } while (0)
00262 
00264 #define LIST_EMPTY(l)  ( (void *)((l)->head.succ) == (void *)(&(l)->tail) )
00265 
00273 #define LIST_ENQUEUE(list, node) \
00274     do { \
00275         PriNode *ln; \
00276         FOREACH_NODE(ln, (list)) \
00277             if (ln->pri < (node)->pri) \
00278                 break; \
00279         INSERT_BEFORE(&(node)->link, &ln->link); \
00280     } while (0)
00281 
00282 
00288 INLINE Node *list_remHead(List *l)
00289 {
00290     Node *n;
00291 
00292     if (LIST_EMPTY(l))
00293         return (Node *)0;
00294 
00295     n = l->head.succ; /* Get first node. */
00296     l->head.succ = n->succ; /* Link list head to second node. */
00297     n->succ->pred = &l->head; /* Link second node to list head. */
00298 
00299     INVALIDATE_NODE(n);
00300     return n;
00301 }
00302 
00308 INLINE Node *list_remTail(List *l)
00309 {
00310     Node *n;
00311 
00312     if (LIST_EMPTY(l))
00313         return (Node *)0;
00314 
00315     n = l->tail.pred; /* Get last node. */
00316     l->tail.pred = n->pred; /* Link list tail to second last node. */
00317     n->pred->succ = &l->tail; /* Link second last node to list tail. */
00318 
00319     INVALIDATE_NODE(n);
00320     return n;
00321 }
00322 
00323 #endif /* MWARE_LIST_H */