xpath MAINTENANCE refactoring, no functionality changes
diff --git a/src/xpath.c b/src/xpath.c
index 16d1ddc..930b8b2 100644
--- a/src/xpath.c
+++ b/src/xpath.c
@@ -5196,43 +5196,61 @@
*/
/**
- * @brief Resolve and find a specific model. Does not log.
+ * @brief Skip prefix and return corresponding model if there is a prefix. Logs directly.
*
- * @param[in] prefix Prefix with various meaning dependning on @p format.
- * @param[in] len Prefix length.
- * @param[in] format Format determining the meaning of @p prefix (LYD_UNKNOWN refers to schema).
- * @param[in] ctx libyang context.
- * @param[in] local_mod Local module of the XPath expression.
- * @return Corresponding module or NULL on error.
+ * @param[in,out] qname Qualified node name. If includes prefix, it is skipped.
+ * @param[in,out] qname_len Length of @p qname, is updated accordingly.
+ * @param[in] set Set with XPath context.
+ * @param[out] moveto_mod Expected module of a matching node.
+ * @return LY_ERR
*/
-static struct lys_module *
-moveto_resolve_model(const char *prefix, uint16_t len, LYD_FORMAT format, struct ly_ctx *ctx, const struct lys_module *local_mod)
+static LY_ERR
+moveto_resolve_model(const char **qname, uint16_t *qname_len, struct lyxp_set *set, const struct lys_module **moveto_mod)
{
- struct lys_module *mod = NULL;
+ const struct lys_module *mod;
+ const char *ptr;
+ int pref_len;
char *str;
- switch (format) {
- case LYD_UNKNOWN:
- /* schema, search all local module imports */
- mod = lys_module_find_prefix(local_mod, prefix, len);
- break;
- case LYD_JSON:
- /* JSON data, search in context */
- str = strndup(prefix, len);
- mod = ly_ctx_get_module(ctx, str, NULL);
- free(str);
- break;
- default:
- LOGINT(ctx);
- return NULL;
- }
+ if ((ptr = ly_strnchr(*qname, ':', *qname_len))) {
+ /* specific module */
+ pref_len = ptr - *qname;
- if (!mod->implemented) {
- /* non-implemented module is not valid */
+ switch (set->format) {
+ case LYD_UNKNOWN:
+ /* schema, search all local module imports */
+ mod = lys_module_find_prefix(set->local_mod, *qname, pref_len);
+ break;
+ case LYD_JSON:
+ /* JSON data, search in context */
+ str = strndup(*qname, pref_len);
+ mod = ly_ctx_get_module(set->ctx, str, NULL);
+ free(str);
+ break;
+ default:
+ LOGINT_RET(set->ctx);
+ }
+
+ if (!mod->implemented) {
+ /* non-implemented module is not valid */
+ mod = NULL;
+ }
+ if (!mod) {
+ LOGVAL(set->ctx, LY_VLOG_LYD, set->ctx_node, LY_VCODE_XP_INMOD, pref_len, *qname);
+ return LY_EVALID;
+ }
+ *qname += pref_len + 1;
+ *qname_len -= pref_len + 1;
+ } else if (((*qname)[0] == '*') && (*qname_len == 1)) {
+ /* all modules - special case */
mod = NULL;
+ } else {
+ /* local module */
+ mod = set->local_mod;
}
- return mod;
+ *moveto_mod = mod;
+ return LY_SUCCESS;
}
/**
@@ -5339,7 +5357,8 @@
* @param[in] root_type XPath root node type.
* @param[in] node_name Node name to move to. Must be in the dictionary!
* @param[in] moveto_mod Expected module of the node.
- * @return LY_ERR (LY_EINCOMPLETE on unresolved when)
+ * @return LY_ERR (LY_ENOT if node does not match, LY_EINCOMPLETE on unresolved when,
+ * LY_EINVAL if netither node nor any children match)
*/
static LY_ERR
moveto_node_check(const struct lyd_node *node, enum lyxp_node_type root_type, const char *node_name,
@@ -5347,17 +5366,17 @@
{
/* module check */
if (moveto_mod && (node->schema->module != moveto_mod)) {
- return LY_EINVAL;
+ return LY_ENOT;
}
- /* context check */
- if ((root_type == LYXP_NODE_ROOT_CONFIG) && (node->schema->flags & LYS_CONFIG_R)) {
+ /* dummy and context check */
+ if ((node->flags & LYD_DUMMY) || ((root_type == LYXP_NODE_ROOT_CONFIG) && (node->schema->flags & LYS_CONFIG_R))) {
return LY_EINVAL;
}
/* name check */
if (strcmp(node_name, "*") && !strcmp(node->schema->name, node_name)) {
- return LY_EINVAL;
+ return LY_ENOT;
}
/* TODO when check */
@@ -5377,7 +5396,7 @@
* @param[in] node_name Node name to move to. Must be in the dictionary!
* @param[in] moveto_mod Expected module of the node.
* @param[in] options XPath options.
- * @return LY_ERR
+ * @return LY_ERR (LY_ENOT if node does not match, LY_EINVAL if neither node nor any children match)
*/
static LY_ERR
moveto_scnode_check(const struct lysc_node *node, enum lyxp_node_type root_type, const char *node_name,
@@ -5399,7 +5418,7 @@
/* module check */
if (strcmp(node_name, "*") && (node->module != moveto_mod)) {
- return LY_EINVAL;
+ return LY_ENOT;
}
/* context check */
@@ -5409,7 +5428,7 @@
/* name check */
if (strcmp(node_name, "*") && !strcmp(node->name, node_name)) {
- return LY_EINVAL;
+ return LY_ENOT;
}
/* match */
@@ -5430,8 +5449,8 @@
moveto_node(struct lyxp_set *set, const char *qname, uint16_t qname_len, int options)
{
uint32_t i;
- int replaced, pref_len;
- const char *ptr, *name_dict = NULL; /* optimization - so we can do (==) instead (!strncmp(...)) in moveto_node_check() */
+ int replaced;
+ const char *name_dict = NULL; /* optimization - so we can do (==) instead (!strncmp(...)) in moveto_node_check() */
const struct lys_module *moveto_mod;
const struct lyd_node *sub;
enum lyxp_node_type root_type;
@@ -5447,25 +5466,8 @@
}
moveto_get_root(set->ctx_node, options, &root_type);
-
- /* prefix */
- if ((ptr = ly_strnchr(qname, ':', qname_len))) {
- /* specific module */
- pref_len = ptr - qname;
- moveto_mod = moveto_resolve_model(qname, pref_len, set->format, set->ctx, set->local_mod);
- if (!moveto_mod) {
- LOGVAL(set->ctx, LY_VLOG_LYD, set->ctx_node, LY_VCODE_XP_INMOD, pref_len, qname);
- return LY_EVALID;
- }
- qname += pref_len + 1;
- qname_len -= pref_len + 1;
- } else if ((qname[0] == '*') && (qname_len == 1)) {
- /* all modules - special case */
- moveto_mod = NULL;
- } else {
- /* local module */
- moveto_mod = set->local_mod;
- }
+ rc = moveto_resolve_model(&qname, &qname_len, set, &moveto_mod);
+ LY_CHECK_RET(rc);
/* name */
name_dict = lydict_insert(set->ctx, qname, qname_len);
@@ -5558,12 +5560,13 @@
static LY_ERR
moveto_scnode(struct lyxp_set *set, const char *qname, uint16_t qname_len, int options)
{
- int i, orig_used, pref_len, idx, temp_ctx = 0;
+ int i, orig_used, idx, temp_ctx = 0;
uint32_t mod_idx;
- const char *ptr, *name_dict = NULL; /* optimization - so we can do (==) instead (!strncmp(...)) in moveto_node_check() */
+ const char *name_dict = NULL; /* optimization - so we can do (==) instead (!strncmp(...)) in moveto_node_check() */
const struct lys_module *moveto_mod;
const struct lysc_node *sub, *start_parent;
enum lyxp_node_type root_type;
+ LY_ERR rc;
if (!set || (set->type == LYXP_SET_EMPTY)) {
return LY_SUCCESS;
@@ -5575,24 +5578,8 @@
}
moveto_scnode_get_root(set->ctx_scnode, options, &root_type);
-
- /* prefix */
- if ((ptr = ly_strnchr(qname, ':', qname_len))) {
- pref_len = ptr - qname;
- moveto_mod = moveto_resolve_model(qname, pref_len, set->format, set->ctx, set->local_mod);
- if (!moveto_mod) {
- LOGVAL(set->ctx, LY_VLOG_LYS, set->ctx_scnode, LY_VCODE_XP_INMOD, pref_len, qname);
- return LY_EVALID;
- }
- qname += pref_len + 1;
- qname_len -= pref_len + 1;
- } else if ((qname[0] == '*') && (qname_len == 1)) {
- /* all modules - special case */
- moveto_mod = NULL;
- } else {
- /* local module */
- moveto_mod = set->local_mod;
- }
+ rc = moveto_resolve_model(&qname, &qname_len, set, &moveto_mod);
+ LY_CHECK_RET(rc);
/* name */
name_dict = lydict_insert(set->ctx, qname, qname_len);
@@ -5674,7 +5661,7 @@
moveto_node_alldesc(struct lyxp_set *set, const char *qname, uint16_t qname_len, int options)
{
uint32_t i;
- int pref_len, all = 0, match;
+ const char *name_dict = NULL; /* optimization - so we can do (==) instead (!strncmp(...)) in moveto_node_check() */
const struct lyd_node *next, *elem, *start;
const struct lys_module *moveto_mod;
enum lyxp_node_type root_type;
@@ -5691,71 +5678,36 @@
}
moveto_get_root(set->ctx_node, options, &root_type);
-
- /* prefix */
- if (ly_strnchr(qname, ':', qname_len)) {
- pref_len = ly_strnchr(qname, ':', qname_len) - qname;
- moveto_mod = moveto_resolve_model(qname, pref_len, set->format, set->ctx, set->local_mod);
- if (!moveto_mod) {
- LOGVAL(set->ctx, LY_VLOG_LYD, set->ctx_node, LY_VCODE_XP_INMOD, pref_len, qname);
- return LY_EVALID;
- }
- qname += pref_len + 1;
- qname_len -= pref_len + 1;
- } else {
- moveto_mod = NULL;
- }
+ rc = moveto_resolve_model(&qname, &qname_len, set, &moveto_mod);
+ LY_CHECK_RET(rc);
/* replace the original nodes (and throws away all text and attr nodes, root is replaced by a child) */
rc = moveto_node(set, "*", 1, options);
LY_CHECK_RET(rc);
- if ((qname_len == 1) && (qname[0] == '*')) {
- all = 1;
- }
+ /* name */
+ name_dict = lydict_insert(set->ctx, qname, qname_len);
- /* this loop traverses all the nodes in the set and addds/keeps only
- * those that match qname */
+ /* this loop traverses all the nodes in the set and adds/keeps only those that match qname */
set_init(&ret_set, set);
for (i = 0; i < set->used; ++i) {
/* TREE DFS */
start = set->val.nodes[i].node;
for (elem = next = start; elem; elem = next) {
-
- /* TODO when check */
- /*if (!LYD_WHEN_DONE(elem->when_status)) {
- return LY_EINCOMPLETE;
- }*/
-
- /* dummy and context check */
- if ((elem->flags & LYD_DUMMY) || ((root_type == LYXP_NODE_ROOT_CONFIG) && (elem->schema->flags & LYS_CONFIG_R))) {
- goto skip_children;
- }
-
- match = 1;
-
- /* module check */
- if (!all) {
- if (moveto_mod && (elem->schema->module != moveto_mod)) {
- match = 0;
- } else if (!moveto_mod && (elem->schema->module != set->ctx_node->schema->module)) {
- match = 0;
- }
- }
-
- /* name check */
- if (match && !all && (strncmp(elem->schema->name, qname, qname_len) || elem->schema->name[qname_len])) {
- match = 0;
- }
-
- if (match) {
+ rc = moveto_node_check(elem, root_type, name_dict, moveto_mod);
+ if (!rc) {
/* add matching node into result set */
set_insert_node(&ret_set, elem, 0, LYXP_NODE_ELEM, ret_set.used);
if (set_dup_node_check(set, elem, LYXP_NODE_ELEM, i)) {
/* the node is a duplicate, we'll process it later in the set */
goto skip_children;
}
+ } else if (rc == LY_EINCOMPLETE) {
+ lydict_remove(set->ctx, name_dict);
+ return rc;
+ } else if (rc == LY_EINVAL) {
+ goto skip_children;
}
/* TREE DFS NEXT ELEM */
@@ -5794,6 +5746,7 @@
set_free_content(set);
memcpy(set, &ret_set, sizeof *set);
+ lydict_remove(set->ctx, name_dict);
return LY_SUCCESS;
}
@@ -5810,10 +5763,11 @@
static LY_ERR
moveto_scnode_alldesc(struct lyxp_set *set, const char *qname, uint16_t qname_len, int options)
{
- int i, orig_used, pref_len, all = 0, match, idx;
+ int i, orig_used, idx;
const struct lysc_node *next, *elem, *start;
const struct lys_module *moveto_mod;
enum lyxp_node_type root_type;
+ LY_ERR rc;
if (!set || (set->type == LYXP_SET_EMPTY)) {
return LY_SUCCESS;
@@ -5825,24 +5779,8 @@
}
moveto_scnode_get_root(set->ctx_scnode, options, &root_type);
-
- /* prefix */
- if (ly_strnchr(qname, ':', qname_len)) {
- pref_len = ly_strnchr(qname, ':', qname_len) - qname;
- moveto_mod = moveto_resolve_model(qname, pref_len, set->format, set->ctx, set->local_mod);
- if (!moveto_mod) {
- LOGVAL(set->ctx, LY_VLOG_LYS, set->ctx_scnode, LY_VCODE_XP_INMOD, pref_len, qname);
- return LY_EVALID;
- }
- qname += pref_len + 1;
- qname_len -= pref_len + 1;
- } else {
- moveto_mod = NULL;
- }
-
- if ((qname_len == 1) && (qname[0] == '*')) {
- all = 1;
- }
+ rc = moveto_resolve_model(&qname, &qname_len, set, &moveto_mod);
+ LY_CHECK_RET(rc);
orig_used = set->used;
for (i = 0; i < orig_used; ++i) {
@@ -5854,44 +5792,13 @@
/* TREE DFS */
start = set->val.scnodes[i].scnode;
for (elem = next = start; elem; elem = next) {
-
- /* context/nodetype check */
- if ((root_type == LYXP_NODE_ROOT_CONFIG) && (elem->flags & LYS_CONFIG_R)) {
- /* valid node, but it is hidden in this context */
- goto skip_children;
- }
- switch (elem->nodetype) {
- case LYS_USES:
- case LYS_CHOICE:
- case LYS_CASE:
- /* schema-only nodes */
+ if ((elem == start) || (elem->nodetype & (LYS_CHOICE | LYS_CASE))) {
+ /* schema-only nodes, skip root */
goto next_iter;
- default:
- break;
}
- match = 1;
-
- /* skip root */
- if (elem == start) {
- match = 0;
- }
-
- /* module check */
- if (match && !all) {
- if (moveto_mod && (elem->module != moveto_mod)) {
- match = 0;
- } else if (!moveto_mod && (elem->module != set->ctx_scnode->module)) {
- match = 0;
- }
- }
-
- /* name check */
- if (match && !all && (strncmp(elem->name, qname, qname_len) || elem->name[qname_len])) {
- match = 0;
- }
-
- if (match) {
+ rc = moveto_scnode_check(elem, root_type, qname, moveto_mod, options);
+ if (!rc) {
if ((idx = set_scnode_dup_node_check(set, elem, LYXP_NODE_ELEM, i)) > -1) {
set->val.scnodes[idx].in_ctx = 1;
if (idx > i) {
@@ -5901,6 +5808,8 @@
} else {
set_scnode_insert_node(set, elem, LYXP_NODE_ELEM);
}
+ } else if (rc == LY_EINVAL) {
+ goto skip_children;
}
next_iter:
@@ -5951,9 +5860,10 @@
moveto_attr(struct lyxp_set *set, const char *qname, uint16_t qname_len, int UNUSED(options))
{
uint32_t i;
- int replaced, all = 0, pref_len;
- struct lys_module *moveto_mod;
+ int replaced, all = 0;
+ const struct lys_module *moveto_mod;
struct lyd_attr *sub;
+ LY_ERR rc;
if (!set || (set->type == LYXP_SET_EMPTY)) {
return LY_SUCCESS;
@@ -5964,19 +5874,8 @@
return LY_EVALID;
}
- /* prefix */
- if (ly_strnchr(qname, ':', qname_len)) {
- pref_len = ly_strnchr(qname, ':', qname_len) - qname;
- moveto_mod = moveto_resolve_model(qname, pref_len, set->format, set->ctx, set->local_mod);
- if (!moveto_mod) {
- LOGVAL(set->ctx, LY_VLOG_LYD, set->ctx_node, LY_VCODE_XP_INMOD, pref_len, qname);
- return LY_EVALID;
- }
- qname += pref_len + 1;
- qname_len -= pref_len + 1;
- } else {
- moveto_mod = NULL;
- }
+ rc = moveto_resolve_model(&qname, &qname_len, set, &moveto_mod);
+ LY_CHECK_RET(rc);
if ((qname_len == 1) && (qname[0] == '*')) {
all = 1;
@@ -6079,9 +5978,9 @@
moveto_attr_alldesc(struct lyxp_set *set, const char *qname, uint16_t qname_len, int options)
{
uint32_t i;
- int pref_len, replaced, all = 0;
+ int replaced, all = 0;
struct lyd_attr *sub;
- struct lys_module *moveto_mod;
+ const struct lys_module *moveto_mod;
struct lyxp_set *set_all_desc = NULL;
LY_ERR rc;
@@ -6094,19 +5993,8 @@
return LY_EVALID;
}
- /* prefix */
- if (ly_strnchr(qname, ':', qname_len)) {
- pref_len = ly_strnchr(qname, ':', qname_len) - qname;
- moveto_mod = moveto_resolve_model(qname, pref_len, set->format, set->ctx, set->local_mod);
- if (!moveto_mod) {
- LOGVAL(set->ctx, LY_VLOG_LYD, set->ctx_node, LY_VCODE_XP_INMOD, pref_len, qname);
- return LY_EVALID;
- }
- qname += pref_len + 1;
- qname_len -= pref_len + 1;
- } else {
- moveto_mod = NULL;
- }
+ rc = moveto_resolve_model(&qname, &qname_len, set, &moveto_mod);
+ LY_CHECK_RET(rc);
/* can be optimized similarly to moveto_node_alldesc() and save considerable amount of memory,
* but it likely won't be used much, so it's a waste of time */