set CHANGE add duplicator callback to the functions duplicating data items
diff --git a/src/set.c b/src/set.c
index b245f40..7cfda31 100644
--- a/src/set.c
+++ b/src/set.c
@@ -81,9 +81,10 @@
}
API struct ly_set *
-ly_set_dup(const struct ly_set *set)
+ly_set_dup(const struct ly_set *set, void *(*duplicator)(void *obj))
{
struct ly_set *new;
+ unsigned int u;
LY_CHECK_ARG_RET(NULL, set, NULL);
@@ -93,7 +94,13 @@
new->size = set->size;
new->objs = malloc(new->size * sizeof *(new->objs));
LY_CHECK_ERR_RET(!new->objs, LOGMEM(NULL); free(new), NULL);
- memcpy(new->objs, set->objs, new->size * sizeof *(new->objs));
+ if (duplicator) {
+ for (u = 0; u < set->count; ++u) {
+ new->objs[u] = duplicator(set->objs[u]);
+ }
+ } else {
+ memcpy(new->objs, set->objs, new->size * sizeof *(new->objs));
+ }
return new;
}
@@ -129,41 +136,28 @@
}
API int
-ly_set_merge(struct ly_set *trg, struct ly_set *src, int options)
+ly_set_merge(struct ly_set *trg, struct ly_set *src, int options, void *(*duplicator)(void *obj))
{
- unsigned int i, ret;
- void **new;
+ unsigned int u, c, ret = 0;
+ int i;
+ void *obj;
LY_CHECK_ARG_RET(NULL, trg, -1);
LY_CHECK_ARG_RET(NULL, src, 0);
- if (!(options & LY_SET_OPT_USEASLIST)) {
- /* remove duplicates */
- i = 0;
- while (i < src->count) {
- if (ly_set_contains(trg, src->objs[i]) > -1) {
- ly_set_rm_index(src, i);
- } else {
- ++i;
- }
+ for (u = 0; u < src->count; ++u) {
+ if (duplicator) {
+ obj = duplicator(src->objs[u]);
+ } else {
+ obj = src->objs[u];
+ }
+ c = trg->count;
+ i = ly_set_add(trg, obj, options);
+ if (i > 0 && (unsigned int)i == c) {
+ ++ret;
}
}
- /* allocate more memory if needed */
- if (trg->size < trg->count + src->count) {
- new = realloc(trg->objs, (trg->count + src->count) * sizeof *(trg->objs));
- LY_CHECK_ERR_RET(!new, LOGMEM(NULL), -1);
- trg->size = trg->count + src->count;
- trg->objs = new;
- }
-
- /* copy contents from src into trg */
- memcpy(trg->objs + trg->count, src->objs, src->count * sizeof *(src->objs));
- ret = src->count;
- trg->count += ret;
-
- /* cleanup */
- ly_set_free(src, NULL);
return ret;
}
diff --git a/src/set.h b/src/set.h
index 85fddd4..e226a5c 100644
--- a/src/set.h
+++ b/src/set.h
@@ -68,9 +68,12 @@
* @brief Duplicate the existing set.
*
* @param[in] set Original set to duplicate
+ * @param[in] duplicator Optional pointer to function that duplicates the objects stored
+ * in the original set. If not provided, the new set points to the exact same objects as
+ * the original set.
* @return Duplication of the original set.
*/
-struct ly_set *ly_set_dup(const struct ly_set *set);
+struct ly_set *ly_set_dup(const struct ly_set *set, void *(*duplicator)(void *obj));
/**
* @brief Add a ::lyd_node or ::lys_node object into the set
@@ -91,15 +94,17 @@
* @brief Add all objects from \p src to \p trg.
*
* Since it is a set, the function checks for duplicities.
- * After success, \p src is completely freed.
*
* @param[in] trg Target (result) set.
* @param[in] src Source set.
* @param[in] options Options to change behavior of the function. Accepted options are:
- * - #LY_SET_OPT_USEASLIST - do not check for duplicities
+ * - #LY_SET_OPT_USEASLIST - add without checking for duplicities
+ * @param[in] duplicator Optional pointer to function that duplicates the objects being added
+ * from \p src into \p trg set. If not provided, the \p trg set will point to the exact same
+ * objects as the \p src set.
* @return -1 on failure, number of objects added into \p trg on success.
*/
-int ly_set_merge(struct ly_set *trg, struct ly_set *src, int options);
+int ly_set_merge(struct ly_set *trg, struct ly_set *src, int options, void *(*duplicator)(void *obj));
/**
* @brief Get know if the set contains the specified object.