1 /*
2  * Copyright (c) 2018-2021, Arm Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 #ifndef __LISTS_H__
8 #define __LISTS_H__
9 
10 /********* Bi-directional list operations ********/
11 /* Bi-directional list structure */
12 struct bi_list_node_t {
13     struct bi_list_node_t *bprev;
14     struct bi_list_node_t *bnext;
15 };
16 
17 /* Init an empty node. */
18 #define BI_LIST_INIT_NODE(node) do {              \
19     (node)->bnext = node;                         \
20     (node)->bprev = node;                         \
21 } while (0)
22 
23 /* Insert a new node after current node: (bnext) of current. */
24 #define BI_LIST_INSERT_AFTER(curr, node) do {     \
25     (node)->bnext = (curr)->bnext;                \
26     (node)->bprev = curr;                         \
27     (curr)->bnext->bprev = node;                  \
28     (curr)->bnext = node;                         \
29 } while (0)
30 
31 /* Add one node into list as the tail: (bprev) of head. */
32 #define BI_LIST_INSERT_BEFORE(curr, node) do {    \
33     (curr)->bprev->bnext = node;                  \
34     (node)->bprev = (curr)->bprev;                \
35     (curr)->bprev = node;                         \
36     (node)->bnext = curr;                         \
37 } while (0)
38 
39 /* Remove one node from the list. */
40 #define BI_LIST_REMOVE_NODE(node) do {            \
41     (node)->bprev->bnext = (node)->bnext;         \
42     (node)->bnext->bprev = (node)->bprev;         \
43 } while (0)
44 
45 /* Is the head empty? */
46 #define BI_LIST_IS_EMPTY(head)      ((head)->bnext == (head))
47 
48 /* The node's next node. */
49 #define BI_LIST_NEXT_NODE(node)     ((node)->bnext)
50 
51 /* Go through each node of a list. */
52 #define BI_LIST_FOR_EACH(node, head)              \
53     for (node = (head)->bnext; node != head; node = (node)->bnext)
54 
55 /********* Uni-directional list operations ********/
56 /* Initialize the head node. */
57 #define UNI_LISI_INIT_NODE(head, link) do {             \
58     if ((head) != NULL) {                               \
59         (head)->link = NULL;                            \
60     }                                                   \
61 } while (0)
62 
63 /* Insert a new node after given position node. */
64 #define UNI_LIST_INSERT_AFTER(posi, node, link) do {    \
65     (node)->link = (posi)->link;                        \
66     (posi)->link = node;                                \
67 } while (0)
68 
69 /* Is list empty? */
70 #define UNI_LIST_IS_EMPTY(node, link)                   \
71     ((node == NULL) || ((node)->link == NULL))
72 
73 /* Pick the next node. */
74 #define UNI_LIST_NEXT_NODE(node, link) ((node)->link)
75 
76 /* Remove one node from the list. */
77 #define UNI_LIST_REMOVE_NODE(prev, node, link) do {     \
78     (prev)->link = (node)->link;                        \
79     (node)->link = NULL;                                \
80 } while (0)
81 
82 /* Remove node by its pointer ('pointer = &prev_of_node->link'). */
83 #define UNI_LIST_REMOVE_NODE_BY_PNODE(pnode, link)      \
84     *(pnode) = (*(pnode))->link
85 
86 /* Move a node after posi node. */
87 #define UNI_LIST_MOVE_AFTER(posi, prev, node, link) do {\
88     if (prev != NULL) {                                 \
89         (prev)->link = (node)->link;                    \
90         (node)->link = (posi)->link;                    \
91         (posi)->link = node;                            \
92     }                                                   \
93 } while (0)
94 
95 /* Go through each node of a list. */
96 #define UNI_LIST_FOREACH(node, head, link)              \
97     for (node = (head)->link; node != NULL; node = (node)->link)
98 
99 /* Go through each node of a list with prev node recorded. */
100 #define UNI_LIST_FOREACH_NODE_PREV(prev, node, head, link)   \
101     for (prev = NULL, node = (head)->link;                   \
102                  node != NULL; prev = node, node = (prev)->link)
103 
104 /* Go through each node of a list with recording node and its holder. */
105 #define UNI_LIST_FOREACH_NODE_PNODE(pnode, node, head, link) \
106     for (pnode = &(head)->link, node = (head)->link;         \
107          node != NULL;                                       \
108          pnode = &(node)->link, node = (node)->link)
109 
110 #endif /* __LISTS_H__ */
111