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.