set CHANGE enhance freeing functions by optional destructor for data

also adds ly_set_erase() for static ly_set objects.
diff --git a/src/context.c b/src/context.c
index 74fc2ea..8a388fd 100644
--- a/src/context.c
+++ b/src/context.c
@@ -111,10 +111,7 @@
         return ly_set_rm_index(&ctx->search_paths, index);
     } else {
         /* remove them all */
-        for (; ctx->search_paths.count; ctx->search_paths.count--) {
-            free(ctx->search_paths.objs[ctx->search_paths.count - 1]);
-        }
-        free(ctx->search_paths.objs);
+        ly_set_erase(&ctx->search_paths, free);
         memset(&ctx->search_paths, 0, sizeof ctx->search_paths);
     }
 
@@ -280,7 +277,7 @@
     free(ctx->list.objs);
 
     /* search paths list */
-    ly_ctx_unset_searchdirs(ctx, -1);
+    ly_set_erase(&ctx->search_paths, free);
 
     /* clean the error list */
     ly_err_clean(ctx, 0);
diff --git a/src/set.c b/src/set.c
index 6cfc0af..c9be886 100644
--- a/src/set.c
+++ b/src/set.c
@@ -26,11 +26,39 @@
 }
 
 API void
-ly_set_free(struct ly_set *set)
+ly_set_clean(struct ly_set *set, void (*destructor)(void *obj))
+{
+    unsigned int u;
+
+    LY_CHECK_ARG_RET(NULL, set,);
+
+    if (destructor) {
+        for (u = 0; u < set->count; ++u) {
+            destructor(set->objs[u]);
+        }
+    }
+    set->count = 0;
+}
+
+API void
+ly_set_erase(struct ly_set *set, void (*destructor)(void *obj))
 {
     LY_CHECK_ARG_RET(NULL, set,);
 
+    ly_set_clean(set, destructor);
+
     free(set->objs);
+    set->size = 0;
+    set->objs = NULL;
+}
+
+API void
+ly_set_free(struct ly_set *set, void (*destructor)(void *obj))
+{
+    LY_CHECK_ARG_RET(NULL, set,);
+
+    ly_set_erase(set, destructor);
+
     free(set);
 }
 
@@ -135,7 +163,7 @@
     trg->count += ret;
 
     /* cleanup */
-    ly_set_free(src);
+    ly_set_free(src, NULL);
     return ret;
 }
 
@@ -176,11 +204,3 @@
     return ly_set_rm_index(set, i);
 }
 
-API LY_ERR
-ly_set_clean(struct ly_set *set)
-{
-    LY_CHECK_ARG_RET(NULL, set, LY_EINVAL);
-
-    set->count = 0;
-    return LY_SUCCESS;
-}
diff --git a/src/set.h b/src/set.h
index f1df154..85fddd4 100644
--- a/src/set.h
+++ b/src/set.h
@@ -113,9 +113,9 @@
  * @brief Remove all objects from the set, but keep the set container for further use.
  *
  * @param[in] set Set to clean.
- * @return LY_ERR return value.
+ * @param[in] destructor Optional function to free the objects in the set.
  */
-LY_ERR ly_set_clean(struct ly_set *set);
+void ly_set_clean(struct ly_set *set, void (*destructor)(void *obj));
 
 /**
  * @brief Remove an object from the set.
@@ -142,11 +142,22 @@
 LY_ERR ly_set_rm_index(struct ly_set *set, unsigned int index);
 
 /**
- * @brief Free the ::ly_set data. Frees only the set structure content, not the referred data.
+ * @brief Free the ::ly_set data. If the destructor is not provided, it frees only the set structure
+ * content, not the referred data.
  *
  * @param[in] set The set to be freed.
+ * @param[in] destructor Optional function to free the objects in the set.
  */
-void ly_set_free(struct ly_set *set);
+void ly_set_free(struct ly_set *set, void (*destructor)(void *obj));
+
+/**
+ * @brief Alternative to the ly_set_free() for static ::ly_set objects - in contrast to ly_set_free()
+ * it does not free the provided ::ly_set object.
+ *
+ * @param[in] set The set to be erased.
+ * @param[in] destructor Optional function to free the objects in the set.
+ */
+void ly_set_erase(struct ly_set *set, void (*destructor)(void *obj));
 
 /** @} lyset */