data-structures-c
Loading...
Searching...
No Matches
list_template.h
Go to the documentation of this file.
1// Copyright (c) 2026 abxh
2// SPDX-License-Identifier: MIT
3
11
16
17#ifdef __cplusplus
18#ifdef __GNUC__
19#define restrict __restrict__
20#else
21#define restrict
22#endif
23extern "C" {
24#endif
25
26#include <stdbool.h>
27#include <stddef.h>
28
29// macro definitions: {{{
30
35#ifndef PASTE
36#define PASTE(a, b) a##b
37#endif
38
43#ifndef XPASTE
44#define XPASTE(a, b) PASTE(a, b)
45#endif
46
51#ifndef JOIN
52#define JOIN(a, b) XPASTE(a, XPASTE(_, b))
53#endif
54
62#ifndef NAME
63#error "Must define NAME."
64#define FUNCTION_DEFINITIONS
65#define TYPE_DEFINITIONS
66#else
67#define LIST_NAME NAME
68#endif
69
74#ifndef FUNCTION_LINKAGE
75#define FUNCTION_LINKAGE
76#endif
77
79#define LIST_NODE_TYPE struct JOIN(LIST_NAME, node)
80#define LIST_NODE_ADD_BETWEEN JOIN(JOIN(internal, LIST_NAME), node_add_between)
81#define LIST_NODE_ATTACH JOIN(JOIN(internal, LIST_NAME), node_attach)
82#define LIST_NODE_INIT JOIN(LIST_NAME, node_init)
83#define LIST_NODE_IS_SINGULAR JOIN(LIST_NAME, node_is_singular)
85
93#ifndef LIST_FOR_EACH
94#define LIST_FOR_EACH(node_ptr, head_ptr) \
95 for ((node_ptr) = (head_ptr)->next_ptr; (node_ptr) != (head_ptr); (node_ptr) = (node_ptr)->next_ptr)
96#endif
97
105#ifndef LIST_FOR_EACH_REVERSE
106#define LIST_FOR_EACH_REVERSE(node_ptr, head_ptr) \
107 for ((node_ptr) = (head_ptr)->prev_ptr; (node_ptr) != (head_ptr); (node_ptr) = (node_ptr)->prev_ptr)
108#endif
109
118#ifndef LIST_FOR_EACH_SAFE
119#define LIST_FOR_EACH_SAFE(node_ptr, next_ptr, head_ptr) \
120 for ((node_ptr) = (head_ptr)->next_ptr, (next_ptr) = (node_ptr)->next_ptr; (node_ptr) != (head_ptr); \
121 (node_ptr) = (next_ptr), (next_ptr) = (node_ptr)->next_ptr)
122#endif
123
132#ifndef LIST_FOR_EACH_REVERSE_SAFE
133#define LIST_FOR_EACH_REVERSE_SAFE(node_ptr, prev_ptr, head_ptr) \
134 for ((node_ptr) = (head_ptr)->prev_ptr, (prev_ptr) = (node_ptr)->prev_ptr; (node_ptr) != (head_ptr); \
135 (node_ptr) = (prev_ptr), (prev_ptr) = (node_ptr)->prev_ptr)
136#endif
137
138// }}}
139
140// type definitions: {{{
141
142struct JOIN(LIST_NAME, node);
143
148#ifdef TYPE_DEFINITIONS
149
153struct JOIN(LIST_NAME, node) {
154 LIST_NODE_TYPE *prev_ptr;
155 LIST_NODE_TYPE *next_ptr;
156};
157
158#endif
159
160// }}}
161
162// function declarations: {{{
163
169FUNCTION_LINKAGE void JOIN(LIST_NAME, node_init)(LIST_NODE_TYPE *node_ptr);
170
181FUNCTION_LINKAGE bool JOIN(LIST_NAME, node_is_first)(const LIST_NODE_TYPE *head_ptr, const LIST_NODE_TYPE *node_ptr);
182
194FUNCTION_LINKAGE bool JOIN(LIST_NAME, node_is_last)(const LIST_NODE_TYPE *head_ptr, const LIST_NODE_TYPE *node_ptr);
195
203FUNCTION_LINKAGE bool JOIN(LIST_NAME, node_is_singular)(const LIST_NODE_TYPE *node_ptr);
204
213FUNCTION_LINKAGE void JOIN(LIST_NAME, node_add_after)(LIST_NODE_TYPE *prev_ptr, LIST_NODE_TYPE *node_ptr);
214
223FUNCTION_LINKAGE void JOIN(LIST_NAME, node_add_before)(LIST_NODE_TYPE *next_ptr, LIST_NODE_TYPE *node_ptr);
224
234FUNCTION_LINKAGE LIST_NODE_TYPE *JOIN(LIST_NAME, node_remove)(LIST_NODE_TYPE *node_ptr);
235
244FUNCTION_LINKAGE void JOIN(LIST_NAME, node_replace)(LIST_NODE_TYPE *restrict old_ptr, LIST_NODE_TYPE *restrict new_ptr);
245
246// }}}
247
248// function definitions: {{{
249
254#ifdef FUNCTION_DEFINITIONS
255
256#include <assert.h>
257
259
260// Add a node between two (known) nodes.
261static inline void JOIN(JOIN(internal, LIST_NAME), node_add_between)(LIST_NODE_TYPE *node_ptr,
262 LIST_NODE_TYPE *before_ptr,
263 LIST_NODE_TYPE *after_ptr)
264{
265 before_ptr->next_ptr = node_ptr;
266 node_ptr->prev_ptr = before_ptr;
267
268 after_ptr->prev_ptr = node_ptr;
269 node_ptr->next_ptr = after_ptr;
270}
271
272// Attach two nodes together, so anything in between is ignored.
273static inline void JOIN(JOIN(internal, LIST_NAME), node_attach)(LIST_NODE_TYPE *prev_ptr, LIST_NODE_TYPE *next_ptr)
274{
275 prev_ptr->next_ptr = next_ptr;
276 next_ptr->prev_ptr = prev_ptr;
277}
278
280
281FUNCTION_LINKAGE void JOIN(LIST_NAME, node_init)(LIST_NODE_TYPE *node_ptr)
282{
283 assert(node_ptr != NULL);
284
285 node_ptr->prev_ptr = node_ptr->next_ptr = node_ptr;
286}
287
288FUNCTION_LINKAGE bool JOIN(LIST_NAME, node_is_first)(const LIST_NODE_TYPE *head_ptr, const LIST_NODE_TYPE *node_ptr)
289{
290 assert(head_ptr != NULL);
291 assert(node_ptr != NULL);
292
293 return node_ptr->prev_ptr == head_ptr;
294}
295
296FUNCTION_LINKAGE bool JOIN(LIST_NAME, node_is_last)(const LIST_NODE_TYPE *head_ptr, const LIST_NODE_TYPE *node_ptr)
297{
298 assert(head_ptr != NULL);
299 assert(node_ptr != NULL);
300
301 return node_ptr->next_ptr == head_ptr;
302}
303
304FUNCTION_LINKAGE bool JOIN(LIST_NAME, node_is_singular)(const LIST_NODE_TYPE *node_ptr)
305{
306 assert(node_ptr != NULL);
307
308 return node_ptr->prev_ptr == node_ptr && node_ptr->next_ptr == node_ptr;
309}
310
311FUNCTION_LINKAGE void JOIN(LIST_NAME, node_add_after)(LIST_NODE_TYPE *prev_ptr, LIST_NODE_TYPE *node_ptr)
312{
313 assert(prev_ptr != NULL);
314 assert(node_ptr != NULL);
315 assert(LIST_NODE_IS_SINGULAR(node_ptr));
316
317 LIST_NODE_ADD_BETWEEN(node_ptr, prev_ptr, prev_ptr->next_ptr);
318}
319
320FUNCTION_LINKAGE void JOIN(LIST_NAME, node_add_before)(LIST_NODE_TYPE *next_ptr, LIST_NODE_TYPE *node_ptr)
321{
322 assert(next_ptr != NULL);
323 assert(node_ptr != NULL);
324 assert(LIST_NODE_IS_SINGULAR(node_ptr));
325
326 LIST_NODE_ADD_BETWEEN(node_ptr, next_ptr->prev_ptr, next_ptr);
327}
328
329FUNCTION_LINKAGE LIST_NODE_TYPE *JOIN(LIST_NAME, node_remove)(LIST_NODE_TYPE *node_ptr)
330{
331 assert(node_ptr != NULL);
332 assert(!LIST_NODE_IS_SINGULAR(node_ptr));
333
334 LIST_NODE_ATTACH(node_ptr->prev_ptr, node_ptr->next_ptr);
335 LIST_NODE_INIT(node_ptr);
336
337 return node_ptr;
338}
339
340FUNCTION_LINKAGE void JOIN(LIST_NAME, node_replace)(LIST_NODE_TYPE *restrict old_ptr, LIST_NODE_TYPE *restrict new_ptr)
341{
342 assert(old_ptr != NULL);
343 assert(new_ptr != NULL);
344 assert(!LIST_NODE_IS_SINGULAR(old_ptr));
345 assert(LIST_NODE_IS_SINGULAR(new_ptr));
346
347 LIST_NODE_ADD_BETWEEN(new_ptr, old_ptr->prev_ptr, old_ptr->next_ptr);
348 LIST_NODE_INIT(old_ptr);
349}
350
351#endif
352
353// }}}
354
355// macro undefs: {{{
356#undef NAME
357#undef FUNCTION_LINKAGE
358#undef FUNCTION_DEFINITIONS
359#undef TYPE_DEFINITIONS
360
361#undef LIST_NAME
362#undef LIST_NODE_TYPE
363#undef LIST_NODE_ADD_BETWEEN
364#undef LIST_NODE_ATTACH
365#undef LIST_NODE_INIT
366#undef LIST_NODE_IS_SINGULAR
367// }}}
368
369#ifdef __cplusplus
370}
371#endif
372
373// vim: ft=c fdm=marker
#define FUNCTION_LINKAGE
Specify function linkage e.g. static inline.
Definition fstack_template.h:145
#define JOIN(a, b)
First expand tokens, then paste them together with a _ in between.
Definition fstack_template.h:50
#define JOIN(a, b)
First expand tokens, then paste them together with a _ in between.
Definition list_template.h:52
list_node_type * next_ptr
next node pointer.
Definition list_template.h:155
list_node_type * prev_ptr
prev node pointer.
Definition list_template.h:154