blob: 6edd60ca6fb7c6fc8bb297cb0bc786f0a1fe73e0 [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 Krejci883355a2021-03-11 11:54:41 +010017#include <stdint.h>
18#include <stdlib.h>
19#include <string.h>
20
21#include "libyang.h"
22#include "plugins_exts.h"
Radek Krejcid6b76452019-09-03 17:03:03 +020023
24/**
25 * @brief Storage for ID used to check plugin API version compatibility.
26 * Ignored here in the internal plugin.
27LYEXT_VERSION_CHECK
28 */
29
Radek Krejci1b2eef82021-02-17 11:17:27 +010030/**
31 * @brief Representation of the compiled metadata substatements - simplify storage for the items available via
32 * ::lysc_ext_substmt.
33 */
34struct lyext_metadata {
35 struct lysc_type *type; /**< type of the metadata (mandatory) */
36 const char *units; /**< units of the leaf's type */
37 struct lysc_iffeature *iffeatures; /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
38 const char *dsc; /**< description */
39 const char *ref; /**< reference */
40 uint16_t flags; /**< [schema node flags](@ref snodeflags) - only LYS_STATUS_* values are allowed */
41};
Radek Krejci38d85362019-09-05 16:26:38 +020042
Radek Krejcid6b76452019-09-03 17:03:03 +020043/**
44 * @brief Compile annotation extension instances.
45 *
46 * Implementation of lyext_clb_compile callback set as lyext_plugin::compile.
47 */
48LY_ERR
49annotation_compile(struct lysc_ctx *cctx, const struct lysp_ext_instance *p_ext, struct lysc_ext_instance *c_ext)
50{
Radek Krejci859a15a2021-03-05 20:56:59 +010051 LY_ERR ret;
Radek Krejcid6b76452019-09-03 17:03:03 +020052 struct lyext_metadata *annotation;
53 struct lysc_module *mod_c;
Michal Vaskofd69e1d2020-07-03 11:57:17 +020054 LY_ARRAY_COUNT_TYPE u;
Radek Krejcid6b76452019-09-03 17:03:03 +020055
56 /* annotations can appear only at the top level of a YANG module or submodule */
Radek Krejciab430862021-03-02 20:13:40 +010057 if ((c_ext->parent_stmt != LY_STMT_MODULE) && (c_ext->parent_stmt != LY_STMT_SUBMODULE)) {
Radek Krejci5f9a3672021-03-05 21:35:22 +010058 lyext_log(c_ext, LY_LLERR, LY_EVALID, lysc_ctx_get_path(cctx),
59 "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 +010060 p_ext->name, ly_stmt2str(c_ext->parent_stmt));
Radek Krejcid6b76452019-09-03 17:03:03 +020061 return LY_EVALID;
62 }
Radek Krejci335332a2019-09-05 13:03:35 +020063 /* check mandatory argument */
64 if (!c_ext->argument) {
Radek Krejci5f9a3672021-03-05 21:35:22 +010065 lyext_log(c_ext, LY_LLERR, LY_EVALID, lysc_ctx_get_path(cctx),
66 "Extension %s is instantiated without mandatory argument representing metadata name.", p_ext->name);
Radek Krejci335332a2019-09-05 13:03:35 +020067 return LY_EVALID;
68 }
Radek Krejcid6b76452019-09-03 17:03:03 +020069
70 mod_c = (struct lysc_module *)c_ext->parent;
71
72 /* check for duplication */
73 LY_ARRAY_FOR(mod_c->exts, u) {
Michal Vasko69730152020-10-09 16:30:07 +020074 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 +020075 /* duplication of the same annotation extension in a single module */
Radek Krejci5f9a3672021-03-05 21:35:22 +010076 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 +020077 return LY_EVALID;
78 }
79 }
80
81 /* compile annotation substatements */
82 c_ext->data = annotation = calloc(1, sizeof *annotation);
Radek Krejci1b2eef82021-02-17 11:17:27 +010083 if (!annotation) {
Radek Krejci859a15a2021-03-05 20:56:59 +010084 goto emem;
Radek Krejci1b2eef82021-02-17 11:17:27 +010085 }
Radek Krejci5f9a3672021-03-05 21:35:22 +010086 LY_ARRAY_CREATE_GOTO(lysc_ctx_get_ctx(cctx), c_ext->substmts, 6, ret, emem);
Radek Krejcid6b76452019-09-03 17:03:03 +020087
Radek Krejci1b2eef82021-02-17 11:17:27 +010088 LY_ARRAY_INCREMENT(c_ext->substmts);
89 c_ext->substmts[ANNOTATION_SUBSTMT_IFF].stmt = LY_STMT_IF_FEATURE;
90 c_ext->substmts[ANNOTATION_SUBSTMT_IFF].cardinality = LY_STMT_CARD_ANY;
91 c_ext->substmts[ANNOTATION_SUBSTMT_IFF].storage = &annotation->iffeatures;
92
93 LY_ARRAY_INCREMENT(c_ext->substmts);
94 c_ext->substmts[ANNOTATION_SUBSTMT_UNITS].stmt = LY_STMT_UNITS;
95 c_ext->substmts[ANNOTATION_SUBSTMT_UNITS].cardinality = LY_STMT_CARD_OPT;
96 c_ext->substmts[ANNOTATION_SUBSTMT_UNITS].storage = &annotation->units;
97
98 LY_ARRAY_INCREMENT(c_ext->substmts);
99 c_ext->substmts[ANNOTATION_SUBSTMT_STATUS].stmt = LY_STMT_STATUS;
100 c_ext->substmts[ANNOTATION_SUBSTMT_STATUS].cardinality = LY_STMT_CARD_OPT;
101 c_ext->substmts[ANNOTATION_SUBSTMT_STATUS].storage = &annotation->flags;
102
103 LY_ARRAY_INCREMENT(c_ext->substmts);
104 c_ext->substmts[ANNOTATION_SUBSTMT_TYPE].stmt = LY_STMT_TYPE;
105 c_ext->substmts[ANNOTATION_SUBSTMT_TYPE].cardinality = LY_STMT_CARD_MAND;
106 c_ext->substmts[ANNOTATION_SUBSTMT_TYPE].storage = &annotation->type;
107
108 LY_ARRAY_INCREMENT(c_ext->substmts);
109 c_ext->substmts[ANNOTATION_SUBSTMT_DSC].stmt = LY_STMT_DESCRIPTION;
110 c_ext->substmts[ANNOTATION_SUBSTMT_DSC].cardinality = LY_STMT_CARD_OPT;
111 c_ext->substmts[ANNOTATION_SUBSTMT_DSC].storage = &annotation->dsc;
112
113 LY_ARRAY_INCREMENT(c_ext->substmts);
114 c_ext->substmts[ANNOTATION_SUBSTMT_REF].stmt = LY_STMT_REFERENCE;
115 c_ext->substmts[ANNOTATION_SUBSTMT_REF].cardinality = LY_STMT_CARD_OPT;
116 c_ext->substmts[ANNOTATION_SUBSTMT_REF].storage = &annotation->ref;
117
Radek Krejci859a15a2021-03-05 20:56:59 +0100118 ret = lys_compile_extension_instance(cctx, p_ext, c_ext);
119 return ret;
Radek Krejcid6b76452019-09-03 17:03:03 +0200120
Radek Krejci859a15a2021-03-05 20:56:59 +0100121emem:
Radek Krejci5f9a3672021-03-05 21:35:22 +0100122 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 +0100123 return LY_EMEM;
Radek Krejcid6b76452019-09-03 17:03:03 +0200124}
125
Radek Krejci38d85362019-09-05 16:26:38 +0200126/**
Radek Krejciadcf63d2021-02-09 10:21:18 +0100127 * @brief INFO printer
128 *
129 * Implementation of lyext_clb_schema_printer set as ::lyext_plugin::sprinter
130 */
131LY_ERR
Radek Krejcif8d7f9a2021-03-10 14:32:36 +0100132annotation_schema_printer(struct lyspr_ctx *ctx, struct lysc_ext_instance *ext, ly_bool *flag)
Radek Krejciadcf63d2021-02-09 10:21:18 +0100133{
134 lysc_print_extension_instance(ctx, ext, flag);
135
136 return LY_SUCCESS;
137}
138
139/**
Radek Krejci38d85362019-09-05 16:26:38 +0200140 * @brief Free annotation extension instances' data.
141 *
Radek Krejciadcf63d2021-02-09 10:21:18 +0100142 * Implementation of lyext_clb_free callback set as ::lyext_plugin::free.
Radek Krejci38d85362019-09-05 16:26:38 +0200143 */
144void
145annotation_free(struct ly_ctx *ctx, struct lysc_ext_instance *ext)
146{
Radek Krejci1b2eef82021-02-17 11:17:27 +0100147 if (!ext->substmts) {
Radek Krejciad5963b2019-09-06 16:03:05 +0200148 return;
149 }
150
Radek Krejci1b2eef82021-02-17 11:17:27 +0100151 lysc_extension_instance_substatements_free(ctx, ext->substmts);
Radek Krejci0f969882020-08-21 16:56:47 +0200152 free(ext->data);
Radek Krejci38d85362019-09-05 16:26:38 +0200153}
Radek Krejcid6b76452019-09-03 17:03:03 +0200154
155/**
156 * @brief Plugin for the Metadata's annotation extension
157 */
158struct lyext_plugin metadata_plugin = {
159 .id = "libyang 2 - metadata, version 1",
160 .compile = &annotation_compile,
161 .validate = NULL,
Radek Krejciadcf63d2021-02-09 10:21:18 +0100162 .sprinter = &annotation_schema_printer,
Radek Krejci38d85362019-09-05 16:26:38 +0200163 .free = annotation_free
Radek Krejcid6b76452019-09-03 17:03:03 +0200164};