3 @brief circular doubly linked list implementation
13 @addtogroup A_LIST circular doubly linked list
18 #define A_LIST_INIT(node) {&(node), &(node)}
22 @brief instance structure for circular doubly linked list
26 struct a_list
*next
, *prev
;
30 @brief cast a list pointer from another type pointer
31 @param[in] _ additional attributes of specified type
32 @param[in] x points to circular doubly linked list
33 @return a pointer to circular doubly linked list
35 #define a_list_(_, x) a_cast_s(a_list _, a_cast_s(void _, x))
38 @brief access the struct for this entry
39 @param ptr the &a_list pointer
40 @param type the type of the struct this is embedded in
41 @param member the name of the a_list within the struct
43 #define a_list_entry(ptr, type, member) a_container_of(ptr, type, member)
44 #define a_list_entry_next(ptr, type, member) a_list_entry((ptr)->next, type, member)
45 #define a_list_entry_prev(ptr, type, member) a_list_entry((ptr)->prev, type, member)
48 @brief iterate over a list
49 @param it the &a_list to use as a loop counter
50 @param ctx points to circular doubly linked list
51 @param next the direction of loop iteration
52 @arg next the backward iteration
53 @arg prev the forward iteration
55 #define a_list_foreach_(it, ctx, next) \
56 for (a_list *it = (ctx)->next; it != (ctx); it = it->next)
57 #define a_list_foreach_next(it, ctx) a_list_foreach_(it, ctx, next)
58 #define a_list_foreach_prev(it, ctx) a_list_foreach_(it, ctx, prev)
61 @brief iterate over a list safe against removal of list entry
62 @param it the &a_list to use as a loop counter
63 @param at another &a_list to use as temporary storage
64 @param ctx points to circular doubly linked list
65 @param next the direction of loop iteration
66 @arg next the backward iteration
67 @arg prev the forward iteration
69 #define a_list_forsafe_(it, at, ctx, next) \
70 for (a_list *it = (ctx)->next, *at = it->next; it != (ctx); it = at, at = it->next)
71 #define a_list_forsafe_next(it, at, ctx) a_list_forsafe_(it, at, ctx, next)
72 #define a_list_forsafe_prev(it, at, ctx) a_list_forsafe_(it, at, ctx, prev)
75 @brief constructor for circular doubly linked list
76 @param[in,out] ctx points to circular doubly linked list
78 A_INTERN
void a_list_ctor(a_list
*ctx
) { ctx
->prev
= ctx
->next
= ctx
; }
81 @brief initialize for circular doubly linked list
82 @param[in,out] ctx points to circular doubly linked list
84 A_INTERN
void a_list_init(a_list
*ctx
) { ctx
->prev
= ctx
->next
= ctx
; }
87 @brief destructor for circular doubly linked list
88 @param[in,out] ctx points to circular doubly linked list
90 A_INTERN
void a_list_dtor(a_list
*ctx
) { ctx
->prev
= ctx
->next
= ctx
; }
93 @brief link head node and tail node
97 nodehead[label="{<prev>prev|<addr>head|<next>next}"]
98 nodetail[label="{<prev>prev|<addr>tail|<next>next}"]
99 nodehead:next -> nodetail:addr [color=green]
100 nodetail:prev -> nodehead:addr [color=green]
101 nodehead -> "..." -> nodetail
104 @param[in,out] head the head node of a list
105 @param[in,out] tail the tail node of a list
107 A_INTERN
void a_list_link(a_list
*head
, a_list
*tail
)
114 @brief loop head node to tail node
116 digraph a_list_loop {
118 nodehead[label="{<prev>prev|<addr>head|<next>next}"]
119 nodetail[label="{<prev>prev|<addr>tail|<next>next}"]
120 nodehead:prev -> nodetail:addr [color=green]
121 nodetail:next -> nodehead:addr [color=green]
122 nodehead -> "..." -> nodetail
125 @param[in,out] head the head node of a list
126 @param[in,out] tail the tail node of a list
128 A_INTERN
void a_list_loop(a_list
*head
, a_list
*tail
)
135 @brief connect list1 and list2
137 digraph a_list_add_ {
140 head1[label="<prev>prev|<addr>head1|<next>next"]
141 tail1[label="<prev>prev|<addr>tail1|<next>next"]
144 head2[label="<prev>prev|<addr>head2|<next>next"]
145 tail2[label="<prev>prev|<addr>tail2|<next>next"]
147 tail1:next -> head2:addr [color=green]
148 head2:prev -> tail1:addr [color=green]
149 tail2:next -> head1:addr [color=blue]
150 head1:prev -> tail2:addr [color=blue]
153 @param[in,out] head1 the head node of the list1
154 @param[in,out] tail1 the tail node of the list1
155 @param[in,out] head2 the head node of the list2
156 @param[in,out] tail2 the tail node of the list2
158 A_INTERN
void a_list_add_(a_list
*head1
, a_list
*tail1
, a_list
*head2
, a_list
*tail2
)
160 a_list_link(tail1
, head2
);
161 a_list_link(tail2
, head1
);
165 @brief insert a node to a list
167 digraph a_list_add_node {
170 0[label="<node>node"]
171 1[label="<head>head|<tail>tail"]
174 2[label="<head>head|<tail>tail|<node>node"]
179 @param[in,out] head the head node of a list
180 @param[in,out] tail the tail node of a list
181 @param[in] node a circular doubly linked list node
183 A_INTERN
void a_list_add_node(a_list
*head
, a_list
*tail
, a_list
*node
)
185 a_list_add_(head
, tail
, node
, node
);
189 @brief append a node to a list forward
191 digraph a_list_add_next {
195 1[label="<prev>prev|<node>node|<next>next"]
198 2[label="<prev>prev|<node>node|<next>next|<0>0"]
203 @param[in,out] ctx points to circular doubly linked list
204 @param[in] node a circular doubly linked list node
206 A_INTERN
void a_list_add_next(a_list
*ctx
, a_list
*node
)
208 a_list_add_(ctx
->next
, ctx
, node
, node
);
212 @brief append a node to a list backward
214 digraph a_list_add_prev {
217 1[label="<prev>prev|<node>node|<next>next"]
221 2[label="<0>0|<prev>prev|<node>node|<next>next"]
226 @param[in,out] ctx points to circular doubly linked list
227 @param[in] node a circular doubly linked list node
229 A_INTERN
void a_list_add_prev(a_list
*ctx
, a_list
*node
)
231 a_list_add_(ctx
, ctx
->prev
, node
, node
);
235 @brief delete a section of a list
237 digraph a_list_del_ {
239 head[label="<prev>prev|<addr>head-prev|<next>next"]
240 tail[label="<prev>prev|<addr>tail-next|<next>next"]
241 nodehead[label="<prev>prev|<addr>head|<next>next"]
242 nodetail[label="<prev>prev|<addr>tail|<next>next"]
243 head:addr -> nodehead:addr -> "..." -> nodetail:addr -> tail:addr [dir=both]
244 head:next -> tail:addr [color=green]
245 tail:prev -> head:addr [color=green]
248 @param[in] head the head node of a list
249 @param[in] tail the tail node of a list
251 A_INTERN
void a_list_del_(a_list
const *head
, a_list
const *tail
)
253 a_list_link(head
->prev
, tail
->next
);
257 @brief delete a node from a list
259 digraph a_list_del_node {
262 1[label="<head>head|<node>node|<tail>tail"]
265 0[label="<node>node"]
266 2[label="<head>head|<tail>tail"]
271 @param[in] node a circular doubly linked list node
273 A_INTERN
void a_list_del_node(a_list
const *node
) { a_list_del_(node
, node
); }
276 @brief remove a node from a list forward
278 digraph a_list_del_next {
281 1[label="<prev>prev|<node>node|<next>next|<0>0"]
285 2[label="<prev>prev|<node>node|<next>next"]
290 @param[in] node a circular doubly linked list node
292 A_INTERN
void a_list_del_next(a_list
const *node
) { a_list_del_(node
->next
, node
->next
); }
295 @brief remove a node from a list backward
297 digraph a_list_del_prev {
300 1[label="<0>0|<prev>prev|<node>node|<next>next"]
303 2[label="<prev>prev|<node>node|<next>next"]
309 @param[in] node a circular doubly linked list node
311 A_INTERN
void a_list_del_prev(a_list
const *node
) { a_list_del_(node
->prev
, node
->prev
); }
314 @brief modify a section of a list
316 digraph a_list_set_ {
319 1[label="<prev>prev|<head>head|<tail>tail|<next>next"]
322 2[label="<prev>prev|<head>head|<tail>tail|<next>next"]
324 1:prev -> 2:head [color=green]
325 2:tail -> 1:next [color=green]
328 @param[in] head1 the head node of the list1
329 @param[in] tail1 the tail node of the list1
330 @param[in,out] head2 the head node of the list2
331 @param[in,out] tail2 the tail node of the list2
333 A_INTERN
void a_list_set_(a_list
const *head1
, a_list
const *tail1
, a_list
*head2
, a_list
*tail2
)
335 a_list_add_(tail1
->next
, head1
->prev
, head2
, tail2
);
339 @brief modify a node of a list
340 @param[in] ctx the current node
341 @param[in,out] rhs the new node
343 A_INTERN
void a_list_set_node(a_list
const *ctx
, a_list
*rhs
)
345 a_list_add_(ctx
->next
, ctx
->prev
, rhs
, rhs
);
349 @brief moving a list from another list forward
351 digraph a_list_mov_next {
355 1[label="<prev>prev|<node>node|<next>next"]
358 2[label="<prev>prev|<node>node|<next>next|<0>0|<1>1"]
363 @param[in,out] ctx points to circular doubly linked list
364 @param[in] rhs another circular doubly linked list
366 A_INTERN
void a_list_mov_next(a_list
*ctx
, a_list
const *rhs
)
368 a_list_add_(ctx
->next
, ctx
, rhs
->next
, rhs
->prev
);
372 @brief moving a list from another list backward
374 digraph a_list_mov_prev {
378 1[label="<prev>prev|<node>node|<next>next"]
381 2[label="<0>0|<1>1|<prev>prev|<node>node|<next>next"]
386 @param[in,out] ctx points to circular doubly linked list
387 @param[in] rhs another circular doubly linked list
389 A_INTERN
void a_list_mov_prev(a_list
*ctx
, a_list
const *rhs
)
391 a_list_add_(ctx
, ctx
->prev
, rhs
->next
, rhs
->prev
);
395 @brief rotate a node in the list backward
397 digraph a_list_rot_next {
400 1[label="<0>0|<1>1|<2>2|<3>3|<prev>prev|<node>node|<next>next"]
403 2[label="<0>0|<1>1|<2>2|<prev>prev|<node>node|<next>next|<3>3"]
405 1:prev -> 1:3 [color=green]
406 1:next -> 1:0 [color=green]
407 2:prev -> 2:2 [color=blue]
408 2:next -> 2:3 [color=blue]
412 @param[in,out] ctx points to circular doubly linked list
414 A_INTERN
void a_list_rot_next(a_list
*ctx
)
416 a_list
*const node
= ctx
->prev
;
417 a_list_del_(node
, node
);
418 a_list_add_(ctx
->next
, ctx
, node
, node
);
422 @brief rotate a node in the list forward
424 digraph a_list_rot_prev {
427 1[label="<prev>prev|<node>node|<next>next|<0>0|<1>1|<2>2|<3>3"]
430 2[label="<0>0|<prev>prev|<node>node|<next>next|<1>1|<2>2|<3>3"]
432 1:prev -> 1:3 [color=green]
433 1:next -> 1:0 [color=green]
434 2:prev -> 2:0 [color=blue]
435 2:next -> 2:1 [color=blue]
439 @param[in,out] ctx points to circular doubly linked list
441 A_INTERN
void a_list_rot_prev(a_list
*ctx
)
443 a_list
*const node
= ctx
->next
;
444 a_list_del_(node
, node
);
445 a_list_add_(ctx
, ctx
->prev
, node
, node
);
449 @brief swap a section of one list and a section of another list
451 digraph a_list_swap_ {
454 1[label="<prev>prev|<head>head|<tail>tail|<next>next"]
457 2[label="<prev>prev|<head>head|<tail>tail|<next>next"]
459 1:prev -> 2:head [color=green]
460 2:tail -> 1:next [color=green]
461 2:prev -> 1:head [color=blue]
462 1:tail -> 2:next [color=blue]
465 @param[in,out] head1 the head node of the list1
466 @param[in,out] tail1 the tail node of the list1
467 @param[in,out] head2 the head node of the list2
468 @param[in,out] tail2 the tail node of the list2
470 A_INTERN
void a_list_swap_(a_list
*head1
, a_list
*tail1
, a_list
*head2
, a_list
*tail2
)
472 a_list
*const head
= tail2
->next
, *const tail
= head2
->prev
;
473 a_list_add_(tail1
->next
, head1
->prev
, head2
, tail2
);
474 a_list_add_(head
, tail
, head1
, tail1
);
478 @brief swap the node lhs and the node rhs
479 @param[in,out] lhs the node on the left
480 @param[in,out] rhs the node on the right
482 A_INTERN
void a_list_swap_node(a_list
*lhs
, a_list
*rhs
)
484 a_list_swap_(lhs
, lhs
, rhs
, rhs
);
489 #endif /* a/list.h */