list.h

Go to the documentation of this file.
00001 
00039 #ifndef STRUCT_LIST_H
00040 #define STRUCT_LIST_H
00041 
00042 #include <cfg/compiler.h> /* INLINE */
00043 #include <cfg/debug.h> /* ASSERT_VALID_PTR() */
00044 
00051 typedef struct _Node
00052 {
00053     struct _Node *succ;
00054     struct _Node *pred;
00055 } Node;
00056 
00066 typedef struct _List
00067 {
00068     Node head;
00069     Node tail;
00070 } List;
00071 
00075 typedef struct _PriNode
00076 {
00077     Node link;
00078     int  pri;
00079 } PriNode;
00080 
00081 
00112 #define DECLARE_NODE_ANON(T) \
00113     T *succ; T *pred;
00114 
00116 #define DECLARE_NODE_TYPE(T) \
00117     typedef struct T##Node { T *succ; T *pred; } T##Node
00118 
00120 #define DECLARE_LIST_TYPE(T) \
00121     DECLARE_NODE_TYPE(T); \
00122     typedef struct T##List { \
00123          T##Node head; \
00124          T##Node tail; \
00125     } T##List
00126 
00127 #define NODE_TYPE(T) T##Node
00128 #define LIST_TYPE(T) T##List
00129 
00135 #define LIST_HEAD(l) ((l)->head.succ)
00136 
00142 #define LIST_TAIL(l) ((l)->tail.pred)
00143 
00144 // TODO: move in compiler.h
00145 #if COMPILER_TYPEOF
00146     #define TYPEOF_OR_VOIDPTR(type) typeof(type)
00147 #else
00148     #define TYPEOF_OR_VOIDPTR(type) void *
00149 #endif
00150 
00158 #define FOREACH_NODE(n, l) \
00159     for( \
00160         (n) = (TYPEOF_OR_VOIDPTR(n))LIST_HEAD(l); \
00161         ((Node *)(n))->succ; \
00162         (n) = (TYPEOF_OR_VOIDPTR(n))(((Node *)(n))->succ) \
00163     )
00164 
00172 #define REVERSE_FOREACH_NODE(n, l) \
00173     for( \
00174         (n) = (TYPEOF_OR_VOIDPTR(n))LIST_TAIL(l); \
00175         ((Node *)(n))->pred; \
00176         (n) = (TYPEOF_OR_VOIDPTR(n))(((Node *)(n))->pred) \
00177     )
00178 
00180 #define LIST_INIT(l) \
00181     do { \
00182         (l)->head.succ = (TYPEOF_OR_VOIDPTR((l)->head.succ)) &(l)->tail; \
00183         (l)->head.pred = NULL; \
00184         (l)->tail.succ = NULL; \
00185         (l)->tail.pred = (TYPEOF_OR_VOIDPTR((l)->tail.pred)) &(l)->head; \
00186     } while (0)
00187 
00188 #ifdef _DEBUG
00189 
00190     #define LIST_ASSERT_VALID(l) \
00191         do { \
00192             Node *n, *pred; \
00193             ASSERT((l)->head.succ != NULL); \
00194             ASSERT((l)->head.pred == NULL); \
00195             ASSERT((l)->tail.succ == NULL); \
00196             ASSERT((l)->tail.pred != NULL); \
00197             pred = &(l)->head; \
00198             FOREACH_NODE(n, l) \
00199             { \
00200                 ASSERT(n->pred == pred); \
00201                 pred = n; \
00202             } \
00203             ASSERT(n == &(l)->tail); \
00204         } while (0)
00205 
00207     #define LIST_ASSERT_NOT_CONTAINS(list,node) \
00208         do { \
00209             Node *ln; \
00210             ASSERT_VALID_PTR(list); \
00211             ASSERT_VALID_PTR(node); \
00212             FOREACH_NODE(ln, list) \
00213                 ASSERT(ln != (Node *)(node)); \
00214         } while (0)
00215 
00216     #define INVALIDATE_NODE(n) ((n)->succ = (n)->pred = NULL)
00217 #else
00218     #define LIST_ASSERT_VALID(l) do {} while (0)
00219     #define LIST_ASSERT_NOT_CONTAINS(list,node) do {} while (0)
00220     #define INVALIDATE_NODE(n) do {} while (0)
00221 #endif
00222 
00224 #define LIST_EMPTY(l)  ( (void *)((l)->head.succ) == (void *)(&(l)->tail) )
00225 
00227 #define ADDHEAD(l,n) \
00228     do { \
00229         LIST_ASSERT_NOT_CONTAINS((l),(n)); \
00230         (n)->succ = (l)->head.succ; \
00231         (n)->pred = (l)->head.succ->pred; \
00232         (n)->succ->pred = (n); \
00233         (n)->pred->succ = (n); \
00234     } while (0)
00235 
00237 #define ADDTAIL(l,n) \
00238     do { \
00239         LIST_ASSERT_NOT_CONTAINS((l),(n)); \
00240         (n)->succ = &(l)->tail; \
00241         (n)->pred = (l)->tail.pred; \
00242         (n)->pred->succ = (n); \
00243         (l)->tail.pred = (n); \
00244     } while (0)
00245 
00252 #define INSERT_BEFORE(n,ln) \
00253     do { \
00254         ASSERT_VALID_PTR(n); \
00255         ASSERT_VALID_PTR(ln); \
00256         (n)->succ = (ln); \
00257         (n)->pred = (ln)->pred; \
00258         (ln)->pred->succ = (n); \
00259         (ln)->pred = (n); \
00260     } while (0)
00261 
00268 #define REMOVE(n) \
00269     do { \
00270         ASSERT_VALID_PTR(n); \
00271         (n)->pred->succ = (n)->succ; \
00272         (n)->succ->pred = (n)->pred; \
00273         INVALIDATE_NODE(n); \
00274     } while (0)
00275 
00283 #define LIST_ENQUEUE(list, node) \
00284     do { \
00285         PriNode *ln; \
00286         LIST_ASSERT_NOT_CONTAINS((list),(node)); \
00287         FOREACH_NODE(ln, (list)) \
00288             if (ln->pri < (node)->pri) \
00289                 break; \
00290         INSERT_BEFORE(&(node)->link, &ln->link); \
00291     } while (0)
00292 
00293 
00299 INLINE Node *list_remHead(List *l)
00300 {
00301     Node *n;
00302 
00303     ASSERT_VALID_PTR(l);
00304 
00305     if (LIST_EMPTY(l))
00306         return (Node *)0;
00307 
00308     n = l->head.succ; /* Get first node. */
00309     l->head.succ = n->succ; /* Link list head to second node. */
00310     n->succ->pred = &l->head; /* Link second node to list head. */
00311 
00312     INVALIDATE_NODE(n);
00313     return n;
00314 }
00315 
00321 INLINE Node *list_remTail(List *l)
00322 {
00323     Node *n;
00324 
00325     ASSERT_VALID_PTR(l);
00326 
00327     if (LIST_EMPTY(l))
00328         return NULL;
00329 
00330     n = l->tail.pred; /* Get last node. */
00331     l->tail.pred = n->pred; /* Link list tail to second last node. */
00332     n->pred->succ = &l->tail; /* Link second last node to list tail. */
00333 
00334     INVALIDATE_NODE(n);
00335     return n;
00336 }
00337 
00338 #endif /* STRUCT_LIST_H */