schema compile OPTIMIZE nodeid dict-based comparison
diff --git a/src/plugins_types.c b/src/plugins_types.c
index 4fe5d8b..6b2fa39 100644
--- a/src/plugins_types.c
+++ b/src/plugins_types.c
@@ -46,27 +46,23 @@
ly_schema_resolve_prefix(const struct ly_ctx *UNUSED(ctx), const char *prefix, size_t prefix_len, const void *prefix_data)
{
const struct lysp_module *prefix_mod = prefix_data;
- struct lys_module *m = NULL;
LY_ARRAY_COUNT_TYPE u;
const char *local_prefix;
local_prefix = prefix_mod->is_submod ? ((struct lysp_submodule *)prefix_mod)->prefix : prefix_mod->mod->prefix;
if (!prefix_len || !ly_strncmp(local_prefix, prefix, prefix_len)) {
/* it is the prefix of the module itself */
- m = prefix_mod->mod;
+ return prefix_mod->mod;
}
/* search in imports */
- if (!m) {
- LY_ARRAY_FOR(prefix_mod->imports, u) {
- if (!ly_strncmp(prefix_mod->imports[u].prefix, prefix, prefix_len)) {
- m = prefix_mod->imports[u].module;
- break;
- }
+ LY_ARRAY_FOR(prefix_mod->imports, u) {
+ if (!ly_strncmp(prefix_mod->imports[u].prefix, prefix, prefix_len)) {
+ return prefix_mod->imports[u].module;
}
}
- return m;
+ return NULL;
}
/**
diff --git a/src/schema_compile.c b/src/schema_compile.c
index 1232228..69a7b2a 100644
--- a/src/schema_compile.c
+++ b/src/schema_compile.c
@@ -1548,9 +1548,9 @@
lysc_update_path(ctx, NULL, aug->ext->name);
}
lysc_update_path(ctx, NULL, "{augment}");
- lysc_update_path(ctx, NULL, aug->nodeid->expr);
+ lysc_update_path(ctx, NULL, aug->nodeid->str);
LOGVAL(ctx->ctx, LYVE_REFERENCE, "Augment%s target node \"%s\" from module \"%s\" was not found.",
- aug->ext ? " extension" : "", aug->nodeid->expr, LYSP_MODULE_NAME(aug->aug_pmod));
+ aug->ext ? " extension" : "", aug->nodeid->str, LYSP_MODULE_NAME(aug->aug_pmod));
ctx->cur_mod = orig_mod;
lysc_update_path(ctx, NULL, NULL);
lysc_update_path(ctx, NULL, NULL);
@@ -1567,9 +1567,9 @@
for (i = 0; i < ctx->devs.count; ++i) {
dev = ctx->devs.objs[i];
lysc_update_path(ctx, NULL, "{deviation}");
- lysc_update_path(ctx, NULL, dev->nodeid->expr);
+ lysc_update_path(ctx, NULL, dev->nodeid->str);
LOGVAL(ctx->ctx, LYVE_REFERENCE, "Deviation(s) target node \"%s\" from module \"%s\" was not found.",
- dev->nodeid->expr, LYSP_MODULE_NAME(dev->dev_pmods[0]));
+ dev->nodeid->str, LYSP_MODULE_NAME(dev->dev_pmods[0]));
lysc_update_path(ctx, NULL, NULL);
lysc_update_path(ctx, NULL, NULL);
}
diff --git a/src/schema_compile_amend.c b/src/schema_compile_amend.c
index 8b570f6..07b5f1b 100644
--- a/src/schema_compile_amend.c
+++ b/src/schema_compile_amend.c
@@ -38,74 +38,180 @@
#include "xpath.h"
/**
+ * @brief Free a nodeid structure.
+ *
+ * @param[in] ctx Context to use.
+ * @param[in] nodeid Nodeid to free.
+ */
+static void
+lysc_nodeid_free(const struct ly_ctx *ctx, struct lysc_nodeid *nodeid)
+{
+ uint32_t i;
+
+ if (!nodeid) {
+ return;
+ }
+
+ for (i = 0; i < nodeid->count; ++i) {
+ lydict_remove(ctx, nodeid->prefix[i]);
+ lydict_remove(ctx, nodeid->name[i]);
+ }
+ free(nodeid->prefix);
+ free(nodeid->name);
+ free(nodeid);
+}
+
+/**
+ * @brief Compile a schema-node-id into a temporary array of prefixes and node names.
+ *
+ * @param[in] ctx Context to use.
+ * @param[in] str Schema-node-id to compile.
+ * @param[out] nodeid Compiled nodeid.
+ * @return LY_ERR value.
+ */
+static LY_ERR
+lys_precompile_nodeid(const struct ly_ctx *ctx, const char *str, struct lysc_nodeid **nodeid)
+{
+ LY_ERR rc = LY_SUCCESS;
+ struct lyxp_expr *exp = NULL;
+ void *mem;
+ const char *ptr, *name;
+ size_t len;
+ uint32_t i;
+
+ *nodeid = NULL;
+
+ /* parse */
+ rc = lyxp_expr_parse(ctx, str, strlen(str), 0, &exp);
+ LY_CHECK_GOTO(rc, cleanup);
+
+ /* alloc */
+ *nodeid = calloc(1, sizeof **nodeid);
+ LY_CHECK_ERR_GOTO(!*nodeid, LOGMEM(ctx); rc = LY_EMEM, cleanup);
+
+ /* store the full schema-node-id */
+ (*nodeid)->str = str;
+
+ /* absolute vs. relative path */
+ i = 0;
+ if (exp->tokens[0] == LYXP_TOKEN_NAMETEST) {
+ goto relative_path;
+ }
+
+ while (i < exp->used) {
+ /* skip '/' */
+ assert(exp->tokens[i] == LYXP_TOKEN_OPER_PATH);
+ ++i;
+
+relative_path:
+ /* new node */
+ mem = realloc((*nodeid)->prefix, ((*nodeid)->count + 1) * sizeof *(*nodeid)->prefix);
+ LY_CHECK_ERR_GOTO(!mem, LOGMEM(ctx); rc = LY_EMEM, cleanup);
+ (*nodeid)->prefix = mem;
+ (*nodeid)->prefix[(*nodeid)->count] = NULL;
+
+ mem = realloc((*nodeid)->name, ((*nodeid)->count + 1) * sizeof *(*nodeid)->name);
+ LY_CHECK_ERR_GOTO(!mem, LOGMEM(ctx); rc = LY_EMEM, cleanup);
+ (*nodeid)->name = mem;
+ (*nodeid)->name[(*nodeid)->count] = NULL;
+
+ ++(*nodeid)->count;
+
+ /* compile the name test */
+ assert(exp->tokens[i] == LYXP_TOKEN_NAMETEST);
+ name = str + exp->tok_pos[i];
+ len = exp->tok_len[i];
+ ptr = ly_strnchr(name, ':', len);
+ if (ptr) {
+ /* store prefix */
+ rc = lydict_insert(ctx, name, ptr - name, &(*nodeid)->prefix[(*nodeid)->count - 1]);
+ LY_CHECK_GOTO(rc, cleanup);
+
+ /* move name */
+ len -= (ptr - name) + 1;
+ name = ptr + 1;
+ }
+
+ /* store name */
+ rc = lydict_insert(ctx, name, len, &(*nodeid)->name[(*nodeid)->count - 1]);
+ LY_CHECK_GOTO(rc, cleanup);
+
+ ++i;
+ }
+
+cleanup:
+ lyxp_expr_free(ctx, exp);
+ if (rc) {
+ lysc_nodeid_free(ctx, *nodeid);
+ *nodeid = NULL;
+ }
+ return rc;
+}
+
+/**
* @brief Get module of a single nodeid node name test.
*
* @param[in] ctx libyang context.
- * @param[in] nametest Nametest with an optional prefix.
- * @param[in] nametest_len Length of @p nametest.
- * @param[in] mod Both current and prefix module for resolving prefixes and to return in case of no prefix.
- * @param[out] name Optional pointer to the name test without the prefix.
- * @param[out] name_len Length of @p name.
+ * @param[in] prefix_dict Optional prefix of the node test, in the dictionary.
+ * @param[in] pmod Both current and prefix module for resolving prefixes and to return in case of no prefix.
* @return Resolved module.
*/
static const struct lys_module *
-lys_schema_node_get_module(const struct ly_ctx *ctx, const char *nametest, size_t nametest_len,
- const struct lysp_module *mod, const char **name, size_t *name_len)
+lys_schema_node_get_module(const struct ly_ctx *ctx, const char *prefix_dict, const struct lysp_module *pmod)
{
- const struct lys_module *target_mod;
- const char *ptr;
+ const char *local_prefix;
+ LY_ARRAY_COUNT_TYPE u;
- ptr = ly_strnchr(nametest, ':', nametest_len);
- if (ptr) {
- target_mod = ly_resolve_prefix(ctx, nametest, ptr - nametest, LY_VALUE_SCHEMA, (void *)mod);
- if (!target_mod) {
- LOGVAL(ctx, LYVE_REFERENCE,
- "Invalid absolute-schema-nodeid nametest \"%.*s\" - prefix \"%.*s\" not defined in module \"%s\".",
- (int)nametest_len, nametest, (int)(ptr - nametest), nametest, LYSP_MODULE_NAME(mod));
- return NULL;
- }
+ if (!prefix_dict) {
+ /* local module */
+ return pmod->mod;
+ }
- if (name) {
- *name = ptr + 1;
- *name_len = nametest_len - ((ptr - nametest) + 1);
- }
- } else {
- target_mod = mod->mod;
- if (name) {
- *name = nametest;
- *name_len = nametest_len;
+ local_prefix = pmod->is_submod ? ((struct lysp_submodule *)pmod)->prefix : pmod->mod->prefix;
+ if (local_prefix == prefix_dict) {
+ /* local module prefix */
+ return pmod->mod;
+ }
+
+ LY_ARRAY_FOR(pmod->imports, u) {
+ if (pmod->imports[u].prefix == prefix_dict) {
+ /* import module prefix */
+ return pmod->imports[u].module;
}
}
- return target_mod;
+ /* prefix module not found */
+ LOGVAL(ctx, LYVE_REFERENCE, "Invalid absolute-schema-nodeid nametest - prefix \"%s\" not defined in module \"%s\".",
+ prefix_dict, LYSP_MODULE_NAME(pmod));
+ return NULL;
}
/**
* @brief Check the syntax of a node-id and collect all the referenced modules.
*
* @param[in] ctx Compile context.
- * @param[in] nodeid Node-id to check.
- * @param[in] abs Whether @p nodeid is absolute.
+ * @param[in] str Node-id to check.
+ * @param[in] abs Whether @p str must be absolute or relative.
* @param[in,out] mod_set Set to add referenced modules into.
- * @param[out] expr Optional node-id parsed into an expression.
+ * @param[out] nodeid Optional compiled node-id.
* @param[out] target_mod Optional target module of the node-id.
* @return LY_ERR value.
*/
static LY_ERR
-lys_nodeid_mod_check(struct lysc_ctx *ctx, const char *nodeid, ly_bool abs, struct ly_set *mod_set,
- struct lyxp_expr **expr, struct lys_module **target_mod)
+lys_nodeid_mod_check(struct lysc_ctx *ctx, const char *str, ly_bool abs, struct ly_set *mod_set,
+ struct lysc_nodeid **nodeid, struct lys_module **target_mod)
{
LY_ERR ret = LY_SUCCESS;
struct lyxp_expr *e = NULL;
+ struct lysc_nodeid *ni = NULL;
struct lys_module *tmod = NULL, *mod;
const char *nodeid_type = abs ? "absolute-schema-nodeid" : "descendant-schema-nodeid";
uint32_t i;
/* parse */
- ret = lyxp_expr_parse(ctx->ctx, nodeid, strlen(nodeid), 0, &e);
+ ret = lyxp_expr_parse(ctx->ctx, str, strlen(str), 0, &e);
if (ret) {
- LOGVAL(ctx->ctx, LYVE_SYNTAX_YANG, "Invalid %s value \"%s\" - invalid syntax.",
- nodeid_type, nodeid);
+ LOGVAL(ctx->ctx, LYVE_SYNTAX_YANG, "Invalid %s value \"%s\" - invalid syntax.", nodeid_type, str);
ret = LY_EVALID;
goto cleanup;
}
@@ -117,7 +223,7 @@
/* descendant schema nodeid */
if (e->tokens[0] != LYXP_TOKEN_NAMETEST) {
LOGVAL(ctx->ctx, LYVE_REFERENCE, "Invalid %s value \"%s\" - name test expected instead of \"%.*s\".",
- nodeid_type, nodeid, e->tok_len[0], e->expr + e->tok_pos[0]);
+ nodeid_type, str, e->tok_len[0], e->expr + e->tok_pos[0]);
ret = LY_EVALID;
goto cleanup;
}
@@ -128,7 +234,7 @@
for ( ; i < e->used; i += 2) {
if (e->tokens[i] != LYXP_TOKEN_OPER_PATH) {
LOGVAL(ctx->ctx, LYVE_REFERENCE, "Invalid %s value \"%s\" - \"/\" expected instead of \"%.*s\".",
- nodeid_type, nodeid, e->tok_len[i], e->expr + e->tok_pos[i]);
+ nodeid_type, str, e->tok_len[i], e->expr + e->tok_pos[i]);
ret = LY_EVALID;
goto cleanup;
} else if (e->used == i + 1) {
@@ -138,12 +244,20 @@
goto cleanup;
} else if (e->tokens[i + 1] != LYXP_TOKEN_NAMETEST) {
LOGVAL(ctx->ctx, LYVE_REFERENCE, "Invalid %s value \"%s\" - name test expected instead of \"%.*s\".",
- nodeid_type, nodeid, e->tok_len[i + 1], e->expr + e->tok_pos[i + 1]);
+ nodeid_type, str, e->tok_len[i + 1], e->expr + e->tok_pos[i + 1]);
ret = LY_EVALID;
goto cleanup;
- } else if (abs) {
- mod = (struct lys_module *)lys_schema_node_get_module(ctx->ctx, e->expr + e->tok_pos[i + 1],
- e->tok_len[i + 1], ctx->pmod, NULL, NULL);
+ }
+ }
+
+ if (abs || nodeid) {
+ /* compile into nodeid, only if needed */
+ LY_CHECK_GOTO(ret = lys_precompile_nodeid(ctx->ctx, str, &ni), cleanup);
+ }
+
+ if (abs) {
+ for (i = 0; i < ni->count; ++i) {
+ mod = (struct lys_module *)lys_schema_node_get_module(ctx->ctx, ni->prefix[i], ctx->pmod);
LY_CHECK_ERR_GOTO(!mod, ret = LY_EVALID, cleanup);
/* only keep the first module */
@@ -156,17 +270,17 @@
}
}
-cleanup:
- if (ret || !expr) {
- lyxp_expr_free(ctx->ctx, e);
- e = NULL;
- }
- if (expr) {
- *expr = ret ? NULL : e;
+ if (nodeid) {
+ *nodeid = ni;
+ ni = NULL;
}
if (target_mod) {
- *target_mod = ret ? NULL : tmod;
+ *target_mod = tmod;
}
+
+cleanup:
+ lyxp_expr_free(ctx->ctx, e);
+ lysc_nodeid_free(ctx->ctx, ni);
return ret;
}
@@ -174,46 +288,38 @@
* @brief Check whether 2 schema nodeids match.
*
* @param[in] ctx libyang context.
- * @param[in] exp1 First schema nodeid.
- * @param[in] exp1p_mod Module of @p exp1 nodes without any prefix.
- * @param[in] exp2 Second schema nodeid.
- * @param[in] exp2_pmod Module of @p exp2 nodes without any prefix.
+ * @param[in] nodeid1 First schema nodeid.
+ * @param[in] nodeid1_pmod Module of @p nodeid1 nodes without any prefix.
+ * @param[in] nodeid2 Second schema nodeid.
+ * @param[in] nodeid2_pmod Module of @p nodeid2 nodes without any prefix.
* @return Whether the schema nodeids match or not.
*/
static ly_bool
-lys_abs_schema_nodeid_match(const struct ly_ctx *ctx, const struct lyxp_expr *exp1, const struct lysp_module *exp1_pmod,
- const struct lyxp_expr *exp2, const struct lysp_module *exp2_pmod)
+lys_abs_schema_nodeid_match(const struct ly_ctx *ctx, const struct lysc_nodeid *nodeid1, const struct lysp_module *nodeid1_pmod,
+ const struct lysc_nodeid *nodeid2, const struct lysp_module *nodeid2_pmod)
{
uint32_t i;
const struct lys_module *mod1, *mod2;
- const char *name1 = NULL, *name2 = NULL;
- size_t name1_len = 0, name2_len = 0;
- if (exp1->used != exp2->used) {
+ if (nodeid1->count != nodeid2->count) {
return 0;
}
- for (i = 0; i < exp1->used; ++i) {
- assert(exp1->tokens[i] == exp2->tokens[i]);
+ for (i = 0; i < nodeid1->count; ++i) {
+ /* check modules of all the nodes in the node ID */
+ mod1 = lys_schema_node_get_module(ctx, nodeid1->prefix[i], nodeid1_pmod);
+ assert(mod1);
+ mod2 = lys_schema_node_get_module(ctx, nodeid2->prefix[i], nodeid2_pmod);
+ assert(mod2);
- if (exp1->tokens[i] == LYXP_TOKEN_NAMETEST) {
- /* check modules of all the nodes in the node ID */
- mod1 = lys_schema_node_get_module(ctx, exp1->expr + exp1->tok_pos[i], exp1->tok_len[i], exp1_pmod,
- &name1, &name1_len);
- assert(mod1);
- mod2 = lys_schema_node_get_module(ctx, exp2->expr + exp2->tok_pos[i], exp2->tok_len[i], exp2_pmod,
- &name2, &name2_len);
- assert(mod2);
+ /* compare modules */
+ if (mod1 != mod2) {
+ return 0;
+ }
- /* compare modules */
- if (mod1 != mod2) {
- return 0;
- }
-
- /* compare names */
- if ((name1_len != name2_len) || strncmp(name1, name2, name1_len)) {
- return 0;
- }
+ /* compare names, both in the dictionary */
+ if (nodeid1->name[i] != nodeid2->name[i]) {
+ return 0;
}
}
@@ -224,7 +330,7 @@
lys_precompile_uses_augments_refines(struct lysc_ctx *ctx, struct lysp_node_uses *uses_p, const struct lysc_node *ctx_node)
{
LY_ERR ret = LY_SUCCESS;
- struct lyxp_expr *exp = NULL;
+ struct lysc_nodeid *nodeid = NULL;
struct lysc_augment *aug;
struct lysp_node_augment *aug_p;
struct lysc_refine *rfn;
@@ -238,15 +344,15 @@
lysc_update_path(ctx, NULL, aug_p->nodeid);
/* parse the nodeid */
- LY_CHECK_GOTO(ret = lys_nodeid_mod_check(ctx, aug_p->nodeid, 0, &mod_set, &exp, NULL), cleanup);
+ LY_CHECK_GOTO(ret = lys_nodeid_mod_check(ctx, aug_p->nodeid, 0, &mod_set, &nodeid, NULL), cleanup);
/* allocate new compiled augment and store it in the set */
aug = calloc(1, sizeof *aug);
LY_CHECK_ERR_GOTO(!aug, LOGMEM(ctx->ctx); ret = LY_EMEM, cleanup);
LY_CHECK_GOTO(ret = ly_set_add(&ctx->uses_augs, aug, 1, NULL), cleanup);
- aug->nodeid = exp;
- exp = NULL;
+ aug->nodeid = nodeid;
+ nodeid = NULL;
aug->aug_pmod = ctx->pmod;
aug->nodeid_ctx_node = ctx_node;
aug->aug_p = aug_p;
@@ -260,12 +366,12 @@
lysc_update_path(ctx, NULL, uses_p->refines[u].nodeid);
/* parse the nodeid */
- LY_CHECK_GOTO(ret = lys_nodeid_mod_check(ctx, uses_p->refines[u].nodeid, 0, &mod_set, &exp, NULL), cleanup);
+ LY_CHECK_GOTO(ret = lys_nodeid_mod_check(ctx, uses_p->refines[u].nodeid, 0, &mod_set, &nodeid, NULL), cleanup);
/* try to find the node in already compiled refines */
rfn = NULL;
for (i = 0; i < ctx->uses_rfns.count; ++i) {
- if (lys_abs_schema_nodeid_match(ctx->ctx, exp, ctx->pmod, ((struct lysc_refine *)ctx->uses_rfns.objs[i])->nodeid,
+ if (lys_abs_schema_nodeid_match(ctx->ctx, nodeid, ctx->pmod, ((struct lysc_refine *)ctx->uses_rfns.objs[i])->nodeid,
ctx->pmod)) {
rfn = ctx->uses_rfns.objs[i];
break;
@@ -278,15 +384,15 @@
LY_CHECK_ERR_GOTO(!rfn, LOGMEM(ctx->ctx); ret = LY_EMEM, cleanup);
LY_CHECK_GOTO(ret = ly_set_add(&ctx->uses_rfns, rfn, 1, NULL), cleanup);
- rfn->nodeid = exp;
- exp = NULL;
+ rfn->nodeid = nodeid;
+ nodeid = NULL;
rfn->nodeid_pmod = ctx->cur_mod->parsed;
rfn->nodeid_ctx_node = ctx_node;
rfn->uses_p = uses_p;
} else {
- /* just free exp */
- lyxp_expr_free(ctx->ctx, exp);
- exp = NULL;
+ /* just free nodeid */
+ lysc_nodeid_free(ctx->ctx, nodeid);
+ nodeid = NULL;
}
/* add new parsed refine structure */
@@ -304,7 +410,7 @@
}
/* should include only this module, will fail later if not */
ly_set_erase(&mod_set, NULL);
- lyxp_expr_free(ctx->ctx, exp);
+ lysc_nodeid_free(ctx->ctx, nodeid);
return ret;
}
@@ -1515,13 +1621,11 @@
*
* @param[in,out] node Compiled node to consider. On a match it is moved to its parent.
* @param[in] mod Expected module.
- * @param[in] name Expected name.
- * @param[in] name_len Length of @p name.
+ * @param[in] name_dict Expected name, in the dictionary.
* @return Whether it is a match or not.
*/
static ly_bool
-lysp_schema_nodeid_match_node(const struct lysc_node **node, const struct lys_module *mod, const char *name,
- size_t name_len)
+lysp_schema_nodeid_match_node(const struct lysc_node **node, const struct lys_module *mod, const char *name_dict)
{
/* compare with the module of the node */
if ((*node)->module != mod) {
@@ -1529,7 +1633,7 @@
}
/* compare names */
- if (ly_strncmp((*node)->name, name, name_len)) {
+ if ((*node)->name != name_dict) {
return 0;
}
@@ -1544,13 +1648,11 @@
*
* @param[in,out] ext Compiled ext instance to consider. On a match it is zeroed to not match again.
* @param[in] mod Expected module.
- * @param[in] name Expected name.
- * @param[in] name_len Length of @p name.
+ * @param[in] name Expected name, in the dictionary.
* @return Whether it is a match or not.
*/
static ly_bool
-lysp_schema_nodeid_match_ext(const struct lysc_ext_instance **ext, const struct lys_module *mod, const char *name,
- size_t name_len)
+lysp_schema_nodeid_match_ext(const struct lysc_ext_instance **ext, const struct lys_module *mod, const char *name_dict)
{
/* compare with the module */
if ((*ext)->module != mod) {
@@ -1558,7 +1660,7 @@
}
/* compare names (argument) */
- if (ly_strncmp((*ext)->argument, name, name_len)) {
+ if ((*ext)->argument != name_dict) {
return 0;
}
@@ -1571,9 +1673,9 @@
/**
* @brief Check whether a node matches specific schema nodeid.
*
- * @param[in] exp Parsed nodeid to match.
- * @param[in] exp_pmod Module to use for nodes in @p exp without a prefix.
- * @param[in] exp_ext Extension instance in which @p exp is defined, it means it targets an extension instance.
+ * @param[in] nodeid Compiled nodeid to match.
+ * @param[in] nodeid_pmod Module to use for nodes in @p nodeid without a prefix.
+ * @param[in] nodeid_ext Extension instance in which @p nodeid is defined, it means it targets an extension instance.
* @param[in] ctx_node Initial context node that should match, only for descendant paths.
* @param[in] parent First compiled parent to consider. If @p pnode is NULL, it is condered the node to be matched.
* @param[in] pnode Parsed node to be matched. May be NULL if the target node was already compiled.
@@ -1582,46 +1684,43 @@
* @return Whether it is a match or not.
*/
static ly_bool
-lysp_schema_nodeid_match(const struct lyxp_expr *exp, const struct lysp_module *exp_pmod,
- const struct lysp_ext_instance *exp_ext, const struct lysc_node *ctx_node, const struct lysc_node *parent,
+lysp_schema_nodeid_match(const struct lysc_nodeid *nodeid, const struct lysp_module *nodeid_pmod,
+ const struct lysp_ext_instance *nodeid_ext, const struct lysc_node *ctx_node, const struct lysc_node *parent,
const struct lysp_node *pnode, const struct lys_module *pnode_mod, const struct lysc_ext_instance *pnode_ext)
{
uint32_t i;
const struct lys_module *mod;
- const char *name = NULL;
- size_t name_len = 0;
- if (exp_ext && !pnode_ext) {
+ if (nodeid_ext && !pnode_ext) {
/* extension instance augment and standard node, will never match */
return 0;
- } else if (!exp_ext && pnode_ext) {
+ } else if (!nodeid_ext && pnode_ext) {
/* standard augment and extension instance node, will never match */
return 0;
}
/* compare last node in the node ID */
- i = exp->used - 1;
+ i = nodeid->count - 1;
/* get exp node ID module */
- mod = lys_schema_node_get_module(exp_pmod->mod->ctx, exp->expr + exp->tok_pos[i], exp->tok_len[i], exp_pmod, &name, &name_len);
+ mod = lys_schema_node_get_module(nodeid_pmod->mod->ctx, nodeid->prefix[i], nodeid_pmod);
assert(mod);
if (pnode) {
/* compare on the last parsed-only node */
- if ((pnode_mod != mod) || ly_strncmp(pnode->name, name, name_len)) {
+ if ((pnode_mod != mod) || (pnode->name != nodeid->name[i])) {
return 0;
}
} else {
/* using parent directly */
- if (!lysp_schema_nodeid_match_node(&parent, mod, name, name_len)) {
+ if (!lysp_schema_nodeid_match_node(&parent, mod, nodeid->name[i])) {
return 0;
}
}
/* now compare all the compiled parents */
- while (i > 1) {
- i -= 2;
- assert(exp->tokens[i] == LYXP_TOKEN_NAMETEST);
+ while (i) {
+ --i;
if (!parent && !pnode_ext) {
/* no more parents but path continues */
@@ -1629,18 +1728,17 @@
}
/* get exp node ID module */
- mod = lys_schema_node_get_module(exp_pmod->mod->ctx, exp->expr + exp->tok_pos[i], exp->tok_len[i], exp_pmod, &name,
- &name_len);
+ mod = lys_schema_node_get_module(nodeid_pmod->mod->ctx, nodeid->prefix[i], nodeid_pmod);
assert(mod);
if (parent) {
/* compare with the parent */
- if (!lysp_schema_nodeid_match_node(&parent, mod, name, name_len)) {
+ if (!lysp_schema_nodeid_match_node(&parent, mod, nodeid->name[i])) {
return 0;
}
} else {
/* compare with the ext instance */
- if (!lysp_schema_nodeid_match_ext(&pnode_ext, mod, name, name_len)) {
+ if (!lysp_schema_nodeid_match_ext(&pnode_ext, mod, nodeid->name[i])) {
return 0;
}
}
@@ -1660,34 +1758,37 @@
void
lysc_augment_free(const struct ly_ctx *ctx, struct lysc_augment *aug)
{
- if (aug) {
- lyxp_expr_free(ctx, aug->nodeid);
-
- free(aug);
+ if (!aug) {
+ return;
}
+
+ lysc_nodeid_free(ctx, aug->nodeid);
+ free(aug);
}
void
lysc_deviation_free(const struct ly_ctx *ctx, struct lysc_deviation *dev)
{
- if (dev) {
- lyxp_expr_free(ctx, dev->nodeid);
- LY_ARRAY_FREE(dev->devs);
- LY_ARRAY_FREE(dev->dev_pmods);
-
- free(dev);
+ if (!dev) {
+ return;
}
+
+ lysc_nodeid_free(ctx, dev->nodeid);
+ LY_ARRAY_FREE(dev->devs);
+ LY_ARRAY_FREE(dev->dev_pmods);
+ free(dev);
}
void
lysc_refine_free(const struct ly_ctx *ctx, struct lysc_refine *rfn)
{
- if (rfn) {
- lyxp_expr_free(ctx, rfn->nodeid);
- LY_ARRAY_FREE(rfn->rfns);
-
- free(rfn);
+ if (!rfn) {
+ return;
}
+
+ lysc_nodeid_free(ctx, rfn->nodeid);
+ LY_ARRAY_FREE(rfn->rfns);
+ free(rfn);
}
void
@@ -2081,15 +2182,15 @@
const struct lysp_ext_instance *ext)
{
LY_ERR ret = LY_SUCCESS;
- struct lyxp_expr *exp = NULL;
+ struct lysc_nodeid *nodeid = NULL;
struct lysc_augment *aug;
const struct lys_module *mod;
- /* parse its target, it was already parsed and fully checked (except for the existence of the nodes) */
- ret = lyxp_expr_parse(ctx->ctx, aug_p->nodeid, strlen(aug_p->nodeid), 0, &exp);
+ /* compile its target, it was already parsed and fully checked (except for the existence of the nodes) */
+ ret = lys_precompile_nodeid(ctx->ctx, aug_p->nodeid, &nodeid);
LY_CHECK_GOTO(ret, cleanup);
- mod = lys_schema_node_get_module(ctx->ctx, exp->expr + exp->tok_pos[1], exp->tok_len[1], pmod, NULL, NULL);
+ mod = lys_schema_node_get_module(ctx->ctx, nodeid->prefix[0], pmod);
LY_CHECK_ERR_GOTO(!mod, LOGINT(ctx->ctx); ret = LY_EINT, cleanup);
if (mod != ctx->cur_mod) {
/* augment for another module, ignore */
@@ -2101,14 +2202,14 @@
LY_CHECK_ERR_GOTO(!aug, LOGMEM(ctx->ctx); ret = LY_EMEM, cleanup);
LY_CHECK_GOTO(ret = ly_set_add(&ctx->augs, aug, 1, NULL), cleanup);
- aug->nodeid = exp;
- exp = NULL;
+ aug->nodeid = nodeid;
+ nodeid = NULL;
aug->aug_pmod = pmod;
aug->ext = ext;
aug->aug_p = aug_p;
cleanup:
- lyxp_expr_free(ctx->ctx, exp);
+ lysc_nodeid_free(ctx->ctx, nodeid);
return ret;
}
@@ -2186,17 +2287,17 @@
{
LY_ERR ret = LY_SUCCESS;
struct lysc_deviation *dev = NULL;
- struct lyxp_expr *exp = NULL;
+ struct lysc_nodeid *nodeid = NULL;
struct lysp_deviation **new_dev;
const struct lys_module *mod;
const struct lysp_module **new_dev_pmod;
uint32_t i;
/* parse its target, it was already parsed and fully checked (except for the existence of the nodes) */
- ret = lyxp_expr_parse(ctx->ctx, dev_p->nodeid, strlen(dev_p->nodeid), 0, &exp);
+ ret = lys_precompile_nodeid(ctx->ctx, dev_p->nodeid, &nodeid);
LY_CHECK_GOTO(ret, cleanup);
- mod = lys_schema_node_get_module(ctx->ctx, exp->expr + exp->tok_pos[1], exp->tok_len[1], pmod, NULL, NULL);
+ mod = lys_schema_node_get_module(ctx->ctx, nodeid->prefix[0], pmod);
LY_CHECK_ERR_GOTO(!mod, LOGINT(ctx->ctx); ret = LY_EINT, cleanup);
if (mod != ctx->cur_mod) {
/* deviation for another module, ignore */
@@ -2205,7 +2306,7 @@
/* try to find the node in already compiled deviations */
for (i = 0; i < ctx->devs.count; ++i) {
- if (lys_abs_schema_nodeid_match(ctx->ctx, exp, pmod, ((struct lysc_deviation *)ctx->devs.objs[i])->nodeid,
+ if (lys_abs_schema_nodeid_match(ctx->ctx, nodeid, pmod, ((struct lysc_deviation *)ctx->devs.objs[i])->nodeid,
((struct lysc_deviation *)ctx->devs.objs[i])->dev_pmods[0])) {
dev = ctx->devs.objs[i];
break;
@@ -2218,8 +2319,8 @@
LY_CHECK_ERR_GOTO(!dev, LOGMEM(ctx->ctx); ret = LY_EMEM, cleanup);
LY_CHECK_GOTO(ret = ly_set_add(&ctx->devs, dev, 1, NULL), cleanup);
- dev->nodeid = exp;
- exp = NULL;
+ dev->nodeid = nodeid;
+ nodeid = NULL;
}
/* add new parsed deviation structure */
@@ -2229,7 +2330,7 @@
*new_dev_pmod = pmod;
cleanup:
- lyxp_expr_free(ctx->ctx, exp);
+ lysc_nodeid_free(ctx->ctx, nodeid);
return ret;
}
@@ -2281,9 +2382,9 @@
orig_cur_mod = ctx->cur_mod;
ctx->cur_mod = dev->dev_pmods[u]->mod;
lysc_update_path(ctx, NULL, "{deviation}");
- lysc_update_path(ctx, NULL, dev->nodeid->expr);
+ lysc_update_path(ctx, NULL, dev->nodeid->str);
LOGVAL(ctx->ctx, LYVE_SEMANTICS,
- "Multiple deviations of \"%s\" with one of them being \"not-supported\".", dev->nodeid->expr);
+ "Multiple deviations of \"%s\" with one of them being \"not-supported\".", dev->nodeid->str);
lysc_update_path(ctx, NULL, NULL);
lysc_update_path(ctx, NULL, NULL);
ctx->cur_mod = orig_cur_mod;
diff --git a/src/schema_compile_amend.h b/src/schema_compile_amend.h
index 344af65..6cd4c05 100644
--- a/src/schema_compile_amend.h
+++ b/src/schema_compile_amend.h
@@ -4,7 +4,7 @@
* @author Michal Vasko <mvasko@cesnet.cz>
* @brief Header for schema compilation of augments, deviations, and refines.
*
- * Copyright (c) 2015 - 2022 CESNET, z.s.p.o.
+ * Copyright (c) 2015 - 2024 CESNET, z.s.p.o.
*
* This source code is licensed under BSD 3-Clause License (the "License").
* You may not use this file except in compliance with the License.
@@ -28,10 +28,21 @@
struct lys_module;
/**
+ * @brief Compiled parsed schema-node-id.
+ */
+struct lysc_nodeid {
+ const char *str; /**< Original schema-node-id, just a pointer (do not free). */
+
+ const char **prefix; /**< Array of node prefixes in the dictionary, NULL if none. */
+ const char **name; /**< Array of node name in the dictionary. */
+ uint32_t count; /**< Number of items in @p prefix and @p name arrays */
+};
+
+/**
* @brief Compiled parsed augment structure. Just a temporary storage for applying the augment to data.
*/
struct lysc_augment {
- struct lyxp_expr *nodeid; /**< augment target */
+ struct lysc_nodeid *nodeid; /**< augment target */
const struct lysp_module *aug_pmod; /**< module where the augment is defined, for top-level augments
used to resolve prefixes, for uses augments used as the context pmod */
const struct lysc_node *nodeid_ctx_node; /**< nodeid context node for relative targets */
@@ -44,7 +55,7 @@
* @brief Compiled parsed deviation structure. Just a temporary storage for applying the deviation to data.
*/
struct lysc_deviation {
- struct lyxp_expr *nodeid; /**< deviation target, taken from the first deviation in
+ struct lysc_nodeid *nodeid; /**< deviation target, taken from the first deviation in
::lysc_deviation.dev_pmods array, this module is used for resolving
prefixes used in the nodeid. */
@@ -58,7 +69,7 @@
* @brief Compiled parsed refine structure. Just a temporary storage for applying the refine to data.
*/
struct lysc_refine {
- struct lyxp_expr *nodeid; /**< refine target */
+ struct lysc_nodeid *nodeid; /**< refine target */
const struct lysp_module *nodeid_pmod; /**< module where the nodeid is defined, used to resolve prefixes */
const struct lysc_node *nodeid_ctx_node; /**< nodeid context node */
struct lysp_node_uses *uses_p; /**< parsed uses node of the refine, for tracking recursive refines */
diff --git a/src/schema_compile_node.c b/src/schema_compile_node.c
index 2723716..a141286 100644
--- a/src/schema_compile_node.c
+++ b/src/schema_compile_node.c
@@ -4040,7 +4040,7 @@
}
LOGVAL(ctx->ctx, LYVE_REFERENCE, "Augment target node \"%s\" in grouping \"%s\" was not found.",
- ((struct lysc_augment *)ctx->uses_augs.objs[i])->nodeid->expr, grp->name);
+ ((struct lysc_augment *)ctx->uses_augs.objs[i])->nodeid->str, grp->name);
rc = LY_ENOTFOUND;
}
LY_CHECK_GOTO(rc, cleanup);
@@ -4053,7 +4053,7 @@
}
LOGVAL(ctx->ctx, LYVE_REFERENCE, "Refine(s) target node \"%s\" in grouping \"%s\" was not found.",
- ((struct lysc_refine *)ctx->uses_rfns.objs[i])->nodeid->expr, grp->name);
+ ((struct lysc_refine *)ctx->uses_rfns.objs[i])->nodeid->str, grp->name);
rc = LY_ENOTFOUND;
}
LY_CHECK_GOTO(rc, cleanup);