docs/Writerside/topics/linked_list.h.md

Sat, 11 Oct 2025 11:55:46 +0200

author
Mike Becker <universe@uap-core.de>
date
Sat, 11 Oct 2025 11:55:46 +0200
changeset 1422
8bfccb342895
parent 1419
e46406fd1b3c
permissions
-rw-r--r--

changes the compare function wrapper for pointer lists so that it no longer invokes the actual compare function for NULL pointers

1143
0559812df10c assign proper names to the documentation topics
Mike Becker <universe@uap-core.de>
parents: 1142
diff changeset
1 # Linked List
1141
a06a2d27c043 create new page structure
Mike Becker <universe@uap-core.de>
parents:
diff changeset
2
a06a2d27c043 create new page structure
Mike Becker <universe@uap-core.de>
parents:
diff changeset
3 On top of implementing the list interface, this header also defines several low-level functions that
a06a2d27c043 create new page structure
Mike Becker <universe@uap-core.de>
parents:
diff changeset
4 work with arbitrary structures.
1241
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
5
1390
ff077f793c5d kv-list: add documentation
Mike Becker <universe@uap-core.de>
parents: 1245
diff changeset
6 The high-level [list interface](list.h.md) is documented on a separate page and explains how lists are used
1245
721e2032fa25 define structure for array_list.h documentation
Mike Becker <universe@uap-core.de>
parents: 1241
diff changeset
7 that are created by one of the following functions.
1241
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
8
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
9 ```C
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
10 #include <cx/linked_list.h>
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
11
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
12 CxList *cxLinkedListCreate(const CxAllocator *allocator,
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
13 cx_compare_func comparator, size_t elem_size);
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
14
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
15 CxList *cxLinkedListCreateSimple(size_t elem_size);
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
16 ```
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
17
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
18 The remaining content of this page concentrates on the low-level functions.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
19
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
20 ## Basic Structure
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
21
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
22 All functions described on this page work with nodes that have the following structure.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
23 ```C
1141
a06a2d27c043 create new page structure
Mike Becker <universe@uap-core.de>
parents:
diff changeset
24 struct node {
a06a2d27c043 create new page structure
Mike Becker <universe@uap-core.de>
parents:
diff changeset
25 node *next;
1241
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
26 node *prev; // optional
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
27 // ... the element data goes here ...
1141
a06a2d27c043 create new page structure
Mike Becker <universe@uap-core.de>
parents:
diff changeset
28 };
1241
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
29 ```
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
30
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
31 Each node must have at least one pointer that contains the address of the subsequent node.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
32 Optionally, for doubly-linked lists, there may be a second pointer that points to the predecessor.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
33
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
34 The functions usually expect a `loc_prev` and a `loc_next` offset.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
35 In the example structure from above you can obtain them with `offsetof(struct node, next)` and `offsetof(struct node, prev)`.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
36 In all functions, `loc_prev` is optional in the sense, that when you do not have a `prev` pointer, you can specify a negative value.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
37 When a function expects a `loc_advance` offset, you can freely choose if you want to pass the offset of the `next` or the `prev` pointer,
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
38 depending on what you want to do.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
39
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
40 If a function expects a `void** begin` and a `void** end` pointer, they are usually both optional, unless otherwise specified.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
41 If non-`NULL`, they point to the variables where the addresses of the first, or the last, node of a list are stored, respectively.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
42 When a list operation results in a new first (or last) node, the addresses are overwritten.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
43 In simple scenarios, you usually keep a pointer to the beginning of a list, and hence you would usually pass `NULL` to the `end` argument.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
44 If you are designing a stack-like linked-list, it may happen that you only want to store the last node of a list (the top of stack),
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
45 hence passing `NULL` to the `begin` argument and the address of your top-of-stack pointer to the `end` argument.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
46 Either way, most functions allow you a big deal of flexibility - please still read the documentation of each function carefully to learn which combinations are allowed.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
47
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
48 When you are working with a singly-linked list, it is still sometimes necessary to access the predecessor of a node.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
49 In the absence of a `prev` pointer, the only chance is to start at the beginning of the list and search for that node.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
50 This is exactly what `cx_linked_list_prev()` does.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
51 ```C
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
52 #include <cx/linked_list.h>
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
53
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
54 void *cx_linked_list_prev(const void *begin,
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
55 ptrdiff_t loc_next, const void *node);
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
56 ```
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
57
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
58 Starting with the `begin` node, the function checks if the next node is exactly the `node` (by pointer-comparison).
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
59 If true, the function terminates and returns the current node.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
60 Otherwise, it moves on with the search.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
61 If `begin` is already the searched `node`, this function immediately returns `NULL` as there is no predecessor.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
62 Note carefully, that the behavior of this function is not defined when `node` is not contained in the list that starts with `begin`.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
63
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
64 > It is advisable to use the low-level functions inside own custom functions that you define particularly for your lists.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
65 > Otherwise you will get a lot of boilerplate code when specifying the offsets to the pointers in your node structure in every call
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
66 > across your entire program.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
67
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
68 ## Link and Unlink
1141
a06a2d27c043 create new page structure
Mike Becker <universe@uap-core.de>
parents:
diff changeset
69
1241
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
70 ```C
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
71 #include <cx/linked_list.h>
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
72
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
73 void cx_linked_list_link(void *left, void *right,
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
74 ptrdiff_t loc_prev, ptrdiff_t loc_next);
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
75
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
76 void cx_linked_list_unlink(void *left, void *right,
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
77 ptrdiff_t loc_prev, ptrdiff_t loc_next);
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
78 ```
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
79
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
80 When you have two nodes `left` and `right` you can link or unlink them with the functions shown above.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
81
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
82 When linking `left` and `right` you should make sure that `left` as currently no successor and `right` has no predecessor,
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
83 because the pointers will be overwritten without unlinking possible existing links, first.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
84
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
85 On the other hand, when unlinking `left` and `right`, they must actually be linked right now.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
86 This is even asserted in debug builds.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
87
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
88 Usually you should not need those functions when working with the [insert](#insert) and [remove](#remove) functions below.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
89
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
90 ## Insert
1141
a06a2d27c043 create new page structure
Mike Becker <universe@uap-core.de>
parents:
diff changeset
91
1241
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
92 ```C
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
93 #include <cx/linked_list.h>
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
94
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
95 void cx_linked_list_add(void **begin, void **end,
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
96 ptrdiff_t loc_prev, ptrdiff_t loc_next,
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
97 void *new_node);
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
98
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
99 void cx_linked_list_prepend(void **begin, void **end,
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
100 ptrdiff_t loc_prev, ptrdiff_t loc_next,
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
101 void *new_node);
1141
a06a2d27c043 create new page structure
Mike Becker <universe@uap-core.de>
parents:
diff changeset
102
1241
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
103 void cx_linked_list_insert(void **begin, void **end,
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
104 ptrdiff_t loc_prev, ptrdiff_t loc_next,
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
105 void *node, void *new_node);
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
106
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
107 void cx_linked_list_insert_chain(void **begin, void **end,
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
108 ptrdiff_t loc_prev, ptrdiff_t loc_next,
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
109 void *node, void *insert_begin, void *insert_end);
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
110
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
111 void cx_linked_list_insert_sorted(void **begin, void **end,
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
112 ptrdiff_t loc_prev, ptrdiff_t loc_next,
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
113 void *new_node, cx_compare_func cmp_func);
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
114
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
115 void cx_linked_list_insert_sorted_chain(void **begin, void **end,
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
116 ptrdiff_t loc_prev, ptrdiff_t loc_next,
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
117 void *insert_begin, cx_compare_func cmp_func);
1419
e46406fd1b3c add functions to insert elements into lists/arrays without duplicates - resolves #557
Mike Becker <universe@uap-core.de>
parents: 1390
diff changeset
118
e46406fd1b3c add functions to insert elements into lists/arrays without duplicates - resolves #557
Mike Becker <universe@uap-core.de>
parents: 1390
diff changeset
119 int cx_linked_list_insert_unique(void **begin, void **end,
e46406fd1b3c add functions to insert elements into lists/arrays without duplicates - resolves #557
Mike Becker <universe@uap-core.de>
parents: 1390
diff changeset
120 ptrdiff_t loc_prev, ptrdiff_t loc_next,
e46406fd1b3c add functions to insert elements into lists/arrays without duplicates - resolves #557
Mike Becker <universe@uap-core.de>
parents: 1390
diff changeset
121 void *new_node, cx_compare_func cmp_func);
e46406fd1b3c add functions to insert elements into lists/arrays without duplicates - resolves #557
Mike Becker <universe@uap-core.de>
parents: 1390
diff changeset
122
e46406fd1b3c add functions to insert elements into lists/arrays without duplicates - resolves #557
Mike Becker <universe@uap-core.de>
parents: 1390
diff changeset
123 void *cx_linked_list_insert_unique_chain(void **begin, void **end,
e46406fd1b3c add functions to insert elements into lists/arrays without duplicates - resolves #557
Mike Becker <universe@uap-core.de>
parents: 1390
diff changeset
124 ptrdiff_t loc_prev, ptrdiff_t loc_next,
e46406fd1b3c add functions to insert elements into lists/arrays without duplicates - resolves #557
Mike Becker <universe@uap-core.de>
parents: 1390
diff changeset
125 void *insert_begin, cx_compare_func cmp_func);
1141
a06a2d27c043 create new page structure
Mike Becker <universe@uap-core.de>
parents:
diff changeset
126 ```
1142
9437530176bc add symbols that need documentation as TODOs
Mike Becker <universe@uap-core.de>
parents: 1141
diff changeset
127
1241
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
128 The above functions can be used to insert one or more elements into a linked list.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
129
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
130 The functions `cx_linked_list_add()` and `cx_linked_list_prepend()` add the `new_node` to the beginning, or the end, of the list, respectively.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
131 Either `begin` or `end` needs to be non-`NULL`.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
132 If you pass `NULL` to `end` in `cx_linked_list_add()`, you have to specify `begin` and `loc_next`, instead.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
133 On the other hand, if you pass `NULL` to `begin` in `cx_linked_list_prepend()`, you have to specify `end` and `loc_prev`, instead.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
134
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
135 The function `cx_linked_list_insert()` behaves like `cx_linked_list_insert_chain()` where both
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
136 `insert_begin` and `insert_end` are set to `new_node`.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
137
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
138 The function `cx_linked_list_insert_chain()` inserts the chain of nodes starting with `insert_begin` after the node `node`.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
139 If `insert_end` is `NULL`, the end is automatically detected, in which case `loc_next` must be available.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
140 If you pass `NULL` to `node`, the entire chain is prepended to the list, in which case either `begin` must be non-`NULL`,
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
141 or `end` must be non-`NULL` and `loc_prev` must be available to determine the start of the list.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
142
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
143 The functions `cx_linked_list_insert_sorted()` and `cx_linked_list_insert_sorted_chain()` are equivalent,
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
144 except that `begin` and `loc_next` are always required, and the target list must already be sorted.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
145 The order is determined by the `cmp_func` to which the pointers to the nodes are passed.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
146
1419
e46406fd1b3c add functions to insert elements into lists/arrays without duplicates - resolves #557
Mike Becker <universe@uap-core.de>
parents: 1390
diff changeset
147 The functions `cx_linked_list_insert_unique()` and `cx_linked_list_insert_unique_chain()` are similar to
e46406fd1b3c add functions to insert elements into lists/arrays without duplicates - resolves #557
Mike Becker <universe@uap-core.de>
parents: 1390
diff changeset
148 `cx_linked_list_insert_sorted()` and `cx_linked_list_insert_sorted_chain()`, except that they only insert the node
e46406fd1b3c add functions to insert elements into lists/arrays without duplicates - resolves #557
Mike Becker <universe@uap-core.de>
parents: 1390
diff changeset
149 if it is not already contained in the list.
e46406fd1b3c add functions to insert elements into lists/arrays without duplicates - resolves #557
Mike Becker <universe@uap-core.de>
parents: 1390
diff changeset
150 When a duplicate is found, `cx_linked_list_insert_unique()` returns non-zero and `cx_linked_list_insert_unique_chain()`
e46406fd1b3c add functions to insert elements into lists/arrays without duplicates - resolves #557
Mike Becker <universe@uap-core.de>
parents: 1390
diff changeset
151 returns a pointer to a new chain starting with the first node that was not inserted.
e46406fd1b3c add functions to insert elements into lists/arrays without duplicates - resolves #557
Mike Becker <universe@uap-core.de>
parents: 1390
diff changeset
152
1241
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
153 > The `cx_linked_list_insert_sorted_chain()` function does not have an `insert_end` argument, because
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
154 > it cannot take advantage of simply inserting the entire chain as-is, as the chain might need to be broken
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
155 > to maintain the sort order.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
156
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
157 ## Access and Find
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
158
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
159 ```C
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
160 #include <cx/linked_list.h>
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
161
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
162 void *cx_linked_list_first(const void *node, ptrdiff_t loc_prev);
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
163
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
164 void *cx_linked_list_last(const void *node, ptrdiff_t loc_next);
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
165
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
166 void *cx_linked_list_at(const void *start,
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
167 size_t start_index, ptrdiff_t loc_advance, size_t index);
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
168
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
169 void *cx_linked_list_find(const void *start,
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
170 ptrdiff_t loc_advance, ptrdiff_t loc_data,
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
171 cx_compare_func cmp_func,
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
172 const void *elem, size_t *found_index);
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
173
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
174 size_t cx_linked_list_size(const void *node, ptrdiff_t loc_next);
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
175 ```
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
176
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
177 The functions `cx_linked_list_first()` and `cx_linked_list_last()` can be used to find the first, or last,
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
178 node in your list in case you are not keeping track of them separately.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
179 They can start at an arbitrary node within the list.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
180
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
181 The function `cx_linked_list_at()` starts at an arbitrary node `start` which is _specified_ to have the index `start_index`,
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
182 and finds the node at `index`.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
183 If `index` is larger than `start_index`, you must pass the offset of the `next` pointer to `loc_advanced`.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
184 On the other hand, if `index` is smaller than `start_index`, you must pass the offset of the `prev` pointer.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
185 If both indices match, the function simply returns `start`.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
186 And if `index` is out-of-bounds, the function returns `NULL`.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
187
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
188 The function `cx_linked_list_find()` starts a search at the `start` node and compares each element with `elem`.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
189 If `loc_data` is non-zero, the data-type of `elem` must be a pointer to data which is compatible to the data located at the specified offset in the node.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
190 If `loc_data` is zero, `elem` is expected to point to a node structure (which is usually artificially created for the sake of comparison and not contained in the list).
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
191 When the searched element is found, a pointer to the node is returned and the index (assuming `start` has index zero) is written to the optional `found_index`, if non-`NULL`.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
192
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
193 The size of a list, or sub-list, can be determined with `cx_linked_list_size()` which may start at an arbitrary `node´ in the list.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
194
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
195 > A creative way of using `cx_linked_list_size()` in doubly-linked lists is to use the offset of the `prev` pointer
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
196 > for `loc_next`, in which case the function will return the index of the node within the list plus one.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
197
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
198 ## Remove
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
199
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
200 ```C
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
201 #include <cx/linked_list.h>
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
202
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
203 void cx_linked_list_remove(void **begin, void **end,
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
204 ptrdiff_t loc_prev, ptrdiff_t loc_next, void *node);
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
205
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
206 size_t cx_linked_list_remove_chain(void **begin, void **end,
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
207 ptrdiff_t loc_prev, ptrdiff_t loc_next,
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
208 void *node, size_t num);
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
209 ```
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
210
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
211 You can either remove a single element or a specified number of subsequent elements from list.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
212
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
213 The function `cx_linked_list_remove()` is equivalent to `cx_linked_list_remove_chain()` where `num` is set to one.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
214
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
215 The function `cx_linked_list_remove_chain()` removes up to `num` number of nodes from the list where `node` is contained, including `node` itself.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
216 It returns the actual number of removed elements, which might be smaller when the list does not contain at least `num` elements.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
217
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
218 The `prev` and `next` pointers of _all_ removed nodes are kept completely intact, allowing traversal within the removed chain,
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
219 as well as identifying the formerly adjacent nodes with the list from which the chain was removed.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
220
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
221 > Both `begin` and `end` pointers are optional, if you specify both `loc_prev` and `loc_next`.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
222 > In case your list does not have a `prev` pointer, specifying `begin` is mandatory (because there would be no other way to determine the predecessor of `node`).
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
223 >{style="note"}
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
224
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
225 > While specifying _only_ `loc_prev` and `end` is technically illegal, you can simply swap roles
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
226 > and use the offset of your `prev` pointer as `loc_next` and the address of your `end` pointer as `begin`.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
227 > The list is then traversed backwards, but otherwise everything works as expected.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
228
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
229 ## Reorder
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
230
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
231 ```C
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
232 #include <cx/linked_list.h>
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
233
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
234 void cx_linked_list_reverse(void **begin, void **end,
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
235 ptrdiff_t loc_prev, ptrdiff_t loc_next);
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
236
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
237 void cx_linked_list_sort(void **begin, void **end,
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
238 ptrdiff_t loc_prev, ptrdiff_t loc_next,
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
239 ptrdiff_t loc_data, cx_compare_func cmp_func);
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
240 ```
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
241
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
242 The function `cx_linked_list_reverse()` swaps all links of all nodes in the specified list, effectively reversing the order of elements.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
243
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
244 The function `cx_linked_list_sort()` uses a recursive _natural mergesort_ implementation to sort the list with respect to the specified `cmp_fnc`.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
245 The non-negative `loc_data` offset is used to calculate the pointers that are passed to the compare function.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
246 If you choose `loc_data` to be zero, the pointers to the nodes themselves are passed.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
247
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
248 > The `begin` pointer is required in all of the above functions while the `end` pointer is still optional.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
249 > {style="note"}
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
250
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
251 > Sorting uses [small buffer optimization](install.md#small-buffer-optimizations) for small list sizes.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
252 > If a list contains no more than `CX_LINKED_LIST_SORT_SBO_SIZE` number of elements, no additional heap memory is allocated during the entire operation.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
253 > Otherwise, merge operations still do not allocate extra memory as long as the length of the merged sub-list is not larger.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
254
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
255 ## Compare
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
256
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
257 ```C
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
258 #include <cx/linked_list.h>
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
259
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
260 int cx_linked_list_compare(
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
261 const void *begin_left, const void *begin_right,
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
262 ptrdiff_t loc_advance, ptrdiff_t loc_data,
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
263 cx_compare_func cmp_func
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
264 );
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
265 ```
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
266
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
267 For comparing two linked list, you need to specify where to start,
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
268 and the offsets for the pointer to the next node and the data.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
269
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
270 In the natural case, `begin_left` and `begin_right` point to the first node of either list,
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
271 and `loc_advance` is the offset of the `next` pointer.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
272 But it is also possible to start with the _last_ node of both lists and use the `prev` pointer to compare them backwards.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
273
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
274 The `loc_data` offset is used to calculate the pointer that is passed to the `cmp_fnc`.
ebcc08023c33 complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents: 1190
diff changeset
275 This can either be the offset of a specific field in the struct, or simply zero in which case the pointers to the nodes themselves are passed to the compare function.
1190
a7b913d5d589 bring incomplete docs into a shape that can be released
Mike Becker <universe@uap-core.de>
parents: 1146
diff changeset
276
a7b913d5d589 bring incomplete docs into a shape that can be released
Mike Becker <universe@uap-core.de>
parents: 1146
diff changeset
277 <seealso>
a7b913d5d589 bring incomplete docs into a shape that can be released
Mike Becker <universe@uap-core.de>
parents: 1146
diff changeset
278 <category ref="apidoc">
a7b913d5d589 bring incomplete docs into a shape that can be released
Mike Becker <universe@uap-core.de>
parents: 1146
diff changeset
279 <a href="https://ucx.sourceforge.io/api/linked__list_8h.html">linked_list.h</a>
a7b913d5d589 bring incomplete docs into a shape that can be released
Mike Becker <universe@uap-core.de>
parents: 1146
diff changeset
280 </category>
a7b913d5d589 bring incomplete docs into a shape that can be released
Mike Becker <universe@uap-core.de>
parents: 1146
diff changeset
281 </seealso>

mercurial