xpath FEATURE get atoms from parsed expr and path
diff --git a/src/tree_schema.c b/src/tree_schema.c
index 1937de1..5f033f3 100644
--- a/src/tree_schema.c
+++ b/src/tree_schema.c
@@ -34,6 +34,7 @@
 #include "in_internal.h"
 #include "parser_internal.h"
 #include "parser_schema.h"
+#include "path.h"
 #include "schema_compile.h"
 #include "schema_compile_amend.h"
 #include "set.h"
@@ -273,10 +274,82 @@
 }
 
 API LY_ERR
+lys_find_path_atoms(const struct ly_path *path, struct ly_set **set)
+{
+    LY_ERR ret = LY_SUCCESS;
+    LY_ARRAY_COUNT_TYPE u, v;
+
+    LY_CHECK_ARG_RET(NULL, path, set, LY_EINVAL);
+
+    /* allocate return set */
+    LY_CHECK_RET(ly_set_new(set));
+
+    LY_ARRAY_FOR(path, u) {
+        /* add nodes from the path */
+        LY_CHECK_GOTO(ret = ly_set_add(*set, (void *)path[u].node, 0, NULL), cleanup);
+        if (path[u].pred_type == LY_PATH_PREDTYPE_LIST) {
+            LY_ARRAY_FOR(path[u].predicates, v) {
+                /* add all the keys in a predicate */
+                LY_CHECK_GOTO(ret = ly_set_add(*set, (void *)path[u].predicates[v].key, 0, NULL), cleanup);
+            }
+        }
+    }
+
+cleanup:
+    if (ret) {
+        ly_set_free(*set, NULL);
+        *set = NULL;
+    }
+    return ret;
+}
+
+API LY_ERR
+lys_find_expr_atoms(const struct lysc_node *ctx_node, const struct lys_module *cur_mod, const struct lyxp_expr *expr,
+        const struct lysc_prefix *prefixes, uint32_t options, struct ly_set **set)
+{
+    LY_ERR ret = LY_SUCCESS;
+    struct lyxp_set xp_set = {0};
+    uint32_t i;
+
+    LY_CHECK_ARG_RET(NULL, cur_mod, expr, prefixes, set, LY_EINVAL);
+    if (!(options & LYXP_SCNODE_ALL)) {
+        options = LYXP_SCNODE;
+    }
+
+    /* atomize expression */
+    ret = lyxp_atomize(expr, cur_mod, LY_PREF_SCHEMA_RESOLVED, (void *)prefixes, ctx_node, &xp_set, options);
+    LY_CHECK_GOTO(ret, cleanup);
+
+    /* allocate return set */
+    ret = ly_set_new(set);
+    LY_CHECK_GOTO(ret, cleanup);
+
+    /* transform into ly_set */
+    (*set)->objs = malloc(xp_set.used * sizeof *(*set)->objs);
+    LY_CHECK_ERR_GOTO(!(*set)->objs, LOGMEM(cur_mod->ctx); ret = LY_EMEM, cleanup);
+    (*set)->size = xp_set.used;
+
+    for (i = 0; i < xp_set.used; ++i) {
+        if ((xp_set.val.scnodes[i].type == LYXP_NODE_ELEM) && (xp_set.val.scnodes[i].in_ctx == 1)) {
+            ret = ly_set_add(*set, xp_set.val.scnodes[i].scnode, 1, NULL);
+            LY_CHECK_GOTO(ret, cleanup);
+        }
+    }
+
+cleanup:
+    lyxp_set_free_content(&xp_set);
+    if (ret) {
+        ly_set_free(*set, NULL);
+        *set = NULL;
+    }
+    return ret;
+}
+
+API LY_ERR
 lys_find_xpath(const struct lysc_node *ctx_node, const char *xpath, uint32_t options, struct ly_set **set)
 {
     LY_ERR ret = LY_SUCCESS;
-    struct lyxp_set xp_set;
+    struct lyxp_set xp_set = {0};
     struct lyxp_expr *exp = NULL;
     uint32_t i;
 
@@ -285,8 +358,6 @@
         options = LYXP_SCNODE;
     }
 
-    memset(&xp_set, 0, sizeof xp_set);
-
     /* compile expression */
     ret = lyxp_expr_parse(ctx_node->module->ctx, xpath, 0, 1, &exp);
     LY_CHECK_GOTO(ret, cleanup);
@@ -314,6 +385,10 @@
 cleanup:
     lyxp_set_free_content(&xp_set);
     lyxp_expr_free(ctx_node->module->ctx, exp);
+     if (ret) {
+        ly_set_free(*set, NULL);
+        *set = NULL;
+    }
     return ret;
 }