extension instances CHANGE access to the extension instance's substatements
Provide libyang a transparent access to the substatements of a specific
extension instances for various generic processing.
The patch introduces lysc_ext_substmt() to simplify work with the newly
added lysc_ext_instance.substmts sized array providing the extension
instance's substatements.
diff --git a/src/plugins_exts.h b/src/plugins_exts.h
index c2b9ba0..7491926 100644
--- a/src/plugins_exts.h
+++ b/src/plugins_exts.h
@@ -90,9 +90,12 @@
/**
* @brief Free the extension instance's data compiled with ::lys_compile_extension_instance().
- * TODO
+ *
+ * @param[in] libyang context
+ * @param[in] substmts The sized array of extension instance's substatements. The whole array is freed except the storage
+ * places which are expected to be covered by the extension plugin.
*/
-void lysc_extension_instance_free(struct ly_ctx *ctx, struct lysc_ext_substmt *substmts);
+void lysc_extension_instance_substatements_free(struct ly_ctx *ctx, struct lysc_ext_substmt *substmts);
/**
* @brief Duplicate the compiled extension (definition) structure.
@@ -105,6 +108,25 @@
struct lysc_ext *lysc_ext_dup(struct lysc_ext *orig);
/**
+ * @brief Get pointer to the storage of the specified substatement in the given extension instance.
+ *
+ * The function simplifies access into the ::lysc_ext_instance.substmts sized array.
+ *
+ * @param[in] ext Compiled extension instance to process.
+ * @param[in] substmt Extension substatement to search for.
+ * @param[out] instance_p Pointer where the storage of the @p substmt will be provided. The specific type returned depends
+ * on the @p substmt and can be found in the documentation of each ::ly_stmt value. Also note that some of the substatements
+ * (::lysc_node based or flags) can share the storage with other substatements. In case the pointer is NULL, still the return
+ * code can be used to at least know if the substatement is allowed for the extension.
+ * @param[out] cardinality_p Pointer to provide allowed cardinality of the substatements in the extension. Note that in some
+ * cases, the type of the storage depends also on the cardinality of the substatement.
+ * @return LY_SUCCESS if the @p substmt found.
+ * @return LY_ENOT in case the @p ext is not able to store (does not allow) the specified @p substmt.
+ */
+LY_ERR lysc_ext_substmt(const struct lysc_ext_instance *ext, enum ly_stmt substmt,
+ void **instance_p, enum ly_stmt_cardinality *cardinality_p);
+
+/**
* @brief Update path in the compile context, which is used for logging where the compilation failed.
*
* @param[in] ctx Compile context with the path.
diff --git a/src/plugins_exts_metadata.c b/src/plugins_exts_metadata.c
index c25e4e1..99df4f0 100644
--- a/src/plugins_exts_metadata.c
+++ b/src/plugins_exts_metadata.c
@@ -26,22 +26,18 @@
LYEXT_VERSION_CHECK
*/
-#define ANNOTATION_SUBSTMT_IFF 0
-#define ANNOTATION_SUBSTMT_UNITS 1
-#define ANNOTATION_SUBSTMT_STATUS 2
-#define ANNOTATION_SUBSTMT_TYPE 3
-#define ANNOTATION_SUBSTMT_DSC 4
-#define ANNOTATION_SUBSTMT_REF 5
-
-#define INIT_ANNOTATION_SUBSTMT { \
- {LY_STMT_IF_FEATURE, LY_STMT_CARD_ANY, NULL}, \
- {LY_STMT_UNITS, LY_STMT_CARD_OPT, NULL}, \
- {LY_STMT_STATUS, LY_STMT_CARD_OPT, NULL}, \
- {LY_STMT_TYPE, LY_STMT_CARD_MAND, NULL}, \
- {LY_STMT_DESCRIPTION, LY_STMT_CARD_OPT, NULL}, \
- {LY_STMT_REFERENCE, LY_STMT_CARD_OPT, NULL}, \
- {0, 0, 0} /* terminating item */ \
-} \
+/**
+ * @brief Representation of the compiled metadata substatements - simplify storage for the items available via
+ * ::lysc_ext_substmt.
+ */
+struct lyext_metadata {
+ struct lysc_type *type; /**< type of the metadata (mandatory) */
+ const char *units; /**< units of the leaf's type */
+ struct lysc_iffeature *iffeatures; /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
+ const char *dsc; /**< description */
+ const char *ref; /**< reference */
+ uint16_t flags; /**< [schema node flags](@ref snodeflags) - only LYS_STATUS_* values are allowed */
+};
/**
* @brief Compile annotation extension instances.
@@ -54,7 +50,6 @@
struct lyext_metadata *annotation;
struct lysc_module *mod_c;
LY_ARRAY_COUNT_TYPE u;
- struct lysc_ext_substmt annotation_substmt[] = INIT_ANNOTATION_SUBSTMT;
/* annotations can appear only at the top level of a YANG module or submodule */
if (c_ext->parent_type != LYEXT_PAR_MODULE) {
@@ -81,15 +76,46 @@
}
/* compile annotation substatements */
+ LY_ARRAY_CREATE_RET(cctx->ctx, c_ext->substmts, 6, LY_EMEM);
c_ext->data = annotation = calloc(1, sizeof *annotation);
- LY_CHECK_ERR_RET(!annotation, LOGMEM(cctx->ctx), LY_EMEM);
- annotation_substmt[ANNOTATION_SUBSTMT_IFF].storage = &annotation->iffeatures;
- annotation_substmt[ANNOTATION_SUBSTMT_UNITS].storage = &annotation->units;
- annotation_substmt[ANNOTATION_SUBSTMT_STATUS].storage = &annotation->flags;
- annotation_substmt[ANNOTATION_SUBSTMT_TYPE].storage = &annotation->type;
- /* description and reference are allowed, but not compiled */
+ if (!annotation) {
+ LOGMEM(cctx->ctx);
+ LY_ARRAY_FREE(c_ext->substmts);
+ c_ext->substmts = NULL;
+ return LY_EMEM;
+ }
- LY_CHECK_RET(lys_compile_extension_instance(cctx, p_ext, annotation_substmt));
+ LY_ARRAY_INCREMENT(c_ext->substmts);
+ c_ext->substmts[ANNOTATION_SUBSTMT_IFF].stmt = LY_STMT_IF_FEATURE;
+ c_ext->substmts[ANNOTATION_SUBSTMT_IFF].cardinality = LY_STMT_CARD_ANY;
+ c_ext->substmts[ANNOTATION_SUBSTMT_IFF].storage = &annotation->iffeatures;
+
+ LY_ARRAY_INCREMENT(c_ext->substmts);
+ c_ext->substmts[ANNOTATION_SUBSTMT_UNITS].stmt = LY_STMT_UNITS;
+ c_ext->substmts[ANNOTATION_SUBSTMT_UNITS].cardinality = LY_STMT_CARD_OPT;
+ c_ext->substmts[ANNOTATION_SUBSTMT_UNITS].storage = &annotation->units;
+
+ LY_ARRAY_INCREMENT(c_ext->substmts);
+ c_ext->substmts[ANNOTATION_SUBSTMT_STATUS].stmt = LY_STMT_STATUS;
+ c_ext->substmts[ANNOTATION_SUBSTMT_STATUS].cardinality = LY_STMT_CARD_OPT;
+ c_ext->substmts[ANNOTATION_SUBSTMT_STATUS].storage = &annotation->flags;
+
+ LY_ARRAY_INCREMENT(c_ext->substmts);
+ c_ext->substmts[ANNOTATION_SUBSTMT_TYPE].stmt = LY_STMT_TYPE;
+ c_ext->substmts[ANNOTATION_SUBSTMT_TYPE].cardinality = LY_STMT_CARD_MAND;
+ c_ext->substmts[ANNOTATION_SUBSTMT_TYPE].storage = &annotation->type;
+
+ LY_ARRAY_INCREMENT(c_ext->substmts);
+ c_ext->substmts[ANNOTATION_SUBSTMT_DSC].stmt = LY_STMT_DESCRIPTION;
+ c_ext->substmts[ANNOTATION_SUBSTMT_DSC].cardinality = LY_STMT_CARD_OPT;
+ c_ext->substmts[ANNOTATION_SUBSTMT_DSC].storage = &annotation->dsc;
+
+ LY_ARRAY_INCREMENT(c_ext->substmts);
+ c_ext->substmts[ANNOTATION_SUBSTMT_REF].stmt = LY_STMT_REFERENCE;
+ c_ext->substmts[ANNOTATION_SUBSTMT_REF].cardinality = LY_STMT_CARD_OPT;
+ c_ext->substmts[ANNOTATION_SUBSTMT_REF].storage = &annotation->ref;
+
+ LY_CHECK_RET(lys_compile_extension_instance(cctx, p_ext, c_ext->substmts));
return LY_SUCCESS;
}
@@ -102,20 +128,11 @@
void
annotation_free(struct ly_ctx *ctx, struct lysc_ext_instance *ext)
{
- struct lysc_ext_substmt annotation_substmt[] = INIT_ANNOTATION_SUBSTMT;
-
- if (!ext->data) {
+ if (!ext->substmts) {
return;
}
- struct lyext_metadata *annotation = (struct lyext_metadata *)ext->data;
-
- annotation_substmt[ANNOTATION_SUBSTMT_IFF].storage = &annotation->iffeatures;
- annotation_substmt[ANNOTATION_SUBSTMT_UNITS].storage = &annotation->units;
- annotation_substmt[ANNOTATION_SUBSTMT_STATUS].storage = &annotation->flags;
- annotation_substmt[ANNOTATION_SUBSTMT_TYPE].storage = &annotation->type;
-
- lysc_extension_instance_free(ctx, annotation_substmt);
+ lysc_extension_instance_substatements_free(ctx, ext->substmts);
free(ext->data);
}
diff --git a/src/plugins_exts_metadata.h b/src/plugins_exts_metadata.h
index 97bfae5..541891b 100644
--- a/src/plugins_exts_metadata.h
+++ b/src/plugins_exts_metadata.h
@@ -21,15 +21,12 @@
extern "C" {
#endif
-/**
- * @brief Representation of the compiled metadata substatements as provided by libyang 2 metadata extension plugin.
- */
-struct lyext_metadata {
- struct lysc_type *type; /**< type of the metadata (mandatory) */
- const char *units; /**< units of the leaf's type */
- struct lysc_iffeature *iffeatures; /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
- uint16_t flags; /**< [schema node flags](@ref snodeflags) - only LYS_STATUS_* values are allowed */
-};
+#define ANNOTATION_SUBSTMT_IFF 0 /**< index for the LY_STMT_IF_FEATURE substatement in annotation's ::lysc_ext_instance.substmts */
+#define ANNOTATION_SUBSTMT_UNITS 1 /**< index for the LY_STMT_UNITS substatement in annotation's ::lysc_ext_instance.substmts */
+#define ANNOTATION_SUBSTMT_STATUS 2 /**< index for the LY_STMT_STATUS substatement in annotation's ::lysc_ext_instance.substmts */
+#define ANNOTATION_SUBSTMT_TYPE 3 /**< index for the LY_STMT_TYPE substatement in annotation's ::lysc_ext_instance.substmts */
+#define ANNOTATION_SUBSTMT_DSC 4 /**< index for the LY_STMT_DSC substatement in annotation's ::lysc_ext_instance.substmts */
+#define ANNOTATION_SUBSTMT_REF 5 /**< index for the LY_STMT_REF substatement in annotation's ::lysc_ext_instance.substmts */
#ifdef __cplusplus
}
diff --git a/src/schema_compile.c b/src/schema_compile.c
index d0c2976..07133d7 100644
--- a/src/schema_compile.c
+++ b/src/schema_compile.c
@@ -205,6 +205,37 @@
return orig;
}
+LY_ERR
+lysc_ext_substmt(const struct lysc_ext_instance *ext, enum ly_stmt substmt, void **instance_p, enum ly_stmt_cardinality *cardinality_p)
+{
+ LY_ARRAY_COUNT_TYPE u;
+
+ LY_ARRAY_FOR(ext->substmts, u) {
+ if (LY_STMT_IS_NODE(substmt)) {
+ if (!LY_STMT_IS_NODE(ext->substmts[u].stmt)) {
+ continue;
+ }
+ } else if (LY_STMT_IS_OP(substmt)) {
+ if (!LY_STMT_IS_OP(ext->substmts[u].stmt)) {
+ continue;
+ }
+ } else if (ext->substmts[u].stmt != substmt) {
+ continue;
+ }
+
+ /* match */
+ if (cardinality_p) {
+ *cardinality_p = ext->substmts[u].cardinality;
+ }
+ if (instance_p) {
+ *instance_p = ext->substmts[u].storage;
+ }
+ return LY_SUCCESS;
+ }
+
+ return LY_ENOT;
+}
+
static void
lysc_unres_dflt_free(const struct ly_ctx *ctx, struct lysc_unres_dflt *r)
{
@@ -602,12 +633,12 @@
if (stmt->flags & (LYS_YIN_ATTR | LYS_YIN_ARGUMENT)) {
continue;
}
- for (u = 0; substmts[u].stmt; ++u) {
+ LY_ARRAY_FOR(substmts, u) {
if (substmts[u].stmt == stmt->kw) {
break;
}
}
- if (!substmts[u].stmt) {
+ if (u == LY_ARRAY_COUNT(substmts)) {
LOGVAL(ctx->ctx, LYVE_SYNTAX_YANG, "Invalid keyword \"%s\" as a child of \"%s%s%s\" extension instance.",
stmt->stmt, ext->name, ext->argument ? " " : "", ext->argument ? ext->argument : "");
goto cleanup;
@@ -618,7 +649,7 @@
/* keep order of the processing the same as the order in the defined substmts,
* the order is important for some of the statements depending on others (e.g. type needs status and units) */
- for (u = 0; substmts[u].stmt; ++u) {
+ LY_ARRAY_FOR(substmts, u) {
ly_bool stmt_present = 0;
for (stmt = ext->child; stmt; stmt = stmt->next) {
@@ -633,6 +664,8 @@
assert(substmts[u].cardinality < LY_STMT_CARD_SOME);
LY_CHECK_ERR_GOTO(r = lysp_stmt_parse(ctx, stmt, &substmts[u].storage, /* TODO */ NULL), ret = r, cleanup);
break;
+ case LY_STMT_DESCRIPTION:
+ case LY_STMT_REFERENCE:
case LY_STMT_UNITS: {
const char **units;
diff --git a/src/tree_data.c b/src/tree_data.c
index 16436fe..246b6c7 100644
--- a/src/tree_data.c
+++ b/src/tree_data.c
@@ -2412,8 +2412,8 @@
LY_CHECK_ERR_GOTO(!mt, LOGMEM(mod->ctx); ret = LY_EMEM, cleanup);
mt->parent = parent;
mt->annotation = ant;
- ret = lyd_value_store(mod->ctx, &mt->value, ((struct lyext_metadata *)ant->data)->type, value, value_len, dynamic,
- format, prefix_data, hints, parent ? parent->schema : NULL, incomplete);
+ ret = lyd_value_store(mod->ctx, &mt->value, *(const struct lysc_type **)ant->substmts[ANNOTATION_SUBSTMT_TYPE].storage,
+ value, value_len, dynamic, format, prefix_data, hints, parent ? parent->schema : NULL, incomplete);
LY_CHECK_ERR_GOTO(ret, free(mt), cleanup);
ret = lydict_insert(mod->ctx, name, name_len, &mt->name);
LY_CHECK_ERR_GOTO(ret, free(mt), cleanup);
diff --git a/src/tree_schema.h b/src/tree_schema.h
index 7e25fb7..546c587 100644
--- a/src/tree_schema.h
+++ b/src/tree_schema.h
@@ -1395,6 +1395,8 @@
LYEXT_SUBSTMT insubstmt; /**< value identifying placement of the extension instance */
LYEXT_PARENT parent_type; /**< type of the parent structure */
struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
+
+ struct lysc_ext_substmt *substmts; /**< list of allowed substatements with the storage to access the present substatements */
void *data; /**< private plugins's data, not used by libyang */
};
diff --git a/src/tree_schema_free.c b/src/tree_schema_free.c
index 071de57..8bcfb5a 100644
--- a/src/tree_schema_free.c
+++ b/src/tree_schema_free.c
@@ -987,9 +987,11 @@
}
API void
-lysc_extension_instance_free(struct ly_ctx *ctx, struct lysc_ext_substmt *substmts)
+lysc_extension_instance_substatements_free(struct ly_ctx *ctx, struct lysc_ext_substmt *substmts)
{
- for (LY_ARRAY_COUNT_TYPE u = 0; substmts[u].stmt; ++u) {
+ LY_ARRAY_COUNT_TYPE u;
+
+ LY_ARRAY_FOR(substmts, u) {
if (!substmts[u].storage) {
continue;
}
@@ -1012,6 +1014,8 @@
FREE_ARRAY(ctx, types, lysc_type2_free);
}
break;
+ case LY_STMT_DESCRIPTION:
+ case LY_STMT_REFERENCE:
case LY_STMT_UNITS:
if (substmts[u].cardinality < LY_STMT_CARD_SOME) {
/* single item */
@@ -1054,6 +1058,8 @@
LOGINT(ctx);
}
}
+
+ LY_ARRAY_FREE(substmts);
}
void
diff --git a/src/validation.c b/src/validation.c
index dcf37a9..e122049 100644
--- a/src/validation.c
+++ b/src/validation.c
@@ -27,6 +27,7 @@
#include "hash_table.h"
#include "log.h"
#include "parser_data.h"
+#include "plugins_exts.h"
#include "plugins_exts_metadata.h"
#include "plugins_types.h"
#include "set.h"
@@ -269,7 +270,7 @@
--i;
struct lyd_meta *meta = meta_types->objs[i];
- struct lysc_type *type = ((struct lyext_metadata *)meta->annotation->data)->type;
+ struct lysc_type *type = *(struct lysc_type **)meta->annotation->substmts[ANNOTATION_SUBSTMT_TYPE].storage;
/* validate and store the value of the metadata */
ret = lyd_value_validate_incomplete(LYD_CTX(meta->parent), type, &meta->value, meta->parent, *tree);
@@ -1322,7 +1323,7 @@
LYD_TREE_DFS_BEGIN(root, node) {
LY_LIST_FOR(node->meta, meta) {
- if (((struct lyext_metadata *)meta->annotation->data)->type->plugin->validate) {
+ if ((*(const struct lysc_type **)meta->annotation->substmts[ANNOTATION_SUBSTMT_TYPE].storage)->plugin->validate) {
/* metadata type resolution */
LY_CHECK_RET(ly_set_add(meta_types, (void *)meta, 1, NULL));
}