| 78 */ |
80 */ |
| 79 void (*deallocate)(struct cx_list_s *list); |
81 void (*deallocate)(struct cx_list_s *list); |
| 80 |
82 |
| 81 /** |
83 /** |
| 82 * Member function for inserting a single element. |
84 * Member function for inserting a single element. |
| 83 * The data pointer may be @c NULL in which case the function shall only allocate memory. |
85 * The data pointer may be @c NULL, in which case the function shall only allocate memory. |
| 84 * Returns a pointer to the data of the inserted element. |
86 * Returns a pointer to the allocated memory or @c NULL if allocation fails. |
| 85 */ |
87 */ |
| 86 void *(*insert_element)( |
88 void *(*insert_element)( |
| 87 struct cx_list_s *list, |
89 struct cx_list_s *list, |
| 88 size_t index, |
90 size_t index, |
| 89 const void *data |
91 const void *data |
| 105 * Member function for inserting sorted elements into a sorted list. |
107 * Member function for inserting sorted elements into a sorted list. |
| 106 * |
108 * |
| 107 * @see cx_list_default_insert_sorted() |
109 * @see cx_list_default_insert_sorted() |
| 108 */ |
110 */ |
| 109 size_t (*insert_sorted)( |
111 size_t (*insert_sorted)( |
| |
112 struct cx_list_s *list, |
| |
113 const void *sorted_data, |
| |
114 size_t n |
| |
115 ); |
| |
116 |
| |
117 /** |
| |
118 * Member function for inserting multiple elements if they do not exist. |
| |
119 * |
| |
120 * @see cx_list_default_insert_unique() |
| |
121 */ |
| |
122 size_t (*insert_unique)( |
| 110 struct cx_list_s *list, |
123 struct cx_list_s *list, |
| 111 const void *sorted_data, |
124 const void *sorted_data, |
| 112 size_t n |
125 size_t n |
| 113 ); |
126 ); |
| 114 |
127 |
| 179 void (*sort)(struct cx_list_s *list); |
192 void (*sort)(struct cx_list_s *list); |
| 180 |
193 |
| 181 /** |
194 /** |
| 182 * Optional member function for comparing this list |
195 * Optional member function for comparing this list |
| 183 * to another list of the same type. |
196 * to another list of the same type. |
| 184 * If set to @c NULL, comparison won't be optimized. |
197 * If set to @c NULL, the comparison won't be optimized. |
| 185 */ |
198 */ |
| 186 cx_attr_nonnull |
|
| 187 int (*compare)( |
199 int (*compare)( |
| 188 const struct cx_list_s *list, |
200 const struct cx_list_s *list, |
| 189 const struct cx_list_s *other |
201 const struct cx_list_s *other |
| 190 ); |
202 ); |
| 191 |
203 |
| 266 const void *sorted_data, |
278 const void *sorted_data, |
| 267 size_t n |
279 size_t n |
| 268 ); |
280 ); |
| 269 |
281 |
| 270 /** |
282 /** |
| |
283 * Default implementation of an array insert where only elements are inserted when they don't exist in the list. |
| |
284 * |
| |
285 * This function is similar to cx_list_default_insert_sorted(), except it skips elements that are already in the list. |
| |
286 * |
| |
287 * @note The return value of this function denotes the number of elements from the @p sorted_data that are definitely |
| |
288 * contained in the list after completing the call. It is @em not the number of elements that were newly inserted. |
| |
289 * That means, when no error occurred, the return value should be @p n. |
| |
290 * |
| |
291 * Use this in your own list class if you do not want to implement an optimized version for your list. |
| |
292 * |
| |
293 * @param list the list |
| |
294 * @param sorted_data a pointer to the array of pre-sorted data to insert |
| |
295 * @param n the number of elements to insert |
| |
296 * @return the number of elements from the @p sorted_data that are definitely present in the list after this call |
| |
297 */ |
| |
298 cx_attr_nonnull |
| |
299 cx_attr_export |
| |
300 size_t cx_list_default_insert_unique( |
| |
301 struct cx_list_s *list, |
| |
302 const void *sorted_data, |
| |
303 size_t n |
| |
304 ); |
| |
305 |
| |
306 /** |
| 271 * Default unoptimized sort implementation. |
307 * Default unoptimized sort implementation. |
| 272 * |
308 * |
| 273 * This function will copy all data to an array, sort the array with standard |
309 * This function will copy all data to an array, sort the array with standard |
| 274 * qsort, and then copy the data back to the list memory. |
310 * qsort, and then copy the data back to the list memory. |
| 275 * |
311 * |
| 302 /** |
338 /** |
| 303 * Initializes a list struct. |
339 * Initializes a list struct. |
| 304 * |
340 * |
| 305 * Only use this function if you are creating your own list implementation. |
341 * Only use this function if you are creating your own list implementation. |
| 306 * The purpose of this function is to be called in the initialization code |
342 * The purpose of this function is to be called in the initialization code |
| 307 * of your list, to set certain members correctly. |
343 * of your list to set certain members correctly. |
| 308 * |
344 * |
| 309 * This is particularly important when you want your list to support |
345 * This is particularly important when you want your list to support |
| 310 * #CX_STORE_POINTERS as @p elem_size. This function will wrap the list |
346 * #CX_STORE_POINTERS as @p elem_size. This function will wrap the list |
| 311 * class accordingly and make sure that you can implement your list as if |
347 * class accordingly and make sure that you can implement your list as if |
| 312 * it was only storing objects and the wrapper will automatically enable |
348 * it was only storing objects, and the wrapper will automatically enable |
| 313 * the feature of storing pointers. |
349 * the feature of storing pointers. |
| 314 * |
350 * |
| 315 * @par Example |
351 * @par Example |
| 316 * |
352 * |
| 317 * @code |
353 * @code |
| 389 * This method is more efficient than invoking cxListAdd() multiple times. |
425 * This method is more efficient than invoking cxListAdd() multiple times. |
| 390 * |
426 * |
| 391 * If there is not enough memory to add all elements, the returned value is |
427 * If there is not enough memory to add all elements, the returned value is |
| 392 * less than @p n. |
428 * less than @p n. |
| 393 * |
429 * |
| 394 * If this list is storing pointers instead of objects @p array is expected to |
430 * If this list is storing pointers instead of objects, @p array is expected to |
| 395 * be an array of pointers. |
431 * be an array of pointers. |
| 396 * |
432 * |
| 397 * @param list the list |
433 * @param list the list |
| 398 * @param array a pointer to the elements to add |
434 * @param array a pointer to the elements to add |
| 399 * @param n the number of elements to add |
435 * @param n the number of elements to add |
| 410 } |
446 } |
| 411 |
447 |
| 412 /** |
448 /** |
| 413 * Inserts an item at the specified index. |
449 * Inserts an item at the specified index. |
| 414 * |
450 * |
| 415 * If @p index equals the list @c size, this is effectively cxListAdd(). |
451 * If the @p index equals the list @c size, this is effectively cxListAdd(). |
| 416 * |
452 * |
| 417 * @param list the list |
453 * @param list the list |
| 418 * @param index the index the element shall have |
454 * @param index the index the element shall have |
| 419 * @param elem a pointer to the element to add |
455 * @param elem a pointer to the element to add |
| 420 * @retval zero success |
456 * @retval zero success |
| 480 cx_attr_nonnull |
516 cx_attr_nonnull |
| 481 static inline int cxListInsertSorted( |
517 static inline int cxListInsertSorted( |
| 482 CxList *list, |
518 CxList *list, |
| 483 const void *elem |
519 const void *elem |
| 484 ) { |
520 ) { |
| 485 list->collection.sorted = true; // guaranteed by definition |
521 assert(list->collection.sorted || list->collection.size == 0); |
| |
522 list->collection.sorted = true; |
| 486 const void *data = list->collection.store_pointer ? &elem : elem; |
523 const void *data = list->collection.store_pointer ? &elem : elem; |
| 487 return list->cl->insert_sorted(list, data, 1) == 0; |
524 return list->cl->insert_sorted(list, data, 1) == 0; |
| 488 } |
525 } |
| 489 |
526 |
| 490 /** |
527 /** |
| |
528 * Inserts an item into a sorted list if it does not exist. |
| |
529 * |
| |
530 * If the list is not sorted already, the behavior is undefined. |
| |
531 * |
| |
532 * @param list the list |
| |
533 * @param elem a pointer to the element to add |
| |
534 * @retval zero success (also when the element was already in the list) |
| |
535 * @retval non-zero memory allocation failure |
| |
536 */ |
| |
537 cx_attr_nonnull |
| |
538 static inline int cxListInsertUnique( |
| |
539 CxList *list, |
| |
540 const void *elem |
| |
541 ) { |
| |
542 assert(list->collection.sorted || list->collection.size == 0); |
| |
543 list->collection.sorted = true; |
| |
544 const void *data = list->collection.store_pointer ? &elem : elem; |
| |
545 return list->cl->insert_unique(list, data, 1) == 0; |
| |
546 } |
| |
547 |
| |
548 /** |
| 491 * Inserts multiple items to the list at the specified index. |
549 * Inserts multiple items to the list at the specified index. |
| 492 * If @p index equals the list size, this is effectively cxListAddArray(). |
550 * If the @p index equals the list size, this is effectively cxListAddArray(). |
| 493 * |
551 * |
| 494 * This method is usually more efficient than invoking cxListInsert() |
552 * This method is usually more efficient than invoking cxListInsert() |
| 495 * multiple times. |
553 * multiple times. |
| 496 * |
554 * |
| 497 * If there is not enough memory to add all elements, the returned value is |
555 * If there is not enough memory to add all elements, the returned value is |
| 498 * less than @p n. |
556 * less than @p n. |
| 499 * |
557 * |
| 500 * If this list is storing pointers instead of objects @p array is expected to |
558 * If this list is storing pointers instead of objects, @p array is expected to |
| 501 * be an array of pointers. |
559 * be an array of pointers. |
| 502 * |
560 * |
| 503 * @param list the list |
561 * @param list the list |
| 504 * @param index the index where to add the elements |
562 * @param index the index where to add the elements |
| 505 * @param array a pointer to the elements to add |
563 * @param array a pointer to the elements to add |
| 518 } |
576 } |
| 519 |
577 |
| 520 /** |
578 /** |
| 521 * Inserts a sorted array into a sorted list. |
579 * Inserts a sorted array into a sorted list. |
| 522 * |
580 * |
| 523 * This method is usually more efficient than inserting each element separately, |
581 * This method is usually more efficient than inserting each element separately |
| 524 * because consecutive chunks of sorted data are inserted in one pass. |
582 * because consecutive chunks of sorted data are inserted in one pass. |
| 525 * |
583 * |
| 526 * If there is not enough memory to add all elements, the returned value is |
584 * If there is not enough memory to add all elements, the returned value is |
| 527 * less than @p n. |
585 * less than @p n. |
| 528 * |
586 * |
| 529 * If this list is storing pointers instead of objects @p array is expected to |
587 * If this list is storing pointers instead of objects, @p array is expected to |
| 530 * be an array of pointers. |
588 * be an array of pointers. |
| 531 * |
589 * |
| 532 * If the list is not sorted already, the behavior is undefined. |
590 * If the list is not sorted already, the behavior is undefined. |
| 533 * |
591 * |
| 534 * @param list the list |
592 * @param list the list |
| 540 static inline size_t cxListInsertSortedArray( |
598 static inline size_t cxListInsertSortedArray( |
| 541 CxList *list, |
599 CxList *list, |
| 542 const void *array, |
600 const void *array, |
| 543 size_t n |
601 size_t n |
| 544 ) { |
602 ) { |
| 545 list->collection.sorted = true; // guaranteed by definition |
603 assert(list->collection.sorted || list->collection.size == 0); |
| |
604 list->collection.sorted = true; |
| 546 return list->cl->insert_sorted(list, array, n); |
605 return list->cl->insert_sorted(list, array, n); |
| |
606 } |
| |
607 |
| |
608 /** |
| |
609 * Inserts a sorted array into a sorted list, skipping duplicates. |
| |
610 * |
| |
611 * This method is usually more efficient than inserting each element separately |
| |
612 * because consecutive chunks of sorted data are inserted in one pass. |
| |
613 * |
| |
614 * If there is not enough memory to add all elements, the returned value is |
| |
615 * less than @p n. |
| |
616 * |
| |
617 * @note The return value of this function denotes the number of elements |
| |
618 * from the @p sorted_data that are definitely contained in the list after |
| |
619 * completing the call. It is @em not the number of elements that were newly |
| |
620 * inserted. That means, when no error occurred, the return value should |
| |
621 * be @p n. |
| |
622 * |
| |
623 * If this list is storing pointers instead of objects @p array is expected to |
| |
624 * be an array of pointers. |
| |
625 * |
| |
626 * If the list is not sorted already, the behavior is undefined. |
| |
627 * This is also the case when the @p array is not sorted. |
| |
628 * |
| |
629 * @param list the list |
| |
630 * @param array a pointer to the elements to add |
| |
631 * @param n the number of elements to add |
| |
632 * @return the number of added elements |
| |
633 * |
| |
634 * @return the number of elements from the @p sorted_data that are definitely present in the list after this call |
| |
635 */ |
| |
636 cx_attr_nonnull |
| |
637 static inline size_t cxListInsertUniqueArray( |
| |
638 CxList *list, |
| |
639 const void *array, |
| |
640 size_t n |
| |
641 ) { |
| |
642 assert(list->collection.sorted || list->collection.size == 0); |
| |
643 list->collection.sorted = true; |
| |
644 return list->cl->insert_unique(list, array, n); |
| 547 } |
645 } |
| 548 |
646 |
| 549 /** |
647 /** |
| 550 * Inserts an element after the current location of the specified iterator. |
648 * Inserts an element after the current location of the specified iterator. |
| 551 * |
649 * |
| 648 * If the list is storing pointers, only the pointer is copied to @p targetbuf. |
746 * If the list is storing pointers, only the pointer is copied to @p targetbuf. |
| 649 * |
747 * |
| 650 * @param list the list |
748 * @param list the list |
| 651 * @param targetbuf a buffer where to copy the element |
749 * @param targetbuf a buffer where to copy the element |
| 652 * @retval zero success |
750 * @retval zero success |
| 653 * @retval non-zero list is empty |
751 * @retval non-zero the list is empty |
| 654 * @see cxListPopFront() |
752 * @see cxListPopFront() |
| 655 * @see cxListRemoveAndGetLast() |
753 * @see cxListRemoveAndGetLast() |
| 656 */ |
754 */ |
| 657 cx_attr_nonnull |
755 cx_attr_nonnull |
| 658 cx_attr_access_w(2) |
756 cx_attr_access_w(2) |
| 673 * If the list is storing pointers, only the pointer is copied to @p targetbuf. |
771 * If the list is storing pointers, only the pointer is copied to @p targetbuf. |
| 674 * |
772 * |
| 675 * @param list (@c CxList*) the list |
773 * @param list (@c CxList*) the list |
| 676 * @param targetbuf (@c void*) a buffer where to copy the element |
774 * @param targetbuf (@c void*) a buffer where to copy the element |
| 677 * @retval zero success |
775 * @retval zero success |
| 678 * @retval non-zero list is empty |
776 * @retval non-zero the list is empty |
| 679 * @see cxListRemoveAndGetFirst() |
777 * @see cxListRemoveAndGetFirst() |
| 680 * @see cxListPop() |
778 * @see cxListPop() |
| 681 */ |
779 */ |
| 682 #define cxListPopFront(list, targetbuf) cxListRemoveAndGetFirst((list), (targetbuf)) |
780 #define cxListPopFront(list, targetbuf) cxListRemoveAndGetFirst((list), (targetbuf)) |
| 683 |
781 |
| 690 * If the list is storing pointers, only the pointer is copied to @p targetbuf. |
788 * If the list is storing pointers, only the pointer is copied to @p targetbuf. |
| 691 * |
789 * |
| 692 * @param list the list |
790 * @param list the list |
| 693 * @param targetbuf a buffer where to copy the element |
791 * @param targetbuf a buffer where to copy the element |
| 694 * @retval zero success |
792 * @retval zero success |
| 695 * @retval non-zero list is empty |
793 * @retval non-zero the list is empty |
| 696 */ |
794 */ |
| 697 cx_attr_nonnull |
795 cx_attr_nonnull |
| 698 cx_attr_access_w(2) |
796 cx_attr_access_w(2) |
| 699 static inline int cxListRemoveAndGetLast( |
797 static inline int cxListRemoveAndGetLast( |
| 700 CxList *list, |
798 CxList *list, |
| 714 * If the list is storing pointers, only the pointer is copied to @p targetbuf. |
812 * If the list is storing pointers, only the pointer is copied to @p targetbuf. |
| 715 * |
813 * |
| 716 * @param list (@c CxList*) the list |
814 * @param list (@c CxList*) the list |
| 717 * @param targetbuf (@c void*) a buffer where to copy the element |
815 * @param targetbuf (@c void*) a buffer where to copy the element |
| 718 * @retval zero success |
816 * @retval zero success |
| 719 * @retval non-zero list is empty |
817 * @retval non-zero the list is empty |
| 720 * @see cxListRemoveAndGetLast() |
818 * @see cxListRemoveAndGetLast() |
| 721 * @see cxListPopFront() |
819 * @see cxListPopFront() |
| 722 */ |
820 */ |
| 723 #define cxListPop(list, targetbuf) cxListRemoveAndGetLast((list), (targetbuf)) |
821 #define cxListPop(list, targetbuf) cxListRemoveAndGetLast((list), (targetbuf)) |
| 724 |
822 |
| 870 /** |
968 /** |
| 871 * Returns an iterator pointing to the item at the specified index. |
969 * Returns an iterator pointing to the item at the specified index. |
| 872 * |
970 * |
| 873 * The returned iterator is position-aware. |
971 * The returned iterator is position-aware. |
| 874 * |
972 * |
| 875 * If the index is out of range, a past-the-end iterator will be returned. |
973 * If the index is out of range or @p list is @c NULL, a past-the-end iterator will be returned. |
| 876 * |
974 * |
| 877 * @param list the list |
975 * @param list the list |
| 878 * @param index the index where the iterator shall point at |
976 * @param index the index where the iterator shall point at |
| 879 * @return a new iterator |
977 * @return a new iterator |
| 880 */ |
978 */ |
| 881 cx_attr_nonnull |
|
| 882 cx_attr_nodiscard |
979 cx_attr_nodiscard |
| 883 static inline CxIterator cxListIteratorAt( |
980 static inline CxIterator cxListIteratorAt( |
| 884 const CxList *list, |
981 const CxList *list, |
| 885 size_t index |
982 size_t index |
| 886 ) { |
983 ) { |
| |
984 if (list == NULL) list = cxEmptyList; |
| 887 return list->cl->iterator(list, index, false); |
985 return list->cl->iterator(list, index, false); |
| 888 } |
986 } |
| 889 |
987 |
| 890 /** |
988 /** |
| 891 * Returns a backwards iterator pointing to the item at the specified index. |
989 * Returns a backwards iterator pointing to the item at the specified index. |
| 892 * |
990 * |
| 893 * The returned iterator is position-aware. |
991 * The returned iterator is position-aware. |
| 894 * |
992 * |
| 895 * If the index is out of range, a past-the-end iterator will be returned. |
993 * If the index is out of range or @p list is @c NULL, a past-the-end iterator will be returned. |
| 896 * |
994 * |
| 897 * @param list the list |
995 * @param list the list |
| 898 * @param index the index where the iterator shall point at |
996 * @param index the index where the iterator shall point at |
| 899 * @return a new iterator |
997 * @return a new iterator |
| 900 */ |
998 */ |
| 901 cx_attr_nonnull |
|
| 902 cx_attr_nodiscard |
999 cx_attr_nodiscard |
| 903 static inline CxIterator cxListBackwardsIteratorAt( |
1000 static inline CxIterator cxListBackwardsIteratorAt( |
| 904 const CxList *list, |
1001 const CxList *list, |
| 905 size_t index |
1002 size_t index |
| 906 ) { |
1003 ) { |
| |
1004 if (list == NULL) list = cxEmptyList; |
| 907 return list->cl->iterator(list, index, true); |
1005 return list->cl->iterator(list, index, true); |
| 908 } |
1006 } |
| 909 |
1007 |
| 910 /** |
1008 /** |
| 911 * Returns a mutating iterator pointing to the item at the specified index. |
1009 * Returns a mutating iterator pointing to the item at the specified index. |
| 912 * |
1010 * |
| 913 * The returned iterator is position-aware. |
1011 * The returned iterator is position-aware. |
| 914 * |
1012 * |
| 915 * If the index is out of range, a past-the-end iterator will be returned. |
1013 * If the index is out of range or @p list is @c NULL, a past-the-end iterator will be returned. |
| 916 * |
1014 * |
| 917 * @param list the list |
1015 * @param list the list |
| 918 * @param index the index where the iterator shall point at |
1016 * @param index the index where the iterator shall point at |
| 919 * @return a new iterator |
1017 * @return a new iterator |
| 920 */ |
1018 */ |
| 921 cx_attr_nonnull |
|
| 922 cx_attr_nodiscard |
1019 cx_attr_nodiscard |
| 923 cx_attr_export |
1020 cx_attr_export |
| 924 CxIterator cxListMutIteratorAt( |
1021 CxIterator cxListMutIteratorAt( |
| 925 CxList *list, |
1022 CxList *list, |
| 926 size_t index |
1023 size_t index |
| 930 * Returns a mutating backwards iterator pointing to the item at the |
1027 * Returns a mutating backwards iterator pointing to the item at the |
| 931 * specified index. |
1028 * specified index. |
| 932 * |
1029 * |
| 933 * The returned iterator is position-aware. |
1030 * The returned iterator is position-aware. |
| 934 * |
1031 * |
| 935 * If the index is out of range, a past-the-end iterator will be returned. |
1032 * If the index is out of range or @p list is @c NULL, a past-the-end iterator will be returned. |
| 936 * |
1033 * |
| 937 * @param list the list |
1034 * @param list the list |
| 938 * @param index the index where the iterator shall point at |
1035 * @param index the index where the iterator shall point at |
| 939 * @return a new iterator |
1036 * @return a new iterator |
| 940 */ |
1037 */ |
| 941 cx_attr_nonnull |
|
| 942 cx_attr_nodiscard |
1038 cx_attr_nodiscard |
| 943 cx_attr_export |
1039 cx_attr_export |
| 944 CxIterator cxListMutBackwardsIteratorAt( |
1040 CxIterator cxListMutBackwardsIteratorAt( |
| 945 CxList *list, |
1041 CxList *list, |
| 946 size_t index |
1042 size_t index |
| 1030 ) { |
1126 ) { |
| 1031 return list->cl->find_remove((CxList*)list, elem, false); |
1127 return list->cl->find_remove((CxList*)list, elem, false); |
| 1032 } |
1128 } |
| 1033 |
1129 |
| 1034 /** |
1130 /** |
| 1035 * Checks, if the list contains the specified element. |
1131 * Checks if the list contains the specified element. |
| 1036 * |
1132 * |
| 1037 * The elements are compared with the list's comparator function. |
1133 * The elements are compared with the list's comparator function. |
| 1038 * |
1134 * |
| 1039 * @param list the list |
1135 * @param list the list |
| 1040 * @param elem the element to find |
1136 * @param elem the element to find |