src/ucx/cx/list.h

changeset 582
82b60a8dd55c
parent 579
e10457d74fe1
child 621
956c03c25edd
equal deleted inserted replaced
581:4a049e416021 582:82b60a8dd55c
78 */ 78 */
79 void (*deallocate)(struct cx_list_s *list); 79 void (*deallocate)(struct cx_list_s *list);
80 80
81 /** 81 /**
82 * Member function for inserting a single element. 82 * Member function for inserting a single element.
83 */ 83 * The data pointer may be @c NULL in which case the function shall only allocate memory.
84 int (*insert_element)( 84 * Returns a pointer to the data of the inserted element.
85 */
86 void *(*insert_element)(
85 struct cx_list_s *list, 87 struct cx_list_s *list,
86 size_t index, 88 size_t index,
87 const void *data 89 const void *data
88 ); 90 );
89 91
199 const struct cx_list_s *list, 201 const struct cx_list_s *list,
200 size_t index, 202 size_t index,
201 bool backward 203 bool backward
202 ); 204 );
203 }; 205 };
206
207 /**
208 * Common type for all list implementations.
209 */
210 typedef struct cx_list_s CxList;
211
212 /**
213 * A shared instance of an empty list.
214 *
215 * Writing to that list is not allowed.
216 *
217 * You can use this is a placeholder for initializing CxList pointers
218 * for which you do not want to reserve memory right from the beginning.
219 */
220 cx_attr_export
221 extern CxList *const cxEmptyList;
204 222
205 /** 223 /**
206 * Default implementation of an array insert. 224 * Default implementation of an array insert.
207 * 225 *
208 * This function uses the element insert function for each element of the array. 226 * This function uses the element insert function for each element of the array.
334 cx_compare_func comparator, 352 cx_compare_func comparator,
335 size_t elem_size 353 size_t elem_size
336 ); 354 );
337 355
338 /** 356 /**
339 * Common type for all list implementations.
340 */
341 typedef struct cx_list_s CxList;
342
343 /**
344 * Returns the number of elements currently stored in the list. 357 * Returns the number of elements currently stored in the list.
345 * 358 *
346 * @param list the list 359 * @param list the list
347 * @return the number of currently stored elements 360 * @return the number of currently stored elements
348 */ 361 */
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,
674 return list->cl->swap(list, i, j); 807 return list->cl->swap(list, i, j);
675 } 808 }
676 809
677 /** 810 /**
678 * Returns a pointer to the element at the specified index. 811 * Returns a pointer to the element at the specified index.
812 *
813 * If the list is storing pointers, returns the pointer stored at the specified index.
679 * 814 *
680 * @param list the list 815 * @param list the list
681 * @param index the index of the element 816 * @param index the index of the element
682 * @return a pointer to the element or @c NULL if the index is out of bounds 817 * @return a pointer to the element or @c NULL if the index is out of bounds
683 */ 818 */
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.
840 * 1018 *
841 * @param list the list 1019 * @param list the list
842 * @param elem the element to find 1020 * @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 1021 * @return the index of the element or the size of the list when the element is not found
844 * @see cxListIndexValid() 1022 * @see cxListIndexValid()
1023 * @see cxListContains()
845 */ 1024 */
846 cx_attr_nonnull 1025 cx_attr_nonnull
847 cx_attr_nodiscard 1026 cx_attr_nodiscard
848 static inline size_t cxListFind( 1027 static inline size_t cxListFind(
849 const CxList *list, 1028 const CxList *list,
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
892 * 1091 *
893 * @param list the list 1092 * @param list the list
894 */ 1093 */
895 cx_attr_nonnull 1094 cx_attr_nonnull
896 static inline void cxListSort(CxList *list) { 1095 static inline void cxListSort(CxList *list) {
1096 if (list->collection.sorted) return;
897 list->cl->sort(list); 1097 list->cl->sort(list);
898 list->collection.sorted = true; 1098 list->collection.sorted = true;
899 } 1099 }
900 1100
901 /** 1101 /**
940 * @param list the list which shall be freed 1140 * @param list the list which shall be freed
941 */ 1141 */
942 cx_attr_export 1142 cx_attr_export
943 void cxListFree(CxList *list); 1143 void cxListFree(CxList *list);
944 1144
945 /**
946 * A shared instance of an empty list.
947 *
948 * Writing to that list is not allowed.
949 *
950 * You can use this is a placeholder for initializing CxList pointers
951 * for which you do not want to reserve memory right from the beginning.
952 */
953 cx_attr_export
954 extern CxList *const cxEmptyList;
955
956 1145
957 #ifdef __cplusplus 1146 #ifdef __cplusplus
958 } // extern "C" 1147 } // extern "C"
959 #endif 1148 #endif
960 1149

mercurial