--- a/ucx/cx/list.h Sun Dec 07 20:16:59 2025 +0100 +++ b/ucx/cx/list.h Fri Dec 19 17:53:18 2025 +0100 @@ -60,10 +60,6 @@ * The list class definition. */ const cx_list_class *cl; - /** - * The actual implementation in case the list class is delegating. - */ - const cx_list_class *climpl; }; /** @@ -170,6 +166,12 @@ void (*reverse)(struct cx_list_s *list); /** + * Optional member function for changing the capacity. + * If the list does not support overallocation, this can be set to @c NULL. + */ + int (*change_capacity)(struct cx_list_s *list, size_t new_capacity); + + /** * Member function for returning an iterator pointing to the specified index. */ struct cx_iterator_s (*iterator)(const struct cx_list_s *list, size_t index, bool backward); @@ -285,30 +287,26 @@ * The purpose of this function is to be called in the initialization code * of your list to set certain members correctly. * - * This is particularly important when you want your list to support - * #CX_STORE_POINTERS as @p elem_size. This function will wrap the list - * class accordingly and make sure that you can implement your list as if - * it was only storing objects, and the wrapper will automatically enable - * the feature of storing pointers. + * This is particularly useful when you want your list to support + * #CX_STORE_POINTERS as @p elem_size. * * @par Example * * @code * CxList *myCustomListCreate( * const CxAllocator *allocator, - * cx_compare_func comparator, * size_t elem_size * ) { * if (allocator == NULL) { * allocator = cxDefaultAllocator; * } * - * MyCustomList *list = cxCalloc(allocator, 1, sizeof(MyCustomList)); + * MyCustomList *list = cxZalloc(allocator, sizeof(MyCustomList)); * if (list == NULL) return NULL; * * // initialize * cx_list_init((CxList*)list, &my_custom_list_class, - * allocator, comparator, elem_size); + * allocator, elem_size); * * // ... some more custom stuff ... * @@ -319,13 +317,24 @@ * @param list the list to initialize * @param cl the list class * @param allocator the allocator for the elements - * @param comparator a compare function for the elements * @param elem_size the size of one element */ cx_attr_nonnull_arg(1, 2, 3) CX_EXPORT void cx_list_init(struct cx_list_s *list, struct cx_list_class_s *cl, const struct cx_allocator_s *allocator, - cx_compare_func comparator, size_t elem_size); + size_t elem_size); + +/** + * A @c cx_compare_func2 compatible wrapper for the compare functions of a list. + * + * @param left first element + * @param right second element + * @param list the list which is comparing the elements + * @return the comparison result + */ +cx_attr_nonnull +CX_EXPORT int cx_list_compare_wrapper( + const void *left, const void *right, void *list); /** * Returns the number of elements currently stored in the list. @@ -978,7 +987,7 @@ * @param data optional additional data that is passed to the clone function * @retval zero when all elements were successfully cloned * @retval non-zero when an allocation error occurred - * @see cxListUnion() + * @see cxListCloneShallow() */ cx_attr_nonnull_arg(1, 2, 3) CX_EXPORT int cxListClone(CxList *dst, const CxList *src, @@ -1001,6 +1010,7 @@ * @param data optional additional data that is passed to the clone function * @retval zero when the elements were successfully cloned * @retval non-zero when an allocation error occurred + * @see cxListDifferenceShallow() */ cx_attr_nonnull_arg(1, 2, 3, 4) CX_EXPORT int cxListDifference(CxList *dst, @@ -1024,6 +1034,7 @@ * @param data optional additional data that is passed to the clone function * @retval zero when the elements were successfully cloned * @retval non-zero when an allocation error occurred + * @see cxListIntersectionShallow() */ cx_attr_nonnull_arg(1, 2, 3, 4) CX_EXPORT int cxListIntersection(CxList *dst, const CxList *src, const CxList *other, @@ -1048,12 +1059,136 @@ * @param data optional additional data that is passed to the clone function * @retval zero when the elements were successfully cloned * @retval non-zero when an allocation error occurred - * @see cxListClone() + * @see cxListUnionShallow() */ cx_attr_nonnull_arg(1, 2, 3, 4) CX_EXPORT int cxListUnion(CxList *dst, const CxList *src, const CxList *other, cx_clone_func clone_func, const CxAllocator *clone_allocator, void *data); +/** + * Performs a shallow clone of one list into another. + * + * This function uses the default allocator, if needed, and performs + * shallow clones with @c memcpy(). + * + * If the destination list already contains elements, the cloned elements + * are appended to that list. + * + * @attention If the cloned elements need to be destroyed by a destructor + * function, you must make sure that the destination list also uses this + * destructor function. + * + * @param dst the destination list + * @param src the source list + * @retval zero when all elements were successfully cloned + * @retval non-zero when an allocation error occurred + * @see cxListClone() + */ +cx_attr_nonnull +CX_EXPORT int cxListCloneShallow(CxList *dst, const CxList *src); + +/** + * Clones elements from a list only if they are not present in another list. + * + * This function uses the default allocator, if needed, and performs + * shallow clones with @c memcpy(). + * + * If the @p minuend does not contain duplicates, this is equivalent to adding + * the set difference to the destination list. + * + * This function is optimized for the case when both the @p minuend and the + * @p subtrahend are sorted. + * + * @param dst the destination list + * @param minuend the list to subtract elements from + * @param subtrahend the elements that shall be subtracted + * @retval zero when the elements were successfully cloned + * @retval non-zero when an allocation error occurred + * @see cxListDifference() + */ +cx_attr_nonnull +CX_EXPORT int cxListDifferenceShallow(CxList *dst, + const CxList *minuend, const CxList *subtrahend); + +/** + * Clones elements from a list only if they are also present in another list. + * + * This function uses the default allocator, if needed, and performs + * shallow clones with @c memcpy(). + * + * This function is optimized for the case when both the @p src and the + * @p other list are sorted. + * + * If the destination list already contains elements, the intersection is appended + * to that list. + * + * @param dst the destination list + * @param src the list to clone the elements from + * @param other the list to check the elements for existence + * @retval zero when the elements were successfully cloned + * @retval non-zero when an allocation error occurred + * @see cxListIntersection() + */ +cx_attr_nonnull +CX_EXPORT int cxListIntersectionShallow(CxList *dst, const CxList *src, const CxList *other); + +/** + * Performs a deep clone of one list into another, skipping duplicates. + * + * This function uses the default allocator, if needed, and performs + * shallow clones with @c memcpy(). + * + * This function is optimized for the case when both the @p src and the + * @p other list are sorted. + * In that case, the union will also be sorted. + * + * If the destination list already contains elements, the union is appended + * to that list. In that case the destination is not necessarily sorted. + * + * @param dst the destination list + * @param src the primary source list + * @param other the other list, where elements are only cloned from + * when they are not in @p src + * @retval zero when the elements were successfully cloned + * @retval non-zero when an allocation error occurred + * @see cxListUnion() + */ +cx_attr_nonnull +CX_EXPORT int cxListUnionShallow(CxList *dst, const CxList *src, const CxList *other); + +/** + * Asks the list to reserve enough memory for a given total number of elements. + * + * List implementations are free to choose if reserving memory upfront makes + * sense. + * For example, array-based implementations usually do support reserving memory + * for additional elements while linked lists usually don't. + * + * @note When the requested capacity is smaller than the current size, + * this function returns zero without performing any action. + * + * @param list the list + * @param capacity the expected total number of elements + * @retval zero on success or when overallocation is not supported + * @retval non-zero when an allocation error occurred + * @see cxListShrink() + */ +cx_attr_nonnull +CX_EXPORT int cxListReserve(CxList *list, size_t capacity); + +/** + * Advises the list to free any overallocated memory. + * + * Lists that do not support overallocation simply return zero. + * + * This function usually returns zero, except for very special and custom + * list and/or allocator implementations where freeing memory can fail. + * + * @param list the list + * @return usually zero + */ +cx_attr_nonnull +CX_EXPORT int cxListShrink(CxList *list); #ifdef __cplusplus } // extern "C"