context FEATURE ly_ctx_get_submodule functions
diff --git a/doc/transition.dox b/doc/transition.dox
index e82aa00..44ec3f1 100644
--- a/doc/transition.dox
+++ b/doc/transition.dox
@@ -117,12 +117,12 @@
* ly_ctx_new_ylpath() | TBD | ^
* - | ::ly_ctx_unset_searchdir_last() | Extend the functionality of the ::ly_ctx_unset_searchdir() to make its use easier.
* ly_ctx_get_module_older() | - | Removed functionality.
- * ly_ctx_get_submodule() | - | Removed functionality since the submodules are only in the parsed tree.
- * ly_ctx_get_submodule2() | - | ^
* - | ::ly_ctx_get_module_implemented() | Supplement for ::ly_ctx_get_module()
* - | ::ly_ctx_get_module_latest() | ^
* - | ::ly_ctx_get_module_implemented_ns() | Supplement for ::ly_ctx_get_module_ns()
* - | ::ly_ctx_get_module_latest_ns() | ^
+ * - | ::ly_ctx_get_submodule_latest() | Supplement for ::ly_ctx_get_submodule()
+ * - | ::ly_ctx_get_submodule2_latest() | Supplement for ::ly_ctx_get_submodule2()
* ly_ctx_get_module_by_ns() | ::ly_ctx_get_module_ns () | Redesign the API - replace some of the parameters with standalone supplement functions.
* - | ::ly_ctx_reset_latests() | The new functionality of maintaining the latest module revision flag.
* ly_ctx_unset_searchdirs() | ::ly_ctx_unset_searchdir() | Simplify API and instead of index numbers, work with the values themselves.
diff --git a/src/common.h b/src/common.h
index 438c7f8..a7c483c 100644
--- a/src/common.h
+++ b/src/common.h
@@ -304,20 +304,6 @@
};
/**
- * @brief Try to find submodule in the context. Submodules are present only in the parsed (lysp_) schema trees, if only
- * the compiled versions of the schemas are present, the submodule cannot be returned even if it was used to compile
- * some of the currently present schemas.
- *
- * @param[in] ctx Context where to search in case @p module is NULL.
- * @param[in] module Submodule parent (belongs-to) module in case @p ctx is NULL.
- * @param[in] submodule Name of the submodule to find.
- * @param[in] revision Optional revision of the submodule to find. If not specified, the latest revision is returned.
- * @return Pointer to the specified submodule if it is present in the context.
- */
-struct lysp_submodule *ly_ctx_get_submodule(const struct ly_ctx *ctx, const struct lys_module *module,
- const char *submodule, const char *revision);
-
-/**
* @brief Get the (only) implemented YANG module specified by its name.
*
* @param[in] ctx Context where to search.
diff --git a/src/context.c b/src/context.c
index 88f2f00..46d9cbd 100644
--- a/src/context.c
+++ b/src/context.c
@@ -516,53 +516,98 @@
return ly_ctx_get_module_implemented_by(ctx, ns, 0, offsetof(struct lys_module, ns));
}
-struct lysp_submodule *
-ly_ctx_get_submodule(const struct ly_ctx *ctx, const struct lys_module *module, const char *submodule, const char *revision)
+/**
+ * @brief Try to find a submodule in a module.
+ *
+ * @param[in] module Module where to search in.
+ * @param[in] submodule Name of the submodule to find.
+ * @param[in] revision Revision of the submodule to find. NULL for submodule with no revision.
+ * @param[in] latest Ignore @p revision and look for the latest revision.
+ * @return Pointer to the specified submodule if it is present in the context.
+ */
+static const struct lysp_submodule *
+_ly_ctx_get_submodule2(const struct lys_module *module, const char *submodule, const char *revision, ly_bool latest)
{
- const struct lys_module *mod;
struct lysp_include *inc;
- uint32_t v;
LY_ARRAY_COUNT_TYPE u;
- assert((ctx || module) && submodule);
+ LY_CHECK_ARG_RET(NULL, module, module->parsed, submodule, NULL);
- if (module) {
- if (!module->parsed) {
- return NULL;
+ LY_ARRAY_FOR(module->parsed->includes, u) {
+ if (module->parsed->includes[u].submodule && !strcmp(submodule, module->parsed->includes[u].submodule->name)) {
+ inc = &module->parsed->includes[u];
+
+ if (latest && inc->submodule->latest_revision) {
+ /* latest revision */
+ return inc->submodule;
+ } else if (!revision && !inc->submodule->revs) {
+ /* no revision */
+ return inc->submodule;
+ } else if (revision && inc->submodule->revs && !strcmp(revision, inc->submodule->revs[0].date)) {
+ /* specific revision */
+ return inc->submodule;
+ }
}
-
- /* check only this module */
- mod = module;
- goto check_mod;
}
+ return NULL;
+}
+
+/**
+ * @brief Try to find a submodule in the context.
+ *
+ * @param[in] ctx Context where to search in.
+ * @param[in] submodule Name of the submodule to find.
+ * @param[in] revision Revision of the submodule to find. NULL for submodule with no revision.
+ * @param[in] latest Ignore @p revision and look for the latest revision.
+ * @return Pointer to the specified submodule if it is present in the context.
+ */
+static const struct lysp_submodule *
+_ly_ctx_get_submodule(const struct ly_ctx *ctx, const char *submodule, const char *revision, ly_bool latest)
+{
+ const struct lys_module *mod;
+ const struct lysp_submodule *submod = NULL;
+ uint32_t v;
+
+ LY_CHECK_ARG_RET(ctx, ctx, submodule, NULL);
+
for (v = 0; v < ctx->list.count; ++v) {
mod = ctx->list.objs[v];
if (!mod->parsed) {
continue;
}
-check_mod:
- LY_ARRAY_FOR(mod->parsed->includes, u) {
- if (mod->parsed->includes[u].submodule && !strcmp(submodule, mod->parsed->includes[u].submodule->name)) {
- inc = &mod->parsed->includes[u];
- if (!revision) {
- if (inc->submodule->latest_revision) {
- return inc->submodule;
- }
- } else if (inc->submodule->revs && !strcmp(revision, inc->submodule->revs[0].date)) {
- return inc->submodule;
- }
- }
- }
-
- if (module) {
- /* do not check other modules */
+ submod = _ly_ctx_get_submodule2(mod, submodule, revision, latest);
+ if (submod) {
break;
}
}
- return NULL;
+ return submod;
+}
+
+API const struct lysp_submodule *
+ly_ctx_get_submodule(const struct ly_ctx *ctx, const char *submodule, const char *revision)
+{
+ return _ly_ctx_get_submodule(ctx, submodule, revision, 0);
+}
+
+API const struct lysp_submodule *
+ly_ctx_get_submodule_latest(const struct ly_ctx *ctx, const char *submodule)
+{
+ return _ly_ctx_get_submodule(ctx, submodule, NULL, 1);
+}
+
+API const struct lysp_submodule *
+ly_ctx_get_submodule2(const struct lys_module *module, const char *submodule, const char *revision)
+{
+ return _ly_ctx_get_submodule2(module, submodule, revision, 0);
+}
+
+API const struct lysp_submodule *
+ly_ctx_get_submodule2_latest(const struct lys_module *module, const char *submodule)
+{
+ return _ly_ctx_get_submodule2(module, submodule, NULL, 1);
}
API void
diff --git a/src/context.h b/src/context.h
index 917fcef..ec55a29 100644
--- a/src/context.h
+++ b/src/context.h
@@ -117,6 +117,10 @@
* - ::ly_ctx_get_module_implemented_ns()
* - ::ly_ctx_get_module_latest()
* - ::ly_ctx_get_module_latest_ns()
+ * - ::ly_ctx_get_submodule()
+ * - ::ly_ctx_get_submodule_latest()
+ * - ::ly_ctx_get_submodule2()
+ * - ::ly_ctx_get_submodule2_latest()
* - ::ly_ctx_reset_latests()
*
* - ::ly_ctx_get_yanglib_data()
@@ -417,6 +421,47 @@
struct lys_module *ly_ctx_get_module_implemented_ns(const struct ly_ctx *ctx, const char *ns);
/**
+ * @brief Get a specific submodule from context. If its belongs-to module is known, use ::ly_ctx_get_submodule2().
+ *
+ * @param[in] ctx libyang context to search in.
+ * @param[in] submodule Submodule name to find.
+ * @param[in] revision Revision of the submodule to find, NULL for a submodule without a revision.
+ * @return Found submodule, NULL if there is none.
+ */
+const struct lysp_submodule *ly_ctx_get_submodule(const struct ly_ctx *ctx, const char *submodule, const char *revision);
+
+/**
+ * @brief Get the latests revision of a submodule from context. If its belongs-to module is known,
+ * use ::ly_ctx_get_submodule2_latest().
+ *
+ * @param[in] ctx libyang context to search in.
+ * @param[in] submodule Submodule name to find.
+ * @return Found submodule, NULL if there is none.
+ */
+const struct lysp_submodule *ly_ctx_get_submodule_latest(const struct ly_ctx *ctx, const char *submodule);
+
+/**
+ * @brief Get a specific submodule from a module. If the belongs-to module is not known, use ::ly_ctx_get_submodule().
+ *
+ * @param[in] module Belongs-to module to search in.
+ * @param[in] submodule Submodule name to find.
+ * @param[in] revision Revision of the submodule to find, NULL for a submodule without a revision.
+ * @return Found submodule, NULL if there is none.
+ */
+const struct lysp_submodule *ly_ctx_get_submodule2(const struct lys_module *module, const char *submodule,
+ const char *revision);
+
+/**
+ * @brief Get the latest revision of a submodule from a module. If the belongs-to module is not known,
+ * use ::ly_ctx_get_submodule_latest().
+ *
+ * @param[in] module Belongs-to module to search in.
+ * @param[in] submodule Submodule name to find.
+ * @return Found submodule, NULL if there is none.
+ */
+const struct lysp_submodule *ly_ctx_get_submodule2_latest(const struct lys_module *module, const char *submodule);
+
+/**
* @brief Reset cached latest revision information of the schemas in the context.
*
* When a (sub)module is imported/included without revision, the latest revision is
diff --git a/src/parser_yang.c b/src/parser_yang.c
index d92bc87..0e11bb0 100644
--- a/src/parser_yang.c
+++ b/src/parser_yang.c
@@ -4021,7 +4021,7 @@
size_t word_len;
enum ly_stmt kw, prev_kw = 0;
enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
- struct lysp_submodule *dup;
+ const struct lysp_submodule *dup;
mod->is_submod = 0;
@@ -4203,7 +4203,7 @@
/* submodules share the namespace with the module names, so there must not be
* a submodule of the same name in the context, no need for revision matching */
- dup = ly_ctx_get_submodule(PARSER_CTX(ctx), NULL, mod->mod->name, NULL);
+ dup = ly_ctx_get_submodule_latest(PARSER_CTX(ctx), mod->mod->name);
if (dup) {
LOGVAL_PARSER(ctx, LY_VCODE_NAME2_COL, "module", "submodule", mod->mod->name);
return LY_EVALID;
@@ -4228,7 +4228,7 @@
size_t word_len;
enum ly_stmt kw, prev_kw = 0;
enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
- struct lysp_submodule *dup;
+ const struct lysp_submodule *dup;
submod->is_submod = 1;
@@ -4407,7 +4407,7 @@
/* submodules share the namespace with the module names, so there must not be
* a submodule of the same name in the context, no need for revision matching */
- dup = ly_ctx_get_submodule(PARSER_CTX(ctx), NULL, submod->name, NULL);
+ dup = ly_ctx_get_submodule_latest(PARSER_CTX(ctx), submod->name);
/* main modules may have different revisions */
if (dup && strcmp(dup->mod->name, submod->mod->name)) {
LOGVAL_PARSER(ctx, LY_VCODE_NAME_COL, "submodules", dup->name);
diff --git a/src/parser_yin.c b/src/parser_yin.c
index 597fc6e..03a2203 100644
--- a/src/parser_yin.c
+++ b/src/parser_yin.c
@@ -3637,7 +3637,7 @@
{
LY_ERR ret = LY_SUCCESS;
struct yin_subelement *subelems = NULL;
- struct lysp_submodule *dup;
+ const struct lysp_submodule *dup;
size_t subelems_size;
mod->is_submod = 0;
@@ -3680,7 +3680,7 @@
/* submodules share the namespace with the module names, so there must not be
* a submodule of the same name in the context, no need for revision matching */
- dup = ly_ctx_get_submodule(ctx->xmlctx->ctx, NULL, mod->mod->name, NULL);
+ dup = ly_ctx_get_submodule_latest(ctx->xmlctx->ctx, mod->mod->name);
if (dup) {
LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_NAME2_COL, "module", "submodule", mod->mod->name);
return LY_EVALID;
@@ -3703,7 +3703,7 @@
{
LY_ERR ret = LY_SUCCESS;
struct yin_subelement *subelems = NULL;
- struct lysp_submodule *dup;
+ const struct lysp_submodule *dup;
size_t subelems_size;
submod->is_submod = 1;
@@ -3745,7 +3745,7 @@
/* submodules share the namespace with the module names, so there must not be
* a submodule of the same name in the context, no need for revision matching */
- dup = ly_ctx_get_submodule(ctx->xmlctx->ctx, NULL, submod->name, NULL);
+ dup = ly_ctx_get_submodule_latest(ctx->xmlctx->ctx, submod->name);
if (dup && strcmp(dup->mod->name, submod->mod->name)) {
LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_NAME_COL, "submodules", dup->name);
return LY_EVALID;
diff --git a/src/tree_schema.c b/src/tree_schema.c
index 831a055..d3bda7a 100644
--- a/src/tree_schema.c
+++ b/src/tree_schema.c
@@ -826,7 +826,7 @@
lysp_sort_revisions(submod->revs);
/* decide the latest revision */
- latest_sp = ly_ctx_get_submodule(NULL, submod->mod, submod->name, NULL);
+ latest_sp = (struct lysp_submodule *)ly_ctx_get_submodule2_latest(submod->mod, submod->name);
if (latest_sp) {
if (submod->revs) {
if (!latest_sp->revs) {