blob: 4b8527e75b48cf0af47abfec2c9108da1ec10334 [file] [log] [blame]
Radek Krejcid6b76452019-09-03 17:03:03 +02001/**
2 * @file plugins_exts_nacm.c
3 * @author Radek Krejci <rkrejci@cesnet.cz>
4 * @brief libyang extension plugin - Metadata (RFC 7952)
5 *
6 * Copyright (c) 2019 CESNET, z.s.p.o.
7 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
Radek Krejcid6b76452019-09-03 17:03:03 +020014
Radek Krejcid6b76452019-09-03 17:03:03 +020015#include "plugins_exts_metadata.h"
Radek Krejci5f9a3672021-03-05 21:35:22 +010016
Radek Krejci859a15a2021-03-05 20:56:59 +010017#include "tree_edit.h"
Michal Vasko69730152020-10-09 16:30:07 +020018#include "tree_schema.h"
Radek Krejcid6b76452019-09-03 17:03:03 +020019
20/**
21 * @brief Storage for ID used to check plugin API version compatibility.
22 * Ignored here in the internal plugin.
23LYEXT_VERSION_CHECK
24 */
25
Radek Krejci1b2eef82021-02-17 11:17:27 +010026/**
27 * @brief Representation of the compiled metadata substatements - simplify storage for the items available via
28 * ::lysc_ext_substmt.
29 */
30struct lyext_metadata {
31 struct lysc_type *type; /**< type of the metadata (mandatory) */
32 const char *units; /**< units of the leaf's type */
33 struct lysc_iffeature *iffeatures; /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
34 const char *dsc; /**< description */
35 const char *ref; /**< reference */
36 uint16_t flags; /**< [schema node flags](@ref snodeflags) - only LYS_STATUS_* values are allowed */
37};
Radek Krejci38d85362019-09-05 16:26:38 +020038
Radek Krejcid6b76452019-09-03 17:03:03 +020039/**
40 * @brief Compile annotation extension instances.
41 *
42 * Implementation of lyext_clb_compile callback set as lyext_plugin::compile.
43 */
44LY_ERR
45annotation_compile(struct lysc_ctx *cctx, const struct lysp_ext_instance *p_ext, struct lysc_ext_instance *c_ext)
46{
Radek Krejci859a15a2021-03-05 20:56:59 +010047 LY_ERR ret;
Radek Krejcid6b76452019-09-03 17:03:03 +020048 struct lyext_metadata *annotation;
49 struct lysc_module *mod_c;
Michal Vaskofd69e1d2020-07-03 11:57:17 +020050 LY_ARRAY_COUNT_TYPE u;
Radek Krejcid6b76452019-09-03 17:03:03 +020051
52 /* annotations can appear only at the top level of a YANG module or submodule */
Radek Krejciab430862021-03-02 20:13:40 +010053 if ((c_ext->parent_stmt != LY_STMT_MODULE) && (c_ext->parent_stmt != LY_STMT_SUBMODULE)) {
Radek Krejci5f9a3672021-03-05 21:35:22 +010054 lyext_log(c_ext, LY_LLERR, LY_EVALID, lysc_ctx_get_path(cctx),
55 "Extension %s is allowed only at the top level of a YANG module or submodule, but it is placed in \"%s\" statement.",
Radek Krejciab430862021-03-02 20:13:40 +010056 p_ext->name, ly_stmt2str(c_ext->parent_stmt));
Radek Krejcid6b76452019-09-03 17:03:03 +020057 return LY_EVALID;
58 }
Radek Krejci335332a2019-09-05 13:03:35 +020059 /* check mandatory argument */
60 if (!c_ext->argument) {
Radek Krejci5f9a3672021-03-05 21:35:22 +010061 lyext_log(c_ext, LY_LLERR, LY_EVALID, lysc_ctx_get_path(cctx),
62 "Extension %s is instantiated without mandatory argument representing metadata name.", p_ext->name);
Radek Krejci335332a2019-09-05 13:03:35 +020063 return LY_EVALID;
64 }
Radek Krejcid6b76452019-09-03 17:03:03 +020065
66 mod_c = (struct lysc_module *)c_ext->parent;
67
68 /* check for duplication */
69 LY_ARRAY_FOR(mod_c->exts, u) {
Michal Vasko69730152020-10-09 16:30:07 +020070 if ((&mod_c->exts[u] != c_ext) && (mod_c->exts[u].def == c_ext->def) && !strcmp(mod_c->exts[u].argument, c_ext->argument)) {
Radek Krejci335332a2019-09-05 13:03:35 +020071 /* duplication of the same annotation extension in a single module */
Radek Krejci5f9a3672021-03-05 21:35:22 +010072 lyext_log(c_ext, LY_LLERR, LY_EVALID, lysc_ctx_get_path(cctx), "Extension %s is instantiated multiple times.", p_ext->name);
Radek Krejcid6b76452019-09-03 17:03:03 +020073 return LY_EVALID;
74 }
75 }
76
77 /* compile annotation substatements */
78 c_ext->data = annotation = calloc(1, sizeof *annotation);
Radek Krejci1b2eef82021-02-17 11:17:27 +010079 if (!annotation) {
Radek Krejci859a15a2021-03-05 20:56:59 +010080 goto emem;
Radek Krejci1b2eef82021-02-17 11:17:27 +010081 }
Radek Krejci5f9a3672021-03-05 21:35:22 +010082 LY_ARRAY_CREATE_GOTO(lysc_ctx_get_ctx(cctx), c_ext->substmts, 6, ret, emem);
Radek Krejcid6b76452019-09-03 17:03:03 +020083
Radek Krejci1b2eef82021-02-17 11:17:27 +010084 LY_ARRAY_INCREMENT(c_ext->substmts);
85 c_ext->substmts[ANNOTATION_SUBSTMT_IFF].stmt = LY_STMT_IF_FEATURE;
86 c_ext->substmts[ANNOTATION_SUBSTMT_IFF].cardinality = LY_STMT_CARD_ANY;
87 c_ext->substmts[ANNOTATION_SUBSTMT_IFF].storage = &annotation->iffeatures;
88
89 LY_ARRAY_INCREMENT(c_ext->substmts);
90 c_ext->substmts[ANNOTATION_SUBSTMT_UNITS].stmt = LY_STMT_UNITS;
91 c_ext->substmts[ANNOTATION_SUBSTMT_UNITS].cardinality = LY_STMT_CARD_OPT;
92 c_ext->substmts[ANNOTATION_SUBSTMT_UNITS].storage = &annotation->units;
93
94 LY_ARRAY_INCREMENT(c_ext->substmts);
95 c_ext->substmts[ANNOTATION_SUBSTMT_STATUS].stmt = LY_STMT_STATUS;
96 c_ext->substmts[ANNOTATION_SUBSTMT_STATUS].cardinality = LY_STMT_CARD_OPT;
97 c_ext->substmts[ANNOTATION_SUBSTMT_STATUS].storage = &annotation->flags;
98
99 LY_ARRAY_INCREMENT(c_ext->substmts);
100 c_ext->substmts[ANNOTATION_SUBSTMT_TYPE].stmt = LY_STMT_TYPE;
101 c_ext->substmts[ANNOTATION_SUBSTMT_TYPE].cardinality = LY_STMT_CARD_MAND;
102 c_ext->substmts[ANNOTATION_SUBSTMT_TYPE].storage = &annotation->type;
103
104 LY_ARRAY_INCREMENT(c_ext->substmts);
105 c_ext->substmts[ANNOTATION_SUBSTMT_DSC].stmt = LY_STMT_DESCRIPTION;
106 c_ext->substmts[ANNOTATION_SUBSTMT_DSC].cardinality = LY_STMT_CARD_OPT;
107 c_ext->substmts[ANNOTATION_SUBSTMT_DSC].storage = &annotation->dsc;
108
109 LY_ARRAY_INCREMENT(c_ext->substmts);
110 c_ext->substmts[ANNOTATION_SUBSTMT_REF].stmt = LY_STMT_REFERENCE;
111 c_ext->substmts[ANNOTATION_SUBSTMT_REF].cardinality = LY_STMT_CARD_OPT;
112 c_ext->substmts[ANNOTATION_SUBSTMT_REF].storage = &annotation->ref;
113
Radek Krejci859a15a2021-03-05 20:56:59 +0100114 ret = lys_compile_extension_instance(cctx, p_ext, c_ext);
115 return ret;
Radek Krejcid6b76452019-09-03 17:03:03 +0200116
Radek Krejci859a15a2021-03-05 20:56:59 +0100117emem:
Radek Krejci5f9a3672021-03-05 21:35:22 +0100118 lyext_log(c_ext, LY_LLERR, LY_EMEM, lysc_ctx_get_path(cctx), "Memory allocation failed (%s()).", __func__);
Radek Krejci859a15a2021-03-05 20:56:59 +0100119 return LY_EMEM;
Radek Krejcid6b76452019-09-03 17:03:03 +0200120}
121
Radek Krejci38d85362019-09-05 16:26:38 +0200122/**
Radek Krejciadcf63d2021-02-09 10:21:18 +0100123 * @brief INFO printer
124 *
125 * Implementation of lyext_clb_schema_printer set as ::lyext_plugin::sprinter
126 */
127LY_ERR
Radek Krejcif8d7f9a2021-03-10 14:32:36 +0100128annotation_schema_printer(struct lyspr_ctx *ctx, struct lysc_ext_instance *ext, ly_bool *flag)
Radek Krejciadcf63d2021-02-09 10:21:18 +0100129{
130 lysc_print_extension_instance(ctx, ext, flag);
131
132 return LY_SUCCESS;
133}
134
135/**
Radek Krejci38d85362019-09-05 16:26:38 +0200136 * @brief Free annotation extension instances' data.
137 *
Radek Krejciadcf63d2021-02-09 10:21:18 +0100138 * Implementation of lyext_clb_free callback set as ::lyext_plugin::free.
Radek Krejci38d85362019-09-05 16:26:38 +0200139 */
140void
141annotation_free(struct ly_ctx *ctx, struct lysc_ext_instance *ext)
142{
Radek Krejci1b2eef82021-02-17 11:17:27 +0100143 if (!ext->substmts) {
Radek Krejciad5963b2019-09-06 16:03:05 +0200144 return;
145 }
146
Radek Krejci1b2eef82021-02-17 11:17:27 +0100147 lysc_extension_instance_substatements_free(ctx, ext->substmts);
Radek Krejci0f969882020-08-21 16:56:47 +0200148 free(ext->data);
Radek Krejci38d85362019-09-05 16:26:38 +0200149}
Radek Krejcid6b76452019-09-03 17:03:03 +0200150
151/**
152 * @brief Plugin for the Metadata's annotation extension
153 */
154struct lyext_plugin metadata_plugin = {
155 .id = "libyang 2 - metadata, version 1",
156 .compile = &annotation_compile,
157 .validate = NULL,
Radek Krejciadcf63d2021-02-09 10:21:18 +0100158 .sprinter = &annotation_schema_printer,
Radek Krejci38d85362019-09-05 16:26:38 +0200159 .free = annotation_free
Radek Krejcid6b76452019-09-03 17:03:03 +0200160};