| 78 /** |
85 /** |
| 79 * Allocates a linked list for storing elements with @p elem_size bytes each. |
86 * Allocates a linked list for storing elements with @p elem_size bytes each. |
| 80 * |
87 * |
| 81 * If @p elem_size is #CX_STORE_POINTERS, the created list stores pointers instead of |
88 * If @p elem_size is #CX_STORE_POINTERS, the created list stores pointers instead of |
| 82 * copies of the added elements, and the compare function will be automatically set |
89 * copies of the added elements, and the compare function will be automatically set |
| 83 * to cx_cmp_ptr() if none is given. |
90 * to cx_cmp_ptr(). |
| 84 * |
91 * |
| 85 * @param allocator the allocator for allocating the list nodes |
92 * @param allocator the allocator for allocating the list nodes |
| 86 * (if @c NULL, the cxDefaultAllocator will be used) |
93 * (if @c NULL, the cxDefaultAllocator will be used) |
| 87 * @param comparator the comparator for the elements |
|
| 88 * (if @c NULL, and the list is not storing pointers, sort and find |
|
| 89 * functions will not work) |
|
| 90 * @param elem_size the size of each element in bytes |
94 * @param elem_size the size of each element in bytes |
| 91 * @return the created list |
95 * @return the created list |
| 92 */ |
96 */ |
| 93 cx_attr_nodiscard cx_attr_malloc cx_attr_dealloc(cxListFree, 1) |
97 cx_attr_nodiscard cx_attr_malloc cx_attr_dealloc(cxListFree, 1) |
| 94 CX_EXPORT CxList *cxLinkedListCreate(const CxAllocator *allocator, |
98 CX_EXPORT CxList *cxLinkedListCreate(const CxAllocator *allocator, |
| 95 cx_compare_func comparator, size_t elem_size); |
99 size_t elem_size); |
| 96 |
100 |
| 97 /** |
101 /** |
| 98 * Allocates a linked list for storing elements with @p elem_size bytes each. |
102 * Instructs the linked list to reserve extra data in each node. |
| 99 * |
103 * |
| 100 * The list will use cxDefaultAllocator and no comparator function. If you want |
104 * The extra data will be aligned and placed behind the element data. |
| 101 * to call functions that need a comparator, you must either set one immediately |
105 * The exact location in the node is stored in the @c loc_extra field |
| 102 * after list creation or use cxLinkedListCreate(). |
106 * of the linked list. |
| 103 * |
107 * |
| 104 * If @p elem_size is #CX_STORE_POINTERS, the created list stores pointers instead of |
108 * You should usually not use this function except when you are creating an |
| 105 * copies of the added elements, and the compare function will be automatically set |
109 * own linked-list implementation that is based on the UCX linked list and |
| 106 * to cx_cmp_ptr(). |
110 * needs to store extra data in each node. |
| 107 * |
111 * |
| 108 * @param elem_size (@c size_t) the size of each element in bytes |
112 * @param list the list (must be a linked list) |
| 109 * @return (@c CxList*) the created list |
113 * @param len the length of the extra data |
| 110 */ |
114 */ |
| 111 #define cxLinkedListCreateSimple(elem_size) \ |
115 cx_attr_nonnull |
| 112 cxLinkedListCreate(NULL, NULL, elem_size) |
116 CX_EXPORT void cx_linked_list_extra_data(cx_linked_list *list, size_t len); |
| 113 |
117 |
| 114 /** |
118 /** |
| 115 * Finds the node at a certain index. |
119 * Finds the node at a certain index. |
| 116 * |
120 * |
| 117 * This function can be used to start at an arbitrary position within the list. |
121 * This function can be used to start at an arbitrary position within the list. |
| 136 * Finds the node containing an element within a linked list. |
140 * Finds the node containing an element within a linked list. |
| 137 * |
141 * |
| 138 * @param start a pointer to the start node |
142 * @param start a pointer to the start node |
| 139 * @param loc_advance the location of the pointer to advance |
143 * @param loc_advance the location of the pointer to advance |
| 140 * @param loc_data the location of the @c data pointer within your node struct |
144 * @param loc_data the location of the @c data pointer within your node struct |
| 141 * @param cmp_func a compare function to compare @p elem against the node data |
|
| 142 * @param elem a pointer to the element to find |
145 * @param elem a pointer to the element to find |
| 143 * @param found_index an optional pointer where the index of the found node |
146 * @param found_index an optional pointer where the index of the found node |
| 144 * (given that @p start has index 0) is stored |
147 * (given that @p start has index 0) is stored |
| |
148 * @param cmp_func a compare function to compare @p elem against the node data |
| 145 * @return a pointer to the found node or @c NULL if no matching node was found |
149 * @return a pointer to the found node or @c NULL if no matching node was found |
| 146 */ |
150 */ |
| 147 cx_attr_nonnull_arg(1, 4, 5) |
151 cx_attr_nonnull_arg(1, 4, 6) |
| 148 CX_EXPORT void *cx_linked_list_find(const void *start, ptrdiff_t loc_advance, |
152 CX_EXPORT void *cx_linked_list_find(const void *start, ptrdiff_t loc_advance, |
| 149 ptrdiff_t loc_data, cx_compare_func cmp_func, const void *elem, |
153 ptrdiff_t loc_data, const void *elem, size_t *found_index, |
| 150 size_t *found_index); |
154 cx_compare_func cmp_func); |
| |
155 |
| |
156 /** |
| |
157 * Finds the node containing an element within a linked list. |
| |
158 * |
| |
159 * @param start a pointer to the start node |
| |
160 * @param loc_advance the location of the pointer to advance |
| |
161 * @param loc_data the location of the @c data pointer within your node struct |
| |
162 * @param elem a pointer to the element to find |
| |
163 * @param found_index an optional pointer where the index of the found node |
| |
164 * (given that @p start has index 0) is stored |
| |
165 * @param cmp_func a compare function to compare @p elem against the node data |
| |
166 * @param context additional context for the compare function |
| |
167 * @return a pointer to the found node or @c NULL if no matching node was found |
| |
168 */ |
| |
169 cx_attr_nonnull_arg(1, 4, 6) |
| |
170 CX_EXPORT void *cx_linked_list_find_c(const void *start, ptrdiff_t loc_advance, |
| |
171 ptrdiff_t loc_data, const void *elem, size_t *found_index, |
| |
172 cx_compare_func2 cmp_func, void *context); |
| 151 |
173 |
| 152 /** |
174 /** |
| 153 * Finds the first node in a linked list. |
175 * Finds the first node in a linked list. |
| 154 * |
176 * |
| 155 * The function starts with the pointer denoted by @p node and traverses the list |
177 * The function starts with the pointer denoted by @p node and traverses the list |
| 368 cx_attr_nonnull_arg(1, 5, 6) cx_attr_nodiscard |
390 cx_attr_nonnull_arg(1, 5, 6) cx_attr_nodiscard |
| 369 CX_EXPORT void *cx_linked_list_insert_unique_chain(void **begin, void **end, |
391 CX_EXPORT void *cx_linked_list_insert_unique_chain(void **begin, void **end, |
| 370 ptrdiff_t loc_prev, ptrdiff_t loc_next, void *insert_begin, cx_compare_func cmp_func); |
392 ptrdiff_t loc_prev, ptrdiff_t loc_next, void *insert_begin, cx_compare_func cmp_func); |
| 371 |
393 |
| 372 /** |
394 /** |
| |
395 * Inserts a node into a sorted linked list. |
| |
396 * The new node must not be part of any list yet. |
| |
397 * |
| |
398 * If the list starting with the node pointed to by @p begin is not sorted |
| |
399 * already, the behavior is undefined. |
| |
400 * |
| |
401 * @param begin a pointer to the beginning node pointer (required) |
| |
402 * @param end a pointer to the end node pointer (if your list has one) |
| |
403 * @param loc_prev the location of a @c prev pointer within your node struct (negative if your struct does not have one) |
| |
404 * @param loc_next the location of a @c next pointer within your node struct (required) |
| |
405 * @param new_node a pointer to the node that shall be inserted |
| |
406 * @param cmp_func a compare function that will receive the node pointers |
| |
407 * @param context context for the compare function |
| |
408 */ |
| |
409 cx_attr_nonnull_arg(1, 5, 6) |
| |
410 CX_EXPORT void cx_linked_list_insert_sorted_c(void **begin, void **end, |
| |
411 ptrdiff_t loc_prev, ptrdiff_t loc_next, void *new_node, cx_compare_func2 cmp_func, void *context); |
| |
412 |
| |
413 /** |
| |
414 * Inserts a chain of nodes into a sorted linked list. |
| |
415 * The chain must not be part of any list yet. |
| |
416 * |
| |
417 * If either the list starting with the node pointed to by @p begin or the list |
| |
418 * starting with @p insert_begin is not sorted, the behavior is undefined. |
| |
419 * |
| |
420 * @attention In contrast to cx_linked_list_insert_chain(), the source chain |
| |
421 * will be broken and inserted into the target list so that the resulting list |
| |
422 * will be sorted according to @p cmp_func. That means each node in the source |
| |
423 * chain may be re-linked with nodes from the target list. |
| |
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 insert_begin a pointer to the first node of the chain that shall be inserted |
| |
430 * @param cmp_func a compare function that will receive the node pointers |
| |
431 * @param context context for the compare function |
| |
432 */ |
| |
433 cx_attr_nonnull_arg(1, 5, 6) |
| |
434 CX_EXPORT void cx_linked_list_insert_sorted_chain_c(void **begin, void **end, |
| |
435 ptrdiff_t loc_prev, ptrdiff_t loc_next, void *insert_begin, cx_compare_func2 cmp_func, void *context); |
| |
436 |
| |
437 /** |
| |
438 * Inserts a node into a sorted linked list if no other node with the same value already exists. |
| |
439 * The new node must not be part of any list yet. |
| |
440 * |
| |
441 * If the list starting with the node pointed to by @p begin is not sorted |
| |
442 * already, the behavior is undefined. |
| |
443 * |
| |
444 * @param begin a pointer to the beginning node pointer (required) |
| |
445 * @param end a pointer to the end node pointer (if your list has one) |
| |
446 * @param loc_prev the location of a @c prev pointer within your node struct (negative if your struct does not have one) |
| |
447 * @param loc_next the location of a @c next pointer within your node struct (required) |
| |
448 * @param new_node a pointer to the node that shall be inserted |
| |
449 * @param cmp_func a compare function that will receive the node pointers |
| |
450 * @retval zero when the node was inserted |
| |
451 * @retval non-zero when a node with the same value already exists |
| |
452 */ |
| |
453 cx_attr_nonnull_arg(1, 5, 6) |
| |
454 CX_EXPORT int cx_linked_list_insert_unique_c(void **begin, void **end, |
| |
455 ptrdiff_t loc_prev, ptrdiff_t loc_next, void *new_node, cx_compare_func2 cmp_func, void *context); |
| |
456 |
| |
457 /** |
| |
458 * Inserts a chain of nodes into a sorted linked list, avoiding duplicates. |
| |
459 * The chain must not be part of any list yet. |
| |
460 * |
| |
461 * If either the list starting with the node pointed to by @p begin or the list |
| |
462 * starting with @p insert_begin is not sorted, the behavior is undefined. |
| |
463 * |
| |
464 * @attention In contrast to cx_linked_list_insert_sorted(), not all nodes of the |
| |
465 * chain might be added. This function returns a new chain consisting of all the duplicates. |
| |
466 * |
| |
467 * @param begin a pointer to the beginning node pointer (required) |
| |
468 * @param end a pointer to the end node pointer (if your list has one) |
| |
469 * @param loc_prev the location of a @c prev pointer within your node struct (negative if your struct does not have one) |
| |
470 * @param loc_next the location of a @c next pointer within your node struct (required) |
| |
471 * @param insert_begin a pointer to the first node of the chain that shall be inserted |
| |
472 * @param cmp_func a compare function that will receive the node pointers |
| |
473 * @param context context for the compare function |
| |
474 * @return a pointer to a new chain with all duplicates that were not inserted (or @c NULL when there were no duplicates) |
| |
475 */ |
| |
476 cx_attr_nonnull_arg(1, 5, 6) cx_attr_nodiscard |
| |
477 CX_EXPORT void *cx_linked_list_insert_unique_chain_c(void **begin, void **end, |
| |
478 ptrdiff_t loc_prev, ptrdiff_t loc_next, void *insert_begin, cx_compare_func2 cmp_func, void *context); |
| |
479 |
| |
480 /** |
| 373 * Removes a chain of nodes from the linked list. |
481 * Removes a chain of nodes from the linked list. |
| 374 * |
482 * |
| 375 * If one of the nodes to remove is the beginning (resp. end) node of the list, and if @p begin (resp. @p end) |
483 * If one of the nodes to remove is the beginning (resp. end) node of the list, and if @p begin (resp. @p end) |
| 376 * addresses are provided, the pointers are adjusted accordingly. |
484 * addresses are provided, the pointers are adjusted accordingly. |
| 377 * |
485 * |
| 450 * @param cmp_func the compare function defining the sort order |
548 * @param cmp_func the compare function defining the sort order |
| 451 */ |
549 */ |
| 452 cx_attr_nonnull_arg(1, 6) |
550 cx_attr_nonnull_arg(1, 6) |
| 453 CX_EXPORT void cx_linked_list_sort(void **begin, void **end, |
551 CX_EXPORT void cx_linked_list_sort(void **begin, void **end, |
| 454 ptrdiff_t loc_prev, ptrdiff_t loc_next, ptrdiff_t loc_data, cx_compare_func cmp_func); |
552 ptrdiff_t loc_prev, ptrdiff_t loc_next, ptrdiff_t loc_data, cx_compare_func cmp_func); |
| |
553 |
| |
554 /** |
| |
555 * Sorts a linked list based on a comparison function. |
| |
556 * |
| |
557 * @note This is a recursive function with at most logarithmic recursion depth. |
| |
558 * |
| |
559 * @param begin a pointer to the beginning node pointer (required) |
| |
560 * @param end a pointer to the end node pointer (optional) |
| |
561 * @param loc_prev the location of a @c prev pointer within your node struct (negative if not present) |
| |
562 * @param loc_next the location of a @c next pointer within your node struct (required) |
| |
563 * @param loc_data the location of the @c data pointer within your node struct |
| |
564 * @param cmp_func the compare function defining the sort order |
| |
565 * @param context additional context for the compare function |
| |
566 */ |
| |
567 cx_attr_nonnull_arg(1, 6) |
| |
568 CX_EXPORT void cx_linked_list_sort_c(void **begin, void **end, |
| |
569 ptrdiff_t loc_prev, ptrdiff_t loc_next, ptrdiff_t loc_data, cx_compare_func2 cmp_func, void *context); |
| 455 |
570 |
| 456 |
571 |
| 457 /** |
572 /** |
| 458 * Compares two lists element wise. |
573 * Compares two lists element wise. |
| 459 * |
574 * |
| 470 cx_attr_nonnull_arg(5) |
585 cx_attr_nonnull_arg(5) |
| 471 CX_EXPORT int cx_linked_list_compare(const void *begin_left, const void *begin_right, |
586 CX_EXPORT int cx_linked_list_compare(const void *begin_left, const void *begin_right, |
| 472 ptrdiff_t loc_advance, ptrdiff_t loc_data, cx_compare_func cmp_func); |
587 ptrdiff_t loc_advance, ptrdiff_t loc_data, cx_compare_func cmp_func); |
| 473 |
588 |
| 474 /** |
589 /** |
| |
590 * Compares two lists element wise. |
| |
591 * |
| |
592 * @attention Both lists must have the same structure. |
| |
593 * |
| |
594 * @param begin_left the beginning of the left list (@c NULL denotes an empty list) |
| |
595 * @param begin_right the beginning of the right list (@c NULL denotes an empty list) |
| |
596 * @param loc_advance the location of the pointer to advance |
| |
597 * @param loc_data the location of the @c data pointer within your node struct |
| |
598 * @param cmp_func the function to compare the elements |
| |
599 * @return the first non-zero result of invoking @p cmp_func or: negative if the left list is smaller than the |
| |
600 * right list, positive if the left list is larger than the right list, zero if both lists are equal. |
| |
601 */ |
| |
602 cx_attr_nonnull_arg(5) |
| |
603 CX_EXPORT int cx_linked_list_compare_c(const void *begin_left, const void *begin_right, |
| |
604 ptrdiff_t loc_advance, ptrdiff_t loc_data, cx_compare_func2 cmp_func, void *context); |
| |
605 |
| |
606 /** |
| 475 * Reverses the order of the nodes in a linked list. |
607 * Reverses the order of the nodes in a linked list. |
| 476 * |
608 * |
| 477 * @param begin a pointer to the beginning node pointer (required) |
609 * @param begin a pointer to the beginning node pointer (required) |
| 478 * @param end a pointer to the end node pointer (optional) |
610 * @param end a pointer to the end node pointer (optional) |
| 479 * @param loc_prev the location of a @c prev pointer within your node struct (negative if your struct does not have one) |
611 * @param loc_prev the location of a @c prev pointer within your node struct (negative if your struct does not have one) |