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