ucx/cx/linked_list.h

changeset 112
c3f2f16fa4b8
parent 108
77254bd6dccb
child 113
dde28a806552
equal deleted inserted replaced
111:81c4f73236a4 112:c3f2f16fa4b8
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
328 void *insert_end 360 void *insert_end
329 ); 361 );
330 362
331 /** 363 /**
332 * Inserts a node into a sorted linked list. 364 * Inserts a node into a sorted linked list.
333 * The new node must not be part of any list already. 365 * The new node must not be part of any list yet.
334 * 366 *
335 * If the list starting with the node pointed to by @p begin is not sorted 367 * If the list starting with the node pointed to by @p begin is not sorted
336 * already, the behavior is undefined. 368 * already, the behavior is undefined.
337 * 369 *
338 * @param begin a pointer to the beginning node pointer (required) 370 * @param begin a pointer to the beginning node pointer (required)
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

mercurial