| 42 #ifdef __cplusplus |
42 #ifdef __cplusplus |
| 43 extern "C" { |
43 extern "C" { |
| 44 #endif |
44 #endif |
| 45 |
45 |
| 46 /** |
46 /** |
| |
47 * Metadata for a linked list. |
| |
48 */ |
| |
49 typedef struct cx_linked_list_s { |
| |
50 /** Base members. */ |
| |
51 struct cx_list_s base; |
| |
52 /** |
| |
53 * Location of the prev pointer (mandatory). |
| |
54 */ |
| |
55 off_t loc_prev; |
| |
56 /** |
| |
57 * Location of the next pointer (mandatory). |
| |
58 */ |
| |
59 off_t loc_next; |
| |
60 /** |
| |
61 * Location of the payload (mandatory). |
| |
62 */ |
| |
63 off_t loc_data; |
| |
64 /** |
| |
65 * Additional bytes to allocate @em behind the payload (e.g. for metadata). |
| |
66 */ |
| |
67 size_t extra_data_len; |
| |
68 /** |
| |
69 * Pointer to the first node. |
| |
70 */ |
| |
71 void *begin; |
| |
72 /** |
| |
73 * Pointer to the last node. |
| |
74 */ |
| |
75 void *end; |
| |
76 } cx_linked_list; |
| |
77 |
| |
78 /** |
| 47 * Allocates a linked list for storing elements with @p elem_size bytes each. |
79 * Allocates a linked list for storing elements with @p elem_size bytes each. |
| 48 * |
80 * |
| 49 * If @p elem_size is #CX_STORE_POINTERS, the created list stores pointers instead of |
81 * If @p elem_size is #CX_STORE_POINTERS, the created list stores pointers instead of |
| 50 * copies of the added elements and the compare function will be automatically set |
82 * copies of the added elements, and the compare function will be automatically set |
| 51 * to cx_cmp_ptr(), if none is given. |
83 * to cx_cmp_ptr() if none is given. |
| 52 * |
84 * |
| 53 * @param allocator the allocator for allocating the list nodes |
85 * @param allocator the allocator for allocating the list nodes |
| 54 * (if @c NULL, the cxDefaultAllocator will be used) |
86 * (if @c NULL, the cxDefaultAllocator will be used) |
| 55 * @param comparator the comparator for the elements |
87 * @param comparator the comparator for the elements |
| 56 * (if @c NULL, and the list is not storing pointers, sort and find |
88 * (if @c NULL, and the list is not storing pointers, sort and find |
| 74 * The list will use cxDefaultAllocator and no comparator function. If you want |
106 * The list will use cxDefaultAllocator and no comparator function. If you want |
| 75 * to call functions that need a comparator, you must either set one immediately |
107 * to call functions that need a comparator, you must either set one immediately |
| 76 * after list creation or use cxLinkedListCreate(). |
108 * after list creation or use cxLinkedListCreate(). |
| 77 * |
109 * |
| 78 * If @p elem_size is #CX_STORE_POINTERS, the created list stores pointers instead of |
110 * If @p elem_size is #CX_STORE_POINTERS, the created list stores pointers instead of |
| 79 * copies of the added elements and the compare function will be automatically set |
111 * copies of the added elements, and the compare function will be automatically set |
| 80 * to cx_cmp_ptr(). |
112 * to cx_cmp_ptr(). |
| 81 * |
113 * |
| 82 * @param elem_size (@c size_t) the size of each element in bytes |
114 * @param elem_size (@c size_t) the size of each element in bytes |
| 83 * @return (@c CxList*) the created list |
115 * @return (@c CxList*) the created list |
| 84 */ |
116 */ |
| 87 |
119 |
| 88 /** |
120 /** |
| 89 * Finds the node at a certain index. |
121 * Finds the node at a certain index. |
| 90 * |
122 * |
| 91 * This function can be used to start at an arbitrary position within the list. |
123 * This function can be used to start at an arbitrary position within the list. |
| 92 * If the search index is large than the start index, @p loc_advance must denote |
124 * If the search index is larger than the start index, @p loc_advance must denote |
| 93 * the location of some sort of @c next pointer (i.e. a pointer to the next node). |
125 * the location of a @c next pointer (i.e., a pointer to the next node). |
| 94 * But it is also possible that the search index is smaller than the start index |
126 * But it is also possible that the search index is smaller than the start index |
| 95 * (e.g. in cases where traversing a list backwards is faster) in which case |
127 * (e.g., in cases where traversing a list backwards is faster). |
| 96 * @p loc_advance must denote the location of some sort of @c prev pointer |
128 * In that case @p loc_advance must denote the location of a @c prev pointer |
| 97 * (i.e. a pointer to the previous node). |
129 * (i.e., a pointer to the previous node). |
| 98 * |
130 * |
| 99 * @param start a pointer to the start node |
131 * @param start a pointer to the start node |
| 100 * @param start_index the start index |
132 * @param start_index the start index |
| 101 * @param loc_advance the location of the pointer to advance |
133 * @param loc_advance the location of the pointer to advance |
| 102 * @param index the search index |
134 * @param index the search index |
| 120 * @param loc_data the location of the @c data pointer within your node struct |
152 * @param loc_data the location of the @c data pointer within your node struct |
| 121 * @param cmp_func a compare function to compare @p elem against the node data |
153 * @param cmp_func a compare function to compare @p elem against the node data |
| 122 * @param elem a pointer to the element to find |
154 * @param elem a pointer to the element to find |
| 123 * @param found_index an optional pointer where the index of the found node |
155 * @param found_index an optional pointer where the index of the found node |
| 124 * (given that @p start has index 0) is stored |
156 * (given that @p start has index 0) is stored |
| 125 * @return the index of the element, if found - unspecified if not found |
157 * @return a pointer to the found node or @c NULL if no matching node was found |
| 126 */ |
158 */ |
| 127 cx_attr_nonnull_arg(1, 4, 5) |
159 cx_attr_nonnull_arg(1, 4, 5) |
| 128 cx_attr_export |
160 cx_attr_export |
| 129 void *cx_linked_list_find( |
161 void *cx_linked_list_find( |
| 130 const void *start, |
162 const void *start, |
| 191 const void *node |
223 const void *node |
| 192 ); |
224 ); |
| 193 |
225 |
| 194 /** |
226 /** |
| 195 * Adds a new node to a linked list. |
227 * Adds a new node to a linked list. |
| 196 * The node must not be part of any list already. |
228 * The node must not be part of any list yet. |
| 197 * |
229 * |
| 198 * @remark One of the pointers @p begin or @p end may be @c NULL, but not both. |
230 * @remark One of the pointers @p begin or @p end may be @c NULL, but not both. |
| 199 * |
231 * |
| 200 * @param begin a pointer to the beginning node pointer (if your list has one) |
232 * @param begin a pointer to the beginning node pointer (if your list has one) |
| 201 * @param end a pointer to the end node pointer (if your list has one) |
233 * @param end a pointer to the end node pointer (if your list has one) |
| 213 void *new_node |
245 void *new_node |
| 214 ); |
246 ); |
| 215 |
247 |
| 216 /** |
248 /** |
| 217 * Prepends a new node to a linked list. |
249 * Prepends a new node to a linked list. |
| 218 * The node must not be part of any list already. |
250 * The node must not be part of any list yet. |
| 219 * |
251 * |
| 220 * @remark One of the pointers @p begin or @p end may be @c NULL, but not both. |
252 * @remark One of the pointers @p begin or @p end may be @c NULL, but not both. |
| 221 * |
253 * |
| 222 * @param begin a pointer to the beginning node pointer (if your list has one) |
254 * @param begin a pointer to the beginning node pointer (if your list has one) |
| 223 * @param end a pointer to the end node pointer (if your list has one) |
255 * @param end a pointer to the end node pointer (if your list has one) |
| 271 ptrdiff_t loc_next |
303 ptrdiff_t loc_next |
| 272 ); |
304 ); |
| 273 |
305 |
| 274 /** |
306 /** |
| 275 * Inserts a new node after a given node of a linked list. |
307 * Inserts a new node after a given node of a linked list. |
| 276 * The new node must not be part of any list already. |
308 * The new node must not be part of any list yet. |
| 277 * |
309 * |
| 278 * @note If you specify @c NULL as the @p node to insert after, this function needs either the @p begin or |
310 * @note If you specify @c NULL as the @p node to insert after, this function needs either the @p begin or |
| 279 * the @p end pointer to determine the start of the list. Then the new node will be prepended to the list. |
311 * the @p end pointer to determine the start of the list. Then the new node will be prepended to the list. |
| 280 * |
312 * |
| 281 * @param begin a pointer to the beginning node pointer (if your list has one) |
313 * @param begin a pointer to the beginning node pointer (if your list has one) |
| 296 void *new_node |
328 void *new_node |
| 297 ); |
329 ); |
| 298 |
330 |
| 299 /** |
331 /** |
| 300 * Inserts a chain of nodes after a given node of a linked list. |
332 * Inserts a chain of nodes after a given node of a linked list. |
| 301 * The chain must not be part of any list already. |
333 * The chain must not be part of any list yet. |
| 302 * |
334 * |
| 303 * If you do not explicitly specify the end of the chain, it will be determined by traversing |
335 * If you do not explicitly specify the end of the chain, it will be determined by traversing |
| 304 * the @c next pointer. |
336 * the @c next pointer. |
| 305 * |
337 * |
| 306 * @note If you specify @c NULL as the @p node to insert after, this function needs either the @p begin or |
338 * @note If you specify @c NULL as the @p node to insert after, this function needs either the @p begin or |
| 353 cx_compare_func cmp_func |
385 cx_compare_func cmp_func |
| 354 ); |
386 ); |
| 355 |
387 |
| 356 /** |
388 /** |
| 357 * Inserts a chain of nodes into a sorted linked list. |
389 * Inserts a chain of nodes into a sorted linked list. |
| 358 * The chain must not be part of any list already. |
390 * The chain must not be part of any list yet. |
| 359 * |
391 * |
| 360 * If either the list starting with the node pointed to by @p begin or the list |
392 * 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. |
393 * starting with @p insert_begin is not sorted, the behavior is undefined. |
| 362 * |
394 * |
| 363 * @attention In contrast to cx_linked_list_insert_chain(), the source chain |
395 * @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 |
396 * 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 |
397 * 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. |
398 * chain may be re-linked with nodes from the target list. |
| 367 * |
399 * |
| 368 * @param begin a pointer to the beginning node pointer (required) |
400 * @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) |
401 * @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) |
402 * @param loc_prev the location of a @c prev pointer within your node struct (negative if your struct does not have one) |
| 382 void *insert_begin, |
414 void *insert_begin, |
| 383 cx_compare_func cmp_func |
415 cx_compare_func cmp_func |
| 384 ); |
416 ); |
| 385 |
417 |
| 386 /** |
418 /** |
| |
419 * Inserts a node into a sorted linked list if no other node with the same value already exists. |
| |
420 * The new node must not be part of any list yet. |
| |
421 * |
| |
422 * If the list starting with the node pointed to by @p begin is not sorted |
| |
423 * already, the behavior is undefined. |
| |
424 * |
| |
425 * @param begin a pointer to the beginning node pointer (required) |
| |
426 * @param end a pointer to the end node pointer (if your list has one) |
| |
427 * @param loc_prev the location of a @c prev pointer within your node struct (negative if your struct does not have one) |
| |
428 * @param loc_next the location of a @c next pointer within your node struct (required) |
| |
429 * @param new_node a pointer to the node that shall be inserted |
| |
430 * @param cmp_func a compare function that will receive the node pointers |
| |
431 * @retval zero when the node was inserted |
| |
432 * @retval non-zero when a node with the same value already exists |
| |
433 */ |
| |
434 cx_attr_nonnull_arg(1, 5, 6) |
| |
435 cx_attr_export |
| |
436 int cx_linked_list_insert_unique( |
| |
437 void **begin, |
| |
438 void **end, |
| |
439 ptrdiff_t loc_prev, |
| |
440 ptrdiff_t loc_next, |
| |
441 void *new_node, |
| |
442 cx_compare_func cmp_func |
| |
443 ); |
| |
444 |
| |
445 /** |
| |
446 * Inserts a chain of nodes into a sorted linked list, avoiding duplicates. |
| |
447 * The chain must not be part of any list yet. |
| |
448 * |
| |
449 * If either the list starting with the node pointed to by @p begin or the list |
| |
450 * starting with @p insert_begin is not sorted, the behavior is undefined. |
| |
451 * |
| |
452 * @attention In contrast to cx_linked_list_insert_sorted(), not all nodes of the |
| |
453 * chain might be added. This function returns a new chain consisting of all the duplicates. |
| |
454 * |
| |
455 * @param begin a pointer to the beginning node pointer (required) |
| |
456 * @param end a pointer to the end node pointer (if your list has one) |
| |
457 * @param loc_prev the location of a @c prev pointer within your node struct (negative if your struct does not have one) |
| |
458 * @param loc_next the location of a @c next pointer within your node struct (required) |
| |
459 * @param insert_begin a pointer to the first node of the chain that shall be inserted |
| |
460 * @param cmp_func a compare function that will receive the node pointers |
| |
461 * @return a pointer to a new chain with all duplicates that were not inserted (or @c NULL when there were no duplicates) |
| |
462 */ |
| |
463 cx_attr_nonnull_arg(1, 5, 6) |
| |
464 cx_attr_nodiscard |
| |
465 cx_attr_export |
| |
466 void *cx_linked_list_insert_unique_chain( |
| |
467 void **begin, |
| |
468 void **end, |
| |
469 ptrdiff_t loc_prev, |
| |
470 ptrdiff_t loc_next, |
| |
471 void *insert_begin, |
| |
472 cx_compare_func cmp_func |
| |
473 ); |
| |
474 |
| |
475 /** |
| 387 * Removes a chain of nodes from the linked list. |
476 * Removes a chain of nodes from the linked list. |
| 388 * |
477 * |
| 389 * If one of the nodes to remove is the beginning (resp. end) node of the list and if @p begin (resp. @p end) |
478 * 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. |
479 * addresses are provided, the pointers are adjusted accordingly. |
| 391 * |
480 * |
| 392 * The following combinations of arguments are valid (more arguments are optional): |
481 * 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) |
482 * @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) |
483 * @li @p loc_next and @p begin (ancestor node is determined by list traversal, overall O(n) performance) |
| 416 ); |
505 ); |
| 417 |
506 |
| 418 /** |
507 /** |
| 419 * Removes a node from the linked list. |
508 * Removes a node from the linked list. |
| 420 * |
509 * |
| 421 * If the node to remove is the beginning (resp. end) node of the list and if @p begin (resp. @p end) |
510 * If the node to remove is the beginning (resp. end) node of the list, and if @p begin (resp. @p end) |
| 422 * addresses are provided, the pointers are adjusted accordingly. |
511 * addresses are provided, the pointers are adjusted accordingly. |
| 423 * |
512 * |
| 424 * The following combinations of arguments are valid (more arguments are optional): |
513 * The following combinations of arguments are valid (more arguments are optional): |
| 425 * @li @p loc_next and @p loc_prev (ancestor node is determined by using the prev pointer, overall O(1) performance) |
514 * @li @p loc_next and @p loc_prev (ancestor node is determined by using the prev pointer, overall O(1) performance) |
| 426 * @li @p loc_next and @p begin (ancestor node is determined by list traversal, overall O(n) performance) |
515 * @li @p loc_next and @p begin (ancestor node is determined by list traversal, overall O(n) performance) |
| 494 |
583 |
| 495 |
584 |
| 496 /** |
585 /** |
| 497 * Compares two lists element wise. |
586 * Compares two lists element wise. |
| 498 * |
587 * |
| 499 * @attention Both list must have the same structure. |
588 * @attention Both lists must have the same structure. |
| 500 * |
589 * |
| 501 * @param begin_left the beginning of the left list (@c NULL denotes an empty list) |
590 * @param begin_left the beginning of the left list (@c NULL denotes an empty list) |
| 502 * @param begin_right the beginning of the right list (@c NULL denotes an empty list) |
591 * @param begin_right the beginning of the right list (@c NULL denotes an empty list) |
| 503 * @param loc_advance the location of the pointer to advance |
592 * @param loc_advance the location of the pointer to advance |
| 504 * @param loc_data the location of the @c data pointer within your node struct |
593 * @param loc_data the location of the @c data pointer within your node struct |