| 85 /** |
85 /** |
| 86 * 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. |
| 87 * |
87 * |
| 88 * 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 |
| 89 * 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 |
| 90 * to cx_cmp_ptr() if none is given. |
90 * to cx_cmp_ptr(). |
| 91 * |
91 * |
| 92 * @param allocator the allocator for allocating the list nodes |
92 * @param allocator the allocator for allocating the list nodes |
| 93 * (if @c NULL, the cxDefaultAllocator will be used) |
93 * (if @c NULL, the cxDefaultAllocator will be used) |
| 94 * @param comparator the comparator for the elements |
|
| 95 * (if @c NULL, and the list is not storing pointers, sort and find |
|
| 96 * functions will not work) |
|
| 97 * @param elem_size the size of each element in bytes |
94 * @param elem_size the size of each element in bytes |
| 98 * @return the created list |
95 * @return the created list |
| 99 */ |
96 */ |
| 100 cx_attr_nodiscard cx_attr_malloc cx_attr_dealloc(cxListFree, 1) |
97 cx_attr_nodiscard cx_attr_malloc cx_attr_dealloc(cxListFree, 1) |
| 101 CX_EXPORT CxList *cxLinkedListCreate(const CxAllocator *allocator, |
98 CX_EXPORT CxList *cxLinkedListCreate(const CxAllocator *allocator, |
| 102 cx_compare_func comparator, size_t elem_size); |
99 size_t elem_size); |
| 103 |
|
| 104 /** |
|
| 105 * Allocates a linked list for storing elements with @p elem_size bytes each. |
|
| 106 * |
|
| 107 * The list will use cxDefaultAllocator and no comparator function. If you want |
|
| 108 * to call functions that need a comparator, you must either set one immediately |
|
| 109 * after list creation or use cxLinkedListCreate(). |
|
| 110 * |
|
| 111 * If @p elem_size is #CX_STORE_POINTERS, the created list stores pointers instead of |
|
| 112 * copies of the added elements, and the compare function will be automatically set |
|
| 113 * to cx_cmp_ptr(). |
|
| 114 * |
|
| 115 * @param elem_size (@c size_t) the size of each element in bytes |
|
| 116 * @return (@c CxList*) the created list |
|
| 117 */ |
|
| 118 #define cxLinkedListCreateSimple(elem_size) \ |
|
| 119 cxLinkedListCreate(NULL, NULL, elem_size) |
|
| 120 |
100 |
| 121 /** |
101 /** |
| 122 * Instructs the linked list to reserve extra data in each node. |
102 * Instructs the linked list to reserve extra data in each node. |
| 123 * |
103 * |
| 124 * The extra data will be aligned and placed behind the element data. |
104 * The extra data will be aligned and placed behind the element data. |
| 160 * Finds the node containing an element within a linked list. |
140 * Finds the node containing an element within a linked list. |
| 161 * |
141 * |
| 162 * @param start a pointer to the start node |
142 * @param start a pointer to the start node |
| 163 * @param loc_advance the location of the pointer to advance |
143 * @param loc_advance the location of the pointer to advance |
| 164 * @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 |
| 165 * @param cmp_func a compare function to compare @p elem against the node data |
|
| 166 * @param elem a pointer to the element to find |
145 * @param elem a pointer to the element to find |
| 167 * @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 |
| 168 * (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 |
| 169 * @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 |
| 170 */ |
150 */ |
| 171 cx_attr_nonnull_arg(1, 4, 5) |
151 cx_attr_nonnull_arg(1, 4, 6) |
| 172 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, |
| 173 ptrdiff_t loc_data, cx_compare_func cmp_func, const void *elem, |
153 ptrdiff_t loc_data, const void *elem, size_t *found_index, |
| 174 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); |
| 175 |
173 |
| 176 /** |
174 /** |
| 177 * Finds the first node in a linked list. |
175 * Finds the first node in a linked list. |
| 178 * |
176 * |
| 179 * 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 |
| 392 cx_attr_nonnull_arg(1, 5, 6) cx_attr_nodiscard |
390 cx_attr_nonnull_arg(1, 5, 6) cx_attr_nodiscard |
| 393 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, |
| 394 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); |
| 395 |
393 |
| 396 /** |
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 /** |
| 397 * Removes a chain of nodes from the linked list. |
481 * Removes a chain of nodes from the linked list. |
| 398 * |
482 * |
| 399 * 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) |
| 400 * addresses are provided, the pointers are adjusted accordingly. |
484 * addresses are provided, the pointers are adjusted accordingly. |
| 401 * |
485 * |
| 474 * @param cmp_func the compare function defining the sort order |
548 * @param cmp_func the compare function defining the sort order |
| 475 */ |
549 */ |
| 476 cx_attr_nonnull_arg(1, 6) |
550 cx_attr_nonnull_arg(1, 6) |
| 477 CX_EXPORT void cx_linked_list_sort(void **begin, void **end, |
551 CX_EXPORT void cx_linked_list_sort(void **begin, void **end, |
| 478 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); |
| 479 |
570 |
| 480 |
571 |
| 481 /** |
572 /** |
| 482 * Compares two lists element wise. |
573 * Compares two lists element wise. |
| 483 * |
574 * |
| 494 cx_attr_nonnull_arg(5) |
585 cx_attr_nonnull_arg(5) |
| 495 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, |
| 496 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); |
| 497 |
588 |
| 498 /** |
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 /** |
| 499 * Reverses the order of the nodes in a linked list. |
607 * Reverses the order of the nodes in a linked list. |
| 500 * |
608 * |
| 501 * @param begin a pointer to the beginning node pointer (required) |
609 * @param begin a pointer to the beginning node pointer (required) |
| 502 * @param end a pointer to the end node pointer (optional) |
610 * @param end a pointer to the end node pointer (optional) |
| 503 * @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) |