Fri, 23 May 2025 12:44:24 +0200
make test-compile depend on both static and shared
the shared lib is not needed for the tests,
but when run with coverage, gcov will be confused
when outdated line information is available from
a previous shared build
1143
0559812df10c
assign proper names to the documentation topics
Mike Becker <universe@uap-core.de>
parents:
1142
diff
changeset
|
1 | # Linked List |
1141 | 2 | |
3 | On top of implementing the list interface, this header also defines several low-level functions that | |
4 | work with arbitrary structures. | |
1241
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
5 | |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
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 | 24 | struct node { |
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 | 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 | 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 | 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 | 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); |
1141 | 118 | ``` |
1142
9437530176bc
add symbols that need documentation as TODOs
Mike Becker <universe@uap-core.de>
parents:
1141
diff
changeset
|
119 | |
1241
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
120 | 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
|
121 | |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
122 | 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
|
123 | 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
|
124 | 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
|
125 | 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
|
126 | |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
127 | 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
|
128 | `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
|
129 | |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
130 | 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
|
131 | 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
|
132 | 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
|
133 | 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
|
134 | |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
135 | 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
|
136 | 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
|
137 | 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
|
138 | |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
139 | > 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
|
140 | > 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
|
141 | > to maintain the sort order. |
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 | ## Access and Find |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
144 | |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
145 | ```C |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
146 | #include <cx/linked_list.h> |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
147 | |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
148 | 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
|
149 | |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
150 | 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
|
151 | |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
152 | void *cx_linked_list_at(const void *start, |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
153 | 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
|
154 | |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
155 | void *cx_linked_list_find(const void *start, |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
156 | ptrdiff_t loc_advance, ptrdiff_t loc_data, |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
157 | cx_compare_func cmp_func, |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
158 | const void *elem, size_t *found_index); |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
159 | |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
160 | 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
|
161 | ``` |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
162 | |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
163 | 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
|
164 | 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
|
165 | 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
|
166 | |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
167 | 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
|
168 | and finds the node at `index`. |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
169 | 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
|
170 | 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
|
171 | 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
|
172 | 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
|
173 | |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
174 | 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
|
175 | 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
|
176 | 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
|
177 | 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
|
178 | |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
179 | 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
|
180 | |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
181 | > 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
|
182 | > 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
|
183 | |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
184 | ## Remove |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
185 | |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
186 | ```C |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
187 | #include <cx/linked_list.h> |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
188 | |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
189 | 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
|
190 | 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
|
191 | |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
192 | 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
|
193 | ptrdiff_t loc_prev, ptrdiff_t loc_next, |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
194 | void *node, size_t num); |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
195 | ``` |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
196 | |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
197 | 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
|
198 | |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
199 | 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
|
200 | |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
201 | 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
|
202 | 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
|
203 | |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
204 | 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
|
205 | 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
|
206 | |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
207 | > 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
|
208 | > 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
|
209 | >{style="note"} |
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 | > 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
|
212 | > 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
|
213 | > 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
|
214 | |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
215 | ## Reorder |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
216 | |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
217 | ```C |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
218 | #include <cx/linked_list.h> |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
219 | |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
220 | 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
|
221 | ptrdiff_t loc_prev, ptrdiff_t loc_next); |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
222 | |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
223 | 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
|
224 | ptrdiff_t loc_prev, ptrdiff_t loc_next, |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
225 | 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
|
226 | ``` |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
227 | |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
228 | 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
|
229 | |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
230 | 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
|
231 | 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
|
232 | 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
|
233 | |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
234 | > 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
|
235 | > {style="note"} |
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 | > 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
|
238 | > 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
|
239 | > 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
|
240 | |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
241 | ## Compare |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
242 | |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
243 | ```C |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
244 | #include <cx/linked_list.h> |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
245 | |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
246 | int cx_linked_list_compare( |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
247 | const void *begin_left, const void *begin_right, |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
248 | ptrdiff_t loc_advance, ptrdiff_t loc_data, |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
249 | cx_compare_func cmp_func |
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 | ``` |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
252 | |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
253 | 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
|
254 | 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
|
255 | |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
256 | 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
|
257 | 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
|
258 | 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
|
259 | |
ebcc08023c33
complete linked_list.h docu
Mike Becker <universe@uap-core.de>
parents:
1190
diff
changeset
|
260 | 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
|
261 | 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
|
262 | |
a7b913d5d589
bring incomplete docs into a shape that can be released
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
263 | <seealso> |
a7b913d5d589
bring incomplete docs into a shape that can be released
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
264 | <category ref="apidoc"> |
a7b913d5d589
bring incomplete docs into a shape that can be released
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
265 | <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
|
266 | </category> |
a7b913d5d589
bring incomplete docs into a shape that can be released
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
267 | </seealso> |