--- a/src/cx/list.h Fri Oct 10 12:26:43 2025 +0200 +++ b/src/cx/list.h Fri Oct 10 17:24:19 2025 +0200 @@ -115,6 +115,17 @@ ); /** + * Member function for inserting multiple elements if they do not exist. + * + * @see cx_list_default_insert_unique() + */ + size_t (*insert_unique)( + struct cx_list_s *list, + const void *sorted_data, + size_t n + ); + + /** * Member function for inserting an element relative to an iterator position. */ int (*insert_iter)( @@ -269,6 +280,31 @@ ); /** + * Default implementation of an array insert where only elements are inserted when they don't exist in the list. + * + * This function is similar to cx_list_default_insert_sorted(), except it skips elements that are already in the list. + * The @p sorted_data itself must not contain duplicates. + * + * @note The return value of this function denotes the number of elements from the @p sorted_data that are definitely + * contained in the list after completing the call. It is @em not the number of elements that were newly inserted. + * That means, when no error occurred, the return value should be @p n. + * + * Use this in your own list class if you do not want to implement an optimized version for your list. + * + * @param list the list + * @param sorted_data a pointer to the array of pre-sorted data to insert + * @param n the number of elements to insert + * @return the number of elements from the @p sorted_data that are definitely present in the list after this call + */ +cx_attr_nonnull +cx_attr_export +size_t cx_list_default_insert_unique( + struct cx_list_s *list, + const void *sorted_data, + size_t n +); + +/** * Default unoptimized sort implementation. * * This function will copy all data to an array, sort the array with standard @@ -490,6 +526,27 @@ } /** + * Inserts an item into a sorted list if it does not exist. + * + * If the list is not sorted already, the behavior is undefined. + * + * @param list the list + * @param elem a pointer to the element to add + * @retval zero success (also when the element was already in the list) + * @retval non-zero memory allocation failure + */ +cx_attr_nonnull +static inline int cxListInsertUnique( + CxList *list, + const void *elem +) { + assert(list->collection.sorted || list->collection.size == 0); + list->collection.sorted = true; + const void *data = list->collection.store_pointer ? &elem : elem; + return list->cl->insert_unique(list, data, 1) == 0; +} + +/** * Inserts multiple items to the list at the specified index. * If @p index equals the list size, this is effectively cxListAddArray(). * @@ -522,7 +579,7 @@ /** * Inserts a sorted array into a sorted list. * - * This method is usually more efficient than inserting each element separately, + * This method is usually more efficient than inserting each element separately * because consecutive chunks of sorted data are inserted in one pass. * * If there is not enough memory to add all elements, the returned value is @@ -550,6 +607,45 @@ } /** + * Inserts a sorted array into a sorted list, skipping duplicates. + * + * This method is usually more efficient than inserting each element separately + * because consecutive chunks of sorted data are inserted in one pass. + * + * If there is not enough memory to add all elements, the returned value is + * less than @p n. + * + * @note The return value of this function denotes the number of elements + * from the @p sorted_data that are definitely contained in the list after + * completing the call. It is @em not the number of elements that were newly + * inserted. That means, when no error occurred, the return value should + * be @p n. + * + * If this list is storing pointers instead of objects @p array is expected to + * be an array of pointers. + * + * If the list is not sorted already, the behavior is undefined. + * This is also the case when the @p array is not sorted or already contains duplicates. + * + * @param list the list + * @param array a pointer to the elements to add + * @param n the number of elements to add + * @return the number of added elements + * + * @return the number of elements from the @p sorted_data that are definitely present in the list after this call + */ +cx_attr_nonnull +static inline size_t cxListInsertUniqueArray( + CxList *list, + const void *array, + size_t n +) { + assert(list->collection.sorted || list->collection.size == 0); + list->collection.sorted = true; + return list->cl->insert_unique(list, array, n); +} + +/** * Inserts an element after the current location of the specified iterator. * * The used iterator remains operational, but all other active iterators should