blob: 23130907cb55279b22bad22d1e7a4c9bdb5ae39e [file] [log] [blame]
Radek Krejcid6b76452019-09-03 17:03:03 +02001/**
aPiecek023f83a2021-05-11 07:37:03 +02002 * @file metadata.c
Radek Krejcid6b76452019-09-03 17:03:03 +02003 * @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 Krejcif1ca0ac2021-04-12 16:00:06 +020015#include "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/**
Radek Krejci1b2eef82021-02-17 11:17:27 +010025 * @brief Representation of the compiled metadata substatements - simplify storage for the items available via
26 * ::lysc_ext_substmt.
27 */
28struct lyext_metadata {
29 struct lysc_type *type; /**< type of the metadata (mandatory) */
30 const char *units; /**< units of the leaf's type */
31 struct lysc_iffeature *iffeatures; /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
32 const char *dsc; /**< description */
33 const char *ref; /**< reference */
34 uint16_t flags; /**< [schema node flags](@ref snodeflags) - only LYS_STATUS_* values are allowed */
35};
Radek Krejci38d85362019-09-05 16:26:38 +020036
Radek Krejcid6b76452019-09-03 17:03:03 +020037/**
38 * @brief Compile annotation extension instances.
39 *
Radek Krejci0b013302021-03-29 15:22:32 +020040 * Implementation of ::lyplg_ext_compile_clb callback set as lyext_plugin::compile.
Radek Krejcid6b76452019-09-03 17:03:03 +020041 */
Radek Krejci3e6632f2021-03-22 22:08:21 +010042static LY_ERR
Radek Krejcid6b76452019-09-03 17:03:03 +020043annotation_compile(struct lysc_ctx *cctx, const struct lysp_ext_instance *p_ext, struct lysc_ext_instance *c_ext)
44{
Radek Krejci859a15a2021-03-05 20:56:59 +010045 LY_ERR ret;
Radek Krejcid6b76452019-09-03 17:03:03 +020046 struct lyext_metadata *annotation;
47 struct lysc_module *mod_c;
Michal Vaskofd69e1d2020-07-03 11:57:17 +020048 LY_ARRAY_COUNT_TYPE u;
Radek Krejcid6b76452019-09-03 17:03:03 +020049
50 /* annotations can appear only at the top level of a YANG module or submodule */
Radek Krejciab430862021-03-02 20:13:40 +010051 if ((c_ext->parent_stmt != LY_STMT_MODULE) && (c_ext->parent_stmt != LY_STMT_SUBMODULE)) {
Radek Krejci0b013302021-03-29 15:22:32 +020052 lyplg_ext_log(c_ext, LY_LLERR, LY_EVALID, lysc_ctx_get_path(cctx),
Radek Krejci5f9a3672021-03-05 21:35:22 +010053 "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 +010054 p_ext->name, ly_stmt2str(c_ext->parent_stmt));
Radek Krejcid6b76452019-09-03 17:03:03 +020055 return LY_EVALID;
56 }
Radek Krejci335332a2019-09-05 13:03:35 +020057 /* check mandatory argument */
58 if (!c_ext->argument) {
Radek Krejci0b013302021-03-29 15:22:32 +020059 lyplg_ext_log(c_ext, LY_LLERR, LY_EVALID, lysc_ctx_get_path(cctx),
Radek Krejci5f9a3672021-03-05 21:35:22 +010060 "Extension %s is instantiated without mandatory argument representing metadata name.", p_ext->name);
Radek Krejci335332a2019-09-05 13:03:35 +020061 return LY_EVALID;
62 }
Radek Krejcid6b76452019-09-03 17:03:03 +020063
64 mod_c = (struct lysc_module *)c_ext->parent;
65
66 /* check for duplication */
67 LY_ARRAY_FOR(mod_c->exts, u) {
Michal Vasko69730152020-10-09 16:30:07 +020068 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 +020069 /* duplication of the same annotation extension in a single module */
Radek Krejci0b013302021-03-29 15:22:32 +020070 lyplg_ext_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 +020071 return LY_EVALID;
72 }
73 }
74
75 /* compile annotation substatements */
76 c_ext->data = annotation = calloc(1, sizeof *annotation);
Radek Krejci1b2eef82021-02-17 11:17:27 +010077 if (!annotation) {
Radek Krejci859a15a2021-03-05 20:56:59 +010078 goto emem;
Radek Krejci1b2eef82021-02-17 11:17:27 +010079 }
Radek Krejci5f9a3672021-03-05 21:35:22 +010080 LY_ARRAY_CREATE_GOTO(lysc_ctx_get_ctx(cctx), c_ext->substmts, 6, ret, emem);
Radek Krejcid6b76452019-09-03 17:03:03 +020081
Radek Krejci1b2eef82021-02-17 11:17:27 +010082 LY_ARRAY_INCREMENT(c_ext->substmts);
83 c_ext->substmts[ANNOTATION_SUBSTMT_IFF].stmt = LY_STMT_IF_FEATURE;
84 c_ext->substmts[ANNOTATION_SUBSTMT_IFF].cardinality = LY_STMT_CARD_ANY;
85 c_ext->substmts[ANNOTATION_SUBSTMT_IFF].storage = &annotation->iffeatures;
86
87 LY_ARRAY_INCREMENT(c_ext->substmts);
88 c_ext->substmts[ANNOTATION_SUBSTMT_UNITS].stmt = LY_STMT_UNITS;
89 c_ext->substmts[ANNOTATION_SUBSTMT_UNITS].cardinality = LY_STMT_CARD_OPT;
90 c_ext->substmts[ANNOTATION_SUBSTMT_UNITS].storage = &annotation->units;
91
92 LY_ARRAY_INCREMENT(c_ext->substmts);
93 c_ext->substmts[ANNOTATION_SUBSTMT_STATUS].stmt = LY_STMT_STATUS;
94 c_ext->substmts[ANNOTATION_SUBSTMT_STATUS].cardinality = LY_STMT_CARD_OPT;
95 c_ext->substmts[ANNOTATION_SUBSTMT_STATUS].storage = &annotation->flags;
96
97 LY_ARRAY_INCREMENT(c_ext->substmts);
98 c_ext->substmts[ANNOTATION_SUBSTMT_TYPE].stmt = LY_STMT_TYPE;
99 c_ext->substmts[ANNOTATION_SUBSTMT_TYPE].cardinality = LY_STMT_CARD_MAND;
100 c_ext->substmts[ANNOTATION_SUBSTMT_TYPE].storage = &annotation->type;
101
102 LY_ARRAY_INCREMENT(c_ext->substmts);
103 c_ext->substmts[ANNOTATION_SUBSTMT_DSC].stmt = LY_STMT_DESCRIPTION;
104 c_ext->substmts[ANNOTATION_SUBSTMT_DSC].cardinality = LY_STMT_CARD_OPT;
105 c_ext->substmts[ANNOTATION_SUBSTMT_DSC].storage = &annotation->dsc;
106
107 LY_ARRAY_INCREMENT(c_ext->substmts);
108 c_ext->substmts[ANNOTATION_SUBSTMT_REF].stmt = LY_STMT_REFERENCE;
109 c_ext->substmts[ANNOTATION_SUBSTMT_REF].cardinality = LY_STMT_CARD_OPT;
110 c_ext->substmts[ANNOTATION_SUBSTMT_REF].storage = &annotation->ref;
111
Radek Krejci859a15a2021-03-05 20:56:59 +0100112 ret = lys_compile_extension_instance(cctx, p_ext, c_ext);
113 return ret;
Radek Krejcid6b76452019-09-03 17:03:03 +0200114
Radek Krejci859a15a2021-03-05 20:56:59 +0100115emem:
Radek Krejci0b013302021-03-29 15:22:32 +0200116 lyplg_ext_log(c_ext, LY_LLERR, LY_EMEM, lysc_ctx_get_path(cctx), "Memory allocation failed (%s()).", __func__);
Radek Krejci859a15a2021-03-05 20:56:59 +0100117 return LY_EMEM;
Radek Krejcid6b76452019-09-03 17:03:03 +0200118}
119
Radek Krejci38d85362019-09-05 16:26:38 +0200120/**
Radek Krejciadcf63d2021-02-09 10:21:18 +0100121 * @brief INFO printer
122 *
Radek Krejci0b013302021-03-29 15:22:32 +0200123 * Implementation of ::lyplg_ext_schema_printer_clb set as ::lyext_plugin::sprinter
Radek Krejciadcf63d2021-02-09 10:21:18 +0100124 */
Radek Krejci3e6632f2021-03-22 22:08:21 +0100125static LY_ERR
Radek Krejcif8d7f9a2021-03-10 14:32:36 +0100126annotation_schema_printer(struct lyspr_ctx *ctx, struct lysc_ext_instance *ext, ly_bool *flag)
Radek Krejciadcf63d2021-02-09 10:21:18 +0100127{
128 lysc_print_extension_instance(ctx, ext, flag);
129
130 return LY_SUCCESS;
131}
132
133/**
Radek Krejci38d85362019-09-05 16:26:38 +0200134 * @brief Free annotation extension instances' data.
135 *
Radek Krejci0b013302021-03-29 15:22:32 +0200136 * Implementation of ::lyplg_ext_free_clb callback set as ::lyext_plugin::free.
Radek Krejci38d85362019-09-05 16:26:38 +0200137 */
Radek Krejci3e6632f2021-03-22 22:08:21 +0100138static void
Radek Krejci38d85362019-09-05 16:26:38 +0200139annotation_free(struct ly_ctx *ctx, struct lysc_ext_instance *ext)
140{
Radek Krejci1b2eef82021-02-17 11:17:27 +0100141 if (!ext->substmts) {
Radek Krejciad5963b2019-09-06 16:03:05 +0200142 return;
143 }
144
Radek Krejci0b013302021-03-29 15:22:32 +0200145 lyplg_ext_instance_substatements_free(ctx, ext->substmts);
Radek Krejci0f969882020-08-21 16:56:47 +0200146 free(ext->data);
Radek Krejci38d85362019-09-05 16:26:38 +0200147}
Radek Krejcid6b76452019-09-03 17:03:03 +0200148
149/**
Radek Krejci3e6632f2021-03-22 22:08:21 +0100150 * @brief Plugin descriptions for the Metadata's annotation extension
Radek Krejcia6f61e72021-03-24 21:00:19 +0100151 *
152 * Note that external plugins are supposed to use:
153 *
154 * LYPLG_EXTENSIONS = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200155 */
Radek Krejci3e6632f2021-03-22 22:08:21 +0100156const struct lyplg_ext_record plugins_metadata[] = {
157 {
158 .module = "ietf-yang-metadata",
159 .revision = "2016-08-05",
160 .name = "annotation",
161
162 .plugin.id = "libyang 2 - metadata, version 1",
163 .plugin.compile = &annotation_compile,
tadeas-vintrlikbf8aa6e2021-11-03 13:07:34 +0100164 .plugin.parse = NULL,
Radek Krejci3e6632f2021-03-22 22:08:21 +0100165 .plugin.validate = NULL,
166 .plugin.sprinter = &annotation_schema_printer,
167 .plugin.free = annotation_free
168 },
169 {0} /* terminating zeroed record */
Radek Krejcid6b76452019-09-03 17:03:03 +0200170};