| 324 * @param allocator the allocator for the elements |
321 * @param allocator the allocator for the elements |
| 325 * @param comparator a compare function for the elements |
322 * @param comparator a compare function for the elements |
| 326 * @param elem_size the size of one element |
323 * @param elem_size the size of one element |
| 327 */ |
324 */ |
| 328 cx_attr_nonnull_arg(1, 2, 3) |
325 cx_attr_nonnull_arg(1, 2, 3) |
| 329 cx_attr_export |
326 CX_EXPORT void cx_list_init(struct cx_list_s *list, |
| 330 void cx_list_init( |
327 struct cx_list_class_s *cl, const struct cx_allocator_s *allocator, |
| 331 struct cx_list_s *list, |
328 cx_compare_func comparator, size_t elem_size); |
| 332 struct cx_list_class_s *cl, |
|
| 333 const struct cx_allocator_s *allocator, |
|
| 334 cx_compare_func comparator, |
|
| 335 size_t elem_size |
|
| 336 ); |
|
| 337 |
|
| 338 /** |
|
| 339 * Common type for all list implementations. |
|
| 340 */ |
|
| 341 typedef struct cx_list_s CxList; |
|
| 342 |
329 |
| 343 /** |
330 /** |
| 344 * Returns the number of elements currently stored in the list. |
331 * Returns the number of elements currently stored in the list. |
| 345 * |
332 * |
| 346 * @param list the list |
333 * @param list the list |
| 347 * @return the number of currently stored elements |
334 * @return the number of currently stored elements |
| 348 */ |
335 */ |
| 349 cx_attr_nonnull |
336 cx_attr_nonnull |
| 350 static inline size_t cxListSize(const CxList *list) { |
337 CX_EXPORT size_t cxListSize(const CxList *list); |
| 351 return list->collection.size; |
|
| 352 } |
|
| 353 |
338 |
| 354 /** |
339 /** |
| 355 * Adds an item to the end of the list. |
340 * Adds an item to the end of the list. |
| 356 * |
341 * |
| 357 * @param list the list |
342 * @param list the list |
| 358 * @param elem a pointer to the element to add |
343 * @param elem a pointer to the element to add |
| 359 * @retval zero success |
344 * @retval zero success |
| 360 * @retval non-zero memory allocation failure |
345 * @retval non-zero memory allocation failure |
| 361 * @see cxListAddArray() |
346 * @see cxListAddArray() |
| 362 */ |
347 * @see cxListEmplace() |
| 363 cx_attr_nonnull |
348 */ |
| 364 static inline int cxListAdd( |
349 cx_attr_nonnull |
| 365 CxList *list, |
350 CX_EXPORT int cxListAdd(CxList *list, const void *elem); |
| 366 const void *elem |
|
| 367 ) { |
|
| 368 list->collection.sorted = false; |
|
| 369 return list->cl->insert_element(list, list->collection.size, elem); |
|
| 370 } |
|
| 371 |
351 |
| 372 /** |
352 /** |
| 373 * Adds multiple items to the end of the list. |
353 * Adds multiple items to the end of the list. |
| 374 * |
354 * |
| 375 * This method is more efficient than invoking cxListAdd() multiple times. |
355 * This method is more efficient than invoking cxListAdd() multiple times. |
| 376 * |
356 * |
| 377 * If there is not enough memory to add all elements, the returned value is |
357 * If there is not enough memory to add all elements, the returned value is |
| 378 * less than @p n. |
358 * less than @p n. |
| 379 * |
359 * |
| 380 * If this list is storing pointers instead of objects @p array is expected to |
360 * If this list is storing pointers instead of objects, @p array is expected to |
| 381 * be an array of pointers. |
361 * be an array of pointers. |
| 382 * |
362 * |
| 383 * @param list the list |
363 * @param list the list |
| 384 * @param array a pointer to the elements to add |
364 * @param array a pointer to the elements to add |
| 385 * @param n the number of elements to add |
365 * @param n the number of elements to add |
| 386 * @return the number of added elements |
366 * @return the number of added elements |
| 387 */ |
367 * @see cxListEmplaceArray() |
| 388 cx_attr_nonnull |
368 */ |
| 389 static inline size_t cxListAddArray( |
369 cx_attr_nonnull |
| 390 CxList *list, |
370 CX_EXPORT size_t cxListAddArray(CxList *list, const void *array, size_t n); |
| 391 const void *array, |
|
| 392 size_t n |
|
| 393 ) { |
|
| 394 list->collection.sorted = false; |
|
| 395 return list->cl->insert_array(list, list->collection.size, array, n); |
|
| 396 } |
|
| 397 |
371 |
| 398 /** |
372 /** |
| 399 * Inserts an item at the specified index. |
373 * Inserts an item at the specified index. |
| 400 * |
374 * |
| 401 * If @p index equals the list @c size, this is effectively cxListAdd(). |
375 * If the @p index equals the list @c size, this is effectively cxListAdd(). |
| 402 * |
376 * |
| 403 * @param list the list |
377 * @param list the list |
| 404 * @param index the index the element shall have |
378 * @param index the index the element shall have |
| 405 * @param elem a pointer to the element to add |
379 * @param elem a pointer to the element to add |
| 406 * @retval zero success |
380 * @retval zero success |
| 407 * @retval non-zero memory allocation failure or the index is out of bounds |
381 * @retval non-zero memory allocation failure or the index is out of bounds |
| 408 * @see cxListInsertAfter() |
382 * @see cxListInsertAfter() |
| 409 * @see cxListInsertBefore() |
383 * @see cxListInsertBefore() |
| 410 */ |
384 * @see cxListEmplaceAt() |
| 411 cx_attr_nonnull |
385 */ |
| 412 static inline int cxListInsert( |
386 cx_attr_nonnull |
| 413 CxList *list, |
387 CX_EXPORT int cxListInsert(CxList *list, size_t index, const void *elem); |
| 414 size_t index, |
388 |
| 415 const void *elem |
389 /** |
| 416 ) { |
390 * Allocates memory for an element at the specified index and returns a pointer to that memory. |
| 417 list->collection.sorted = false; |
391 * |
| 418 return list->cl->insert_element(list, index, elem); |
392 * @remark When the list is storing pointers, this will return a @c void**. |
| 419 } |
393 * |
| |
394 * @param list the list |
| |
395 * @param index the index where to emplace the element |
| |
396 * @return a pointer to the allocated memory; @c NULL when the operation fails, or the index is out-of-bounds |
| |
397 * @see cxListEmplace() |
| |
398 * @see cxListEmplaceArrayAt() |
| |
399 * @see cxListInsert() |
| |
400 */ |
| |
401 cx_attr_nonnull |
| |
402 CX_EXPORT void *cxListEmplaceAt(CxList *list, size_t index); |
| |
403 |
| |
404 /** |
| |
405 * Allocates memory for an element at the end of the list and returns a pointer to that memory. |
| |
406 * |
| |
407 * @remark When the list is storing pointers, this will return a @c void**. |
| |
408 * |
| |
409 * @param list the list |
| |
410 * @return a pointer to the allocated memory; @c NULL when the operation fails, or the index is out-of-bounds |
| |
411 * @see cxListEmplaceAt() |
| |
412 * @see cxListAdd() |
| |
413 */ |
| |
414 cx_attr_nonnull |
| |
415 CX_EXPORT void *cxListEmplace(CxList *list); |
| |
416 |
| |
417 /** |
| |
418 * Allocates memory for multiple elements and returns an iterator. |
| |
419 * |
| |
420 * The iterator will only iterate over the successfully allocated elements. |
| |
421 * The @c elem_count attribute is set to that number, and the @c index attribute |
| |
422 * will range from zero to @c elem_count minus one. |
| |
423 * |
| |
424 * @remark When the list is storing pointers, the iterator will iterate over |
| |
425 * the @c void** elements. |
| |
426 * |
| |
427 * @param list the list |
| |
428 * @param index the index where to insert the new data |
| |
429 * @param n the number of elements for which to allocate the memory |
| |
430 * @return an iterator, iterating over the new memory |
| |
431 * @see cxListEmplaceAt() |
| |
432 * @see cxListInsertArray() |
| |
433 */ |
| |
434 cx_attr_nonnull |
| |
435 CX_EXPORT CxIterator cxListEmplaceArrayAt(CxList *list, size_t index, size_t n); |
| |
436 |
| |
437 /** |
| |
438 * Allocates memory for multiple elements and returns an iterator. |
| |
439 * |
| |
440 * The iterator will only iterate over the successfully allocated elements. |
| |
441 * The @c elem_count attribute is set to that number, and the @c index attribute |
| |
442 * will range from zero to @c elem_count minus one. |
| |
443 * |
| |
444 * @remark When the list is storing pointers, the iterator will iterate over |
| |
445 * the @c void** elements. |
| |
446 * |
| |
447 * @param list the list |
| |
448 * @param n the number of elements for which to allocate the memory |
| |
449 * @return an iterator, iterating over the new memory |
| |
450 * @see cxListEmplace() |
| |
451 * @see cxListAddArray() |
| |
452 */ |
| |
453 cx_attr_nonnull |
| |
454 CX_EXPORT CxIterator cxListEmplaceArray(CxList *list, size_t n); |
| 420 |
455 |
| 421 /** |
456 /** |
| 422 * Inserts an item into a sorted list. |
457 * Inserts an item into a sorted list. |
| 423 * |
458 * |
| 424 * If the list is not sorted already, the behavior is undefined. |
459 * If the list is not sorted already, the behavior is undefined. |
| 427 * @param elem a pointer to the element to add |
462 * @param elem a pointer to the element to add |
| 428 * @retval zero success |
463 * @retval zero success |
| 429 * @retval non-zero memory allocation failure |
464 * @retval non-zero memory allocation failure |
| 430 */ |
465 */ |
| 431 cx_attr_nonnull |
466 cx_attr_nonnull |
| 432 static inline int cxListInsertSorted( |
467 CX_EXPORT int cxListInsertSorted(CxList *list, const void *elem); |
| 433 CxList *list, |
468 |
| 434 const void *elem |
469 /** |
| 435 ) { |
470 * Inserts an item into a list if it does not exist. |
| 436 list->collection.sorted = true; // guaranteed by definition |
471 * |
| 437 const void *data = list->collection.store_pointer ? &elem : elem; |
472 * If the list is not sorted already, this function will check all elements |
| 438 return list->cl->insert_sorted(list, data, 1) == 0; |
473 * and append the new element when it was not found. |
| 439 } |
474 * It is strongly recommended to use this function only on sorted lists, where |
| |
475 * the element, if it is not contained, is inserted at the correct position. |
| |
476 * |
| |
477 * @param list the list |
| |
478 * @param elem a pointer to the element to add |
| |
479 * @retval zero success (also when the element was already in the list) |
| |
480 * @retval non-zero memory allocation failure |
| |
481 */ |
| |
482 cx_attr_nonnull |
| |
483 CX_EXPORT int cxListInsertUnique(CxList *list, const void *elem); |
| 440 |
484 |
| 441 /** |
485 /** |
| 442 * Inserts multiple items to the list at the specified index. |
486 * Inserts multiple items to the list at the specified index. |
| 443 * If @p index equals the list size, this is effectively cxListAddArray(). |
487 * If the @p index equals the list size, this is effectively cxListAddArray(). |
| 444 * |
488 * |
| 445 * This method is usually more efficient than invoking cxListInsert() |
489 * This method is usually more efficient than invoking cxListInsert() |
| 446 * multiple times. |
490 * multiple times. |
| 447 * |
491 * |
| 448 * If there is not enough memory to add all elements, the returned value is |
492 * If there is not enough memory to add all elements, the returned value is |
| 449 * less than @p n. |
493 * less than @p n. |
| 450 * |
494 * |
| 451 * If this list is storing pointers instead of objects @p array is expected to |
495 * If this list is storing pointers instead of objects, @p array is expected to |
| 452 * be an array of pointers. |
496 * be an array of pointers. |
| 453 * |
497 * |
| 454 * @param list the list |
498 * @param list the list |
| 455 * @param index the index where to add the elements |
499 * @param index the index where to add the elements |
| 456 * @param array a pointer to the elements to add |
500 * @param array a pointer to the elements to add |
| 457 * @param n the number of elements to add |
501 * @param n the number of elements to add |
| 458 * @return the number of added elements |
502 * @return the number of added elements |
| 459 */ |
503 * @see cxListEmplaceArrayAt() |
| 460 cx_attr_nonnull |
504 */ |
| 461 static inline size_t cxListInsertArray( |
505 cx_attr_nonnull |
| 462 CxList *list, |
506 CX_EXPORT size_t cxListInsertArray(CxList *list, size_t index, const void *array, size_t n); |
| 463 size_t index, |
|
| 464 const void *array, |
|
| 465 size_t n |
|
| 466 ) { |
|
| 467 list->collection.sorted = false; |
|
| 468 return list->cl->insert_array(list, index, array, n); |
|
| 469 } |
|
| 470 |
507 |
| 471 /** |
508 /** |
| 472 * Inserts a sorted array into a sorted list. |
509 * Inserts a sorted array into a sorted list. |
| 473 * |
510 * |
| 474 * This method is usually more efficient than inserting each element separately, |
511 * This method is usually more efficient than inserting each element separately |
| 475 * because consecutive chunks of sorted data are inserted in one pass. |
512 * because consecutive chunks of sorted data are inserted in one pass. |
| 476 * |
513 * |
| 477 * If there is not enough memory to add all elements, the returned value is |
514 * If there is not enough memory to add all elements, the returned value is |
| 478 * less than @p n. |
515 * less than @p n. |
| 479 * |
516 * |
| 480 * If this list is storing pointers instead of objects @p array is expected to |
517 * If this list is storing pointers instead of objects, @p array is expected to |
| 481 * be an array of pointers. |
518 * be an array of pointers. |
| 482 * |
519 * |
| 483 * If the list is not sorted already, the behavior is undefined. |
520 * If the list is not sorted already, the behavior is undefined. |
| 484 * |
521 * |
| 485 * @param list the list |
522 * @param list the list |
| 486 * @param array a pointer to the elements to add |
523 * @param array a pointer to the elements to add |
| 487 * @param n the number of elements to add |
524 * @param n the number of elements to add |
| 488 * @return the number of added elements |
525 * @return the number of added elements |
| 489 */ |
526 */ |
| 490 cx_attr_nonnull |
527 cx_attr_nonnull |
| 491 static inline size_t cxListInsertSortedArray( |
528 CX_EXPORT size_t cxListInsertSortedArray(CxList *list, const void *array, size_t n); |
| 492 CxList *list, |
529 |
| 493 const void *array, |
530 /** |
| 494 size_t n |
531 * Inserts an array into a list, skipping duplicates. |
| 495 ) { |
532 * |
| 496 list->collection.sorted = true; // guaranteed by definition |
533 * The @p list does not need to be sorted (in contrast to cxListInsertSortedArray()). |
| 497 return list->cl->insert_sorted(list, array, n); |
534 * But it is strongly recommended to use this function only on sorted lists, |
| 498 } |
535 * because otherwise it will fall back to an inefficient algorithm which inserts |
| |
536 * all elements one by one. |
| |
537 * If the @p list is not sorted, the @p array also does not need to be sorted. |
| |
538 * But when the @p list is sorted, the @p array must also be sorted. |
| |
539 * |
| |
540 * This method is usually more efficient than inserting each element separately |
| |
541 * because consecutive chunks of sorted data are inserted in one pass. |
| |
542 * |
| |
543 * If there is not enough memory to add all elements, the returned value is |
| |
544 * less than @p n. |
| |
545 * |
| |
546 * @note The return value of this function denotes the number of elements |
| |
547 * from the @p sorted_data that are definitely contained in the list after |
| |
548 * completing the call. It is @em not the number of elements that were newly |
| |
549 * inserted. That means, when no error occurred, the return value should |
| |
550 * be @p n. |
| |
551 * |
| |
552 * If this list is storing pointers instead of objects @p array is expected to |
| |
553 * be an array of pointers. |
| |
554 * |
| |
555 * @param list the list |
| |
556 * @param array a pointer to the elements to add |
| |
557 * @param n the number of elements to add |
| |
558 * @return the number of added elements |
| |
559 * |
| |
560 * @return the number of elements from the @p sorted_data that are definitely present in the list after this call |
| |
561 */ |
| |
562 cx_attr_nonnull |
| |
563 CX_EXPORT size_t cxListInsertUniqueArray(CxList *list, const void *array, size_t n); |
| 499 |
564 |
| 500 /** |
565 /** |
| 501 * Inserts an element after the current location of the specified iterator. |
566 * Inserts an element after the current location of the specified iterator. |
| 502 * |
567 * |
| 503 * The used iterator remains operational, but all other active iterators should |
568 * The used iterator remains operational, but all other active iterators should |
| 559 * @param index the index of the element |
610 * @param index the index of the element |
| 560 * @retval zero success |
611 * @retval zero success |
| 561 * @retval non-zero index out of bounds |
612 * @retval non-zero index out of bounds |
| 562 */ |
613 */ |
| 563 cx_attr_nonnull |
614 cx_attr_nonnull |
| 564 static inline int cxListRemove( |
615 CX_EXPORT int cxListRemove(CxList *list, size_t index); |
| 565 CxList *list, |
|
| 566 size_t index |
|
| 567 ) { |
|
| 568 return list->cl->remove(list, index, 1, NULL) == 0; |
|
| 569 } |
|
| 570 |
616 |
| 571 /** |
617 /** |
| 572 * Removes and returns the element at the specified index. |
618 * Removes and returns the element at the specified index. |
| 573 * |
619 * |
| 574 * No destructor is called and instead the element is copied to the |
620 * No destructor is called, and instead the element is copied to the |
| 575 * @p targetbuf which MUST be large enough to hold the removed element. |
621 * @p targetbuf which MUST be large enough to hold the removed element. |
| |
622 * If the list is storing pointers, only the pointer is copied to @p targetbuf. |
| 576 * |
623 * |
| 577 * @param list the list |
624 * @param list the list |
| 578 * @param index the index of the element |
625 * @param index the index of the element |
| 579 * @param targetbuf a buffer where to copy the element |
626 * @param targetbuf a buffer where to copy the element |
| 580 * @retval zero success |
627 * @retval zero success |
| 581 * @retval non-zero index out of bounds |
628 * @retval non-zero index out of bounds |
| 582 */ |
629 */ |
| 583 cx_attr_nonnull |
630 cx_attr_nonnull cx_attr_access_w(3) |
| 584 cx_attr_access_w(3) |
631 CX_EXPORT int cxListRemoveAndGet(CxList *list, size_t index, void *targetbuf); |
| 585 static inline int cxListRemoveAndGet( |
632 |
| 586 CxList *list, |
633 /** |
| 587 size_t index, |
634 * Removes and returns the first element of the list. |
| 588 void *targetbuf |
635 * |
| 589 ) { |
636 * No destructor is called, and instead the element is copied to the |
| 590 return list->cl->remove(list, index, 1, targetbuf) == 0; |
637 * @p targetbuf which MUST be large enough to hold the removed element. |
| 591 } |
638 * If the list is storing pointers, only the pointer is copied to @p targetbuf. |
| |
639 * |
| |
640 * @param list the list |
| |
641 * @param targetbuf a buffer where to copy the element |
| |
642 * @retval zero success |
| |
643 * @retval non-zero the list is empty |
| |
644 * @see cxListPopFront() |
| |
645 * @see cxListRemoveAndGetLast() |
| |
646 */ |
| |
647 cx_attr_nonnull cx_attr_access_w(2) |
| |
648 CX_EXPORT int cxListRemoveAndGetFirst(CxList *list, void *targetbuf); |
| |
649 |
| |
650 /** |
| |
651 * Removes and returns the first element of the list. |
| |
652 * |
| |
653 * Alias for cxListRemoveAndGetFirst(). |
| |
654 * |
| |
655 * No destructor is called, and instead the element is copied to the |
| |
656 * @p targetbuf which MUST be large enough to hold the removed element. |
| |
657 * If the list is storing pointers, only the pointer is copied to @p targetbuf. |
| |
658 * |
| |
659 * @param list (@c CxList*) the list |
| |
660 * @param targetbuf (@c void*) a buffer where to copy the element |
| |
661 * @retval zero success |
| |
662 * @retval non-zero the list is empty |
| |
663 * @see cxListRemoveAndGetFirst() |
| |
664 * @see cxListPop() |
| |
665 */ |
| |
666 #define cxListPopFront(list, targetbuf) cxListRemoveAndGetFirst((list), (targetbuf)) |
| |
667 |
| |
668 |
| |
669 /** |
| |
670 * Removes and returns the last element of the list. |
| |
671 * |
| |
672 * No destructor is called, and instead the element is copied to the |
| |
673 * @p targetbuf which MUST be large enough to hold the removed element. |
| |
674 * If the list is storing pointers, only the pointer is copied to @p targetbuf. |
| |
675 * |
| |
676 * @param list the list |
| |
677 * @param targetbuf a buffer where to copy the element |
| |
678 * @retval zero success |
| |
679 * @retval non-zero the list is empty |
| |
680 */ |
| |
681 cx_attr_nonnull cx_attr_access_w(2) |
| |
682 CX_EXPORT int cxListRemoveAndGetLast(CxList *list, void *targetbuf); |
| |
683 |
| |
684 /** |
| |
685 * Removes and returns the last element of the list. |
| |
686 * |
| |
687 * Alias for cxListRemoveAndGetLast(). |
| |
688 * |
| |
689 * No destructor is called, and instead the element is copied to the |
| |
690 * @p targetbuf which MUST be large enough to hold the removed element. |
| |
691 * If the list is storing pointers, only the pointer is copied to @p targetbuf. |
| |
692 * |
| |
693 * @param list (@c CxList*) the list |
| |
694 * @param targetbuf (@c void*) a buffer where to copy the element |
| |
695 * @retval zero success |
| |
696 * @retval non-zero the list is empty |
| |
697 * @see cxListRemoveAndGetLast() |
| |
698 * @see cxListPopFront() |
| |
699 */ |
| |
700 #define cxListPop(list, targetbuf) cxListRemoveAndGetLast((list), (targetbuf)) |
| 592 |
701 |
| 593 /** |
702 /** |
| 594 * Removes multiple element starting at the specified index. |
703 * Removes multiple element starting at the specified index. |
| 595 * |
704 * |
| 596 * If an element destructor function is specified, it is called for each |
705 * If an element destructor function is specified, it is called for each |
| 597 * element. It is guaranteed that the destructor is called before removing |
706 * element. It is guaranteed that the destructor is called before removing |
| 598 * the element, however, due to possible optimizations it is neither guaranteed |
707 * the element. However, due to possible optimizations, it is neither guaranteed |
| 599 * that the destructors are invoked for all elements before starting to remove |
708 * that the destructors are invoked for all elements before starting to remove |
| 600 * them, nor that the element is removed immediately after the destructor call |
709 * them, nor that the element is removed immediately after the destructor call |
| 601 * before proceeding to the next element. |
710 * before proceeding to the next element. |
| 602 * |
711 * |
| 603 * @param list the list |
712 * @param list the list |
| 604 * @param index the index of the element |
713 * @param index the index of the element |
| 605 * @param num the number of elements to remove |
714 * @param num the number of elements to remove |
| 606 * @return the actual number of removed elements |
715 * @return the actual number of removed elements |
| 607 */ |
716 */ |
| 608 cx_attr_nonnull |
717 cx_attr_nonnull |
| 609 static inline size_t cxListRemoveArray( |
718 CX_EXPORT size_t cxListRemoveArray(CxList *list, size_t index, size_t num); |
| 610 CxList *list, |
719 |
| 611 size_t index, |
720 /** |
| 612 size_t num |
721 * Removes and returns multiple elements starting at the specified index. |
| 613 ) { |
722 * |
| 614 return list->cl->remove(list, index, num, NULL); |
723 * No destructor is called, and instead the elements are copied to the |
| 615 } |
|
| 616 |
|
| 617 /** |
|
| 618 * Removes and returns multiple element starting at the specified index. |
|
| 619 * |
|
| 620 * No destructor is called and instead the elements are copied to the |
|
| 621 * @p targetbuf which MUST be large enough to hold all removed elements. |
724 * @p targetbuf which MUST be large enough to hold all removed elements. |
| |
725 * If the list is storing pointers, @p targetbuf is expected to be an array of pointers. |
| 622 * |
726 * |
| 623 * @param list the list |
727 * @param list the list |
| 624 * @param index the index of the element |
728 * @param index the index of the element |
| 625 * @param num the number of elements to remove |
729 * @param num the number of elements to remove |
| 626 * @param targetbuf a buffer where to copy the elements |
730 * @param targetbuf a buffer where to copy the elements |
| 627 * @return the actual number of removed elements |
731 * @return the actual number of removed elements |
| 628 */ |
732 */ |
| 629 cx_attr_nonnull |
733 cx_attr_nonnull cx_attr_access_w(4) |
| 630 cx_attr_access_w(4) |
734 CX_EXPORT size_t cxListRemoveArrayAndGet(CxList *list, size_t index, size_t num, void *targetbuf); |
| 631 static inline size_t cxListRemoveArrayAndGet( |
|
| 632 CxList *list, |
|
| 633 size_t index, |
|
| 634 size_t num, |
|
| 635 void *targetbuf |
|
| 636 ) { |
|
| 637 return list->cl->remove(list, index, num, targetbuf); |
|
| 638 } |
|
| 639 |
735 |
| 640 /** |
736 /** |
| 641 * Removes all elements from this list. |
737 * Removes all elements from this list. |
| 642 * |
738 * |
| 643 * If element destructor functions are specified, they are called for each |
739 * If element destructor functions are specified, they are called for each |
| 644 * element before removing them. |
740 * element before removing them. |
| 645 * |
741 * |
| 646 * @param list the list |
742 * @param list the list |
| 647 */ |
743 */ |
| 648 cx_attr_nonnull |
744 cx_attr_nonnull |
| 649 static inline void cxListClear(CxList *list) { |
745 CX_EXPORT void cxListClear(CxList *list); |
| 650 list->collection.sorted = true; // empty lists are always sorted |
|
| 651 list->cl->clear(list); |
|
| 652 } |
|
| 653 |
746 |
| 654 /** |
747 /** |
| 655 * Swaps two items in the list. |
748 * Swaps two items in the list. |
| 656 * |
749 * |
| 657 * Implementations should only allocate temporary memory for the swap, if |
750 * Implementations should only allocate temporary memory for the swap if |
| 658 * it is necessary. |
751 * it is necessary. |
| 659 * |
752 * |
| 660 * @param list the list |
753 * @param list the list |
| 661 * @param i the index of the first element |
754 * @param i the index of the first element |
| 662 * @param j the index of the second element |
755 * @param j the index of the second element |
| 663 * @retval zero success |
756 * @retval zero success |
| 664 * @retval non-zero one of the indices is out of bounds |
757 * @retval non-zero one of the indices is out of bounds, |
| 665 * or the swap needed extra memory but allocation failed |
758 * or the swap needed extra memory, but allocation failed |
| 666 */ |
759 */ |
| 667 cx_attr_nonnull |
760 cx_attr_nonnull |
| 668 static inline int cxListSwap( |
761 CX_EXPORT int cxListSwap(CxList *list, size_t i, size_t j); |
| 669 CxList *list, |
|
| 670 size_t i, |
|
| 671 size_t j |
|
| 672 ) { |
|
| 673 list->collection.sorted = false; |
|
| 674 return list->cl->swap(list, i, j); |
|
| 675 } |
|
| 676 |
762 |
| 677 /** |
763 /** |
| 678 * Returns a pointer to the element at the specified index. |
764 * Returns a pointer to the element at the specified index. |
| |
765 * |
| |
766 * If the list is storing pointers, returns the pointer stored at the specified index. |
| 679 * |
767 * |
| 680 * @param list the list |
768 * @param list the list |
| 681 * @param index the index of the element |
769 * @param index the index of the element |
| 682 * @return a pointer to the element or @c NULL if the index is out of bounds |
770 * @return a pointer to the element or @c NULL if the index is out of bounds |
| 683 */ |
771 */ |
| 684 cx_attr_nonnull |
772 cx_attr_nonnull |
| 685 static inline void *cxListAt( |
773 CX_EXPORT void *cxListAt(const CxList *list, size_t index); |
| 686 const CxList *list, |
774 |
| 687 size_t index |
775 /** |
| 688 ) { |
776 * Returns a pointer to the first element. |
| 689 return list->cl->at(list, index); |
777 * |
| 690 } |
778 * If the list is storing pointers, returns the first pointer stored in the list. |
| |
779 * |
| |
780 * @param list the list |
| |
781 * @return a pointer to the first element or @c NULL if the list is empty |
| |
782 */ |
| |
783 cx_attr_nonnull |
| |
784 CX_EXPORT void *cxListFirst(const CxList *list); |
| |
785 |
| |
786 /** |
| |
787 * Returns a pointer to the last element. |
| |
788 * |
| |
789 * If the list is storing pointers, returns the last pointer stored in the list. |
| |
790 * |
| |
791 * @param list the list |
| |
792 * @return a pointer to the last element or @c NULL if the list is empty |
| |
793 */ |
| |
794 cx_attr_nonnull |
| |
795 CX_EXPORT void *cxListLast(const CxList *list); |
| |
796 |
| |
797 /** |
| |
798 * Sets the element at the specified index in the list. |
| |
799 * |
| |
800 * This overwrites the element in-place without calling any destructor |
| |
801 * on the overwritten element. |
| |
802 * |
| |
803 * @param list the list to set the element in |
| |
804 * @param index the index to set the element at |
| |
805 * @param elem element to set |
| |
806 * @retval zero on success |
| |
807 * @retval non-zero when index is out of bounds |
| |
808 */ |
| |
809 cx_attr_nonnull |
| |
810 CX_EXPORT int cxListSet(CxList *list, size_t index, const void *elem); |
| 691 |
811 |
| 692 /** |
812 /** |
| 693 * Returns an iterator pointing to the item at the specified index. |
813 * Returns an iterator pointing to the item at the specified index. |
| 694 * |
814 * |
| 695 * The returned iterator is position-aware. |
815 * The returned iterator is position-aware. |
| 696 * |
816 * |
| 697 * If the index is out of range, a past-the-end iterator will be returned. |
817 * If the index is out of range or @p list is @c NULL, a past-the-end iterator will be returned. |
| 698 * |
818 * |
| 699 * @param list the list |
819 * @param list the list |
| 700 * @param index the index where the iterator shall point at |
820 * @param index the index where the iterator shall point at |
| 701 * @return a new iterator |
821 * @return a new iterator |
| 702 */ |
822 */ |
| 703 cx_attr_nonnull |
|
| 704 cx_attr_nodiscard |
823 cx_attr_nodiscard |
| 705 static inline CxIterator cxListIteratorAt( |
824 CX_EXPORT CxIterator cxListIteratorAt(const CxList *list, size_t index); |
| 706 const CxList *list, |
|
| 707 size_t index |
|
| 708 ) { |
|
| 709 return list->cl->iterator(list, index, false); |
|
| 710 } |
|
| 711 |
825 |
| 712 /** |
826 /** |
| 713 * Returns a backwards iterator pointing to the item at the specified index. |
827 * Returns a backwards iterator pointing to the item at the specified index. |
| 714 * |
828 * |
| 715 * The returned iterator is position-aware. |
829 * The returned iterator is position-aware. |
| 716 * |
830 * |
| 717 * If the index is out of range, a past-the-end iterator will be returned. |
831 * If the index is out of range or @p list is @c NULL, a past-the-end iterator will be returned. |
| 718 * |
832 * |
| 719 * @param list the list |
833 * @param list the list |
| 720 * @param index the index where the iterator shall point at |
834 * @param index the index where the iterator shall point at |
| 721 * @return a new iterator |
835 * @return a new iterator |
| 722 */ |
836 */ |
| 723 cx_attr_nonnull |
|
| 724 cx_attr_nodiscard |
837 cx_attr_nodiscard |
| 725 static inline CxIterator cxListBackwardsIteratorAt( |
838 CX_EXPORT CxIterator cxListBackwardsIteratorAt(const CxList *list, size_t index); |
| 726 const CxList *list, |
839 |
| 727 size_t index |
840 /** |
| 728 ) { |
841 * Returns an iterator pointing to the first item of the list. |
| 729 return list->cl->iterator(list, index, true); |
|
| 730 } |
|
| 731 |
|
| 732 /** |
|
| 733 * Returns a mutating iterator pointing to the item at the specified index. |
|
| 734 * |
842 * |
| 735 * The returned iterator is position-aware. |
843 * The returned iterator is position-aware. |
| 736 * |
844 * |
| 737 * If the index is out of range, a past-the-end iterator will be returned. |
845 * If the list is empty or @c NULL, a past-the-end iterator will be returned. |
| 738 * |
846 * |
| 739 * @param list the list |
847 * @param list the list |
| 740 * @param index the index where the iterator shall point at |
|
| 741 * @return a new iterator |
848 * @return a new iterator |
| 742 */ |
849 */ |
| 743 cx_attr_nonnull |
|
| 744 cx_attr_nodiscard |
850 cx_attr_nodiscard |
| 745 cx_attr_export |
851 CX_EXPORT CxIterator cxListIterator(const CxList *list); |
| 746 CxIterator cxListMutIteratorAt( |
852 |
| 747 CxList *list, |
853 /** |
| 748 size_t index |
854 * Returns a backwards iterator pointing to the last item of the list. |
| 749 ); |
|
| 750 |
|
| 751 /** |
|
| 752 * Returns a mutating backwards iterator pointing to the item at the |
|
| 753 * specified index. |
|
| 754 * |
855 * |
| 755 * The returned iterator is position-aware. |
856 * The returned iterator is position-aware. |
| 756 * |
857 * |
| 757 * If the index is out of range, a past-the-end iterator will be returned. |
858 * If the list is empty or @c NULL, a past-the-end iterator will be returned. |
| 758 * |
859 * |
| 759 * @param list the list |
860 * @param list the list |
| 760 * @param index the index where the iterator shall point at |
|
| 761 * @return a new iterator |
861 * @return a new iterator |
| 762 */ |
862 */ |
| 763 cx_attr_nonnull |
|
| 764 cx_attr_nodiscard |
863 cx_attr_nodiscard |
| 765 cx_attr_export |
864 CX_EXPORT CxIterator cxListBackwardsIterator(const CxList *list); |
| 766 CxIterator cxListMutBackwardsIteratorAt( |
|
| 767 CxList *list, |
|
| 768 size_t index |
|
| 769 ); |
|
| 770 |
|
| 771 /** |
|
| 772 * Returns an iterator pointing to the first item of the list. |
|
| 773 * |
|
| 774 * The returned iterator is position-aware. |
|
| 775 * |
|
| 776 * If the list is empty, a past-the-end iterator will be returned. |
|
| 777 * |
|
| 778 * @param list the list |
|
| 779 * @return a new iterator |
|
| 780 */ |
|
| 781 cx_attr_nonnull |
|
| 782 cx_attr_nodiscard |
|
| 783 static inline CxIterator cxListIterator(const CxList *list) { |
|
| 784 return list->cl->iterator(list, 0, false); |
|
| 785 } |
|
| 786 |
|
| 787 /** |
|
| 788 * Returns a mutating iterator pointing to the first item of the list. |
|
| 789 * |
|
| 790 * The returned iterator is position-aware. |
|
| 791 * |
|
| 792 * If the list is empty, a past-the-end iterator will be returned. |
|
| 793 * |
|
| 794 * @param list the list |
|
| 795 * @return a new iterator |
|
| 796 */ |
|
| 797 cx_attr_nonnull |
|
| 798 cx_attr_nodiscard |
|
| 799 static inline CxIterator cxListMutIterator(CxList *list) { |
|
| 800 return cxListMutIteratorAt(list, 0); |
|
| 801 } |
|
| 802 |
|
| 803 |
|
| 804 /** |
|
| 805 * Returns a backwards iterator pointing to the last item of the list. |
|
| 806 * |
|
| 807 * The returned iterator is position-aware. |
|
| 808 * |
|
| 809 * If the list is empty, a past-the-end iterator will be returned. |
|
| 810 * |
|
| 811 * @param list the list |
|
| 812 * @return a new iterator |
|
| 813 */ |
|
| 814 cx_attr_nonnull |
|
| 815 cx_attr_nodiscard |
|
| 816 static inline CxIterator cxListBackwardsIterator(const CxList *list) { |
|
| 817 return list->cl->iterator(list, list->collection.size - 1, true); |
|
| 818 } |
|
| 819 |
|
| 820 /** |
|
| 821 * Returns a mutating backwards iterator pointing to the last item of the list. |
|
| 822 * |
|
| 823 * The returned iterator is position-aware. |
|
| 824 * |
|
| 825 * If the list is empty, a past-the-end iterator will be returned. |
|
| 826 * |
|
| 827 * @param list the list |
|
| 828 * @return a new iterator |
|
| 829 */ |
|
| 830 cx_attr_nonnull |
|
| 831 cx_attr_nodiscard |
|
| 832 static inline CxIterator cxListMutBackwardsIterator(CxList *list) { |
|
| 833 return cxListMutBackwardsIteratorAt(list, list->collection.size - 1); |
|
| 834 } |
|
| 835 |
865 |
| 836 /** |
866 /** |
| 837 * Returns the index of the first element that equals @p elem. |
867 * Returns the index of the first element that equals @p elem. |
| 838 * |
868 * |
| 839 * Determining equality is performed by the list's comparator function. |
869 * Determining equality is performed by the list's comparator function. |
| 840 * |
870 * |
| 841 * @param list the list |
871 * @param list the list |
| 842 * @param elem the element to find |
872 * @param elem the element to find |
| 843 * @return the index of the element or the size of the list when the element is not found |
873 * @return the index of the element or the size of the list when the element is not found |
| 844 * @see cxListIndexValid() |
874 * @see cxListIndexValid() |
| 845 */ |
875 * @see cxListContains() |
| 846 cx_attr_nonnull |
876 */ |
| 847 cx_attr_nodiscard |
877 cx_attr_nonnull cx_attr_nodiscard |
| 848 static inline size_t cxListFind( |
878 CX_EXPORT size_t cxListFind(const CxList *list, const void *elem); |
| 849 const CxList *list, |
879 |
| 850 const void *elem |
880 /** |
| 851 ) { |
881 * Checks if the list contains the specified element. |
| 852 return list->cl->find_remove((CxList*)list, elem, false); |
882 * |
| 853 } |
883 * The elements are compared with the list's comparator function. |
| |
884 * |
| |
885 * @param list the list |
| |
886 * @param elem the element to find |
| |
887 * @retval true if the element is contained |
| |
888 * @retval false if the element is not contained |
| |
889 * @see cxListFind() |
| |
890 */ |
| |
891 cx_attr_nonnull cx_attr_nodiscard |
| |
892 CX_EXPORT bool cxListContains(const CxList* list, const void* elem); |
| 854 |
893 |
| 855 /** |
894 /** |
| 856 * Checks if the specified index is within bounds. |
895 * Checks if the specified index is within bounds. |
| 857 * |
896 * |
| 858 * @param list the list |
897 * @param list the list |
| 859 * @param index the index |
898 * @param index the index |
| 860 * @retval true if the index is within bounds |
899 * @retval true if the index is within bounds |
| 861 * @retval false if the index is out of bounds |
900 * @retval false if the index is out of bounds |
| 862 */ |
901 */ |
| 863 cx_attr_nonnull |
902 cx_attr_nonnull cx_attr_nodiscard |
| 864 cx_attr_nodiscard |
903 CX_EXPORT bool cxListIndexValid(const CxList *list, size_t index); |
| 865 static inline bool cxListIndexValid(const CxList *list, size_t index) { |
|
| 866 return index < list->collection.size; |
|
| 867 } |
|
| 868 |
904 |
| 869 /** |
905 /** |
| 870 * Removes and returns the index of the first element that equals @p elem. |
906 * Removes and returns the index of the first element that equals @p elem. |
| 871 * |
907 * |
| 872 * Determining equality is performed by the list's comparator function. |
908 * Determining equality is performed by the list's comparator function. |
| 876 * @return the index of the now removed element or the list size |
912 * @return the index of the now removed element or the list size |
| 877 * when the element is not found or could not be removed |
913 * when the element is not found or could not be removed |
| 878 * @see cxListIndexValid() |
914 * @see cxListIndexValid() |
| 879 */ |
915 */ |
| 880 cx_attr_nonnull |
916 cx_attr_nonnull |
| 881 static inline size_t cxListFindRemove( |
917 CX_EXPORT size_t cxListFindRemove(CxList *list, const void *elem); |
| 882 CxList *list, |
|
| 883 const void *elem |
|
| 884 ) { |
|
| 885 return list->cl->find_remove(list, elem, true); |
|
| 886 } |
|
| 887 |
918 |
| 888 /** |
919 /** |
| 889 * Sorts the list. |
920 * Sorts the list. |
| 890 * |
921 * |
| 891 * @remark The underlying sort algorithm is implementation defined. |
922 * @remark The underlying sort algorithm is implementation defined. |
| 892 * |
923 * |
| 893 * @param list the list |
924 * @param list the list |
| 894 */ |
925 */ |
| 895 cx_attr_nonnull |
926 cx_attr_nonnull |
| 896 static inline void cxListSort(CxList *list) { |
927 CX_EXPORT void cxListSort(CxList *list); |
| 897 list->cl->sort(list); |
|
| 898 list->collection.sorted = true; |
|
| 899 } |
|
| 900 |
928 |
| 901 /** |
929 /** |
| 902 * Reverses the order of the items. |
930 * Reverses the order of the items. |
| 903 * |
931 * |
| 904 * @param list the list |
932 * @param list the list |
| 905 */ |
933 */ |
| 906 cx_attr_nonnull |
934 cx_attr_nonnull |
| 907 static inline void cxListReverse(CxList *list) { |
935 CX_EXPORT void cxListReverse(CxList *list); |
| 908 // still sorted, but not according to the cmp_func |
|
| 909 list->collection.sorted = false; |
|
| 910 list->cl->reverse(list); |
|
| 911 } |
|
| 912 |
936 |
| 913 /** |
937 /** |
| 914 * Compares a list to another list of the same type. |
938 * Compares a list to another list of the same type. |
| 915 * |
939 * |
| 916 * First, the list sizes are compared. |
940 * First, the list sizes are compared. |
| 917 * If they match, the lists are compared element-wise. |
941 * If they match, the lists are compared element-wise. |
| 918 * |
942 * |
| 919 * @param list the list |
943 * @param list the list |
| 920 * @param other the list to compare to |
944 * @param other the list to compare to |
| 921 * @retval zero both lists are equal element wise |
945 * @retval zero both lists are equal element wise |
| 922 * @retval negative the first list is smaller |
946 * @retval negative the first list is smaller, |
| 923 * or the first non-equal element in the first list is smaller |
947 * or the first non-equal element in the first list is smaller |
| 924 * @retval positive the first list is larger |
948 * @retval positive the first list is larger |
| 925 * or the first non-equal element in the first list is larger |
949 * or the first non-equal element in the first list is larger |
| 926 */ |
950 */ |
| 927 cx_attr_nonnull |
951 cx_attr_nonnull cx_attr_nodiscard |
| 928 cx_attr_nodiscard |
952 CX_EXPORT int cxListCompare(const CxList *list, const CxList *other); |
| 929 cx_attr_export |
|
| 930 int cxListCompare( |
|
| 931 const CxList *list, |
|
| 932 const CxList *other |
|
| 933 ); |
|
| 934 |
953 |
| 935 /** |
954 /** |
| 936 * Deallocates the memory of the specified list structure. |
955 * Deallocates the memory of the specified list structure. |
| 937 * |
956 * |
| 938 * Also calls the content destructor functions for each element, if specified. |
957 * Also calls the content destructor functions for each element, if specified. |
| 939 * |
958 * |
| 940 * @param list the list which shall be freed |
959 * @param list the list that shall be freed |
| 941 */ |
960 */ |
| 942 cx_attr_export |
961 CX_EXPORT void cxListFree(CxList *list); |
| 943 void cxListFree(CxList *list); |
962 |
| 944 |
963 |
| 945 /** |
964 /** |
| 946 * A shared instance of an empty list. |
965 * Performs a deep clone of one list into another. |
| 947 * |
966 * |
| 948 * Writing to that list is not allowed. |
967 * If the destination list already contains elements, the cloned elements |
| 949 * |
968 * are appended to that list. |
| 950 * You can use this is a placeholder for initializing CxList pointers |
969 * |
| 951 * for which you do not want to reserve memory right from the beginning. |
970 * @attention If the cloned elements need to be destroyed by a destructor |
| 952 */ |
971 * function, you must make sure that the destination list also uses this |
| 953 cx_attr_export |
972 * destructor function. |
| 954 extern CxList *const cxEmptyList; |
973 * |
| |
974 * @param dst the destination list |
| |
975 * @param src the source list |
| |
976 * @param clone_func the clone function for the elements |
| |
977 * @param clone_allocator the allocator that is passed to the clone function |
| |
978 * @param data optional additional data that is passed to the clone function |
| |
979 * @retval zero when all elements were successfully cloned |
| |
980 * @retval non-zero when an allocation error occurred |
| |
981 * @see cxListUnion() |
| |
982 */ |
| |
983 cx_attr_nonnull_arg(1, 2, 3) |
| |
984 CX_EXPORT int cxListClone(CxList *dst, const CxList *src, |
| |
985 cx_clone_func clone_func, const CxAllocator *clone_allocator, void *data); |
| |
986 |
| |
987 /** |
| |
988 * Clones elements from a list only if they are not present in another list. |
| |
989 * |
| |
990 * If the @p minuend does not contain duplicates, this is equivalent to adding |
| |
991 * the set difference to the destination list. |
| |
992 * |
| |
993 * This function is optimized for the case when both the @p minuend and the |
| |
994 * @p subtrahend are sorted. |
| |
995 * |
| |
996 * @param dst the destination list |
| |
997 * @param minuend the list to subtract elements from |
| |
998 * @param subtrahend the elements that shall be subtracted |
| |
999 * @param clone_func the clone function for the elements |
| |
1000 * @param clone_allocator the allocator that is passed to the clone function |
| |
1001 * @param data optional additional data that is passed to the clone function |
| |
1002 * @retval zero when the elements were successfully cloned |
| |
1003 * @retval non-zero when an allocation error occurred |
| |
1004 */ |
| |
1005 cx_attr_nonnull_arg(1, 2, 3, 4) |
| |
1006 CX_EXPORT int cxListDifference(CxList *dst, |
| |
1007 const CxList *minuend, const CxList *subtrahend, |
| |
1008 cx_clone_func clone_func, const CxAllocator *clone_allocator, void *data); |
| |
1009 |
| |
1010 /** |
| |
1011 * Clones elements from a list only if they are also present in another list. |
| |
1012 * |
| |
1013 * This function is optimized for the case when both the @p src and the |
| |
1014 * @p other list are sorted. |
| |
1015 * |
| |
1016 * If the destination list already contains elements, the intersection is appended |
| |
1017 * to that list. |
| |
1018 * |
| |
1019 * @param dst the destination list |
| |
1020 * @param src the list to clone the elements from |
| |
1021 * @param other the list to check the elements for existence |
| |
1022 * @param clone_func the clone function for the elements |
| |
1023 * @param clone_allocator the allocator that is passed to the clone function |
| |
1024 * @param data optional additional data that is passed to the clone function |
| |
1025 * @retval zero when the elements were successfully cloned |
| |
1026 * @retval non-zero when an allocation error occurred |
| |
1027 */ |
| |
1028 cx_attr_nonnull_arg(1, 2, 3, 4) |
| |
1029 CX_EXPORT int cxListIntersection(CxList *dst, const CxList *src, const CxList *other, |
| |
1030 cx_clone_func clone_func, const CxAllocator *clone_allocator, void *data); |
| |
1031 |
| |
1032 /** |
| |
1033 * Performs a deep clone of one list into another, skipping duplicates. |
| |
1034 * |
| |
1035 * This function is optimized for the case when both the @p src and the |
| |
1036 * @p other list are sorted. |
| |
1037 * In that case, the union will also be sorted. |
| |
1038 * |
| |
1039 * If the destination list already contains elements, the union is appended |
| |
1040 * to that list. In that case the destination is not necessarily sorted. |
| |
1041 * |
| |
1042 * @param dst the destination list |
| |
1043 * @param src the primary source list |
| |
1044 * @param other the other list, where elements are only cloned from |
| |
1045 * when they are not in @p src |
| |
1046 * @param clone_func the clone function for the elements |
| |
1047 * @param clone_allocator the allocator that is passed to the clone function |
| |
1048 * @param data optional additional data that is passed to the clone function |
| |
1049 * @retval zero when the elements were successfully cloned |
| |
1050 * @retval non-zero when an allocation error occurred |
| |
1051 * @see cxListClone() |
| |
1052 */ |
| |
1053 cx_attr_nonnull_arg(1, 2, 3, 4) |
| |
1054 CX_EXPORT int cxListUnion(CxList *dst, const CxList *src, const CxList *other, |
| |
1055 cx_clone_func clone_func, const CxAllocator *clone_allocator, void *data); |
| 955 |
1056 |
| 956 |
1057 |
| 957 #ifdef __cplusplus |
1058 #ifdef __cplusplus |
| 958 } // extern "C" |
1059 } // extern "C" |
| 959 #endif |
1060 #endif |