Sat, 01 Nov 2025 19:48:50 +0100
specify the intersection functions
relates to #554 and issue #555
--- a/CHANGELOG Sat Nov 01 19:31:48 2025 +0100 +++ b/CHANGELOG Sat Nov 01 19:48:50 2025 +0100 @@ -8,6 +8,7 @@ * adds support for comparing arbitrary strings without explicit call to cx_strcast() * adds cxListClone() and cxMapClone() * adds cxListDifference(), cxMapDifference(), and cxMapListDifference() + * adds cxListIntersection(), cxMapIntersection(), and cxMapListIntersection() * adds cxListContains() and cxMapContains() * adds cxListSet() * adds cxListFirst() and cxListLast()
--- a/docs/Writerside/topics/about.md Sat Nov 01 19:31:48 2025 +0100 +++ b/docs/Writerside/topics/about.md Sat Nov 01 19:48:50 2025 +0100 @@ -35,6 +35,7 @@ * adds support for comparing arbitrary strings without explicit call to cx_strcast() * adds cxListClone() and cxMapClone() * adds cxListDifference(), cxMapDifference(), and cxMapListDifference() +* adds cxListIntersection(), cxMapIntersection(), and cxMapListIntersection() * adds cxListContains() and cxMapContains() * adds cxListSet() * adds cxListFirst() and cxListLast()
--- a/docs/Writerside/topics/list.h.md Sat Nov 01 19:31:48 2025 +0100 +++ b/docs/Writerside/topics/list.h.md Sat Nov 01 19:48:50 2025 +0100 @@ -374,6 +374,12 @@ cx_clone_func clone_func, const CxAllocator *clone_allocator, void *data); + +int cxListIntersection(CxList *dst, + const CxList *src, const CxList *other, + cx_clone_func clone_func, + const CxAllocator *clone_allocator, + void *data); ``` With `cxListClone()` you can create deep copies of the elements in a list and insert them into another list. @@ -382,8 +388,9 @@ to insert anything. The function `cxListDifference()` is similar to `cxListClone()`, -except that it only clones elements from the minuend that are _not_ contained in the subtrahend. -It is optimized for sorted lists, in which case it will take linear time instead of quadratic time for the operation. +except that it only clones elements from the minuend that are _not_ contained in the subtrahend, +while `cxListIntersection()` only clones elements that _are_ contained in both lists. +Both functions are optimized for sorted lists, in which case they will take linear time instead of quadratic time for the operation. Refer to the documentation of the [clone-function callback](allocator.h.md#clone-function) to learn how to implement it.
--- a/docs/Writerside/topics/map.h.md Sat Nov 01 19:31:48 2025 +0100 +++ b/docs/Writerside/topics/map.h.md Sat Nov 01 19:48:50 2025 +0100 @@ -312,6 +312,18 @@ cx_clone_func clone_func, const CxAllocator *clone_allocator, void *data); + +int cxMapIntersection(CxMap *dst, + const CxMap *src, const CxMap *other, + cx_clone_func clone_func, + const CxAllocator *clone_allocator, + void *data); + +int cxMapListIntersection(CxMap *dst, + const CxMap *src, const CxList *keys, + cx_clone_func clone_func, + const CxAllocator *clone_allocator, + void *data); ``` With `cxMapClone()` you can create deep copies of the values in one map and insert them into another map. @@ -323,6 +335,8 @@ except that they only clone an element from the source map, when the key is _not_ contained in the other map (or list, respectively). This is equivalent to computing the set difference for the set of keys. +Likewise, `cxMapIntersection()` and `cxMapListIntersection()` only clone an element from the source map, +when the key is contained in _both_ collections. Refer to the documentation of the [clone-function callback](allocator.h.md#clone-function) to learn how to implement it.
--- a/src/cx/list.h Sat Nov 01 19:31:48 2025 +0100 +++ b/src/cx/list.h Sat Nov 01 19:48:50 2025 +0100 @@ -1011,6 +1011,28 @@ const CxList *minuend, const CxList *subtrahend, cx_clone_func clone_func, const CxAllocator *clone_allocator, void *data); +/** + * Clones elements from a list only if they are also present in another list. + * + * This function is optimized for the case when both the @p minuend and the + * @p subtrahend 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 + * @param clone_func the clone function for the elements + * @param clone_allocator the allocator that is passed to the clone function + * @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 + */ +cx_attr_nonnull_arg(1, 2, 3) +CX_EXPORT int cxListIntersection(CxList *dst, const CxList *src, const CxList *other, + cx_clone_func clone_func, const CxAllocator *clone_allocator, void *data); + #ifdef __cplusplus } // extern "C" #endif
--- a/src/cx/map.h Sat Nov 01 19:31:48 2025 +0100 +++ b/src/cx/map.h Sat Nov 01 19:48:50 2025 +0100 @@ -545,6 +545,44 @@ CX_EXPORT int cxMapListDifference(CxMap *dst, const CxMap *src, const CxList *keys, cx_clone_func clone_func, const CxAllocator *clone_allocator, void *data); + +/** + * Clones entries of a map only if their key is present in another map. + * + * @param dst the destination map + * @param src the map to clone the entries from + * @param other the map to check for existence of the keys + * @param clone_func the clone function for the values + * @param clone_allocator the allocator that is passed to the clone function + * @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 + */ +cx_attr_nonnull_arg(1, 2, 3, 4) +CX_EXPORT int cxMapIntersection(CxMap *dst, const CxMap *src, const CxMap *other, + cx_clone_func clone_func, const CxAllocator *clone_allocator, void *data); + +/** + * Clones entries of a map only if their key is present in a list. + * + * Note that the list must contain keys of type @c CxKey + * (or pointers to such keys) and must use @c cx_hash_key_cmp + * as the compare function. + * Generic key types cannot be processed in this case. + * + * @param dst the destination map + * @param src the source map + * @param keys the list of @c CxKey items + * @param clone_func the clone function for the values + * @param clone_allocator the allocator that is passed to the clone function + * @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 + */ +cx_attr_nonnull_arg(1, 2, 3, 4) +CX_EXPORT int cxMapListIntersection(CxMap *dst, const CxMap *src, const CxList *keys, + cx_clone_func clone_func, const CxAllocator *clone_allocator, void *data); + #ifdef __cplusplus } // extern "C" #endif