ucx/cx/list.h

changeset 112
c3f2f16fa4b8
parent 108
77254bd6dccb
child 113
dde28a806552
equal deleted inserted replaced
111:81c4f73236a4 112:c3f2f16fa4b8
37 #define UCX_LIST_H 37 #define UCX_LIST_H
38 38
39 #include "common.h" 39 #include "common.h"
40 #include "collection.h" 40 #include "collection.h"
41 41
42 #include <assert.h>
43
42 #ifdef __cplusplus 44 #ifdef __cplusplus
43 extern "C" { 45 extern "C" {
44 #endif 46 #endif
45 47
46 /** 48 /**
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
212 /** 224 /**
213 * A shared instance of an empty list. 225 * A shared instance of an empty list.
214 * 226 *
215 * Writing to that list is not allowed. 227 * Writing to that list is not allowed.
216 * 228 *
217 * You can use this is a placeholder for initializing CxList pointers 229 * You can use this as a placeholder for initializing CxList pointers
218 * for which you do not want to reserve memory right from the beginning. 230 * for which you do not want to reserve memory right from the beginning.
219 */ 231 */
220 cx_attr_export 232 cx_attr_export
221 extern CxList *const cxEmptyList; 233 extern CxList *const cxEmptyList;
222 234
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
778 * 876 *
779 * @param list the list 877 * @param list the list
780 */ 878 */
781 cx_attr_nonnull 879 cx_attr_nonnull
782 static inline void cxListClear(CxList *list) { 880 static inline void cxListClear(CxList *list) {
881 list->cl->clear(list);
783 list->collection.sorted = true; // empty lists are always sorted 882 list->collection.sorted = true; // empty lists are always sorted
784 list->cl->clear(list);
785 } 883 }
786 884
787 /** 885 /**
788 * Swaps two items in the list. 886 * Swaps two items in the list.
789 * 887 *
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
1135 /** 1231 /**
1136 * Deallocates the memory of the specified list structure. 1232 * Deallocates the memory of the specified list structure.
1137 * 1233 *
1138 * Also calls the content destructor functions for each element, if specified. 1234 * Also calls the content destructor functions for each element, if specified.
1139 * 1235 *
1140 * @param list the list which shall be freed 1236 * @param list the list that shall be freed
1141 */ 1237 */
1142 cx_attr_export 1238 cx_attr_export
1143 void cxListFree(CxList *list); 1239 void cxListFree(CxList *list);
1144 1240
1145 1241

mercurial