| 357 * @param list the list |
369 * @param list the list |
| 358 * @param elem a pointer to the element to add |
370 * @param elem a pointer to the element to add |
| 359 * @retval zero success |
371 * @retval zero success |
| 360 * @retval non-zero memory allocation failure |
372 * @retval non-zero memory allocation failure |
| 361 * @see cxListAddArray() |
373 * @see cxListAddArray() |
| |
374 * @see cxListEmplace() |
| 362 */ |
375 */ |
| 363 cx_attr_nonnull |
376 cx_attr_nonnull |
| 364 static inline int cxListAdd( |
377 static inline int cxListAdd( |
| 365 CxList *list, |
378 CxList *list, |
| 366 const void *elem |
379 const void *elem |
| 367 ) { |
380 ) { |
| 368 list->collection.sorted = false; |
381 list->collection.sorted = false; |
| 369 return list->cl->insert_element(list, list->collection.size, elem); |
382 return list->cl->insert_element(list, list->collection.size, elem) == NULL; |
| 370 } |
383 } |
| 371 |
384 |
| 372 /** |
385 /** |
| 373 * Adds multiple items to the end of the list. |
386 * Adds multiple items to the end of the list. |
| 374 * |
387 * |
| 405 * @param elem a pointer to the element to add |
418 * @param elem a pointer to the element to add |
| 406 * @retval zero success |
419 * @retval zero success |
| 407 * @retval non-zero memory allocation failure or the index is out of bounds |
420 * @retval non-zero memory allocation failure or the index is out of bounds |
| 408 * @see cxListInsertAfter() |
421 * @see cxListInsertAfter() |
| 409 * @see cxListInsertBefore() |
422 * @see cxListInsertBefore() |
| |
423 * @see cxListEmplaceAt() |
| 410 */ |
424 */ |
| 411 cx_attr_nonnull |
425 cx_attr_nonnull |
| 412 static inline int cxListInsert( |
426 static inline int cxListInsert( |
| 413 CxList *list, |
427 CxList *list, |
| 414 size_t index, |
428 size_t index, |
| 415 const void *elem |
429 const void *elem |
| 416 ) { |
430 ) { |
| 417 list->collection.sorted = false; |
431 list->collection.sorted = false; |
| 418 return list->cl->insert_element(list, index, elem); |
432 return list->cl->insert_element(list, index, elem) == NULL; |
| |
433 } |
| |
434 |
| |
435 /** |
| |
436 * Allocates memory for an element at the specified index and returns a pointer to that memory. |
| |
437 * |
| |
438 * @remark When the list is storing pointers, this will return a @c void**. |
| |
439 * |
| |
440 * @param list the list |
| |
441 * @param index the index where to emplace the element |
| |
442 * @return a pointer to the allocated memory; @c NULL when the operation fails, or the index is out-of-bounds |
| |
443 * @see cxListEmplace() |
| |
444 * @see cxListInsert() |
| |
445 */ |
| |
446 cx_attr_nonnull |
| |
447 static inline void *cxListEmplaceAt(CxList *list, size_t index) { |
| |
448 list->collection.sorted = false; |
| |
449 return list->cl->insert_element(list, index, NULL); |
| |
450 } |
| |
451 |
| |
452 |
| |
453 /** |
| |
454 * Allocates memory for an element at the end of the list and returns a pointer to that memory. |
| |
455 * |
| |
456 * @remark When the list is storing pointers, this will return a @c void**. |
| |
457 * |
| |
458 * @param list the list |
| |
459 * @return a pointer to the allocated memory; @c NULL when the operation fails, or the index is out-of-bounds |
| |
460 * @see cxListEmplaceAt() |
| |
461 * @see cxListAdd() |
| |
462 */ |
| |
463 cx_attr_nonnull |
| |
464 static inline void *cxListEmplace(CxList *list) { |
| |
465 list->collection.sorted = false; |
| |
466 return list->cl->insert_element(list, list->collection.size, NULL); |
| 419 } |
467 } |
| 420 |
468 |
| 421 /** |
469 /** |
| 422 * Inserts an item into a sorted list. |
470 * Inserts an item into a sorted list. |
| 423 * |
471 * |
| 569 } |
617 } |
| 570 |
618 |
| 571 /** |
619 /** |
| 572 * Removes and returns the element at the specified index. |
620 * Removes and returns the element at the specified index. |
| 573 * |
621 * |
| 574 * No destructor is called and instead the element is copied to the |
622 * 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. |
623 * @p targetbuf which MUST be large enough to hold the removed element. |
| |
624 * If the list is storing pointers, only the pointer is copied to @p targetbuf. |
| 576 * |
625 * |
| 577 * @param list the list |
626 * @param list the list |
| 578 * @param index the index of the element |
627 * @param index the index of the element |
| 579 * @param targetbuf a buffer where to copy the element |
628 * @param targetbuf a buffer where to copy the element |
| 580 * @retval zero success |
629 * @retval zero success |
| 589 ) { |
638 ) { |
| 590 return list->cl->remove(list, index, 1, targetbuf) == 0; |
639 return list->cl->remove(list, index, 1, targetbuf) == 0; |
| 591 } |
640 } |
| 592 |
641 |
| 593 /** |
642 /** |
| |
643 * Removes and returns the first element of the list. |
| |
644 * |
| |
645 * No destructor is called, and instead the element is copied to the |
| |
646 * @p targetbuf which MUST be large enough to hold the removed element. |
| |
647 * If the list is storing pointers, only the pointer is copied to @p targetbuf. |
| |
648 * |
| |
649 * @param list the list |
| |
650 * @param targetbuf a buffer where to copy the element |
| |
651 * @retval zero success |
| |
652 * @retval non-zero list is empty |
| |
653 * @see cxListPopFront() |
| |
654 * @see cxListRemoveAndGetLast() |
| |
655 */ |
| |
656 cx_attr_nonnull |
| |
657 cx_attr_access_w(2) |
| |
658 static inline int cxListRemoveAndGetFirst( |
| |
659 CxList *list, |
| |
660 void *targetbuf |
| |
661 ) { |
| |
662 return list->cl->remove(list, 0, 1, targetbuf) == 0; |
| |
663 } |
| |
664 |
| |
665 /** |
| |
666 * Removes and returns the first element of the list. |
| |
667 * |
| |
668 * Alias for cxListRemoveAndGetFirst(). |
| |
669 * |
| |
670 * No destructor is called, and instead the element is copied to the |
| |
671 * @p targetbuf which MUST be large enough to hold the removed element. |
| |
672 * If the list is storing pointers, only the pointer is copied to @p targetbuf. |
| |
673 * |
| |
674 * @param list (@c CxList*) the list |
| |
675 * @param targetbuf (@c void*) a buffer where to copy the element |
| |
676 * @retval zero success |
| |
677 * @retval non-zero list is empty |
| |
678 * @see cxListRemoveAndGetFirst() |
| |
679 * @see cxListPop() |
| |
680 */ |
| |
681 #define cxListPopFront(list, targetbuf) cxListRemoveAndGetFirst((list), (targetbuf)) |
| |
682 |
| |
683 |
| |
684 /** |
| |
685 * Removes and returns the last element of the list. |
| |
686 * |
| |
687 * No destructor is called, and instead the element is copied to the |
| |
688 * @p targetbuf which MUST be large enough to hold the removed element. |
| |
689 * If the list is storing pointers, only the pointer is copied to @p targetbuf. |
| |
690 * |
| |
691 * @param list the list |
| |
692 * @param targetbuf a buffer where to copy the element |
| |
693 * @retval zero success |
| |
694 * @retval non-zero list is empty |
| |
695 */ |
| |
696 cx_attr_nonnull |
| |
697 cx_attr_access_w(2) |
| |
698 static inline int cxListRemoveAndGetLast( |
| |
699 CxList *list, |
| |
700 void *targetbuf |
| |
701 ) { |
| |
702 // note: index may wrap - member function will catch that |
| |
703 return list->cl->remove(list, list->collection.size - 1, 1, targetbuf) == 0; |
| |
704 } |
| |
705 |
| |
706 /** |
| |
707 * Removes and returns the last element of the list. |
| |
708 * |
| |
709 * Alias for cxListRemoveAndGetLast(). |
| |
710 * |
| |
711 * No destructor is called, and instead the element is copied to the |
| |
712 * @p targetbuf which MUST be large enough to hold the removed element. |
| |
713 * If the list is storing pointers, only the pointer is copied to @p targetbuf. |
| |
714 * |
| |
715 * @param list (@c CxList*) the list |
| |
716 * @param targetbuf (@c void*) a buffer where to copy the element |
| |
717 * @retval zero success |
| |
718 * @retval non-zero list is empty |
| |
719 * @see cxListRemoveAndGetLast() |
| |
720 * @see cxListPopFront() |
| |
721 */ |
| |
722 #define cxListPop(list, targetbuf) cxListRemoveAndGetLast((list), (targetbuf)) |
| |
723 |
| |
724 /** |
| 594 * Removes multiple element starting at the specified index. |
725 * Removes multiple element starting at the specified index. |
| 595 * |
726 * |
| 596 * If an element destructor function is specified, it is called for each |
727 * If an element destructor function is specified, it is called for each |
| 597 * element. It is guaranteed that the destructor is called before removing |
728 * element. It is guaranteed that the destructor is called before removing |
| 598 * the element, however, due to possible optimizations it is neither guaranteed |
729 * the element. However, due to possible optimizations, it is neither guaranteed |
| 599 * that the destructors are invoked for all elements before starting to remove |
730 * 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 |
731 * them, nor that the element is removed immediately after the destructor call |
| 601 * before proceeding to the next element. |
732 * before proceeding to the next element. |
| 602 * |
733 * |
| 603 * @param list the list |
734 * @param list the list |
| 613 ) { |
744 ) { |
| 614 return list->cl->remove(list, index, num, NULL); |
745 return list->cl->remove(list, index, num, NULL); |
| 615 } |
746 } |
| 616 |
747 |
| 617 /** |
748 /** |
| 618 * Removes and returns multiple element starting at the specified index. |
749 * Removes and returns multiple elements starting at the specified index. |
| 619 * |
750 * |
| 620 * No destructor is called and instead the elements are copied to the |
751 * 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. |
752 * @p targetbuf which MUST be large enough to hold all removed elements. |
| |
753 * If the list is storing pointers, @p targetbuf is expected to be an array of pointers. |
| 622 * |
754 * |
| 623 * @param list the list |
755 * @param list the list |
| 624 * @param index the index of the element |
756 * @param index the index of the element |
| 625 * @param num the number of elements to remove |
757 * @param num the number of elements to remove |
| 626 * @param targetbuf a buffer where to copy the elements |
758 * @param targetbuf a buffer where to copy the elements |
| 652 } |
784 } |
| 653 |
785 |
| 654 /** |
786 /** |
| 655 * Swaps two items in the list. |
787 * Swaps two items in the list. |
| 656 * |
788 * |
| 657 * Implementations should only allocate temporary memory for the swap, if |
789 * Implementations should only allocate temporary memory for the swap if |
| 658 * it is necessary. |
790 * it is necessary. |
| 659 * |
791 * |
| 660 * @param list the list |
792 * @param list the list |
| 661 * @param i the index of the first element |
793 * @param i the index of the first element |
| 662 * @param j the index of the second element |
794 * @param j the index of the second element |
| 663 * @retval zero success |
795 * @retval zero success |
| 664 * @retval non-zero one of the indices is out of bounds |
796 * @retval non-zero one of the indices is out of bounds, |
| 665 * or the swap needed extra memory but allocation failed |
797 * or the swap needed extra memory, but allocation failed |
| 666 */ |
798 */ |
| 667 cx_attr_nonnull |
799 cx_attr_nonnull |
| 668 static inline int cxListSwap( |
800 static inline int cxListSwap( |
| 669 CxList *list, |
801 CxList *list, |
| 670 size_t i, |
802 size_t i, |
| 688 ) { |
822 ) { |
| 689 return list->cl->at(list, index); |
823 return list->cl->at(list, index); |
| 690 } |
824 } |
| 691 |
825 |
| 692 /** |
826 /** |
| |
827 * Returns a pointer to the first element. |
| |
828 * |
| |
829 * If the list is storing pointers, returns the first pointer stored in the list. |
| |
830 * |
| |
831 * @param list the list |
| |
832 * @return a pointer to the first element or @c NULL if the list is empty |
| |
833 */ |
| |
834 cx_attr_nonnull |
| |
835 static inline void *cxListFirst(const CxList *list) { |
| |
836 return list->cl->at(list, 0); |
| |
837 } |
| |
838 |
| |
839 /** |
| |
840 * Returns a pointer to the last element. |
| |
841 * |
| |
842 * If the list is storing pointers, returns the last pointer stored in the list. |
| |
843 * |
| |
844 * @param list the list |
| |
845 * @return a pointer to the last element or @c NULL if the list is empty |
| |
846 */ |
| |
847 cx_attr_nonnull |
| |
848 static inline void *cxListLast(const CxList *list) { |
| |
849 return list->cl->at(list, list->collection.size - 1); |
| |
850 } |
| |
851 |
| |
852 /** |
| |
853 * Sets the element at the specified index in the list |
| |
854 * |
| |
855 * @param list the list to set the element in |
| |
856 * @param index the index to set the element at |
| |
857 * @param elem element to set |
| |
858 * @retval zero on success |
| |
859 * @retval non-zero when index is out of bounds |
| |
860 */ |
| |
861 cx_attr_nonnull |
| |
862 cx_attr_export |
| |
863 int cxListSet( |
| |
864 CxList *list, |
| |
865 size_t index, |
| |
866 const void *elem |
| |
867 ); |
| |
868 |
| |
869 /** |
| 693 * Returns an iterator pointing to the item at the specified index. |
870 * Returns an iterator pointing to the item at the specified index. |
| 694 * |
871 * |
| 695 * The returned iterator is position-aware. |
872 * The returned iterator is position-aware. |
| 696 * |
873 * |
| 697 * If the index is out of range, a past-the-end iterator will be returned. |
874 * If the index is out of range or @p list is @c NULL, a past-the-end iterator will be returned. |
| 698 * |
875 * |
| 699 * @param list the list |
876 * @param list the list |
| 700 * @param index the index where the iterator shall point at |
877 * @param index the index where the iterator shall point at |
| 701 * @return a new iterator |
878 * @return a new iterator |
| 702 */ |
879 */ |
| 703 cx_attr_nonnull |
|
| 704 cx_attr_nodiscard |
880 cx_attr_nodiscard |
| 705 static inline CxIterator cxListIteratorAt( |
881 static inline CxIterator cxListIteratorAt( |
| 706 const CxList *list, |
882 const CxList *list, |
| 707 size_t index |
883 size_t index |
| 708 ) { |
884 ) { |
| |
885 if (list == NULL) list = cxEmptyList; |
| 709 return list->cl->iterator(list, index, false); |
886 return list->cl->iterator(list, index, false); |
| 710 } |
887 } |
| 711 |
888 |
| 712 /** |
889 /** |
| 713 * Returns a backwards iterator pointing to the item at the specified index. |
890 * Returns a backwards iterator pointing to the item at the specified index. |
| 714 * |
891 * |
| 715 * The returned iterator is position-aware. |
892 * The returned iterator is position-aware. |
| 716 * |
893 * |
| 717 * If the index is out of range, a past-the-end iterator will be returned. |
894 * If the index is out of range or @p list is @c NULL, a past-the-end iterator will be returned. |
| 718 * |
895 * |
| 719 * @param list the list |
896 * @param list the list |
| 720 * @param index the index where the iterator shall point at |
897 * @param index the index where the iterator shall point at |
| 721 * @return a new iterator |
898 * @return a new iterator |
| 722 */ |
899 */ |
| 723 cx_attr_nonnull |
|
| 724 cx_attr_nodiscard |
900 cx_attr_nodiscard |
| 725 static inline CxIterator cxListBackwardsIteratorAt( |
901 static inline CxIterator cxListBackwardsIteratorAt( |
| 726 const CxList *list, |
902 const CxList *list, |
| 727 size_t index |
903 size_t index |
| 728 ) { |
904 ) { |
| |
905 if (list == NULL) list = cxEmptyList; |
| 729 return list->cl->iterator(list, index, true); |
906 return list->cl->iterator(list, index, true); |
| 730 } |
907 } |
| 731 |
908 |
| 732 /** |
909 /** |
| 733 * Returns a mutating iterator pointing to the item at the specified index. |
910 * Returns a mutating iterator pointing to the item at the specified index. |
| 734 * |
911 * |
| 735 * The returned iterator is position-aware. |
912 * The returned iterator is position-aware. |
| 736 * |
913 * |
| 737 * If the index is out of range, a past-the-end iterator will be returned. |
914 * If the index is out of range or @p list is @c NULL, a past-the-end iterator will be returned. |
| 738 * |
915 * |
| 739 * @param list the list |
916 * @param list the list |
| 740 * @param index the index where the iterator shall point at |
917 * @param index the index where the iterator shall point at |
| 741 * @return a new iterator |
918 * @return a new iterator |
| 742 */ |
919 */ |
| 743 cx_attr_nonnull |
|
| 744 cx_attr_nodiscard |
920 cx_attr_nodiscard |
| 745 cx_attr_export |
921 cx_attr_export |
| 746 CxIterator cxListMutIteratorAt( |
922 CxIterator cxListMutIteratorAt( |
| 747 CxList *list, |
923 CxList *list, |
| 748 size_t index |
924 size_t index |
| 771 /** |
946 /** |
| 772 * Returns an iterator pointing to the first item of the list. |
947 * Returns an iterator pointing to the first item of the list. |
| 773 * |
948 * |
| 774 * The returned iterator is position-aware. |
949 * The returned iterator is position-aware. |
| 775 * |
950 * |
| 776 * If the list is empty, a past-the-end iterator will be returned. |
951 * If the list is empty or @c NULL, a past-the-end iterator will be returned. |
| 777 * |
952 * |
| 778 * @param list the list |
953 * @param list the list |
| 779 * @return a new iterator |
954 * @return a new iterator |
| 780 */ |
955 */ |
| 781 cx_attr_nonnull |
|
| 782 cx_attr_nodiscard |
956 cx_attr_nodiscard |
| 783 static inline CxIterator cxListIterator(const CxList *list) { |
957 static inline CxIterator cxListIterator(const CxList *list) { |
| |
958 if (list == NULL) list = cxEmptyList; |
| 784 return list->cl->iterator(list, 0, false); |
959 return list->cl->iterator(list, 0, false); |
| 785 } |
960 } |
| 786 |
961 |
| 787 /** |
962 /** |
| 788 * Returns a mutating iterator pointing to the first item of the list. |
963 * Returns a mutating iterator pointing to the first item of the list. |
| 789 * |
964 * |
| 790 * The returned iterator is position-aware. |
965 * The returned iterator is position-aware. |
| 791 * |
966 * |
| 792 * If the list is empty, a past-the-end iterator will be returned. |
967 * If the list is empty or @c NULL, a past-the-end iterator will be returned. |
| 793 * |
968 * |
| 794 * @param list the list |
969 * @param list the list |
| 795 * @return a new iterator |
970 * @return a new iterator |
| 796 */ |
971 */ |
| 797 cx_attr_nonnull |
|
| 798 cx_attr_nodiscard |
972 cx_attr_nodiscard |
| 799 static inline CxIterator cxListMutIterator(CxList *list) { |
973 static inline CxIterator cxListMutIterator(CxList *list) { |
| |
974 if (list == NULL) list = cxEmptyList; |
| 800 return cxListMutIteratorAt(list, 0); |
975 return cxListMutIteratorAt(list, 0); |
| 801 } |
976 } |
| 802 |
977 |
| 803 |
978 |
| 804 /** |
979 /** |
| 805 * Returns a backwards iterator pointing to the last item of the list. |
980 * Returns a backwards iterator pointing to the last item of the list. |
| 806 * |
981 * |
| 807 * The returned iterator is position-aware. |
982 * The returned iterator is position-aware. |
| 808 * |
983 * |
| 809 * If the list is empty, a past-the-end iterator will be returned. |
984 * If the list is empty or @c NULL, a past-the-end iterator will be returned. |
| 810 * |
985 * |
| 811 * @param list the list |
986 * @param list the list |
| 812 * @return a new iterator |
987 * @return a new iterator |
| 813 */ |
988 */ |
| 814 cx_attr_nonnull |
|
| 815 cx_attr_nodiscard |
989 cx_attr_nodiscard |
| 816 static inline CxIterator cxListBackwardsIterator(const CxList *list) { |
990 static inline CxIterator cxListBackwardsIterator(const CxList *list) { |
| |
991 if (list == NULL) list = cxEmptyList; |
| 817 return list->cl->iterator(list, list->collection.size - 1, true); |
992 return list->cl->iterator(list, list->collection.size - 1, true); |
| 818 } |
993 } |
| 819 |
994 |
| 820 /** |
995 /** |
| 821 * Returns a mutating backwards iterator pointing to the last item of the list. |
996 * Returns a mutating backwards iterator pointing to the last item of the list. |
| 822 * |
997 * |
| 823 * The returned iterator is position-aware. |
998 * The returned iterator is position-aware. |
| 824 * |
999 * |
| 825 * If the list is empty, a past-the-end iterator will be returned. |
1000 * If the list is empty or @c NULL, a past-the-end iterator will be returned. |
| 826 * |
1001 * |
| 827 * @param list the list |
1002 * @param list the list |
| 828 * @return a new iterator |
1003 * @return a new iterator |
| 829 */ |
1004 */ |
| 830 cx_attr_nonnull |
|
| 831 cx_attr_nodiscard |
1005 cx_attr_nodiscard |
| 832 static inline CxIterator cxListMutBackwardsIterator(CxList *list) { |
1006 static inline CxIterator cxListMutBackwardsIterator(CxList *list) { |
| |
1007 if (list == NULL) list = cxEmptyList; |
| 833 return cxListMutBackwardsIteratorAt(list, list->collection.size - 1); |
1008 return cxListMutBackwardsIteratorAt(list, list->collection.size - 1); |
| 834 } |
1009 } |
| 835 |
1010 |
| 836 /** |
1011 /** |
| 837 * Returns the index of the first element that equals @p elem. |
1012 * Returns the index of the first element that equals @p elem. |
| 851 ) { |
1027 ) { |
| 852 return list->cl->find_remove((CxList*)list, elem, false); |
1028 return list->cl->find_remove((CxList*)list, elem, false); |
| 853 } |
1029 } |
| 854 |
1030 |
| 855 /** |
1031 /** |
| |
1032 * Checks, if the list contains the specified element. |
| |
1033 * |
| |
1034 * The elements are compared with the list's comparator function. |
| |
1035 * |
| |
1036 * @param list the list |
| |
1037 * @param elem the element to find |
| |
1038 * @retval true if the element is contained |
| |
1039 * @retval false if the element is not contained |
| |
1040 * @see cxListFind() |
| |
1041 */ |
| |
1042 cx_attr_nonnull |
| |
1043 cx_attr_nodiscard |
| |
1044 static inline bool cxListContains( |
| |
1045 const CxList* list, |
| |
1046 const void* elem |
| |
1047 ) { |
| |
1048 return list->cl->find_remove((CxList*)list, elem, false) < list->collection.size; |
| |
1049 } |
| |
1050 |
| |
1051 /** |
| 856 * Checks if the specified index is within bounds. |
1052 * Checks if the specified index is within bounds. |
| 857 * |
1053 * |
| 858 * @param list the list |
1054 * @param list the list |
| 859 * @param index the index |
1055 * @param index the index |
| 860 * @retval true if the index is within bounds |
1056 * @retval true if the index is within bounds |