44 #ifdef __cplusplus |
42 #ifdef __cplusplus |
45 extern "C" { |
43 extern "C" { |
46 #endif |
44 #endif |
47 |
45 |
48 /** |
46 /** |
49 * Set this flag to true, if you want to disable the use of SBO for |
47 * Allocates a linked list for storing elements with @p elem_size bytes each. |
50 * linked list swap operations. |
48 * |
51 */ |
49 * If @p elem_size is #CX_STORE_POINTERS, the created list stores pointers instead of |
52 extern bool CX_DISABLE_LINKED_LIST_SWAP_SBO; |
50 * copies of the added elements and the compare function will be automatically set |
53 |
51 * to cx_cmp_ptr(), if none is given. |
54 /** |
|
55 * Allocates a linked list for storing elements with \p item_size bytes each. |
|
56 * |
|
57 * If \p item_size is CX_STORE_POINTERS, the created list will be created as if |
|
58 * cxListStorePointers() was called immediately after creation. |
|
59 * |
52 * |
60 * @param allocator the allocator for allocating the list nodes |
53 * @param allocator the allocator for allocating the list nodes |
61 * (if \c NULL the cxDefaultAllocator will be used) |
54 * (if @c NULL, a default stdlib allocator will be used) |
62 * @param comparator the comparator for the elements |
55 * @param comparator the comparator for the elements |
63 * (if \c NULL sort and find functions will not work) |
56 * (if @c NULL, and the list is not storing pointers, sort and find |
64 * @param item_size the size of each element in bytes |
57 * functions will not work) |
|
58 * @param elem_size the size of each element in bytes |
65 * @return the created list |
59 * @return the created list |
66 */ |
60 */ |
|
61 cx_attr_nodiscard |
|
62 cx_attr_malloc |
|
63 cx_attr_dealloc(cxListFree, 1) |
|
64 cx_attr_export |
67 CxList *cxLinkedListCreate( |
65 CxList *cxLinkedListCreate( |
68 CxAllocator const *allocator, |
66 const CxAllocator *allocator, |
69 cx_compare_func comparator, |
67 cx_compare_func comparator, |
70 size_t item_size |
68 size_t elem_size |
71 ); |
69 ); |
72 |
70 |
73 /** |
71 /** |
74 * Allocates a linked list for storing elements with \p item_size bytes each. |
72 * Allocates a linked list for storing elements with @p elem_size bytes each. |
75 * |
73 * |
76 * The list will use cxDefaultAllocator and no comparator function. If you want |
74 * The list will use cxDefaultAllocator and no comparator function. If you want |
77 * to call functions that need a comparator, you must either set one immediately |
75 * to call functions that need a comparator, you must either set one immediately |
78 * after list creation or use cxLinkedListCreate(). |
76 * after list creation or use cxLinkedListCreate(). |
79 * |
77 * |
80 * If \p item_size is CX_STORE_POINTERS, the created list will be created as if |
78 * If @p elem_size is #CX_STORE_POINTERS, the created list stores pointers instead of |
81 * cxListStorePointers() was called immediately after creation. |
79 * copies of the added elements and the compare function will be automatically set |
82 * |
80 * to cx_cmp_ptr(), if none is given. |
83 * @param item_size the size of each element in bytes |
81 * |
84 * @return the created list |
82 * @param elem_size (@c size_t) the size of each element in bytes |
85 */ |
83 * @return (@c CxList*) the created list |
86 #define cxLinkedListCreateSimple(item_size) \ |
84 */ |
87 cxLinkedListCreate(NULL, NULL, item_size) |
85 #define cxLinkedListCreateSimple(elem_size) \ |
|
86 cxLinkedListCreate(NULL, NULL, elem_size) |
88 |
87 |
89 /** |
88 /** |
90 * Finds the node at a certain index. |
89 * Finds the node at a certain index. |
91 * |
90 * |
92 * This function can be used to start at an arbitrary position within the list. |
91 * This function can be used to start at an arbitrary position within the list. |
93 * If the search index is large than the start index, \p loc_advance must denote |
92 * If the search index is large than the start index, @p loc_advance must denote |
94 * the location of some sort of \c next pointer (i.e. a pointer to the next node). |
93 * the location of some sort of @c next pointer (i.e. a pointer to the next node). |
95 * But it is also possible that the search index is smaller than the start index |
94 * But it is also possible that the search index is smaller than the start index |
96 * (e.g. in cases where traversing a list backwards is faster) in which case |
95 * (e.g. in cases where traversing a list backwards is faster) in which case |
97 * \p loc_advance must denote the location of some sort of \c prev pointer |
96 * @p loc_advance must denote the location of some sort of @c prev pointer |
98 * (i.e. a pointer to the previous node). |
97 * (i.e. a pointer to the previous node). |
99 * |
98 * |
100 * @param start a pointer to the start node |
99 * @param start a pointer to the start node |
101 * @param start_index the start index |
100 * @param start_index the start index |
102 * @param loc_advance the location of the pointer to advance |
101 * @param loc_advance the location of the pointer to advance |
103 * @param index the search index |
102 * @param index the search index |
104 * @return the node found at the specified index |
103 * @return the node found at the specified index |
105 */ |
104 */ |
|
105 cx_attr_nonnull |
|
106 cx_attr_nodiscard |
|
107 cx_attr_export |
106 void *cx_linked_list_at( |
108 void *cx_linked_list_at( |
107 void const *start, |
109 const void *start, |
108 size_t start_index, |
110 size_t start_index, |
109 ptrdiff_t loc_advance, |
111 ptrdiff_t loc_advance, |
110 size_t index |
112 size_t index |
111 ) __attribute__((__nonnull__)); |
113 ); |
112 |
114 |
113 /** |
115 /** |
114 * Finds the index of an element within a linked list. |
116 * Finds the node containing an element within a linked list. |
115 * |
117 * |
116 * @param start a pointer to the start node |
118 * @param start a pointer to the start node |
117 * @param loc_advance the location of the pointer to advance |
119 * @param loc_advance the location of the pointer to advance |
118 * @param loc_data the location of the \c data pointer within your node struct |
120 * @param loc_data the location of the @c data pointer within your node struct |
119 * @param cmp_func a compare function to compare \p elem against the node data |
121 * @param cmp_func a compare function to compare @p elem against the node data |
120 * @param elem a pointer to the element to find |
122 * @param elem a pointer to the element to find |
121 * @return the index of the element or a negative value if it could not be found |
123 * @param found_index an optional pointer where the index of the found node |
122 */ |
124 * (given that @p start has index 0) is stored |
123 ssize_t cx_linked_list_find( |
125 * @return the index of the element, if found - unspecified if not found |
124 void const *start, |
126 */ |
|
127 cx_attr_nonnull_arg(1, 4, 5) |
|
128 cx_attr_export |
|
129 void *cx_linked_list_find( |
|
130 const void *start, |
125 ptrdiff_t loc_advance, |
131 ptrdiff_t loc_advance, |
126 ptrdiff_t loc_data, |
132 ptrdiff_t loc_data, |
127 cx_compare_func cmp_func, |
133 cx_compare_func cmp_func, |
128 void const *elem |
134 const void *elem, |
129 ) __attribute__((__nonnull__)); |
135 size_t *found_index |
|
136 ); |
130 |
137 |
131 /** |
138 /** |
132 * Finds the first node in a linked list. |
139 * Finds the first node in a linked list. |
133 * |
140 * |
134 * The function starts with the pointer denoted by \p node and traverses the list |
141 * The function starts with the pointer denoted by @p node and traverses the list |
135 * along a prev pointer whose location within the node struct is |
142 * along a prev pointer whose location within the node struct is |
136 * denoted by \p loc_prev. |
143 * denoted by @p loc_prev. |
137 * |
144 * |
138 * @param node a pointer to a node in the list |
145 * @param node a pointer to a node in the list |
139 * @param loc_prev the location of the \c prev pointer |
146 * @param loc_prev the location of the @c prev pointer |
140 * @return a pointer to the first node |
147 * @return a pointer to the first node |
141 */ |
148 */ |
|
149 cx_attr_nonnull |
|
150 cx_attr_returns_nonnull |
|
151 cx_attr_export |
142 void *cx_linked_list_first( |
152 void *cx_linked_list_first( |
143 void const *node, |
153 const void *node, |
144 ptrdiff_t loc_prev |
154 ptrdiff_t loc_prev |
145 ) __attribute__((__nonnull__)); |
155 ); |
146 |
156 |
147 /** |
157 /** |
148 * Finds the last node in a linked list. |
158 * Finds the last node in a linked list. |
149 * |
159 * |
150 * The function starts with the pointer denoted by \p node and traverses the list |
160 * The function starts with the pointer denoted by @p node and traverses the list |
151 * along a next pointer whose location within the node struct is |
161 * along a next pointer whose location within the node struct is |
152 * denoted by \p loc_next. |
162 * denoted by @p loc_next. |
153 * |
163 * |
154 * @param node a pointer to a node in the list |
164 * @param node a pointer to a node in the list |
155 * @param loc_next the location of the \c next pointer |
165 * @param loc_next the location of the @c next pointer |
156 * @return a pointer to the last node |
166 * @return a pointer to the last node |
157 */ |
167 */ |
|
168 cx_attr_nonnull |
|
169 cx_attr_returns_nonnull |
|
170 cx_attr_export |
158 void *cx_linked_list_last( |
171 void *cx_linked_list_last( |
159 void const *node, |
172 const void *node, |
160 ptrdiff_t loc_next |
173 ptrdiff_t loc_next |
161 ) __attribute__((__nonnull__)); |
174 ); |
162 |
175 |
163 /** |
176 /** |
164 * Finds the predecessor of a node in case it is not linked. |
177 * Finds the predecessor of a node in case it is not linked. |
165 * |
178 * |
166 * \remark If \p node is not contained in the list starting with \p begin, the behavior is undefined. |
179 * @remark If @p node is not contained in the list starting with @p begin, the behavior is undefined. |
167 * |
180 * |
168 * @param begin the node where to start the search |
181 * @param begin the node where to start the search |
169 * @param loc_next the location of the \c next pointer |
182 * @param loc_next the location of the @c next pointer |
170 * @param node the successor of the node to find |
183 * @param node the successor of the node to find |
171 * @return the node or \c NULL if \p node has no predecessor |
184 * @return the node or @c NULL if @p node has no predecessor |
172 */ |
185 */ |
|
186 cx_attr_nonnull |
|
187 cx_attr_export |
173 void *cx_linked_list_prev( |
188 void *cx_linked_list_prev( |
174 void const *begin, |
189 const void *begin, |
175 ptrdiff_t loc_next, |
190 ptrdiff_t loc_next, |
176 void const *node |
191 const void *node |
177 ) __attribute__((__nonnull__)); |
192 ); |
178 |
193 |
179 /** |
194 /** |
180 * Adds a new node to a linked list. |
195 * Adds a new node to a linked list. |
181 * The node must not be part of any list already. |
196 * The node must not be part of any list already. |
182 * |
197 * |
183 * \remark One of the pointers \p begin or \p end may be \c NULL, but not both. |
198 * @remark One of the pointers @p begin or @p end may be @c NULL, but not both. |
184 * |
199 * |
185 * @param begin a pointer to the begin node pointer (if your list has one) |
200 * @param begin a pointer to the beginning node pointer (if your list has one) |
186 * @param end a pointer to the end node pointer (if your list has one) |
201 * @param end a pointer to the end node pointer (if your list has one) |
187 * @param loc_prev the location of a \c prev pointer within your node struct (negative if your struct does not have one) |
202 * @param loc_prev the location of a @c prev pointer within your node struct (negative if your struct does not have one) |
188 * @param loc_next the location of a \c next pointer within your node struct (required) |
203 * @param loc_next the location of a @c next pointer within your node struct (required) |
189 * @param new_node a pointer to the node that shall be appended |
204 * @param new_node a pointer to the node that shall be appended |
190 */ |
205 */ |
|
206 cx_attr_nonnull_arg(5) |
|
207 cx_attr_export |
191 void cx_linked_list_add( |
208 void cx_linked_list_add( |
192 void **begin, |
209 void **begin, |
193 void **end, |
210 void **end, |
194 ptrdiff_t loc_prev, |
211 ptrdiff_t loc_prev, |
195 ptrdiff_t loc_next, |
212 ptrdiff_t loc_next, |
196 void *new_node |
213 void *new_node |
197 ) __attribute__((__nonnull__(5))); |
214 ); |
198 |
215 |
199 /** |
216 /** |
200 * Prepends a new node to a linked list. |
217 * Prepends a new node to a linked list. |
201 * The node must not be part of any list already. |
218 * The node must not be part of any list already. |
202 * |
219 * |
203 * \remark One of the pointers \p begin or \p end may be \c NULL, but not both. |
220 * @remark One of the pointers @p begin or @p end may be @c NULL, but not both. |
204 * |
221 * |
205 * @param begin a pointer to the begin node pointer (if your list has one) |
222 * @param begin a pointer to the beginning node pointer (if your list has one) |
206 * @param end a pointer to the end node pointer (if your list has one) |
223 * @param end a pointer to the end node pointer (if your list has one) |
207 * @param loc_prev the location of a \c prev pointer within your node struct (negative if your struct does not have one) |
224 * @param loc_prev the location of a @c prev pointer within your node struct (negative if your struct does not have one) |
208 * @param loc_next the location of a \c next pointer within your node struct (required) |
225 * @param loc_next the location of a @c next pointer within your node struct (required) |
209 * @param new_node a pointer to the node that shall be prepended |
226 * @param new_node a pointer to the node that shall be prepended |
210 */ |
227 */ |
|
228 cx_attr_nonnull_arg(5) |
|
229 cx_attr_export |
211 void cx_linked_list_prepend( |
230 void cx_linked_list_prepend( |
212 void **begin, |
231 void **begin, |
213 void **end, |
232 void **end, |
214 ptrdiff_t loc_prev, |
233 ptrdiff_t loc_prev, |
215 ptrdiff_t loc_next, |
234 ptrdiff_t loc_next, |
216 void *new_node |
235 void *new_node |
217 ) __attribute__((__nonnull__(5))); |
236 ); |
218 |
237 |
219 /** |
238 /** |
220 * Links two nodes. |
239 * Links two nodes. |
221 * |
240 * |
222 * @param left the new predecessor of \p right |
241 * @param left the new predecessor of @p right |
223 * @param right the new successor of \p left |
242 * @param right the new successor of @p left |
224 * @param loc_prev the location of a \c prev pointer within your node struct (negative if your struct does not have one) |
243 * @param loc_prev the location of a @c prev pointer within your node struct (negative if your struct does not have one) |
225 * @param loc_next the location of a \c next pointer within your node struct (required) |
244 * @param loc_next the location of a @c next pointer within your node struct (required) |
226 */ |
245 */ |
|
246 cx_attr_nonnull |
|
247 cx_attr_export |
227 void cx_linked_list_link( |
248 void cx_linked_list_link( |
228 void *left, |
249 void *left, |
229 void *right, |
250 void *right, |
230 ptrdiff_t loc_prev, |
251 ptrdiff_t loc_prev, |
231 ptrdiff_t loc_next |
252 ptrdiff_t loc_next |
232 ) __attribute__((__nonnull__)); |
253 ); |
233 |
254 |
234 /** |
255 /** |
235 * Unlinks two nodes. |
256 * Unlinks two nodes. |
236 * |
257 * |
237 * If right is not the successor of left, the behavior is undefined. |
258 * If right is not the successor of left, the behavior is undefined. |
238 * |
259 * |
239 * @param left the predecessor of \p right |
260 * @param left the predecessor of @p right |
240 * @param right the successor of \p left |
261 * @param right the successor of @p left |
241 * @param loc_prev the location of a \c prev pointer within your node struct (negative if your struct does not have one) |
262 * @param loc_prev the location of a @c prev pointer within your node struct (negative if your struct does not have one) |
242 * @param loc_next the location of a \c next pointer within your node struct (required) |
263 * @param loc_next the location of a @c next pointer within your node struct (required) |
243 */ |
264 */ |
|
265 cx_attr_nonnull |
|
266 cx_attr_export |
244 void cx_linked_list_unlink( |
267 void cx_linked_list_unlink( |
245 void *left, |
268 void *left, |
246 void *right, |
269 void *right, |
247 ptrdiff_t loc_prev, |
270 ptrdiff_t loc_prev, |
248 ptrdiff_t loc_next |
271 ptrdiff_t loc_next |
249 ) __attribute__((__nonnull__)); |
272 ); |
250 |
273 |
251 /** |
274 /** |
252 * Inserts a new node after a given node of a linked list. |
275 * Inserts a new node after a given node of a linked list. |
253 * The new node must not be part of any list already. |
276 * The new node must not be part of any list already. |
254 * |
277 * |
255 * \note If you specify \c NULL as the \p node to insert after, this function needs either the \p begin or |
278 * @note If you specify @c NULL as the @p node to insert after, this function needs either the @p begin or |
256 * the \p end pointer to determine the start of the list. Then the new node will be prepended to the list. |
279 * the @p end pointer to determine the start of the list. Then the new node will be prepended to the list. |
257 * |
280 * |
258 * @param begin a pointer to the begin node pointer (if your list has one) |
281 * @param begin a pointer to the beginning node pointer (if your list has one) |
259 * @param end a pointer to the end node pointer (if your list has one) |
282 * @param end a pointer to the end node pointer (if your list has one) |
260 * @param loc_prev the location of a \c prev pointer within your node struct (negative if your struct does not have one) |
283 * @param loc_prev the location of a @c prev pointer within your node struct (negative if your struct does not have one) |
261 * @param loc_next the location of a \c next pointer within your node struct (required) |
284 * @param loc_next the location of a @c next pointer within your node struct (required) |
262 * @param node the node after which to insert (\c NULL if you want to prepend the node to the list) |
285 * @param node the node after which to insert (@c NULL if you want to prepend the node to the list) |
263 * @param new_node a pointer to the node that shall be prepended |
286 * @param new_node a pointer to the node that shall be inserted |
264 */ |
287 */ |
|
288 cx_attr_nonnull_arg(6) |
|
289 cx_attr_export |
265 void cx_linked_list_insert( |
290 void cx_linked_list_insert( |
266 void **begin, |
291 void **begin, |
267 void **end, |
292 void **end, |
268 ptrdiff_t loc_prev, |
293 ptrdiff_t loc_prev, |
269 ptrdiff_t loc_next, |
294 ptrdiff_t loc_next, |
270 void *node, |
295 void *node, |
271 void *new_node |
296 void *new_node |
272 ) __attribute__((__nonnull__(6))); |
297 ); |
273 |
298 |
274 /** |
299 /** |
275 * Inserts a chain of nodes after a given node of a linked list. |
300 * Inserts a chain of nodes after a given node of a linked list. |
276 * The chain must not be part of any list already. |
301 * The chain must not be part of any list already. |
277 * |
302 * |
278 * If you do not explicitly specify the end of the chain, it will be determined by traversing |
303 * If you do not explicitly specify the end of the chain, it will be determined by traversing |
279 * the \c next pointer. |
304 * the @c next pointer. |
280 * |
305 * |
281 * \note If you specify \c NULL as the \p node to insert after, this function needs either the \p begin or |
306 * @note If you specify @c NULL as the @p node to insert after, this function needs either the @p begin or |
282 * the \p end pointer to determine the start of the list. If only the \p end pointer is specified, you also need |
307 * the @p end pointer to determine the start of the list. If only the @p end pointer is specified, you also need |
283 * to provide a valid \p loc_prev location. |
308 * to provide a valid @p loc_prev location. |
284 * Then the chain will be prepended to the list. |
309 * Then the chain will be prepended to the list. |
285 * |
310 * |
286 * @param begin a pointer to the begin node pointer (if your list has one) |
311 * @param begin a pointer to the beginning node pointer (if your list has one) |
287 * @param end a pointer to the end node pointer (if your list has one) |
312 * @param end a pointer to the end node pointer (if your list has one) |
288 * @param loc_prev the location of a \c prev pointer within your node struct (negative if your struct does not have one) |
313 * @param loc_prev the location of a @c prev pointer within your node struct (negative if your struct does not have one) |
289 * @param loc_next the location of a \c next pointer within your node struct (required) |
314 * @param loc_next the location of a @c next pointer within your node struct (required) |
290 * @param node the node after which to insert (\c NULL to prepend the chain to the list) |
315 * @param node the node after which to insert (@c NULL to prepend the chain to the list) |
291 * @param insert_begin a pointer to the first node of the chain that shall be inserted |
316 * @param insert_begin a pointer to the first node of the chain that shall be inserted |
292 * @param insert_end a pointer to the last node of the chain (or NULL if the last node shall be determined) |
317 * @param insert_end a pointer to the last node of the chain (or NULL if the last node shall be determined) |
293 */ |
318 */ |
|
319 cx_attr_nonnull_arg(6) |
|
320 cx_attr_export |
294 void cx_linked_list_insert_chain( |
321 void cx_linked_list_insert_chain( |
295 void **begin, |
322 void **begin, |
296 void **end, |
323 void **end, |
297 ptrdiff_t loc_prev, |
324 ptrdiff_t loc_prev, |
298 ptrdiff_t loc_next, |
325 ptrdiff_t loc_next, |
299 void *node, |
326 void *node, |
300 void *insert_begin, |
327 void *insert_begin, |
301 void *insert_end |
328 void *insert_end |
302 ) __attribute__((__nonnull__(6))); |
329 ); |
|
330 |
|
331 /** |
|
332 * Inserts a node into a sorted linked list. |
|
333 * The new node must not be part of any list already. |
|
334 * |
|
335 * If the list starting with the node pointed to by @p begin is not sorted |
|
336 * already, the behavior is undefined. |
|
337 * |
|
338 * @param begin a pointer to the beginning node pointer (required) |
|
339 * @param end a pointer to the end node pointer (if your list has one) |
|
340 * @param loc_prev the location of a @c prev pointer within your node struct (negative if your struct does not have one) |
|
341 * @param loc_next the location of a @c next pointer within your node struct (required) |
|
342 * @param new_node a pointer to the node that shall be inserted |
|
343 * @param cmp_func a compare function that will receive the node pointers |
|
344 */ |
|
345 cx_attr_nonnull_arg(1, 5, 6) |
|
346 cx_attr_export |
|
347 void cx_linked_list_insert_sorted( |
|
348 void **begin, |
|
349 void **end, |
|
350 ptrdiff_t loc_prev, |
|
351 ptrdiff_t loc_next, |
|
352 void *new_node, |
|
353 cx_compare_func cmp_func |
|
354 ); |
|
355 |
|
356 /** |
|
357 * Inserts a chain of nodes into a sorted linked list. |
|
358 * The chain must not be part of any list already. |
|
359 * |
|
360 * If either the list starting with the node pointed to by @p begin or the list |
|
361 * starting with @p insert_begin is not sorted, the behavior is undefined. |
|
362 * |
|
363 * @attention In contrast to cx_linked_list_insert_chain(), the source chain |
|
364 * will be broken and inserted into the target list so that the resulting list |
|
365 * will be sorted according to @p cmp_func. That means, each node in the source |
|
366 * chain may be re-linked with nodes from the target list. |
|
367 * |
|
368 * @param begin a pointer to the beginning node pointer (required) |
|
369 * @param end a pointer to the end node pointer (if your list has one) |
|
370 * @param loc_prev the location of a @c prev pointer within your node struct (negative if your struct does not have one) |
|
371 * @param loc_next the location of a @c next pointer within your node struct (required) |
|
372 * @param insert_begin a pointer to the first node of the chain that shall be inserted |
|
373 * @param cmp_func a compare function that will receive the node pointers |
|
374 */ |
|
375 cx_attr_nonnull_arg(1, 5, 6) |
|
376 cx_attr_export |
|
377 void cx_linked_list_insert_sorted_chain( |
|
378 void **begin, |
|
379 void **end, |
|
380 ptrdiff_t loc_prev, |
|
381 ptrdiff_t loc_next, |
|
382 void *insert_begin, |
|
383 cx_compare_func cmp_func |
|
384 ); |
|
385 |
|
386 /** |
|
387 * Removes a chain of nodes from the linked list. |
|
388 * |
|
389 * If one of the nodes to remove is the beginning (resp. end) node of the list and if @p begin (resp. @p end) |
|
390 * addresses are provided, the pointers are adjusted accordingly. |
|
391 * |
|
392 * The following combinations of arguments are valid (more arguments are optional): |
|
393 * @li @p loc_next and @p loc_prev (ancestor node is determined by using the prev pointer, overall O(1) performance) |
|
394 * @li @p loc_next and @p begin (ancestor node is determined by list traversal, overall O(n) performance) |
|
395 * |
|
396 * @remark The @c next and @c prev pointers of the removed node are not cleared by this function and may still be used |
|
397 * to traverse to a former adjacent node in the list, or within the chain. |
|
398 * |
|
399 * @param begin a pointer to the beginning node pointer (optional) |
|
400 * @param end a pointer to the end node pointer (optional) |
|
401 * @param loc_prev the location of a @c prev pointer within your node struct (negative if your struct does not have one) |
|
402 * @param loc_next the location of a @c next pointer within your node struct (required) |
|
403 * @param node the start node of the chain |
|
404 * @param num the number of nodes to remove |
|
405 * @return the actual number of nodes that were removed (can be less when the list did not have enough nodes) |
|
406 */ |
|
407 cx_attr_nonnull_arg(5) |
|
408 cx_attr_export |
|
409 size_t cx_linked_list_remove_chain( |
|
410 void **begin, |
|
411 void **end, |
|
412 ptrdiff_t loc_prev, |
|
413 ptrdiff_t loc_next, |
|
414 void *node, |
|
415 size_t num |
|
416 ); |
303 |
417 |
304 /** |
418 /** |
305 * Removes a node from the linked list. |
419 * Removes a node from the linked list. |
306 * |
420 * |
307 * If the node to remove is the begin (resp. end) node of the list and if \p begin (resp. \p end) |
421 * If the node to remove is the beginning (resp. end) node of the list and if @p begin (resp. @p end) |
308 * addresses are provided, the pointers are adjusted accordingly. |
422 * addresses are provided, the pointers are adjusted accordingly. |
309 * |
423 * |
310 * The following combinations of arguments are valid (more arguments are optional): |
424 * The following combinations of arguments are valid (more arguments are optional): |
311 * \li \p loc_next and \p loc_prev (ancestor node is determined by using the prev pointer, overall O(1) performance) |
425 * @li @p loc_next and @p loc_prev (ancestor node is determined by using the prev pointer, overall O(1) performance) |
312 * \li \p loc_next and \p begin (ancestor node is determined by list traversal, overall O(n) performance) |
426 * @li @p loc_next and @p begin (ancestor node is determined by list traversal, overall O(n) performance) |
313 * |
427 * |
314 * \remark The \c next and \c prev pointers of the removed node are not cleared by this function and may still be used |
428 * @remark The @c next and @c prev pointers of the removed node are not cleared by this function and may still be used |
315 * to traverse to a former adjacent node in the list. |
429 * to traverse to a former adjacent node in the list. |
316 * |
430 * |
317 * @param begin a pointer to the begin node pointer (optional) |
431 * @param begin a pointer to the beginning node pointer (optional) |
318 * @param end a pointer to the end node pointer (optional) |
432 * @param end a pointer to the end node pointer (optional) |
319 * @param loc_prev the location of a \c prev pointer within your node struct (negative if your struct does not have one) |
433 * @param loc_prev the location of a @c prev pointer within your node struct (negative if your struct does not have one) |
320 * @param loc_next the location of a \c next pointer within your node struct (required) |
434 * @param loc_next the location of a @c next pointer within your node struct (required) |
321 * @param node the node to remove |
435 * @param node the node to remove |
322 */ |
436 */ |
323 void cx_linked_list_remove( |
437 cx_attr_nonnull_arg(5) |
|
438 static inline void cx_linked_list_remove( |
324 void **begin, |
439 void **begin, |
325 void **end, |
440 void **end, |
326 ptrdiff_t loc_prev, |
441 ptrdiff_t loc_prev, |
327 ptrdiff_t loc_next, |
442 ptrdiff_t loc_next, |
328 void *node |
443 void *node |
329 ) __attribute__((__nonnull__(5))); |
444 ) { |
330 |
445 cx_linked_list_remove_chain(begin, end, loc_prev, loc_next, node, 1); |
331 |
446 } |
332 /** |
447 |
333 * Determines the size of a linked list starting with \p node. |
448 /** |
|
449 * Determines the size of a linked list starting with @p node. |
|
450 * |
334 * @param node the first node |
451 * @param node the first node |
335 * @param loc_next the location of the \c next pointer within the node struct |
452 * @param loc_next the location of the @c next pointer within the node struct |
336 * @return the size of the list or zero if \p node is \c NULL |
453 * @return the size of the list or zero if @p node is @c NULL |
337 */ |
454 */ |
|
455 cx_attr_nodiscard |
|
456 cx_attr_export |
338 size_t cx_linked_list_size( |
457 size_t cx_linked_list_size( |
339 void const *node, |
458 const void *node, |
340 ptrdiff_t loc_next |
459 ptrdiff_t loc_next |
341 ); |
460 ); |
342 |
461 |
343 /** |
462 /** |
344 * Sorts a linked list based on a comparison function. |
463 * Sorts a linked list based on a comparison function. |
345 * |
464 * |
346 * This function can work with linked lists of the following structure: |
465 * This function can work with linked lists of the following structure: |
347 * \code |
466 * @code |
348 * typedef struct node node; |
467 * typedef struct node node; |
349 * struct node { |
468 * struct node { |
350 * node* prev; |
469 * node* prev; |
351 * node* next; |
470 * node* next; |
352 * my_payload data; |
471 * my_payload data; |
353 * } |
472 * } |
354 * \endcode |
473 * @endcode |
355 * |
474 * |
356 * @note This is a recursive function with at most logarithmic recursion depth. |
475 * @note This is a recursive function with at most logarithmic recursion depth. |
357 * |
476 * |
358 * @param begin a pointer to the begin node pointer (required) |
477 * @param begin a pointer to the beginning node pointer (required) |
359 * @param end a pointer to the end node pointer (optional) |
478 * @param end a pointer to the end node pointer (optional) |
360 * @param loc_prev the location of a \c prev pointer within your node struct (negative if not present) |
479 * @param loc_prev the location of a @c prev pointer within your node struct (negative if not present) |
361 * @param loc_next the location of a \c next pointer within your node struct (required) |
480 * @param loc_next the location of a @c next pointer within your node struct (required) |
362 * @param loc_data the location of the \c data pointer within your node struct |
481 * @param loc_data the location of the @c data pointer within your node struct |
363 * @param cmp_func the compare function defining the sort order |
482 * @param cmp_func the compare function defining the sort order |
364 */ |
483 */ |
|
484 cx_attr_nonnull_arg(1, 6) |
|
485 cx_attr_export |
365 void cx_linked_list_sort( |
486 void cx_linked_list_sort( |
366 void **begin, |
487 void **begin, |
367 void **end, |
488 void **end, |
368 ptrdiff_t loc_prev, |
489 ptrdiff_t loc_prev, |
369 ptrdiff_t loc_next, |
490 ptrdiff_t loc_next, |
370 ptrdiff_t loc_data, |
491 ptrdiff_t loc_data, |
371 cx_compare_func cmp_func |
492 cx_compare_func cmp_func |
372 ) __attribute__((__nonnull__(1, 6))); |
493 ); |
373 |
494 |
374 |
495 |
375 /** |
496 /** |
376 * Compares two lists element wise. |
497 * Compares two lists element wise. |
377 * |
498 * |
378 * \note Both list must have the same structure. |
499 * @attention Both list must have the same structure. |
379 * |
500 * |
380 * @param begin_left the begin of the left list (\c NULL denotes an empty list) |
501 * @param begin_left the beginning of the left list (@c NULL denotes an empty list) |
381 * @param begin_right the begin of the right list (\c NULL denotes an empty list) |
502 * @param begin_right the beginning of the right list (@c NULL denotes an empty list) |
382 * @param loc_advance the location of the pointer to advance |
503 * @param loc_advance the location of the pointer to advance |
383 * @param loc_data the location of the \c data pointer within your node struct |
504 * @param loc_data the location of the @c data pointer within your node struct |
384 * @param cmp_func the function to compare the elements |
505 * @param cmp_func the function to compare the elements |
385 * @return the first non-zero result of invoking \p cmp_func or: negative if the left list is smaller than the |
506 * @return the first non-zero result of invoking @p cmp_func or: negative if the left list is smaller than the |
386 * right list, positive if the left list is larger than the right list, zero if both lists are equal. |
507 * right list, positive if the left list is larger than the right list, zero if both lists are equal. |
387 */ |
508 */ |
|
509 cx_attr_nonnull_arg(5) |
|
510 cx_attr_export |
388 int cx_linked_list_compare( |
511 int cx_linked_list_compare( |
389 void const *begin_left, |
512 const void *begin_left, |
390 void const *begin_right, |
513 const void *begin_right, |
391 ptrdiff_t loc_advance, |
514 ptrdiff_t loc_advance, |
392 ptrdiff_t loc_data, |
515 ptrdiff_t loc_data, |
393 cx_compare_func cmp_func |
516 cx_compare_func cmp_func |
394 ) __attribute__((__nonnull__(5))); |
517 ); |
395 |
518 |
396 /** |
519 /** |
397 * Reverses the order of the nodes in a linked list. |
520 * Reverses the order of the nodes in a linked list. |
398 * |
521 * |
399 * @param begin a pointer to the begin node pointer (required) |
522 * @param begin a pointer to the beginning node pointer (required) |
400 * @param end a pointer to the end node pointer (optional) |
523 * @param end a pointer to the end node pointer (optional) |
401 * @param loc_prev the location of a \c prev pointer within your node struct (negative if your struct does not have one) |
524 * @param loc_prev the location of a @c prev pointer within your node struct (negative if your struct does not have one) |
402 * @param loc_next the location of a \c next pointer within your node struct (required) |
525 * @param loc_next the location of a @c next pointer within your node struct (required) |
403 */ |
526 */ |
|
527 cx_attr_nonnull_arg(1) |
|
528 cx_attr_export |
404 void cx_linked_list_reverse( |
529 void cx_linked_list_reverse( |
405 void **begin, |
530 void **begin, |
406 void **end, |
531 void **end, |
407 ptrdiff_t loc_prev, |
532 ptrdiff_t loc_prev, |
408 ptrdiff_t loc_next |
533 ptrdiff_t loc_next |
409 ) __attribute__((__nonnull__(1))); |
534 ); |
410 |
535 |
411 #ifdef __cplusplus |
536 #ifdef __cplusplus |
412 } // extern "C" |
537 } // extern "C" |
413 #endif |
538 #endif |
414 |
539 |