summaryrefslogtreecommitdiffstats
path: root/src/xpath.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/xpath.c')
-rw-r--r--src/xpath.c473
1 files changed, 299 insertions, 174 deletions
diff --git a/src/xpath.c b/src/xpath.c
index ab7921e..bc5f695 100644
--- a/src/xpath.c
+++ b/src/xpath.c
@@ -43,8 +43,6 @@
#include "tree_schema_internal.h"
#include "xml.h"
-static LY_ERR set_scnode_insert_node(struct lyxp_set *set, const struct lysc_node *node, enum lyxp_node_type node_type,
- enum lyxp_axis axis, uint32_t *index_p);
static LY_ERR reparse_or_expr(const struct ly_ctx *ctx, struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t depth);
static LY_ERR eval_expr_select(const struct lyxp_expr *exp, uint32_t *tok_idx, enum lyxp_expr_type etype,
struct lyxp_set *set, uint32_t options);
@@ -123,6 +121,8 @@ lyxp_token2str(enum lyxp_token tok)
return "@";
case LYXP_TOKEN_COMMA:
return ",";
+ case LYXP_TOKEN_DCOLON:
+ return "::";
case LYXP_TOKEN_NAMETEST:
return "NameTest";
case LYXP_TOKEN_NODETYPE:
@@ -147,6 +147,8 @@ lyxp_token2str(enum lyxp_token tok)
return "Operator(Path)";
case LYXP_TOKEN_OPER_RPATH:
return "Operator(Recursive Path)";
+ case LYXP_TOKEN_AXISNAME:
+ return "AxisName";
case LYXP_TOKEN_LITERAL:
return "Literal";
case LYXP_TOKEN_NUMBER:
@@ -217,16 +219,53 @@ str2axis(const char *str, uint32_t str_len)
}
/**
- * @brief Print the whole expression \p exp to debug output.
+ * @brief Append a string to a dynamic string variable.
+ *
+ * @param[in,out] str String to use.
+ * @param[in,out] size String size.
+ * @param[in,out] used String used size excluding terminating zero.
+ * @param[in] format Message format.
+ * @param[in] ... Message format arguments.
+ */
+static void
+print_expr_str(char **str, size_t *size, size_t *used, const char *format, ...)
+{
+ int p;
+ va_list ap;
+
+ va_start(ap, format);
+
+ /* try to append the string */
+ p = vsnprintf(*str ? *str + *used : NULL, *size - *used, format, ap);
+
+ if ((unsigned)p >= *size - *used) {
+ /* realloc */
+ *str = ly_realloc(*str, *size + p + 1);
+ *size += p + 1;
+
+ /* restart ap */
+ va_end(ap);
+ va_start(ap, format);
+
+ /* print */
+ p = vsnprintf(*str + *used, *size - *used, format, ap);
+ }
+
+ *used += p;
+ va_end(ap);
+}
+
+/**
+ * @brief Print the whole expression @p exp to debug output.
*
* @param[in] exp Expression to use.
*/
static void
print_expr_struct_debug(const struct lyxp_expr *exp)
{
-#define MSG_BUFFER_SIZE 128
- char tmp[MSG_BUFFER_SIZE];
+ char *buf = NULL;
uint32_t i, j;
+ size_t size = 0, used = 0;
if (!exp || (ly_ll < LY_LLDBG)) {
return;
@@ -234,18 +273,21 @@ print_expr_struct_debug(const struct lyxp_expr *exp)
LOGDBG(LY_LDGXPATH, "expression \"%s\":", exp->expr);
for (i = 0; i < exp->used; ++i) {
- sprintf(tmp, "\ttoken %s, in expression \"%.*s\"", lyxp_token2str(exp->tokens[i]), exp->tok_len[i],
- &exp->expr[exp->tok_pos[i]]);
+ print_expr_str(&buf, &size, &used, "\ttoken %s, in expression \"%.*s\"",
+ lyxp_token2str(exp->tokens[i]), exp->tok_len[i], &exp->expr[exp->tok_pos[i]]);
+
if (exp->repeat && exp->repeat[i]) {
- sprintf(tmp + strlen(tmp), " (repeat %d", exp->repeat[i][0]);
+ print_expr_str(&buf, &size, &used, " (repeat %d", exp->repeat[i][0]);
for (j = 1; exp->repeat[i][j]; ++j) {
- sprintf(tmp + strlen(tmp), ", %d", exp->repeat[i][j]);
+ print_expr_str(&buf, &size, &used, ", %d", exp->repeat[i][j]);
}
- strcat(tmp, ")");
+ print_expr_str(&buf, &size, &used, ")");
}
- LOGDBG(LY_LDGXPATH, tmp);
+ LOGDBG(LY_LDGXPATH, buf);
+ used = 0;
}
-#undef MSG_BUFFER_SIZE
+
+ free(buf);
}
#ifndef NDEBUG
@@ -284,18 +326,19 @@ print_set_debug(struct lyxp_set *set)
LOGDBG(LY_LDGXPATH, "\t%d (pos %u): ROOT CONFIG", i + 1, item->pos);
break;
case LYXP_NODE_ELEM:
- if ((item->node->schema->nodetype == LYS_LIST) && (lyd_child(item->node)->schema->nodetype == LYS_LEAF)) {
+ if (item->node->schema && (item->node->schema->nodetype == LYS_LIST) &&
+ (lyd_child(item->node)->schema->nodetype == LYS_LEAF)) {
LOGDBG(LY_LDGXPATH, "\t%d (pos %u): ELEM %s (1st child val: %s)", i + 1, item->pos,
item->node->schema->name, lyd_get_value(lyd_child(item->node)));
- } else if (item->node->schema->nodetype == LYS_LEAFLIST) {
+ } else if ((!item->node->schema && !lyd_child(item->node)) || (item->node->schema->nodetype == LYS_LEAFLIST)) {
LOGDBG(LY_LDGXPATH, "\t%d (pos %u): ELEM %s (val: %s)", i + 1, item->pos,
- item->node->schema->name, lyd_get_value(item->node));
+ LYD_NAME(item->node), lyd_get_value(item->node));
} else {
- LOGDBG(LY_LDGXPATH, "\t%d (pos %u): ELEM %s", i + 1, item->pos, item->node->schema->name);
+ LOGDBG(LY_LDGXPATH, "\t%d (pos %u): ELEM %s", i + 1, item->pos, LYD_NAME(item->node));
}
break;
case LYXP_NODE_TEXT:
- if (item->node->schema->nodetype & LYS_ANYDATA) {
+ if (item->node->schema && (item->node->schema->nodetype & LYS_ANYDATA)) {
LOGDBG(LY_LDGXPATH, "\t%d (pos %u): TEXT <%s>", i + 1, item->pos,
item->node->schema->nodetype == LYS_ANYXML ? "anyxml" : "anydata");
} else {
@@ -416,13 +459,14 @@ cast_string_recursive(const struct lyd_node *node, struct lyxp_set *set, uint32_
{
char *buf, *line, *ptr = NULL;
const char *value_str;
+ uint16_t nodetype;
const struct lyd_node *child;
enum lyxp_node_type child_type;
struct lyd_node *tree;
struct lyd_node_any *any;
LY_ERR rc;
- if ((set->root_type == LYXP_NODE_ROOT_CONFIG) && node && (node->schema->flags & LYS_CONFIG_R)) {
+ if ((set->root_type == LYXP_NODE_ROOT_CONFIG) && node && node->schema && (node->schema->flags & LYS_CONFIG_R)) {
return LY_SUCCESS;
}
@@ -448,7 +492,15 @@ cast_string_recursive(const struct lyd_node *node, struct lyxp_set *set, uint32_
--indent;
} else {
- switch (node->schema->nodetype) {
+ if (node->schema) {
+ nodetype = node->schema->nodetype;
+ } else if (lyd_child(node)) {
+ nodetype = LYS_CONTAINER;
+ } else {
+ nodetype = LYS_LEAF;
+ }
+
+ switch (nodetype) {
case LYS_CONTAINER:
case LYS_LIST:
case LYS_RPC:
@@ -691,29 +743,29 @@ set_insert_node_hash(struct lyxp_set *set, struct lyd_node *node, enum lyxp_node
hnode.node = set->val.nodes[i].node;
hnode.type = set->val.nodes[i].type;
- hash = dict_hash_multi(0, (const char *)&hnode.node, sizeof hnode.node);
- hash = dict_hash_multi(hash, (const char *)&hnode.type, sizeof hnode.type);
- hash = dict_hash_multi(hash, NULL, 0);
+ hash = lyht_hash_multi(0, (const char *)&hnode.node, sizeof hnode.node);
+ hash = lyht_hash_multi(hash, (const char *)&hnode.type, sizeof hnode.type);
+ hash = lyht_hash_multi(hash, NULL, 0);
r = lyht_insert(set->ht, &hnode, hash, NULL);
assert(!r);
(void)r;
- if (hnode.node == node) {
+ if ((hnode.node == node) && (hnode.type == type)) {
/* it was just added, do not add it twice */
- node = NULL;
+ return;
}
}
}
- if (set->ht && node) {
+ if (set->ht) {
/* add the new node into hash table */
hnode.node = node;
hnode.type = type;
- hash = dict_hash_multi(0, (const char *)&hnode.node, sizeof hnode.node);
- hash = dict_hash_multi(hash, (const char *)&hnode.type, sizeof hnode.type);
- hash = dict_hash_multi(hash, NULL, 0);
+ hash = lyht_hash_multi(0, (const char *)&hnode.node, sizeof hnode.node);
+ hash = lyht_hash_multi(hash, (const char *)&hnode.type, sizeof hnode.type);
+ hash = lyht_hash_multi(hash, NULL, 0);
r = lyht_insert(set->ht, &hnode, hash, NULL);
assert(!r);
@@ -739,16 +791,16 @@ set_remove_node_hash(struct lyxp_set *set, struct lyd_node *node, enum lyxp_node
hnode.node = node;
hnode.type = type;
- hash = dict_hash_multi(0, (const char *)&hnode.node, sizeof hnode.node);
- hash = dict_hash_multi(hash, (const char *)&hnode.type, sizeof hnode.type);
- hash = dict_hash_multi(hash, NULL, 0);
+ hash = lyht_hash_multi(0, (const char *)&hnode.node, sizeof hnode.node);
+ hash = lyht_hash_multi(hash, (const char *)&hnode.type, sizeof hnode.type);
+ hash = lyht_hash_multi(hash, NULL, 0);
r = lyht_remove(set->ht, &hnode, hash);
assert(!r);
(void)r;
if (!set->ht->used) {
- lyht_free(set->ht);
+ lyht_free(set->ht, NULL);
set->ht = NULL;
}
}
@@ -772,9 +824,9 @@ set_dup_node_hash_check(const struct lyxp_set *set, struct lyd_node *node, enum
hnode.node = node;
hnode.type = type;
- hash = dict_hash_multi(0, (const char *)&hnode.node, sizeof hnode.node);
- hash = dict_hash_multi(hash, (const char *)&hnode.type, sizeof hnode.type);
- hash = dict_hash_multi(hash, NULL, 0);
+ hash = lyht_hash_multi(0, (const char *)&hnode.node, sizeof hnode.node);
+ hash = lyht_hash_multi(hash, (const char *)&hnode.type, sizeof hnode.type);
+ hash = lyht_hash_multi(hash, NULL, 0);
if (!lyht_find(set->ht, &hnode, hash, (void **)&match_p)) {
if ((skip_idx > -1) && (set->val.nodes[skip_idx].node == match_p->node) && (set->val.nodes[skip_idx].type == match_p->type)) {
@@ -802,10 +854,10 @@ lyxp_set_free_content(struct lyxp_set *set)
if (set->type == LYXP_SET_NODE_SET) {
free(set->val.nodes);
- lyht_free(set->ht);
+ lyht_free(set->ht, NULL);
} else if (set->type == LYXP_SET_SCNODE_SET) {
free(set->val.scnodes);
- lyht_free(set->ht);
+ lyht_free(set->ht, NULL);
} else {
if (set->type == LYXP_SET_STRING) {
free(set->val.str);
@@ -847,18 +899,21 @@ static void
set_init(struct lyxp_set *new, const struct lyxp_set *set)
{
memset(new, 0, sizeof *new);
- if (set) {
- new->non_child_axis = set->non_child_axis;
- new->ctx = set->ctx;
- new->cur_node = set->cur_node;
- new->root_type = set->root_type;
- new->context_op = set->context_op;
- new->tree = set->tree;
- new->cur_mod = set->cur_mod;
- new->format = set->format;
- new->prefix_data = set->prefix_data;
- new->vars = set->vars;
+ if (!set) {
+ return;
}
+
+ new->non_child_axis = set->non_child_axis;
+ new->not_found = set->not_found;
+ new->ctx = set->ctx;
+ new->cur_node = set->cur_node;
+ new->root_type = set->root_type;
+ new->context_op = set->context_op;
+ new->tree = set->tree;
+ new->cur_mod = set->cur_mod;
+ new->format = set->format;
+ new->prefix_data = set->prefix_data;
+ new->vars = set->vars;
}
/**
@@ -889,7 +944,7 @@ set_copy(struct lyxp_set *set)
(set->val.scnodes[i].in_ctx == LYXP_SET_SCNODE_START)) {
uint32_t idx;
- LY_CHECK_ERR_RET(set_scnode_insert_node(ret, set->val.scnodes[i].scnode, set->val.scnodes[i].type,
+ LY_CHECK_ERR_RET(lyxp_set_scnode_insert_node(ret, set->val.scnodes[i].scnode, set->val.scnodes[i].type,
set->val.scnodes[i].axis, &idx), lyxp_set_free(ret), NULL);
/* coverity seems to think scnodes can be NULL */
if (!ret->val.scnodes) {
@@ -989,11 +1044,7 @@ set_fill_set(struct lyxp_set *trg, const struct lyxp_set *src)
return;
}
- if (trg->type == LYXP_SET_NODE_SET) {
- free(trg->val.nodes);
- } else if (trg->type == LYXP_SET_STRING) {
- free(trg->val.str);
- }
+ lyxp_set_free_content(trg);
set_init(trg, src);
if (src->type == LYXP_SET_SCNODE_SET) {
@@ -1314,19 +1365,8 @@ set_insert_node(struct lyxp_set *set, const struct lyd_node *node, uint32_t pos,
set_insert_node_hash(set, (struct lyd_node *)node, node_type);
}
-/**
- * @brief Insert schema node into set.
- *
- * @param[in] set Set to insert into.
- * @param[in] node Node to insert.
- * @param[in] node_type Node type of @p node.
- * @param[in] axis Axis that @p node was reached on.
- * @param[out] index_p Optional pointer to store index if the inserted @p node.
- * @return LY_SUCCESS on success.
- * @return LY_EMEM on memory allocation failure.
- */
-static LY_ERR
-set_scnode_insert_node(struct lyxp_set *set, const struct lysc_node *node, enum lyxp_node_type node_type,
+LY_ERR
+lyxp_set_scnode_insert_node(struct lyxp_set *set, const struct lysc_node *node, enum lyxp_node_type node_type,
enum lyxp_axis axis, uint32_t *index_p)
{
uint32_t index;
@@ -1346,7 +1386,7 @@ set_scnode_insert_node(struct lyxp_set *set, const struct lysc_node *node, enum
}
if (lyxp_set_scnode_contains(set, node, node_type, -1, &index)) {
- /* BUG if axes differs, this new one is thrown away */
+ /* BUG if axes differ, this new one is thrown away */
set->val.scnodes[index].in_ctx = LYXP_SET_SCNODE_ATOM_CTX;
} else {
if (set->used == set->size) {
@@ -1445,7 +1485,7 @@ dfs_search:
LYD_TREE_DFS_continue = 0;
}
- if (!elem->schema || ((root_type == LYXP_NODE_ROOT_CONFIG) && (elem->schema->flags & LYS_CONFIG_R))) {
+ if ((root_type == LYXP_NODE_ROOT_CONFIG) && elem->schema && (elem->schema->flags & LYS_CONFIG_R)) {
/* skip */
LYD_TREE_DFS_continue = 1;
} else {
@@ -1662,7 +1702,7 @@ set_comp_canonize(struct lyxp_set *set, const struct lyxp_set_node *xp_node)
/* is there anything to canonize even? */
if (set->type == LYXP_SET_STRING) {
/* do we have a type to use for canonization? */
- if ((xp_node->type == LYXP_NODE_ELEM) && (xp_node->node->schema->nodetype & LYD_NODE_TERM)) {
+ if ((xp_node->type == LYXP_NODE_ELEM) && xp_node->node->schema && (xp_node->node->schema->nodetype & LYD_NODE_TERM)) {
type = ((struct lyd_node_term *)xp_node->node)->value.realtype;
} else if (xp_node->type == LYXP_NODE_META) {
type = ((struct lyd_meta *)xp_node->node)->value.realtype;
@@ -1785,9 +1825,9 @@ set_sort(struct lyxp_set *set)
hnode.node = set->val.nodes[i].node;
hnode.type = set->val.nodes[i].type;
- hash = dict_hash_multi(0, (const char *)&hnode.node, sizeof hnode.node);
- hash = dict_hash_multi(hash, (const char *)&hnode.type, sizeof hnode.type);
- hash = dict_hash_multi(hash, NULL, 0);
+ hash = lyht_hash_multi(0, (const char *)&hnode.node, sizeof hnode.node);
+ hash = lyht_hash_multi(hash, (const char *)&hnode.type, sizeof hnode.type);
+ hash = lyht_hash_multi(hash, NULL, 0);
assert(!lyht_find(set->ht, &hnode, hash, NULL));
}
@@ -1993,11 +2033,11 @@ lyxp_next_token2(const struct ly_ctx *ctx, const struct lyxp_expr *exp, uint32_t
* @brief Stack operation push on the repeat array.
*
* @param[in] exp Expression to use.
- * @param[in] tok_idx Position in the expresion \p exp.
- * @param[in] repeat_op_idx Index from \p exp of the operator token. This value is pushed.
+ * @param[in] tok_idx Position in the expresion @p exp.
+ * @param[in] repeat_expr_type Repeated expression type, this value is pushed.
*/
static void
-exp_repeat_push(struct lyxp_expr *exp, uint32_t tok_idx, uint32_t repeat_op_idx)
+exp_repeat_push(struct lyxp_expr *exp, uint32_t tok_idx, enum lyxp_expr_type repeat_expr_type)
{
uint32_t i;
@@ -2005,12 +2045,12 @@ exp_repeat_push(struct lyxp_expr *exp, uint32_t tok_idx, uint32_t repeat_op_idx)
for (i = 0; exp->repeat[tok_idx][i]; ++i) {}
exp->repeat[tok_idx] = realloc(exp->repeat[tok_idx], (i + 2) * sizeof *exp->repeat[tok_idx]);
LY_CHECK_ERR_RET(!exp->repeat[tok_idx], LOGMEM(NULL), );
- exp->repeat[tok_idx][i] = repeat_op_idx;
+ exp->repeat[tok_idx][i] = repeat_expr_type;
exp->repeat[tok_idx][i + 1] = 0;
} else {
exp->repeat[tok_idx] = calloc(2, sizeof *exp->repeat[tok_idx]);
LY_CHECK_ERR_RET(!exp->repeat[tok_idx], LOGMEM(NULL), );
- exp->repeat[tok_idx][0] = repeat_op_idx;
+ exp->repeat[tok_idx][0] = repeat_expr_type;
}
}
@@ -2994,7 +3034,7 @@ lyxp_expr_parse(const struct ly_ctx *ctx, const char *expr_str, size_t expr_len,
parsed++;
ncname_len = parse_ncname(&expr_str[parsed]);
LY_CHECK_ERR_GOTO(ncname_len < 1, LOGVAL(ctx, LY_VCODE_XP_INEXPR, expr_str[parsed - ncname_len],
- parsed - ncname_len + 1, expr_str); ret = LY_EVALID, error);
+ (uint32_t)(parsed - ncname_len + 1), expr_str); ret = LY_EVALID, error);
tok_len = ncname_len;
LY_CHECK_ERR_GOTO(expr_str[parsed + tok_len] == ':',
LOGVAL(ctx, LYVE_XPATH, "Variable with prefix is not supported."); ret = LY_EVALID,
@@ -3084,7 +3124,7 @@ lyxp_expr_parse(const struct ly_ctx *ctx, const char *expr_str, size_t expr_len,
ret = LY_EVALID;
goto error;
} else {
- LOGVAL(ctx, LY_VCODE_XP_INEXPR, expr_str[parsed], parsed + 1, expr_str);
+ LOGVAL(ctx, LY_VCODE_XP_INEXPR, expr_str[parsed], (uint32_t)(parsed + 1), expr_str);
ret = LY_EVALID;
goto error;
}
@@ -3096,7 +3136,7 @@ lyxp_expr_parse(const struct ly_ctx *ctx, const char *expr_str, size_t expr_len,
} else {
ncname_len = parse_ncname(&expr_str[parsed]);
LY_CHECK_ERR_GOTO(ncname_len < 1, LOGVAL(ctx, LY_VCODE_XP_INEXPR, expr_str[parsed - ncname_len],
- parsed - ncname_len + 1, expr_str); ret = LY_EVALID, error);
+ (uint32_t)(parsed - ncname_len + 1), expr_str); ret = LY_EVALID, error);
}
tok_len = ncname_len;
@@ -3104,7 +3144,8 @@ lyxp_expr_parse(const struct ly_ctx *ctx, const char *expr_str, size_t expr_len,
if (!strncmp(&expr_str[parsed + tok_len], "::", 2)) {
/* axis */
LY_CHECK_ERR_GOTO(expr_parse_axis(&expr_str[parsed], ncname_len),
- LOGVAL(ctx, LY_VCODE_XP_INEXPR, expr_str[parsed], parsed + 1, expr_str); ret = LY_EVALID, error);
+ LOGVAL(ctx, LY_VCODE_XP_INEXPR, expr_str[parsed], (uint32_t)(parsed + 1), expr_str); ret = LY_EVALID,
+ error);
tok_type = LYXP_TOKEN_AXISNAME;
LY_CHECK_GOTO(ret = exp_add_token(ctx, expr, tok_type, parsed, tok_len), error);
@@ -3122,7 +3163,7 @@ lyxp_expr_parse(const struct ly_ctx *ctx, const char *expr_str, size_t expr_len,
} else {
ncname_len = parse_ncname(&expr_str[parsed]);
LY_CHECK_ERR_GOTO(ncname_len < 1, LOGVAL(ctx, LY_VCODE_XP_INEXPR, expr_str[parsed - ncname_len],
- parsed - ncname_len + 1, expr_str); ret = LY_EVALID, error);
+ (uint32_t)(parsed - ncname_len + 1), expr_str); ret = LY_EVALID, error);
}
tok_len = ncname_len;
@@ -3136,7 +3177,7 @@ lyxp_expr_parse(const struct ly_ctx *ctx, const char *expr_str, size_t expr_len,
} else {
ncname_len = parse_ncname(&expr_str[parsed + tok_len]);
LY_CHECK_ERR_GOTO(ncname_len < 1, LOGVAL(ctx, LY_VCODE_XP_INEXPR, expr_str[parsed - ncname_len],
- parsed - ncname_len + 1, expr_str); ret = LY_EVALID, error);
+ (uint32_t)(parsed - ncname_len + 1), expr_str); ret = LY_EVALID, error);
tok_len += ncname_len;
}
/* remove old flags to prevent ambiguities */
@@ -3934,10 +3975,10 @@ xpath_current(struct lyxp_set **args, uint32_t arg_count, struct lyxp_set *set,
set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_NODE);
if (set->cur_scnode) {
- LY_CHECK_RET(set_scnode_insert_node(set, set->cur_scnode, LYXP_NODE_ELEM, LYXP_AXIS_SELF, NULL));
+ LY_CHECK_RET(lyxp_set_scnode_insert_node(set, set->cur_scnode, LYXP_NODE_ELEM, LYXP_AXIS_SELF, NULL));
} else {
/* root node */
- LY_CHECK_RET(set_scnode_insert_node(set, NULL, set->root_type, LYXP_AXIS_SELF, NULL));
+ LY_CHECK_RET(lyxp_set_scnode_insert_node(set, NULL, set->root_type, LYXP_AXIS_SELF, NULL));
}
} else {
lyxp_set_free_content(set);
@@ -4003,7 +4044,7 @@ xpath_deref(struct lyxp_set **args, uint32_t UNUSED(arg_count), struct lyxp_set
target = p[LY_ARRAY_COUNT(p) - 1].node;
ly_path_free(set->ctx, p);
- LY_CHECK_RET(set_scnode_insert_node(set, target, LYXP_NODE_ELEM, LYXP_AXIS_SELF, NULL));
+ LY_CHECK_RET(lyxp_set_scnode_insert_node(set, target, LYXP_NODE_ELEM, LYXP_AXIS_SELF, NULL));
} /* else the target was found before but is disabled so it was removed */
}
@@ -4030,7 +4071,7 @@ xpath_deref(struct lyxp_set **args, uint32_t UNUSED(arg_count), struct lyxp_set
}
} else {
assert(sleaf->type->basetype == LY_TYPE_INST);
- if (ly_path_eval(leaf->value.target, set->tree, &node)) {
+ if (ly_path_eval(leaf->value.target, set->tree, NULL, &node)) {
LOGERR(set->ctx, LY_EVALID, "Invalid instance-identifier \"%s\" value - required instance not found.",
lyd_get_value(&leaf->node));
return LY_EVALID;
@@ -4274,9 +4315,25 @@ xpath_false(struct lyxp_set **UNUSED(args), uint32_t UNUSED(arg_count), struct l
* @return LY_ERR
*/
static LY_ERR
-xpath_floor(struct lyxp_set **args, uint32_t UNUSED(arg_count), struct lyxp_set *set, uint32_t UNUSED(options))
+xpath_floor(struct lyxp_set **args, uint32_t UNUSED(arg_count), struct lyxp_set *set, uint32_t options)
{
- LY_ERR rc;
+ struct lysc_node_leaf *sleaf;
+ LY_ERR rc = LY_SUCCESS;
+
+ if (options & LYXP_SCNODE_ALL) {
+ if (args[0]->type != LYXP_SET_SCNODE_SET) {
+ LOGWRN(set->ctx, "Argument #1 of %s not a node-set as expected.", __func__);
+ } else if ((sleaf = (struct lysc_node_leaf *)warn_get_scnode_in_ctx(args[0]))) {
+ if (!(sleaf->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
+ LOGWRN(set->ctx, "Argument #1 of %s is a %s node \"%s\".", __func__, lys_nodetype2str(sleaf->nodetype),
+ sleaf->name);
+ } else if (!warn_is_specific_type(sleaf->type, LY_TYPE_DEC64)) {
+ LOGWRN(set->ctx, "Argument #1 of %s is node \"%s\", not of type \"decimal64\".", __func__, sleaf->name);
+ }
+ }
+ set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_VAL);
+ return rc;
+ }
rc = lyxp_set_cast(args[0], LYXP_SET_NUMBER);
LY_CHECK_RET(rc);
@@ -4474,7 +4531,7 @@ xpath_local_name(struct lyxp_set **args, uint32_t arg_count, struct lyxp_set *se
set_fill_string(set, "", 0);
break;
case LYXP_NODE_ELEM:
- set_fill_string(set, item->node->schema->name, strlen(item->node->schema->name));
+ set_fill_string(set, LYD_NAME(item->node), strlen(LYD_NAME(item->node)));
break;
case LYXP_NODE_META:
set_fill_string(set, ((struct lyd_meta *)item->node)->name, strlen(((struct lyd_meta *)item->node)->name));
@@ -4498,7 +4555,7 @@ static LY_ERR
xpath_name(struct lyxp_set **args, uint32_t arg_count, struct lyxp_set *set, uint32_t options)
{
struct lyxp_set_node *item;
- struct lys_module *mod = NULL;
+ const struct lys_module *mod = NULL;
char *str;
const char *name = NULL;
@@ -4544,8 +4601,8 @@ xpath_name(struct lyxp_set **args, uint32_t arg_count, struct lyxp_set *set, uin
/* keep NULL */
break;
case LYXP_NODE_ELEM:
- mod = item->node->schema->module;
- name = item->node->schema->name;
+ mod = lyd_node_module(item->node);
+ name = LYD_NAME(item->node);
break;
case LYXP_NODE_META:
mod = ((struct lyd_meta *)item->node)->annotation->module;
@@ -4580,7 +4637,7 @@ static LY_ERR
xpath_namespace_uri(struct lyxp_set **args, uint32_t arg_count, struct lyxp_set *set, uint32_t options)
{
struct lyxp_set_node *item;
- struct lys_module *mod;
+ const struct lys_module *mod;
/* suppress unused variable warning */
(void)options;
@@ -4630,7 +4687,7 @@ xpath_namespace_uri(struct lyxp_set **args, uint32_t arg_count, struct lyxp_set
case LYXP_NODE_ELEM:
case LYXP_NODE_META:
if (item->type == LYXP_NODE_ELEM) {
- mod = item->node->schema->module;
+ mod = lyd_node_module(item->node);
} else { /* LYXP_NODE_META */
/* annotations */
mod = ((struct lyd_meta *)item->node)->annotation->module;
@@ -5541,7 +5598,7 @@ xpath_pi_text(struct lyxp_set *set, enum lyxp_axis axis, uint32_t options)
case LYXP_NODE_NONE:
LOGINT_RET(set->ctx);
case LYXP_NODE_ELEM:
- if (set->val.nodes[i].node->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
+ if (!set->val.nodes[i].node->schema || (set->val.nodes[i].node->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
set->val.nodes[i].type = LYXP_NODE_TEXT;
break;
}
@@ -5588,7 +5645,7 @@ moveto_resolve_model(const char **qname, uint32_t *qname_len, const struct lyxp_
/* check for errors and non-implemented modules, as they are not valid */
if (!mod || !mod->implemented) {
- LOGVAL(set->ctx, LY_VCODE_XP_INMOD, pref_len, *qname);
+ LOGVAL(set->ctx, LY_VCODE_XP_INMOD, (int)pref_len, *qname);
return LY_EVALID;
}
@@ -5641,10 +5698,9 @@ moveto_root(struct lyxp_set *set, uint32_t options)
if (options & LYXP_SCNODE_ALL) {
set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_NODE);
- LY_CHECK_RET(set_scnode_insert_node(set, NULL, set->root_type, LYXP_AXIS_SELF, NULL));
+ LY_CHECK_RET(lyxp_set_scnode_insert_node(set, NULL, set->root_type, LYXP_AXIS_SELF, NULL));
} else {
- set->type = LYXP_SET_NODE_SET;
- set->used = 0;
+ lyxp_set_free_content(set);
set_insert_node(set, NULL, 0, set->root_type, 0);
set->non_child_axis = 0;
}
@@ -5668,6 +5724,8 @@ static LY_ERR
moveto_node_check(const struct lyd_node *node, enum lyxp_node_type node_type, const struct lyxp_set *set,
const char *node_name, const struct lys_module *moveto_mod, uint32_t options)
{
+ const struct lysc_node *schema;
+
if ((node_type == LYXP_NODE_ROOT_CONFIG) || (node_type == LYXP_NODE_ROOT)) {
assert(node_type == set->root_type);
@@ -5681,39 +5739,40 @@ moveto_node_check(const struct lyd_node *node, enum lyxp_node_type node_type, co
return LY_ENOT;
}
- if (!node->schema) {
- /* opaque node never matches */
+ /* get schema node even of an opaque node */
+ schema = lyd_node_schema(node);
+ if (!schema) {
+ /* unknown opaque node never matches */
return LY_ENOT;
}
/* module check */
if (moveto_mod) {
- if ((set->ctx == LYD_CTX(node)) && (node->schema->module != moveto_mod)) {
+ if ((set->ctx == LYD_CTX(node)) && (schema->module != moveto_mod)) {
return LY_ENOT;
- } else if ((set->ctx != LYD_CTX(node)) && strcmp(node->schema->module->name, moveto_mod->name)) {
+ } else if ((set->ctx != LYD_CTX(node)) && strcmp(schema->module->name, moveto_mod->name)) {
return LY_ENOT;
}
}
/* context check */
- if ((set->root_type == LYXP_NODE_ROOT_CONFIG) && (node->schema->flags & LYS_CONFIG_R)) {
+ if ((set->root_type == LYXP_NODE_ROOT_CONFIG) && (schema->flags & LYS_CONFIG_R)) {
return LY_EINVAL;
- } else if (set->context_op && (node->schema->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)) &&
- (node->schema != set->context_op)) {
+ } else if (set->context_op && (schema->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)) && (schema != set->context_op)) {
return LY_EINVAL;
}
/* name check */
if (node_name) {
- if ((set->ctx == LYD_CTX(node)) && (node->schema->name != node_name)) {
+ if ((set->ctx == LYD_CTX(node)) && (schema->name != node_name)) {
return LY_ENOT;
- } else if ((set->ctx != LYD_CTX(node)) && strcmp(node->schema->name, node_name)) {
+ } else if ((set->ctx != LYD_CTX(node)) && strcmp(schema->name, node_name)) {
return LY_ENOT;
}
}
/* when check, accept the context node because it should only be the path ".", we have checked the when is valid before */
- if (!(options & LYXP_IGNORE_WHEN) && lysc_has_when(node->schema) && !(node->flags & LYD_WHEN_TRUE) &&
+ if (!(options & LYXP_IGNORE_WHEN) && lysc_has_when(schema) && !(node->flags & LYD_WHEN_TRUE) &&
(node != set->cur_node)) {
return LY_EINCOMPLETE;
}
@@ -6144,7 +6203,7 @@ moveto_node_hash_child(struct lyxp_set *set, const struct lysc_node *scnode, con
/* create specific data instance if needed */
if (scnode->nodetype == LYS_LIST) {
- LY_CHECK_GOTO(ret = lyd_create_list(scnode, predicates, &inst), cleanup);
+ LY_CHECK_GOTO(ret = lyd_create_list(scnode, predicates, NULL, &inst), cleanup);
} else if (scnode->nodetype == LYS_LEAFLIST) {
LY_CHECK_GOTO(ret = lyd_create_term2(scnode, &predicates[0].value, &inst), cleanup);
}
@@ -6168,6 +6227,10 @@ moveto_node_hash_child(struct lyxp_set *set, const struct lysc_node *scnode, con
} else {
r = lyd_find_sibling_val(siblings, scnode, NULL, 0, &sub);
}
+ if (r == LY_ENOTFOUND) {
+ /* may still be an opaque node */
+ r = lyd_find_sibling_opaq_next(siblings, scnode->name, &sub);
+ }
LY_CHECK_ERR_GOTO(r && (r != LY_ENOTFOUND), ret = r, cleanup);
/* when check */
@@ -6655,7 +6718,7 @@ moveto_scnode(struct lyxp_set *set, const struct lys_module *moveto_mod, const c
{
ly_bool temp_ctx = 0;
uint32_t getnext_opts, orig_used, i, mod_idx, idx;
- const struct lys_module *mod;
+ const struct lys_module *mod = NULL;
const struct lysc_node *iter;
enum lyxp_node_type iter_type;
@@ -6673,6 +6736,9 @@ moveto_scnode(struct lyxp_set *set, const struct lys_module *moveto_mod, const c
if (options & LYXP_SCNODE_OUTPUT) {
getnext_opts |= LYS_GETNEXT_OUTPUT;
}
+ if (options & LYXP_SCNODE_SCHEMAMOUNT) {
+ getnext_opts |= LYS_GETNEXT_WITHSCHEMAMOUNT;
+ }
orig_used = set->used;
for (i = 0; i < orig_used; ++i) {
@@ -6691,7 +6757,7 @@ moveto_scnode(struct lyxp_set *set, const struct lys_module *moveto_mod, const c
}
/* insert */
- LY_CHECK_RET(set_scnode_insert_node(set, iter, iter_type, axis, &idx));
+ LY_CHECK_RET(lyxp_set_scnode_insert_node(set, iter, iter_type, axis, &idx));
/* we need to prevent these nodes from being considered in this moveto */
if ((idx < orig_used) && (idx > i)) {
@@ -6704,7 +6770,7 @@ moveto_scnode(struct lyxp_set *set, const struct lys_module *moveto_mod, const c
(set->val.scnodes[i].type == LYXP_NODE_ELEM) && !ly_nested_ext_schema(NULL, set->val.scnodes[i].scnode,
moveto_mod->name, strlen(moveto_mod->name), LY_VALUE_JSON, NULL, ncname, strlen(ncname), &iter, NULL)) {
/* there is a matching node from an extension, use it */
- LY_CHECK_RET(set_scnode_insert_node(set, iter, LYXP_NODE_ELEM, axis, &idx));
+ LY_CHECK_RET(lyxp_set_scnode_insert_node(set, iter, LYXP_NODE_ELEM, axis, &idx));
if ((idx < orig_used) && (idx > i)) {
set->val.scnodes[idx].in_ctx = LYXP_SET_SCNODE_ATOM_NEW_CTX;
temp_ctx = 1;
@@ -6848,7 +6914,7 @@ moveto_scnode_dfs(struct lyxp_set *set, const struct lysc_node *start, uint32_t
goto skip_children;
}
} else {
- LY_CHECK_RET(set_scnode_insert_node(set, elem, LYXP_NODE_ELEM, LYXP_AXIS_DESCENDANT, NULL));
+ LY_CHECK_RET(lyxp_set_scnode_insert_node(set, elem, LYXP_NODE_ELEM, LYXP_AXIS_DESCENDANT, NULL));
}
} else if (rc == LY_EINVAL) {
goto skip_children;
@@ -7459,7 +7525,11 @@ only_parse:
*tok_idx = orig_exp;
rc = eval_expr_select(exp, tok_idx, 0, &set2, options);
- if (rc != LY_SUCCESS) {
+ if (!rc && set2.not_found) {
+ set->not_found = 1;
+ break;
+ }
+ if (rc) {
lyxp_set_free_content(&set2);
return rc;
}
@@ -7508,6 +7578,9 @@ only_parse:
*tok_idx = orig_exp;
rc = eval_expr_select(exp, tok_idx, 0, set, options);
+ if (!rc && set->not_found) {
+ break;
+ }
LY_CHECK_RET(rc);
set->val.scnodes[i].in_ctx = pred_in_ctx;
@@ -7527,7 +7600,7 @@ only_parse:
set_fill_set(&set2, set);
rc = eval_expr_select(exp, tok_idx, 0, &set2, options);
- if (rc != LY_SUCCESS) {
+ if (rc) {
lyxp_set_free_content(&set2);
return rc;
}
@@ -7702,14 +7775,13 @@ cleanup:
* @param[in] ctx_scnode Found schema node as the context for the predicate.
* @param[in] set Context set.
* @param[out] predicates Parsed predicates.
- * @param[out] pred_type Type of @p predicates.
* @return LY_SUCCESS on success,
* @return LY_ENOT if a predicate could not be compiled.
* @return LY_ERR on any error.
*/
static LY_ERR
eval_name_test_try_compile_predicates(const struct lyxp_expr *exp, uint32_t *tok_idx, const struct lysc_node *ctx_scnode,
- const struct lyxp_set *set, struct ly_path_predicate **predicates, enum ly_path_pred_type *pred_type)
+ const struct lyxp_set *set, struct ly_path_predicate **predicates)
{
LY_ERR rc = LY_SUCCESS;
uint32_t e_idx, val_start_idx, pred_idx = 0, temp_lo = 0, pred_len = 0, nested_pred;
@@ -7848,7 +7920,7 @@ eval_name_test_try_compile_predicates(const struct lyxp_expr *exp, uint32_t *tok
/* compile */
rc = ly_path_compile_predicate(set->ctx, set->cur_node ? set->cur_node->schema : NULL, set->cur_mod, ctx_scnode, exp2,
- &pred_idx, LY_VALUE_JSON, NULL, predicates, pred_type);
+ &pred_idx, LY_VALUE_JSON, NULL, predicates);
LY_CHECK_GOTO(rc, cleanup);
/* success, the predicate must include all the needed information for hash-based search */
@@ -7881,7 +7953,7 @@ eval_name_test_with_predicate_get_scnode(const struct ly_ctx *ctx, const struct
uint32_t name_len, const struct lys_module *moveto_mod, enum lyxp_node_type root_type, LY_VALUE_FORMAT format,
const struct lysc_node **found)
{
- const struct lysc_node *scnode;
+ const struct lysc_node *scnode, *scnode2;
const struct lys_module *mod;
uint32_t idx = 0;
@@ -7919,7 +7991,19 @@ continue_search:
}
/* search in children, do not repeat the same search */
- scnode = lys_find_child(node->schema, moveto_mod, name, name_len, 0, 0);
+ if (node->schema->nodetype & (LYS_RPC | LYS_ACTION)) {
+ /* make sure the node is unique, whether in input or output */
+ scnode = lys_find_child(node->schema, moveto_mod, name, name_len, 0, 0);
+ scnode2 = lys_find_child(node->schema, moveto_mod, name, name_len, 0, LYS_GETNEXT_OUTPUT);
+ if (scnode && scnode2) {
+ /* conflict, do not use hashes */
+ scnode = NULL;
+ } else if (scnode2) {
+ scnode = scnode2;
+ }
+ } else {
+ scnode = lys_find_child(node->schema, moveto_mod, name, name_len, 0, 0);
+ }
} /* else skip redundant search */
/* additional context check */
@@ -7977,14 +8061,14 @@ eval_name_test_scnode_no_match_msg(struct lyxp_set *set, const struct lyxp_set_s
if (ppath) {
format = "Schema node \"%.*s\" for parent \"%s\" not found; in expr \"%.*s\" with context node \"%s\".";
if (options & LYXP_SCNODE_ERROR) {
- LOGERR(set->ctx, LY_EVALID, format, ncname_len, ncname, ppath, (ncname - expr) + ncname_len, expr, path);
+ LOGERR(set->ctx, LY_ENOTFOUND, format, ncname_len, ncname, ppath, (ncname - expr) + ncname_len, expr, path);
} else {
LOGWRN(set->ctx, format, ncname_len, ncname, ppath, (ncname - expr) + ncname_len, expr, path);
}
} else {
format = "Schema node \"%.*s\" not found; in expr \"%.*s\" with context node \"%s\".";
if (options & LYXP_SCNODE_ERROR) {
- LOGERR(set->ctx, LY_EVALID, format, ncname_len, ncname, (ncname - expr) + ncname_len, expr, path);
+ LOGERR(set->ctx, LY_ENOTFOUND, format, ncname_len, ncname, (ncname - expr) + ncname_len, expr, path);
} else {
LOGWRN(set->ctx, format, ncname_len, ncname, (ncname - expr) + ncname_len, expr, path);
}
@@ -8018,7 +8102,6 @@ eval_name_test_with_predicate(const struct lyxp_expr *exp, uint32_t *tok_idx, en
const struct lys_module *moveto_mod = NULL;
const struct lysc_node *scnode = NULL;
struct ly_path_predicate *predicates = NULL;
- enum ly_path_pred_type pred_type = 0;
int scnode_skip_pred = 0;
LOGDBG(LY_LDGXPATH, "%-27s %s %s[%u]", __func__, (options & LYXP_SKIP_EXPR ? "skipped" : "parsed"),
@@ -8060,7 +8143,7 @@ eval_name_test_with_predicate(const struct lyxp_expr *exp, uint32_t *tok_idx, en
if (scnode && (scnode->nodetype & (LYS_LIST | LYS_LEAFLIST))) {
/* try to create the predicates */
- if (eval_name_test_try_compile_predicates(exp, tok_idx, scnode, set, &predicates, &pred_type)) {
+ if (eval_name_test_try_compile_predicates(exp, tok_idx, scnode, set, &predicates)) {
/* hashes cannot be used */
scnode = NULL;
}
@@ -8132,8 +8215,7 @@ moveto:
if (options & LYXP_SCNODE_ERROR) {
/* error */
- rc = LY_EVALID;
- goto cleanup;
+ set->not_found = 1;
}
/* skip the predicates and the rest of this path to not generate invalid warnings */
@@ -8175,10 +8257,8 @@ cleanup:
/* restore options */
options &= ~LYXP_SKIP_EXPR;
}
- if (!(options & LYXP_SKIP_EXPR)) {
- lydict_remove(set->ctx, ncname_dict);
- ly_path_predicates_free(set->ctx, pred_type, predicates);
- }
+ lydict_remove(set->ctx, ncname_dict);
+ ly_path_predicates_free(set->ctx, predicates);
return rc;
}
@@ -8350,8 +8430,9 @@ step:
rc = eval_name_test_with_predicate(exp, tok_idx, axis, all_desc, set, options);
if (rc == LY_ENOT) {
assert(options & LYXP_SCNODE_ALL);
- /* skip the rest of this path */
rc = LY_SUCCESS;
+
+ /* skip the rest of this path */
scnode_skip_path = 1;
options |= LYXP_SKIP_EXPR;
}
@@ -8600,8 +8681,9 @@ eval_function_call(const struct lyxp_expr *exp, uint32_t *tok_idx, struct lyxp_s
rc = eval_expr_select(exp, tok_idx, 0, args[0], options);
LY_CHECK_GOTO(rc, cleanup);
+ set->not_found = args[0]->not_found;
} else {
- rc = eval_expr_select(exp, tok_idx, 0, set, options | LYXP_SKIP_EXPR);
+ rc = eval_expr_select(exp, tok_idx, 0, set, options);
LY_CHECK_GOTO(rc, cleanup);
}
}
@@ -8623,8 +8705,11 @@ eval_function_call(const struct lyxp_expr *exp, uint32_t *tok_idx, struct lyxp_s
rc = eval_expr_select(exp, tok_idx, 0, args[arg_count - 1], options);
LY_CHECK_GOTO(rc, cleanup);
+ if (args[arg_count - 1]->not_found) {
+ set->not_found = 1;
+ }
} else {
- rc = eval_expr_select(exp, tok_idx, 0, set, options | LYXP_SKIP_EXPR);
+ rc = eval_expr_select(exp, tok_idx, 0, set, options);
LY_CHECK_GOTO(rc, cleanup);
}
}
@@ -8698,27 +8783,30 @@ eval_number(struct ly_ctx *ctx, const struct lyxp_expr *exp, uint32_t *tok_idx,
}
LY_ERR
-lyxp_vars_find(struct lyxp_var *vars, const char *name, size_t name_len, struct lyxp_var **var)
+lyxp_vars_find(const struct ly_ctx *ctx, const struct lyxp_var *vars, const char *name, size_t name_len,
+ struct lyxp_var **var)
{
- LY_ERR ret = LY_ENOTFOUND;
LY_ARRAY_COUNT_TYPE u;
- assert(vars && name);
+ assert(name);
- name_len = name_len ? name_len : strlen(name);
+ if (!name_len) {
+ name_len = strlen(name);
+ }
LY_ARRAY_FOR(vars, u) {
if (!strncmp(vars[u].name, name, name_len)) {
- ret = LY_SUCCESS;
- break;
+ if (var) {
+ *var = (struct lyxp_var *)&vars[u];
+ }
+ return LY_SUCCESS;
}
}
- if (var && !ret) {
- *var = &vars[u];
+ if (ctx) {
+ LOGERR(ctx, LY_ENOTFOUND, "Variable \"%.*s\" not defined.", (int)name_len, name);
}
-
- return ret;
+ return LY_ENOTFOUND;
}
/**
@@ -8737,17 +8825,14 @@ eval_variable_reference(const struct lyxp_expr *exp, uint32_t *tok_idx, struct l
LY_ERR ret;
const char *name;
struct lyxp_var *var;
- const struct lyxp_var *vars;
struct lyxp_expr *tokens = NULL;
uint32_t token_index, name_len;
- vars = set->vars;
-
/* find out the name and value of the variable */
name = &exp->expr[exp->tok_pos[*tok_idx]];
name_len = exp->tok_len[*tok_idx];
- ret = lyxp_vars_find((struct lyxp_var *)vars, name, name_len, &var);
- LY_CHECK_ERR_RET(ret, LOGERR(set->ctx, ret, "XPath variable \"%.*s\" not defined.", (int)name_len, name), ret);
+ ret = lyxp_vars_find(set->ctx, set->vars, name, name_len, &var);
+ LY_CHECK_RET(ret);
/* parse value */
ret = lyxp_expr_parse(set->ctx, var->value, 0, 1, &tokens);
@@ -8917,8 +9002,9 @@ static LY_ERR
eval_union_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t repeat, struct lyxp_set *set, uint32_t options)
{
LY_ERR rc = LY_SUCCESS;
- struct lyxp_set orig_set, set2;
uint32_t i;
+ struct lyxp_set orig_set, set2;
+ ly_bool found = 0;
assert(repeat);
@@ -8929,6 +9015,11 @@ eval_union_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t repeat,
rc = eval_expr_select(exp, tok_idx, LYXP_EXPR_UNION, set, options);
LY_CHECK_GOTO(rc, cleanup);
+ if (set->not_found) {
+ set->not_found = 0;
+ } else {
+ found = 1;
+ }
/* ('|' PathExpr)* */
for (i = 0; i < repeat; ++i) {
@@ -8946,6 +9037,9 @@ eval_union_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t repeat,
set_fill_set(&set2, &orig_set);
rc = eval_expr_select(exp, tok_idx, LYXP_EXPR_UNION, &set2, options);
LY_CHECK_GOTO(rc, cleanup);
+ if (!set2.not_found) {
+ found = 1;
+ }
/* eval */
if (options & LYXP_SCNODE_ALL) {
@@ -8959,6 +9053,9 @@ eval_union_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t repeat,
cleanup:
lyxp_set_free_content(&orig_set);
lyxp_set_free_content(&set2);
+ if (!found) {
+ set->not_found = 1;
+ }
return rc;
}
@@ -9026,7 +9123,7 @@ static LY_ERR
eval_multiplicative_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t repeat, struct lyxp_set *set,
uint32_t options)
{
- LY_ERR rc;
+ LY_ERR rc = LY_SUCCESS;
uint32_t i, this_op;
struct lyxp_set orig_set, set2;
@@ -9058,6 +9155,9 @@ eval_multiplicative_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_
set_fill_set(&set2, &orig_set);
rc = eval_expr_select(exp, tok_idx, LYXP_EXPR_MULTIPLICATIVE, &set2, options);
LY_CHECK_GOTO(rc, cleanup);
+ if (set2.not_found) {
+ set->not_found = 1;
+ }
/* eval */
if (options & LYXP_SCNODE_ALL) {
@@ -9093,7 +9193,7 @@ cleanup:
static LY_ERR
eval_additive_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t repeat, struct lyxp_set *set, uint32_t options)
{
- LY_ERR rc;
+ LY_ERR rc = LY_SUCCESS;
uint32_t i, this_op;
struct lyxp_set orig_set, set2;
@@ -9125,6 +9225,9 @@ eval_additive_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t repe
set_fill_set(&set2, &orig_set);
rc = eval_expr_select(exp, tok_idx, LYXP_EXPR_ADDITIVE, &set2, options);
LY_CHECK_GOTO(rc, cleanup);
+ if (set2.not_found) {
+ set->not_found = 1;
+ }
/* eval */
if (options & LYXP_SCNODE_ALL) {
@@ -9162,7 +9265,7 @@ cleanup:
static LY_ERR
eval_relational_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t repeat, struct lyxp_set *set, uint32_t options)
{
- LY_ERR rc;
+ LY_ERR rc = LY_SUCCESS;
uint32_t i, this_op;
struct lyxp_set orig_set, set2;
@@ -9194,6 +9297,9 @@ eval_relational_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t re
set_fill_set(&set2, &orig_set);
rc = eval_expr_select(exp, tok_idx, LYXP_EXPR_RELATIONAL, &set2, options);
LY_CHECK_GOTO(rc, cleanup);
+ if (set2.not_found) {
+ set->not_found = 1;
+ }
/* eval */
if (options & LYXP_SCNODE_ALL) {
@@ -9231,7 +9337,7 @@ cleanup:
static LY_ERR
eval_equality_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t repeat, struct lyxp_set *set, uint32_t options)
{
- LY_ERR rc;
+ LY_ERR rc = LY_SUCCESS;
uint32_t i, this_op;
struct lyxp_set orig_set, set2;
@@ -9263,6 +9369,9 @@ eval_equality_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t repe
set_fill_set(&set2, &orig_set);
rc = eval_expr_select(exp, tok_idx, LYXP_EXPR_EQUALITY, &set2, options);
LY_CHECK_GOTO(rc, cleanup);
+ if (set2.not_found) {
+ set->not_found = 1;
+ }
/* eval */
if (options & LYXP_SCNODE_ALL) {
@@ -9301,7 +9410,7 @@ cleanup:
static LY_ERR
eval_and_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t repeat, struct lyxp_set *set, uint32_t options)
{
- LY_ERR rc;
+ LY_ERR rc = LY_SUCCESS;
struct lyxp_set orig_set, set2;
uint32_t i;
@@ -9315,11 +9424,13 @@ eval_and_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t repeat, s
rc = eval_expr_select(exp, tok_idx, LYXP_EXPR_AND, set, options);
LY_CHECK_GOTO(rc, cleanup);
- /* cast to boolean, we know that will be the final result */
- if (!(options & LYXP_SKIP_EXPR) && (options & LYXP_SCNODE_ALL)) {
- set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_NODE);
- } else {
- lyxp_set_cast(set, LYXP_SET_BOOLEAN);
+ if (!(options & LYXP_SKIP_EXPR)) {
+ if (options & LYXP_SCNODE_ALL) {
+ set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_NODE);
+ } else {
+ /* cast to boolean, we know that will be the final result */
+ lyxp_set_cast(set, LYXP_SET_BOOLEAN);
+ }
}
/* ('and' EqualityExpr)* */
@@ -9339,6 +9450,9 @@ eval_and_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t repeat, s
set_fill_set(&set2, &orig_set);
rc = eval_expr_select(exp, tok_idx, LYXP_EXPR_AND, &set2, options);
LY_CHECK_GOTO(rc, cleanup);
+ if (set2.not_found) {
+ set->not_found = 1;
+ }
/* eval - just get boolean value actually */
if (set->type == LYXP_SET_SCNODE_SET) {
@@ -9371,7 +9485,7 @@ cleanup:
static LY_ERR
eval_or_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t repeat, struct lyxp_set *set, uint32_t options)
{
- LY_ERR rc;
+ LY_ERR rc = LY_SUCCESS;
struct lyxp_set orig_set, set2;
uint32_t i;
@@ -9385,11 +9499,13 @@ eval_or_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t repeat, st
rc = eval_expr_select(exp, tok_idx, LYXP_EXPR_OR, set, options);
LY_CHECK_GOTO(rc, cleanup);
- /* cast to boolean, we know that will be the final result */
- if (!(options & LYXP_SKIP_EXPR) && (options & LYXP_SCNODE_ALL)) {
- set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_NODE);
- } else {
- lyxp_set_cast(set, LYXP_SET_BOOLEAN);
+ if (!(options & LYXP_SKIP_EXPR)) {
+ if (options & LYXP_SCNODE_ALL) {
+ set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_NODE);
+ } else {
+ /* cast to boolean, we know that will be the final result */
+ lyxp_set_cast(set, LYXP_SET_BOOLEAN);
+ }
}
/* ('or' AndExpr)* */
@@ -9411,6 +9527,9 @@ eval_or_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t repeat, st
* but it does not matter */
rc = eval_expr_select(exp, tok_idx, LYXP_EXPR_OR, &set2, options);
LY_CHECK_GOTO(rc, cleanup);
+ if (set2.not_found) {
+ set->not_found = 1;
+ }
/* eval - just get boolean value actually */
if (set->type == LYXP_SET_SCNODE_SET) {
@@ -9523,7 +9642,7 @@ lyxp_get_root_type(const struct lyd_node *ctx_node, const struct lysc_node *ctx_
/* schema */
for (op = ctx_scnode; op && !(op->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)); op = op->parent) {}
- if (op || (options & LYXP_SCNODE)) {
+ if (op || !(options & LYXP_SCNODE_SCHEMA)) {
/* general root that can access everything */
return LYXP_NODE_ROOT;
} else if (!ctx_scnode || (ctx_scnode->flags & LYS_CONFIG_W)) {
@@ -9597,7 +9716,10 @@ lyxp_eval(const struct ly_ctx *ctx, const struct lyxp_expr *exp, const struct ly
/* evaluate */
rc = eval_expr_select(exp, &tok_idx, 0, set, options);
- if (rc != LY_SUCCESS) {
+ if (!rc && set->not_found) {
+ rc = LY_ENOTFOUND;
+ }
+ if (rc) {
lyxp_set_free_content(set);
}
@@ -9838,7 +9960,7 @@ lyxp_atomize(const struct ly_ctx *ctx, const struct lyxp_expr *exp, const struct
LY_VALUE_FORMAT format, void *prefix_data, const struct lysc_node *cur_scnode,
const struct lysc_node *ctx_scnode, struct lyxp_set *set, uint32_t options)
{
- LY_ERR ret;
+ LY_ERR rc;
uint32_t tok_idx = 0;
LY_CHECK_ARG_RET(ctx, ctx, exp, set, LY_EINVAL);
@@ -9851,7 +9973,7 @@ lyxp_atomize(const struct ly_ctx *ctx, const struct lyxp_expr *exp, const struct
memset(set, 0, sizeof *set);
set->type = LYXP_SET_SCNODE_SET;
set->root_type = lyxp_get_root_type(NULL, ctx_scnode, options);
- LY_CHECK_RET(set_scnode_insert_node(set, ctx_scnode, ctx_scnode ? LYXP_NODE_ELEM : set->root_type, LYXP_AXIS_SELF, NULL));
+ LY_CHECK_RET(lyxp_set_scnode_insert_node(set, ctx_scnode, ctx_scnode ? LYXP_NODE_ELEM : set->root_type, LYXP_AXIS_SELF, NULL));
set->val.scnodes[0].in_ctx = LYXP_SET_SCNODE_START;
set->ctx = (struct ly_ctx *)ctx;
@@ -9866,10 +9988,13 @@ lyxp_atomize(const struct ly_ctx *ctx, const struct lyxp_expr *exp, const struct
LOG_LOCSET(set->cur_scnode, NULL, NULL, NULL);
/* evaluate */
- ret = eval_expr_select(exp, &tok_idx, 0, set, options);
+ rc = eval_expr_select(exp, &tok_idx, 0, set, options);
+ if (!rc && set->not_found) {
+ rc = LY_ENOTFOUND;
+ }
LOG_LOCBACK(set->cur_scnode ? 1 : 0, 0, 0, 0);
- return ret;
+ return rc;
}
LIBYANG_API_DEF const char *