1 
2 #ifndef _LLIST_H
3 #define _LLIST_H
4 
5 #include "../Utils/Logger.h"
6 
7 // this file provides macros which implement common operations on linked lists.
8 // this saves a little bit of thinking and helps prevent bugs caused by
9 // forgetting one of the steps.
10 
11 // call them giving them the node to work on and the names of the fields
12 // for next, prev, first and last nodes.
13 
14 // add a node to the end of a linked list
15 #define LL_ADD_END(O, PREV, NEXT, FIRST, LAST)                                                                         \
16   {                                                                                                                    \
17     if (LAST)                                                                                                          \
18       LAST->NEXT = O;                                                                                                  \
19     else                                                                                                               \
20       FIRST = O;                                                                                                       \
21                                                                                                                        \
22     O->PREV = LAST;                                                                                                    \
23     O->NEXT = NULL;                                                                                                    \
24     LAST    = O;                                                                                                       \
25   }
26 
27 // add a node at the start of a linked list
28 #define LL_ADD_BEGIN(O, PREV, NEXT, FIRST, LAST)                                                                       \
29   {                                                                                                                    \
30     O->NEXT = FIRST;                                                                                                   \
31     O->PREV = NULL;                                                                                                    \
32                                                                                                                        \
33     if (FIRST)                                                                                                         \
34       FIRST->PREV = O;                                                                                                 \
35     else                                                                                                               \
36       FIRST = LAST = O;                                                                                                \
37   }
38 
39 // insert a node just before another node
40 #define LL_INSERT_BEFORE(O, BEHIND, PREV, NEXT, FIRST, LAST)                                                           \
41   {                                                                                                                    \
42     if (BEHIND == FIRST)                                                                                               \
43       FIRST = O;                                                                                                       \
44     else                                                                                                               \
45       BEHIND->PREV->NEXT = O;                                                                                          \
46                                                                                                                        \
47     O->NEXT      = BEHIND;                                                                                             \
48     O->PREV      = BEHIND->PREV;                                                                                       \
49     BEHIND->PREV = O;                                                                                                  \
50   }
51 
52 // insert a node just after another node
53 #define LL_INSERT_AFTER(O, AFTER, PREV, NEXT, FIRST, LAST)                                                             \
54   {                                                                                                                    \
55     if (AFTER == LAST)                                                                                                 \
56       LAST = O;                                                                                                        \
57     else                                                                                                               \
58       AFTER->NEXT->PREV = O;                                                                                           \
59                                                                                                                        \
60     O->NEXT     = AFTER->NEXT;                                                                                         \
61     O->PREV     = AFTER;                                                                                               \
62     AFTER->NEXT = O;                                                                                                   \
63   }
64 
65 // remove a node from a linked list
66 #define LL_REMOVE(O, PREV, NEXT, FIRST, LAST)                                                                          \
67   {                                                                                                                    \
68     if (O == FIRST)                                                                                                    \
69       FIRST = FIRST->NEXT;                                                                                             \
70     else if (O->PREV)                                                                                                  \
71       O->PREV->NEXT = O->NEXT;                                                                                         \
72                                                                                                                        \
73     if (O == LAST)                                                                                                     \
74       LAST = LAST->PREV;                                                                                               \
75     else if (O->NEXT)                                                                                                  \
76       O->NEXT->PREV = O->PREV;                                                                                         \
77   }
78 
79 // debug function
80 #define LL_DUMP_LIST(START, PREV, NEXT, NODETYPE)                                                                      \
81   {                                                                                                                    \
82     LOG_DEBUG("LL_DUMP_LIST from {} using {}", #START, #NEXT);                                                         \
83                                                                                                                        \
84     NODETYPE *n = START;                                                                                               \
85     int iter    = 0;                                                                                                   \
86     while (n)                                                                                                          \
87     {                                                                                                                  \
88       LOG_DEBUG("{}: {:#08x}   P:{:#08x}  N:{:#08x}", iter++, n, n->PREV, n->NEXT);                                    \
89       n = n->NEXT;                                                                                                     \
90     }                                                                                                                  \
91   }
92 
93 #endif
94