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>
00045 #include <cfg/debug.h>
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
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;
00296 l->head.succ = n->succ;
00297 n->succ->pred = &l->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;
00316 l->tail.pred = n->pred;
00317 n->pred->succ = &l->tail;
00318
00319 INVALIDATE_NODE(n);
00320 return n;
00321 }
00322
00323 #endif