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;
}
diff --git a/src/tree_schema.h b/src/tree_schema.h
index 28301e3..aa10ef6 100644
--- a/src/tree_schema.h
+++ b/src/tree_schema.h
@@ -1910,22 +1910,47 @@
*/
/**
- * @brief Get all the schema nodes (atoms) that are required for \p xpath to be evaluated.
+ * @brief Get all the schema nodes that are required for @p xpath to be evaluated (atoms).
*
* @param[in] ctx_node XPath schema context node.
- * @param[in] xpath Data XPath expression filtering the matching nodes. ::LYD_JSON format is expected.
+ * @param[in] xpath Data XPath expression filtering the matching nodes. ::LY_PREF_JSON prefix format is expected.
* @param[in] options Whether to apply some node access restrictions, see @ref findxpathoptions.
* @param[out] set Set of found atoms (schema nodes).
* @return LY_SUCCESS on success, @p set is returned.
- * @return LY_ERR value if an error occurred.
+ * @return LY_ERR value on error.
*/
LY_ERR lys_find_xpath_atoms(const struct lysc_node *ctx_node, const char *xpath, uint32_t options, struct ly_set **set);
/**
- * @brief Evaluate an \p xpath expression on schema nodes.
+ * @brief Get all the schema nodes that are required for @p path to be evaluated (atoms).
+ *
+ * @param[in] path Compiled path to use.
+ * @param[out] set Set of found atoms (schema nodes).
+ * @return LY_SUCCESS on success, @p set is returned.
+ * @return LY_ERR value on error.
+ */
+LY_ERR lys_find_path_atoms(const struct ly_path *path, struct ly_set **set);
+
+/**
+ * @brief Get all the schema nodes that are required for @p expr to be evaluated (atoms).
*
* @param[in] ctx_node XPath schema context node.
- * @param[in] xpath Data XPath expression filtering the matching nodes. ::LYD_JSON format is expected.
+ * @param[in] cur_mod Current module for the expression (where it was "instantiated").
+ * @param[in] expr Parsed expression to use.
+ * @param[in] prefixes Sized array of compiled prefixes.
+ * @param[in] options Whether to apply some node access restrictions, see @ref findxpathoptions.
+ * @param[out] set Set of found atoms (schema nodes).
+ * @return LY_SUCCESS on success, @p set is returned.
+ * @return LY_ERR value on error.
+ */
+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);
+
+/**
+ * @brief Evaluate an @p xpath expression on schema nodes.
+ *
+ * @param[in] ctx_node XPath schema context node.
+ * @param[in] xpath Data XPath expression filtering the matching nodes. ::LY_PREF_JSON prefix format is expected.
* @param[in] options Whether to apply some node access restrictions, see @ref findxpathoptions.
* @param[out] set Set of found schema nodes.
* @return LY_SUCCESS on success, @p set is returned.
diff --git a/src/xpath.c b/src/xpath.c
index d3c0b4c..1e5cf39 100644
--- a/src/xpath.c
+++ b/src/xpath.c
@@ -45,7 +45,8 @@
#include "xml.h"
static LY_ERR reparse_or_expr(const struct ly_ctx *ctx, struct lyxp_expr *exp, uint16_t *tok_idx);
-static LY_ERR eval_expr_select(struct lyxp_expr *exp, uint16_t *tok_idx, enum lyxp_expr_type etype, struct lyxp_set *set, uint32_t options);
+static LY_ERR eval_expr_select(const struct lyxp_expr *exp, uint16_t *tok_idx, enum lyxp_expr_type etype,
+ struct lyxp_set *set, uint32_t options);
/**
* @brief Print the type of an XPath \p set.
@@ -130,7 +131,7 @@
* @param[in] exp Expression to use.
*/
static void
-print_expr_struct_debug(struct lyxp_expr *exp)
+print_expr_struct_debug(const struct lyxp_expr *exp)
{
uint16_t i, j;
char tmp[128];
@@ -1871,7 +1872,7 @@
/* just like lyxp_check_token() but tests for 2 tokens */
static LY_ERR
-exp_check_token2(const struct ly_ctx *ctx, struct lyxp_expr *exp, uint16_t tok_idx, enum lyxp_token want_tok1,
+exp_check_token2(const struct ly_ctx *ctx, const struct lyxp_expr *exp, uint16_t tok_idx, enum lyxp_token want_tok1,
enum lyxp_token want_tok2)
{
if (exp->used == tok_idx) {
@@ -3303,7 +3304,8 @@
* @param[in] last_equal_exp Index of the end of the equality expression in @p exp.
*/
static void
-warn_equality_value(struct lyxp_expr *exp, struct lyxp_set *set, uint16_t val_exp, uint16_t equal_exp, uint16_t last_equal_exp)
+warn_equality_value(const struct lyxp_expr *exp, struct lyxp_set *set, uint16_t val_exp, uint16_t equal_exp,
+ uint16_t last_equal_exp)
{
struct lysc_node *scnode;
struct lysc_type *type;
@@ -6726,7 +6728,7 @@
* @return LY_ERR (LY_EINCOMPLETE on unresolved when)
*/
static LY_ERR
-eval_predicate(struct lyxp_expr *exp, uint16_t *tok_idx, struct lyxp_set *set, uint32_t options, ly_bool parent_pos_pred)
+eval_predicate(const struct lyxp_expr *exp, uint16_t *tok_idx, struct lyxp_set *set, uint32_t options, ly_bool parent_pos_pred)
{
LY_ERR rc;
uint16_t i, orig_exp;
@@ -6872,7 +6874,7 @@
* @param[in,out] set Context and result set. On NULL the rule is only parsed.
*/
static void
-eval_literal(struct lyxp_expr *exp, uint16_t *tok_idx, struct lyxp_set *set)
+eval_literal(const struct lyxp_expr *exp, uint16_t *tok_idx, struct lyxp_set *set)
{
if (set) {
if (exp->tok_len[*tok_idx] == 2) {
@@ -6902,7 +6904,7 @@
* @return LY_ERR on any error.
*/
static LY_ERR
-eval_name_test_try_compile_predicates(struct lyxp_expr *exp, uint16_t *tok_idx, const struct lysc_node *ctx_node,
+eval_name_test_try_compile_predicates(const struct lyxp_expr *exp, uint16_t *tok_idx, const struct lysc_node *ctx_node,
const struct lys_module *cur_mod, const struct lysc_node *cur_node, LY_PREFIX_FORMAT format, void *prefix_data,
struct ly_path_predicate **predicates, enum ly_path_pred_type *pred_type)
{
@@ -7077,7 +7079,7 @@
* @return LY_ERR (LY_EINCOMPLETE on unresolved when)
*/
static LY_ERR
-eval_name_test_with_predicate(struct lyxp_expr *exp, uint16_t *tok_idx, ly_bool attr_axis, ly_bool all_desc,
+eval_name_test_with_predicate(const struct lyxp_expr *exp, uint16_t *tok_idx, ly_bool attr_axis, ly_bool all_desc,
struct lyxp_set *set, uint32_t options)
{
char *path;
@@ -7231,7 +7233,7 @@
* @return LY_ERR (LY_EINCOMPLETE on unresolved when)
*/
static LY_ERR
-eval_node_type_with_predicate(struct lyxp_expr *exp, uint16_t *tok_idx, ly_bool attr_axis, ly_bool all_desc,
+eval_node_type_with_predicate(const struct lyxp_expr *exp, uint16_t *tok_idx, ly_bool attr_axis, ly_bool all_desc,
struct lyxp_set *set, uint32_t options)
{
LY_ERR rc;
@@ -7296,7 +7298,8 @@
* @return LY_ERR (YL_EINCOMPLETE on unresolved when)
*/
static LY_ERR
-eval_relative_location_path(struct lyxp_expr *exp, uint16_t *tok_idx, ly_bool all_desc, struct lyxp_set *set, uint32_t options)
+eval_relative_location_path(const struct lyxp_expr *exp, uint16_t *tok_idx, ly_bool all_desc, struct lyxp_set *set,
+ uint32_t options)
{
ly_bool attr_axis;
LY_ERR rc;
@@ -7386,7 +7389,7 @@
* @return LY_ERR (LY_EINCOMPLETE on unresolved when)
*/
static LY_ERR
-eval_absolute_location_path(struct lyxp_expr *exp, uint16_t *tok_idx, struct lyxp_set *set, uint32_t options)
+eval_absolute_location_path(const struct lyxp_expr *exp, uint16_t *tok_idx, struct lyxp_set *set, uint32_t options)
{
ly_bool all_desc;
@@ -7444,7 +7447,7 @@
* @return LY_ERR (LY_EINCOMPLETE on unresolved when)
*/
static LY_ERR
-eval_function_call(struct lyxp_expr *exp, uint16_t *tok_idx, struct lyxp_set *set, uint32_t options)
+eval_function_call(const struct lyxp_expr *exp, uint16_t *tok_idx, struct lyxp_set *set, uint32_t options)
{
LY_ERR rc;
@@ -7664,7 +7667,7 @@
* @return LY_ERR
*/
static LY_ERR
-eval_number(struct ly_ctx *ctx, struct lyxp_expr *exp, uint16_t *tok_idx, struct lyxp_set *set)
+eval_number(struct ly_ctx *ctx, const struct lyxp_expr *exp, uint16_t *tok_idx, struct lyxp_set *set)
{
long double num;
char *endptr;
@@ -7709,7 +7712,7 @@
* @return LY_ERR (LY_EINCOMPLETE on unresolved when)
*/
static LY_ERR
-eval_path_expr(struct lyxp_expr *exp, uint16_t *tok_idx, struct lyxp_set *set, uint32_t options)
+eval_path_expr(const struct lyxp_expr *exp, uint16_t *tok_idx, struct lyxp_set *set, uint32_t options)
{
ly_bool all_desc, parent_pos_pred;
LY_ERR rc;
@@ -7843,7 +7846,7 @@
* @return LY_ERR (LY_EINCOMPLETE on unresolved when)
*/
static LY_ERR
-eval_union_expr(struct lyxp_expr *exp, uint16_t *tok_idx, uint16_t repeat, struct lyxp_set *set, uint32_t options)
+eval_union_expr(const struct lyxp_expr *exp, uint16_t *tok_idx, uint16_t repeat, struct lyxp_set *set, uint32_t options)
{
LY_ERR rc = LY_SUCCESS;
struct lyxp_set orig_set, set2;
@@ -7904,7 +7907,7 @@
* @return LY_ERR (LY_EINCOMPLETE on unresolved when)
*/
static LY_ERR
-eval_unary_expr(struct lyxp_expr *exp, uint16_t *tok_idx, uint16_t repeat, struct lyxp_set *set, uint32_t options)
+eval_unary_expr(const struct lyxp_expr *exp, uint16_t *tok_idx, uint16_t repeat, struct lyxp_set *set, uint32_t options)
{
LY_ERR rc;
uint16_t this_op, i;
@@ -7952,7 +7955,8 @@
* @return LY_ERR (LY_EINCOMPLETE on unresolved when)
*/
static LY_ERR
-eval_multiplicative_expr(struct lyxp_expr *exp, uint16_t *tok_idx, uint16_t repeat, struct lyxp_set *set, uint32_t options)
+eval_multiplicative_expr(const struct lyxp_expr *exp, uint16_t *tok_idx, uint16_t repeat, struct lyxp_set *set,
+ uint32_t options)
{
LY_ERR rc;
uint16_t this_op;
@@ -8020,7 +8024,7 @@
* @return LY_ERR (LY_EINCOMPLETE on unresolved when)
*/
static LY_ERR
-eval_additive_expr(struct lyxp_expr *exp, uint16_t *tok_idx, uint16_t repeat, struct lyxp_set *set, uint32_t options)
+eval_additive_expr(const struct lyxp_expr *exp, uint16_t *tok_idx, uint16_t repeat, struct lyxp_set *set, uint32_t options)
{
LY_ERR rc;
uint16_t this_op;
@@ -8090,7 +8094,7 @@
* @return LY_ERR (LY_EINCOMPLETE on unresolved when)
*/
static LY_ERR
-eval_relational_expr(struct lyxp_expr *exp, uint16_t *tok_idx, uint16_t repeat, struct lyxp_set *set, uint32_t options)
+eval_relational_expr(const struct lyxp_expr *exp, uint16_t *tok_idx, uint16_t repeat, struct lyxp_set *set, uint32_t options)
{
LY_ERR rc;
uint16_t this_op;
@@ -8157,7 +8161,7 @@
* @return LY_ERR (LY_EINCOMPLETE on unresolved when)
*/
static LY_ERR
-eval_equality_expr(struct lyxp_expr *exp, uint16_t *tok_idx, uint16_t repeat, struct lyxp_set *set, uint32_t options)
+eval_equality_expr(const struct lyxp_expr *exp, uint16_t *tok_idx, uint16_t repeat, struct lyxp_set *set, uint32_t options)
{
LY_ERR rc;
uint16_t this_op;
@@ -8225,7 +8229,7 @@
* @return LY_ERR (LY_EINCOMPLETE on unresolved when)
*/
static LY_ERR
-eval_and_expr(struct lyxp_expr *exp, uint16_t *tok_idx, uint16_t repeat, struct lyxp_set *set, uint32_t options)
+eval_and_expr(const struct lyxp_expr *exp, uint16_t *tok_idx, uint16_t repeat, struct lyxp_set *set, uint32_t options)
{
LY_ERR rc;
struct lyxp_set orig_set, set2;
@@ -8295,7 +8299,7 @@
* @return LY_ERR (LY_EINCOMPLETE on unresolved when)
*/
static LY_ERR
-eval_or_expr(struct lyxp_expr *exp, uint16_t *tok_idx, uint16_t repeat, struct lyxp_set *set, uint32_t options)
+eval_or_expr(const struct lyxp_expr *exp, uint16_t *tok_idx, uint16_t repeat, struct lyxp_set *set, uint32_t options)
{
LY_ERR rc;
struct lyxp_set orig_set, set2;
@@ -8365,7 +8369,8 @@
* @return LY_ERR (LY_EINCOMPLETE on unresolved when)
*/
static LY_ERR
-eval_expr_select(struct lyxp_expr *exp, uint16_t *tok_idx, enum lyxp_expr_type etype, struct lyxp_set *set, uint32_t options)
+eval_expr_select(const struct lyxp_expr *exp, uint16_t *tok_idx, enum lyxp_expr_type etype, struct lyxp_set *set,
+ uint32_t options)
{
uint16_t i, count;
enum lyxp_expr_type next_etype;
@@ -8466,7 +8471,7 @@
}
LY_ERR
-lyxp_eval(struct lyxp_expr *exp, const struct lys_module *cur_mod, LY_PREFIX_FORMAT format, void *prefix_data,
+lyxp_eval(const struct lyxp_expr *exp, const struct lys_module *cur_mod, LY_PREFIX_FORMAT format, void *prefix_data,
const struct lyd_node *ctx_node, const struct lyd_node *tree, struct lyxp_set *set, uint32_t options)
{
uint16_t tok_idx = 0;
@@ -8732,7 +8737,7 @@
}
LY_ERR
-lyxp_atomize(struct lyxp_expr *exp, const struct lys_module *cur_mod, LY_PREFIX_FORMAT format, void *prefix_data,
+lyxp_atomize(const struct lyxp_expr *exp, const struct lys_module *cur_mod, LY_PREFIX_FORMAT format, void *prefix_data,
const struct lysc_node *ctx_scnode, struct lyxp_set *set, uint32_t options)
{
uint16_t tok_idx = 0;
diff --git a/src/xpath.h b/src/xpath.h
index 05a059a..ae75320 100644
--- a/src/xpath.h
+++ b/src/xpath.h
@@ -289,7 +289,7 @@
* @return LY_EINCOMPLETE for unresolved when,
* @return LY_EINVAL, LY_EMEM, LY_EINT for other errors.
*/
-LY_ERR lyxp_eval(struct lyxp_expr *exp, const struct lys_module *cur_mod, LY_PREFIX_FORMAT format, void *prefix_data,
+LY_ERR lyxp_eval(const struct lyxp_expr *exp, const struct lys_module *cur_mod, LY_PREFIX_FORMAT format, void *prefix_data,
const struct lyd_node *ctx_node, const struct lyd_node *tree, struct lyxp_set *set, uint32_t options);
@@ -305,7 +305,7 @@
* @param[in] options Whether to apply some evaluation restrictions, one flag must always be used.
* @return LY_ERR (same as ::lyxp_eval()).
*/
-LY_ERR lyxp_atomize(struct lyxp_expr *exp, const struct lys_module *cur_mod, LY_PREFIX_FORMAT format, void *prefix_data,
+LY_ERR lyxp_atomize(const struct lyxp_expr *exp, const struct lys_module *cur_mod, LY_PREFIX_FORMAT format, void *prefix_data,
const struct lysc_node *ctx_scnode, struct lyxp_set *set, uint32_t options);
/* used only internally, maps with @ref findxpathoptions */