| 45 #endif |
45 #endif |
| 46 |
46 |
| 47 /** |
47 /** |
| 48 * The maximum item size that uses SBO swap instead of relinking. |
48 * The maximum item size that uses SBO swap instead of relinking. |
| 49 */ |
49 */ |
| 50 extern unsigned cx_linked_list_swap_sbo_size; |
50 extern const unsigned cx_linked_list_swap_sbo_size; |
| 51 |
51 |
| 52 /** |
52 /** |
| 53 * Allocates a linked list for storing elements with \p elem_size bytes each. |
53 * Allocates a linked list for storing elements with \p elem_size bytes each. |
| 54 * |
54 * |
| 55 * If \p elem_size is CX_STORE_POINTERS, the created list will be created as if |
55 * If \p elem_size is CX_STORE_POINTERS, the created list will be created as if |
| 56 * cxListStorePointers() was called immediately after creation and the compare |
56 * cxListStorePointers() was called immediately after creation and the compare |
| 57 * function will be automatically set to cx_cmp_ptr(), if none is given. |
57 * function will be automatically set to cx_cmp_ptr(), if none is given. |
| 58 * |
58 * |
| 59 * @param allocator the allocator for allocating the list nodes |
59 * @param allocator the allocator for allocating the list nodes |
| 60 * (if \c NULL the cxDefaultAllocator will be used) |
60 * (if \c NULL, a default stdlib allocator will be used) |
| 61 * @param comparator the comparator for the elements |
61 * @param comparator the comparator for the elements |
| 62 * (if \c NULL, and the list is not storing pointers, sort and find |
62 * (if \c NULL, and the list is not storing pointers, sort and find |
| 63 * functions will not work) |
63 * functions will not work) |
| 64 * @param elem_size the size of each element in bytes |
64 * @param elem_size the size of each element in bytes |
| 65 * @return the created list |
65 * @return the created list |
| 66 */ |
66 */ |
| |
67 cx_attr_nodiscard |
| |
68 cx_attr_malloc |
| |
69 cx_attr_dealloc(cxListFree, 1) |
| 67 CxList *cxLinkedListCreate( |
70 CxList *cxLinkedListCreate( |
| 68 CxAllocator const *allocator, |
71 const CxAllocator *allocator, |
| 69 cx_compare_func comparator, |
72 cx_compare_func comparator, |
| 70 size_t elem_size |
73 size_t elem_size |
| 71 ); |
74 ); |
| 72 |
75 |
| 73 /** |
76 /** |
| 228 * @param end a pointer to the end node pointer (if your list has one) |
241 * @param end a pointer to the end node pointer (if your list has one) |
| 229 * @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_prev the location of a \c prev pointer within your node struct (negative if your struct does not have one) |
| 230 * @param loc_next the location of a \c next pointer within your node struct (required) |
243 * @param loc_next the location of a \c next pointer within your node struct (required) |
| 231 * @param new_node a pointer to the node that shall be prepended |
244 * @param new_node a pointer to the node that shall be prepended |
| 232 */ |
245 */ |
| |
246 cx_attr_nonnull_arg(5) |
| 233 void cx_linked_list_prepend( |
247 void cx_linked_list_prepend( |
| 234 void **begin, |
248 void **begin, |
| 235 void **end, |
249 void **end, |
| 236 ptrdiff_t loc_prev, |
250 ptrdiff_t loc_prev, |
| 237 ptrdiff_t loc_next, |
251 ptrdiff_t loc_next, |
| 238 void *new_node |
252 void *new_node |
| 239 ) __attribute__((__nonnull__(5))); |
253 ); |
| 240 |
254 |
| 241 /** |
255 /** |
| 242 * Links two nodes. |
256 * Links two nodes. |
| 243 * |
257 * |
| 244 * @param left the new predecessor of \p right |
258 * @param left the new predecessor of \p right |
| 245 * @param right the new successor of \p left |
259 * @param right the new successor of \p left |
| 246 * @param loc_prev the location of a \c prev pointer within your node struct (negative if your struct does not have one) |
260 * @param loc_prev the location of a \c prev pointer within your node struct (negative if your struct does not have one) |
| 247 * @param loc_next the location of a \c next pointer within your node struct (required) |
261 * @param loc_next the location of a \c next pointer within your node struct (required) |
| 248 */ |
262 */ |
| |
263 cx_attr_nonnull |
| 249 void cx_linked_list_link( |
264 void cx_linked_list_link( |
| 250 void *left, |
265 void *left, |
| 251 void *right, |
266 void *right, |
| 252 ptrdiff_t loc_prev, |
267 ptrdiff_t loc_prev, |
| 253 ptrdiff_t loc_next |
268 ptrdiff_t loc_next |
| 254 ) __attribute__((__nonnull__)); |
269 ); |
| 255 |
270 |
| 256 /** |
271 /** |
| 257 * Unlinks two nodes. |
272 * Unlinks two nodes. |
| 258 * |
273 * |
| 259 * If right is not the successor of left, the behavior is undefined. |
274 * If right is not the successor of left, the behavior is undefined. |
| 311 * @param loc_next the location of a \c next pointer within your node struct (required) |
328 * @param loc_next the location of a \c next pointer within your node struct (required) |
| 312 * @param node the node after which to insert (\c NULL to prepend the chain to the list) |
329 * @param node the node after which to insert (\c NULL to prepend the chain to the list) |
| 313 * @param insert_begin a pointer to the first node of the chain that shall be inserted |
330 * @param insert_begin a pointer to the first node of the chain that shall be inserted |
| 314 * @param insert_end a pointer to the last node of the chain (or NULL if the last node shall be determined) |
331 * @param insert_end a pointer to the last node of the chain (or NULL if the last node shall be determined) |
| 315 */ |
332 */ |
| |
333 cx_attr_nonnull_arg(6) |
| 316 void cx_linked_list_insert_chain( |
334 void cx_linked_list_insert_chain( |
| 317 void **begin, |
335 void **begin, |
| 318 void **end, |
336 void **end, |
| 319 ptrdiff_t loc_prev, |
337 ptrdiff_t loc_prev, |
| 320 ptrdiff_t loc_next, |
338 ptrdiff_t loc_next, |
| 321 void *node, |
339 void *node, |
| 322 void *insert_begin, |
340 void *insert_begin, |
| 323 void *insert_end |
341 void *insert_end |
| 324 ) __attribute__((__nonnull__(6))); |
342 ); |
| 325 |
343 |
| 326 /** |
344 /** |
| 327 * Removes a node from the linked list. |
345 * Inserts a node into a sorted linked list. |
| 328 * |
346 * The new node must not be part of any list already. |
| 329 * If the node to remove is the begin (resp. end) node of the list and if \p begin (resp. \p end) |
347 * |
| |
348 * If the list starting with the node pointed to by \p begin is not sorted |
| |
349 * already, the behavior is undefined. |
| |
350 * |
| |
351 * @param begin a pointer to the begin node pointer (required) |
| |
352 * @param end a pointer to the end node pointer (if your list has one) |
| |
353 * @param loc_prev the location of a \c prev pointer within your node struct (negative if your struct does not have one) |
| |
354 * @param loc_next the location of a \c next pointer within your node struct (required) |
| |
355 * @param new_node a pointer to the node that shall be inserted |
| |
356 * @param cmp_func a compare function that will receive the node pointers |
| |
357 */ |
| |
358 cx_attr_nonnull_arg(1, 5, 6) |
| |
359 void cx_linked_list_insert_sorted( |
| |
360 void **begin, |
| |
361 void **end, |
| |
362 ptrdiff_t loc_prev, |
| |
363 ptrdiff_t loc_next, |
| |
364 void *new_node, |
| |
365 cx_compare_func cmp_func |
| |
366 ); |
| |
367 |
| |
368 /** |
| |
369 * Inserts a chain of nodes into a sorted linked list. |
| |
370 * The chain must not be part of any list already. |
| |
371 * |
| |
372 * If either the list starting with the node pointed to by \p begin or the list |
| |
373 * starting with \p insert_begin is not sorted, the behavior is undefined. |
| |
374 * |
| |
375 * \attention In contrast to cx_linked_list_insert_chain(), the source chain |
| |
376 * will be broken and inserted into the target list so that the resulting list |
| |
377 * will be sorted according to \p cmp_func. That means, each node in the source |
| |
378 * chain may be re-linked with nodes from the target list. |
| |
379 * |
| |
380 * @param begin a pointer to the begin node pointer (required) |
| |
381 * @param end a pointer to the end node pointer (if your list has one) |
| |
382 * @param loc_prev the location of a \c prev pointer within your node struct (negative if your struct does not have one) |
| |
383 * @param loc_next the location of a \c next pointer within your node struct (required) |
| |
384 * @param insert_begin a pointer to the first node of the chain that shall be inserted |
| |
385 * @param cmp_func a compare function that will receive the node pointers |
| |
386 */ |
| |
387 cx_attr_nonnull_arg(1, 5, 6) |
| |
388 void cx_linked_list_insert_sorted_chain( |
| |
389 void **begin, |
| |
390 void **end, |
| |
391 ptrdiff_t loc_prev, |
| |
392 ptrdiff_t loc_next, |
| |
393 void *insert_begin, |
| |
394 cx_compare_func cmp_func |
| |
395 ); |
| |
396 |
| |
397 /** |
| |
398 * Removes a chain of nodes from the linked list. |
| |
399 * |
| |
400 * If one of the nodes to remove is the begin (resp. end) node of the list and if \p begin (resp. \p end) |
| 330 * addresses are provided, the pointers are adjusted accordingly. |
401 * addresses are provided, the pointers are adjusted accordingly. |
| 331 * |
402 * |
| 332 * The following combinations of arguments are valid (more arguments are optional): |
403 * The following combinations of arguments are valid (more arguments are optional): |
| 333 * \li \p loc_next and \p loc_prev (ancestor node is determined by using the prev pointer, overall O(1) performance) |
404 * \li \p loc_next and \p loc_prev (ancestor node is determined by using the prev pointer, overall O(1) performance) |
| 334 * \li \p loc_next and \p begin (ancestor node is determined by list traversal, overall O(n) performance) |
405 * \li \p loc_next and \p begin (ancestor node is determined by list traversal, overall O(n) performance) |
| 335 * |
406 * |
| 336 * \remark The \c next and \c prev pointers of the removed node are not cleared by this function and may still be used |
407 * \remark The \c next and \c prev pointers of the removed node are not cleared by this function and may still be used |
| 337 * to traverse to a former adjacent node in the list. |
408 * to traverse to a former adjacent node in the list, or within the chain. |
| 338 * |
409 * |
| 339 * @param begin a pointer to the begin node pointer (optional) |
410 * @param begin a pointer to the begin node pointer (optional) |
| 340 * @param end a pointer to the end node pointer (optional) |
411 * @param end a pointer to the end node pointer (optional) |
| 341 * @param loc_prev the location of a \c prev pointer within your node struct (negative if your struct does not have one) |
412 * @param loc_prev the location of a \c prev pointer within your node struct (negative if your struct does not have one) |
| 342 * @param loc_next the location of a \c next pointer within your node struct (required) |
413 * @param loc_next the location of a \c next pointer within your node struct (required) |
| |
414 * @param node the start node of the chain |
| |
415 * @param num the number of nodes to remove |
| |
416 * @return the actual number of nodes that were removed (may be less when the list did not have enough nodes) |
| |
417 */ |
| |
418 cx_attr_nonnull_arg(5) |
| |
419 size_t cx_linked_list_remove_chain( |
| |
420 void **begin, |
| |
421 void **end, |
| |
422 ptrdiff_t loc_prev, |
| |
423 ptrdiff_t loc_next, |
| |
424 void *node, |
| |
425 size_t num |
| |
426 ); |
| |
427 |
| |
428 /** |
| |
429 * Removes a node from the linked list. |
| |
430 * |
| |
431 * If the node to remove is the begin (resp. end) node of the list and if \p begin (resp. \p end) |
| |
432 * addresses are provided, the pointers are adjusted accordingly. |
| |
433 * |
| |
434 * The following combinations of arguments are valid (more arguments are optional): |
| |
435 * \li \p loc_next and \p loc_prev (ancestor node is determined by using the prev pointer, overall O(1) performance) |
| |
436 * \li \p loc_next and \p begin (ancestor node is determined by list traversal, overall O(n) performance) |
| |
437 * |
| |
438 * \remark The \c next and \c prev pointers of the removed node are not cleared by this function and may still be used |
| |
439 * to traverse to a former adjacent node in the list. |
| |
440 * |
| |
441 * @param begin a pointer to the begin node pointer (optional) |
| |
442 * @param end a pointer to the end node pointer (optional) |
| |
443 * @param loc_prev the location of a \c prev pointer within your node struct (negative if your struct does not have one) |
| |
444 * @param loc_next the location of a \c next pointer within your node struct (required) |
| 343 * @param node the node to remove |
445 * @param node the node to remove |
| 344 */ |
446 */ |
| 345 void cx_linked_list_remove( |
447 cx_attr_nonnull_arg(5) |
| |
448 static inline void cx_linked_list_remove( |
| 346 void **begin, |
449 void **begin, |
| 347 void **end, |
450 void **end, |
| 348 ptrdiff_t loc_prev, |
451 ptrdiff_t loc_prev, |
| 349 ptrdiff_t loc_next, |
452 ptrdiff_t loc_next, |
| 350 void *node |
453 void *node |
| 351 ) __attribute__((__nonnull__(5))); |
454 ) { |
| 352 |
455 cx_linked_list_remove_chain(begin, end, loc_prev, loc_next, node, 1); |
| |
456 } |
| 353 |
457 |
| 354 /** |
458 /** |
| 355 * Determines the size of a linked list starting with \p node. |
459 * Determines the size of a linked list starting with \p node. |
| 356 * @param node the first node |
460 * @param node the first node |
| 357 * @param loc_next the location of the \c next pointer within the node struct |
461 * @param loc_next the location of the \c next pointer within the node struct |
| 358 * @return the size of the list or zero if \p node is \c NULL |
462 * @return the size of the list or zero if \p node is \c NULL |
| 359 */ |
463 */ |
| 360 size_t cx_linked_list_size( |
464 size_t cx_linked_list_size( |
| 361 void const *node, |
465 const void *node, |
| 362 ptrdiff_t loc_next |
466 ptrdiff_t loc_next |
| 363 ); |
467 ); |
| 364 |
468 |
| 365 /** |
469 /** |
| 366 * Sorts a linked list based on a comparison function. |
470 * Sorts a linked list based on a comparison function. |
| 405 * @param loc_data the location of the \c data pointer within your node struct |
510 * @param loc_data the location of the \c data pointer within your node struct |
| 406 * @param cmp_func the function to compare the elements |
511 * @param cmp_func the function to compare the elements |
| 407 * @return the first non-zero result of invoking \p cmp_func or: negative if the left list is smaller than the |
512 * @return the first non-zero result of invoking \p cmp_func or: negative if the left list is smaller than the |
| 408 * right list, positive if the left list is larger than the right list, zero if both lists are equal. |
513 * right list, positive if the left list is larger than the right list, zero if both lists are equal. |
| 409 */ |
514 */ |
| |
515 cx_attr_nonnull_arg(5) |
| 410 int cx_linked_list_compare( |
516 int cx_linked_list_compare( |
| 411 void const *begin_left, |
517 const void *begin_left, |
| 412 void const *begin_right, |
518 const void *begin_right, |
| 413 ptrdiff_t loc_advance, |
519 ptrdiff_t loc_advance, |
| 414 ptrdiff_t loc_data, |
520 ptrdiff_t loc_data, |
| 415 cx_compare_func cmp_func |
521 cx_compare_func cmp_func |
| 416 ) __attribute__((__nonnull__(5))); |
522 ); |
| 417 |
523 |
| 418 /** |
524 /** |
| 419 * Reverses the order of the nodes in a linked list. |
525 * Reverses the order of the nodes in a linked list. |
| 420 * |
526 * |
| 421 * @param begin a pointer to the begin node pointer (required) |
527 * @param begin a pointer to the begin node pointer (required) |
| 422 * @param end a pointer to the end node pointer (optional) |
528 * @param end a pointer to the end node pointer (optional) |
| 423 * @param loc_prev the location of a \c prev pointer within your node struct (negative if your struct does not have one) |
529 * @param loc_prev the location of a \c prev pointer within your node struct (negative if your struct does not have one) |
| 424 * @param loc_next the location of a \c next pointer within your node struct (required) |
530 * @param loc_next the location of a \c next pointer within your node struct (required) |
| 425 */ |
531 */ |
| |
532 cx_attr_nonnull_arg(1) |
| 426 void cx_linked_list_reverse( |
533 void cx_linked_list_reverse( |
| 427 void **begin, |
534 void **begin, |
| 428 void **end, |
535 void **end, |
| 429 ptrdiff_t loc_prev, |
536 ptrdiff_t loc_prev, |
| 430 ptrdiff_t loc_next |
537 ptrdiff_t loc_next |
| 431 ) __attribute__((__nonnull__(1))); |
538 ); |
| 432 |
539 |
| 433 #ifdef __cplusplus |
540 #ifdef __cplusplus |
| 434 } // extern "C" |
541 } // extern "C" |
| 435 #endif |
542 #endif |
| 436 |
543 |