blob: 2704f08ea797222fc197a9c9d831bc366a50bf0f [file] [log] [blame]
Radek Krejcie534c132016-11-23 13:32:31 +01001/**
2 * @file extensions.h
3 * @author Radek Krejci <rkrejci@cesnet.cz>
4 * @brief libyang support for YANG extension implementations.
5 *
6 * Copyright (c) 2016 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 */
14
15#ifndef LY_EXTENSIONS_H_
16#define LY_EXTENSIONS_H_
17
Radek Krejcic25fe432017-02-22 16:20:09 +010018#include "libyang.h"
Radek Krejcie534c132016-11-23 13:32:31 +010019
20#ifdef __cplusplus
21extern "C" {
22#endif
23
Radek Krejcie534c132016-11-23 13:32:31 +010024/**
Radek Krejci8d6b7422017-02-03 14:42:13 +010025 * @addtogroup extensions
26 * @{
27 */
28
29/**
Radek Krejcibe336392017-02-07 10:54:24 +010030 * @brief Extension instance structure parent enumeration
31 */
32typedef enum {
33 LYEXT_PAR_MODULE, /**< ::lys_module or ::lys_submodule */
34 LYEXT_PAR_NODE, /**< ::lys_node (and the derived structures) */
35 LYEXT_PAR_TPDF, /**< ::lys_tpdf */
36 LYEXT_PAR_TYPE, /**< ::lys_type */
37 LYEXT_PAR_TYPE_BIT, /**< ::lys_type_bit */
38 LYEXT_PAR_TYPE_ENUM, /**< ::lys_type_enum */
39 LYEXT_PAR_FEATURE, /**< ::lys_feature */
40 LYEXT_PAR_RESTR, /**< ::lys_restr - YANG's must, range, length and pattern statements */
41 LYEXT_PAR_WHEN, /**< ::lys_when */
42 LYEXT_PAR_IDENT, /**< ::lys_ident */
43 LYEXT_PAR_EXT, /**< ::lys_ext */
44 LYEXT_PAR_EXTINST, /**< ::lys_ext_instance */
45 LYEXT_PAR_REFINE, /**< ::lys_refine */
46 LYEXT_PAR_DEVIATION, /**< ::lys_deviation */
47 LYEXT_PAR_DEVIATE, /**< ::lys_deviate */
48 LYEXT_PAR_IMPORT, /**< ::lys_import */
49 LYEXT_PAR_INCLUDE, /**< ::lys_include */
50 LYEXT_PAR_REVISION, /**< ::lys_revision */
51 LYEXT_PAR_IFFEATURE /**< ::lys_iffeature */
52} LYEXT_PAR;
53
54/**
55 * @brief List of substatement without extensions storage. If the module contains extension instances in these
56 * substatements, they are stored with the extensions of the parent statement and flag to show to which substatement
57 * they belongs to.
58 *
59 * For example, if the extension is supposed to be instantiated as a child to the description statement, libyang
60 * stores the description just as its value. So, for example in case of the module's description, the description's
Radek Krejci89db0592017-02-16 15:07:13 +010061 * extension instance is actually stored in the lys_module's extensions list with the ::lys_ext_instance#insubstmt set to
Radek Krejcibe336392017-02-07 10:54:24 +010062 * #LYEXT_SUBSTMT_DESCRIPTION, ::lys_ext_instance#parent_type is LYEXT_PAR_MODULE and the ::lys_ext_instance#parent
63 * points to the ::lys_module structure.
64 *
65 * The values are (convertible) subset of #LY_STMT
66 */
67typedef enum {
68 LYEXT_SUBSTMT_ALL = -1, /**< special value for the lys_ext_iter() */
69 LYEXT_SUBSTMT_SELF = 0, /**< extension of the structure itself, not substatement's */
70 LYEXT_SUBSTMT_ARGUMENT, /**< extension of the argument statement, can appear in lys_ext */
71 LYEXT_SUBSTMT_BASE, /**< extension of the base statement, can appear (repeatedly) in lys_type and lys_ident */
72 LYEXT_SUBSTMT_BELONGSTO, /**< extension of the belongs-to statement, can appear in lys_submodule */
73 LYEXT_SUBSTMT_CONTACT, /**< extension of the contact statement, can appear in lys_module */
74 LYEXT_SUBSTMT_DEFAULT, /**< extension of the default statement, can appear in lys_node_leaf, lys_node_leaflist,
75 lys_node_choice and lys_deviate */
76 LYEXT_SUBSTMT_DESCRIPTION, /**< extension of the description statement, can appear in lys_module, lys_submodule,
77 lys_node, lys_import, lys_include, lys_ext, lys_feature, lys_tpdf, lys_restr,
78 lys_ident, lys_deviation, lys_type_enum, lys_type_bit, lys_when and lys_revision */
79 LYEXT_SUBSTMT_ERRTAG, /**< extension of the error-app-tag statement, can appear in lys_restr */
80 LYEXT_SUBSTMT_ERRMSG, /**< extension of the error-message statement, can appear in lys_restr */
81 LYEXT_SUBSTMT_KEY, /**< extension of the key statement, can appear in lys_node_list */
82 LYEXT_SUBSTMT_NAMESPACE, /**< extension of the namespace statement, can appear in lys_module */
83 LYEXT_SUBSTMT_ORGANIZATION, /**< extension of the organization statement, can appear in lys_module and lys_submodule */
84 LYEXT_SUBSTMT_PATH, /**< extension of the path statement, can appear in lys_type */
85 LYEXT_SUBSTMT_PREFIX, /**< extension of the prefix statement, can appear in lys_module, lys_submodule (for
86 belongs-to's prefix) and lys_import */
87 LYEXT_SUBSTMT_PRESENCE, /**< extension of the presence statement, can appear in lys_node_container */
88 LYEXT_SUBSTMT_REFERENCE, /**< extension of the reference statement, can appear in lys_module, lys_submodule,
89 lys_node, lys_import, lys_include, lys_revision, lys_tpdf, lys_restr, lys_ident,
90 lys_ext, lys_feature, lys_deviation, lys_type_enum, lys_type_bit and lys_when */
91 LYEXT_SUBSTMT_REVISIONDATE, /**< extension of the revision-date statement, can appear in lys_import and lys_include */
92 LYEXT_SUBSTMT_UNITS, /**< extension of the units statement, can appear in lys_tpdf, lys_node_leaf,
93 lys_node_leaflist and lys_deviate */
94 LYEXT_SUBSTMT_VALUE, /**< extension of the value statement, can appear in lys_type_enum */
95 LYEXT_SUBSTMT_VERSION, /**< extension of the yang-version statement, can appear in lys_module and lys_submodule */
96 LYEXT_SUBSTMT_MODIFIER, /**< extension of the modifier statement, can appear in lys_restr */
97 LYEXT_SUBSTMT_REQINSTANCE, /**< extension of the require-instance statement, can appear in lys_type */
98 LYEXT_SUBSTMT_YINELEM, /**< extension of the yin-element statement, can appear in lys_ext */
99 LYEXT_SUBSTMT_CONFIG, /**< extension of the config statement, can appear in lys_node and lys_deviate */
100 LYEXT_SUBSTMT_MANDATORY, /**< extension of the mandatory statement, can appear in lys_node_leaf, lys_node_choice,
101 lys_node_anydata and lys_deviate */
102 LYEXT_SUBSTMT_ORDEREDBY, /**< extension of the ordered-by statement, can appear in lys_node_list and lys_node_leaflist */
103 LYEXT_SUBSTMT_STATUS, /**< extension of the status statement, can appear in lys_tpdf, lys_node, lys_ident,
104 lys_ext, lys_feature, lys_type_enum and lys_type_bit */
105 LYEXT_SUBSTMT_DIGITS, /**< extension of the fraction-digits statement, can appear in lys_type */
106 LYEXT_SUBSTMT_MAX, /**< extension of the max-elements statement, can appear in lys_node_list,
107 lys_node_leaflist and lys_deviate */
108 LYEXT_SUBSTMT_MIN, /**< extension of the min-elements statement, can appear in lys_node_list,
109 lys_node_leaflist and lys_deviate */
110 LYEXT_SUBSTMT_POSITION, /**< extension of the position statement, can appear in lys_type_bit */
111 LYEXT_SUBSTMT_UNIQUE, /**< extension of the unique statement, can appear in lys_node_list and lys_deviate */
112} LYEXT_SUBSTMT;
113
114/**
Radek Krejcie534c132016-11-23 13:32:31 +0100115 * @brief Callback to check that the extension can be instantiated inside the provided node
116 *
Radek Krejci43ce4b72017-01-04 11:02:38 +0100117 * @param[in] parent The parent of the instantiated extension.
118 * @param[in] parent_type The type of the structure provided as \p parent.
119 * @param[in] substmt_type libyang does not store all the extension instances in the structures where they are
120 * instantiated in the module. In some cases (see #LYEXT_SUBSTMT) they are stored in parent
121 * structure and marked with flag to know in which substatement of the parent the extension
122 * was originally instantiated.
123 * @return 0 - yes
124 * 1 - no
125 * 2 - ignore / skip without an error
126 */
127typedef int (*lyext_check_position_clb)(const void *parent, LYEXT_PAR parent_type, LYEXT_SUBSTMT substmt_type);
128
129/**
130 * @brief Callback to check that the extension instance is correct - have
Radek Krejci2b107412017-02-22 15:26:42 +0100131 * the valid argument, cardinality, etc.
Radek Krejci43ce4b72017-01-04 11:02:38 +0100132 *
Radek Krejci80056d52017-01-05 13:13:33 +0100133 * @param[in] ext Extension instance to be checked.
Radek Krejci90db7552017-01-04 16:17:46 +0100134 * @return 0 - ok
135 * 1 - error
Radek Krejcie534c132016-11-23 13:32:31 +0100136 */
Radek Krejci43ce4b72017-01-04 11:02:38 +0100137typedef int (*lyext_check_result_clb)(struct lys_ext_instance *ext);
Radek Krejcie534c132016-11-23 13:32:31 +0100138
Radek Krejci80056d52017-01-05 13:13:33 +0100139/**
140 * @brief Callback to decide whether the extension will be inherited into the provided schema node. The extension
Radek Krejci89db0592017-02-16 15:07:13 +0100141 * instance is always from some of the node's parents. The inherited extension instances are marked with the
142 * #LYEXT_OPT_INHERIT flag.
Radek Krejci80056d52017-01-05 13:13:33 +0100143 *
144 * @param[in] ext Extension instance to be inherited.
145 * @param[in] node Schema node where the node is supposed to be inherited.
146 * @return 0 - yes
147 * 1 - no (do not process the node's children)
148 * 2 - no, but continue with children
149 */
150typedef int (*lyext_check_inherit_clb)(struct lys_ext_instance *ext, struct lys_node *node);
151
Radek Krejci43ce4b72017-01-04 11:02:38 +0100152struct lyext_plugin {
153 LYEXT_TYPE type; /**< type of the extension, according to it the structure will be casted */
Radek Krejci80056d52017-01-05 13:13:33 +0100154 uint16_t flags; /**< [extension flags](@ref extflags) */
Radek Krejcie534c132016-11-23 13:32:31 +0100155
Radek Krejci80056d52017-01-05 13:13:33 +0100156 lyext_check_position_clb check_position; /**< callbcak for testing that the extension can be instantiated
Radek Krejci43ce4b72017-01-04 11:02:38 +0100157 under the provided parent. Mandatory callback. */
Radek Krejci80056d52017-01-05 13:13:33 +0100158 lyext_check_result_clb check_result; /**< callback for testing if the argument value of the extension instance
Radek Krejci43ce4b72017-01-04 11:02:38 +0100159 is valid. Mandatory if the extension has the argument. */
Radek Krejci80056d52017-01-05 13:13:33 +0100160 lyext_check_inherit_clb check_inherit; /**< callback to decide if the extension is supposed to be inherited into
Radek Krejci89db0592017-02-16 15:07:13 +0100161 the provided node, the callback is used only if the flags contains
162 #LYEXT_OPT_INHERIT flag */
Radek Krejcie534c132016-11-23 13:32:31 +0100163};
164
Radek Krejci8d6b7422017-02-03 14:42:13 +0100165struct lyext_plugin_complex {
166 LYEXT_TYPE type; /**< type of the extension, according to it the structure will be casted */
167 uint16_t flags; /**< [extension flags](@ref extflags) */
168
169 lyext_check_position_clb check_position; /**< callbcak for testing that the extension can be instantiated
170 under the provided parent. Mandatory callback. */
171 lyext_check_result_clb check_result; /**< callback for testing if the argument value of the extension instance
172 is valid. Mandatory if the extension has the argument. */
173 lyext_check_inherit_clb check_inherit; /**< callback to decide if the extension is supposed to be inherited into
Radek Krejci89db0592017-02-16 15:07:13 +0100174 the provided node, the callback is used only if the flags contains
175 #LYEXT_OPT_INHERIT flag */
Radek Krejci8d6b7422017-02-03 14:42:13 +0100176 struct lyext_substmt *substmt; /**< NULL-terminated array of allowed substatements and restrictions
177 to their instantiation inside the extension instance */
178 size_t instance_size; /**< size of the instance structure to allocate, the structure is
179 is provided as ::lys_ext_instance_complex, but the content array
180 is accessed according to the substmt specification provided by
181 plugin */
182};
183
Radek Krejci43ce4b72017-01-04 11:02:38 +0100184struct lyext_plugin_list {
Radek Krejci3b88c6c2017-01-04 16:12:12 +0100185 const char *module; /**< name of the module where the extension is defined */
186 const char *revision; /**< optional module revision - if not specified, the plugin applies to any revision,
187 which is not an optional approach due to a possible future revisions of the module.
188 Instead, there should be defined multiple items in the plugins list, each with the
189 different revision, but all with the same pointer to the plugin extension. The
190 only valid use case for the NULL revision is the case the module has no revision. */
Radek Krejci43ce4b72017-01-04 11:02:38 +0100191 const char *name; /**< name of the extension */
192 struct lyext_plugin *plugin; /**< plugin for the extension */
Radek Krejcie534c132016-11-23 13:32:31 +0100193};
194
Radek Krejci8d6b7422017-02-03 14:42:13 +0100195/**
Radek Krejcic25fe432017-02-22 16:20:09 +0100196 * @brief Logging function for extension plugins, use #LYEXT_LOG macro instead!
197 */
Michal Vasko53b7da02018-02-13 15:28:42 +0100198void lyext_log(const struct ly_ctx *ctx, LY_LOG_LEVEL level, const char *plugin, const char *function, const char *format, ...);
Radek Krejcic25fe432017-02-22 16:20:09 +0100199
200/**
201 * @brief Logging macro for extension plugins
202 *
Michal Vasko53b7da02018-02-13 15:28:42 +0100203 * @param[in] ctx Context to store the error in.
Radek Krejcic25fe432017-02-22 16:20:09 +0100204 * @param[in] level #LY_LOG_LEVEL value with the message importance.
Radek Krejci24f86902017-02-23 13:07:48 +0100205 * @param[in] plugin Plugin name.
Radek Krejcic25fe432017-02-22 16:20:09 +0100206 * @param[in] str Format string as in case of printf function.
207 * @param[in] args Parameters to expand in format string.
208 */
Michal Vasko53b7da02018-02-13 15:28:42 +0100209#define LYEXT_LOG(ctx, level, plugin, str, args...) \
210 lyext_log(ctx, level, plugin, __func__, str, ##args); \
Radek Krejcic25fe432017-02-22 16:20:09 +0100211
212/**
Radek Krejci8d6b7422017-02-03 14:42:13 +0100213 * @}
214 */
Radek Krejci43ce4b72017-01-04 11:02:38 +0100215
Radek Krejcie534c132016-11-23 13:32:31 +0100216#ifdef __cplusplus
217}
218#endif
219
220#endif /* LY_EXTENSIONS_H_ */