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>
00043 #include <cfg/debug.h>
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
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;
00309 l->head.succ = n->succ;
00310 n->succ->pred = &l->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;
00331 l->tail.pred = n->pred;
00332 n->pred->succ = &l->tail;
00333
00334 INVALIDATE_NODE(n);
00335 return n;
00336 }
00337
00338 #endif