libyang 2.0.231
libyang is YANG data modelling language parser and toolkit written (and providing API) in C.
node_instanceid.c
Go to the documentation of this file.
1
15#include "plugins_types.h"
16
17#include <stdint.h>
18#include <stdlib.h>
19
20#include "libyang.h"
21
22/* additional internal headers for some useful simple macros */
23#include "common.h"
24#include "compat.h"
25#include "path.h"
26#include "plugins_internal.h" /* LY_TYPE_*_STR */
27#include "xpath.h"
28
47static LY_ERR
48node_instanceid_path2str(const struct ly_path *path, LY_VALUE_FORMAT format, void *prefix_data, char **str)
49{
50 LY_ERR ret = LY_SUCCESS;
52 char *result = NULL, quot;
53 const struct lys_module *mod = NULL;
54 ly_bool inherit_prefix = 0, d;
55 const char *strval;
56
57 if (!path) {
58 /* special path */
59 ret = ly_strcat(&result, "/");
60 goto cleanup;
61 }
62
63 switch (format) {
64 case LY_VALUE_XML:
65 case LY_VALUE_SCHEMA:
67 /* everything is prefixed */
68 inherit_prefix = 0;
69 break;
70 case LY_VALUE_CANON:
71 case LY_VALUE_JSON:
72 case LY_VALUE_LYB:
73 case LY_VALUE_STR_NS:
74 /* the same prefix is inherited and skipped */
75 inherit_prefix = 1;
76 break;
77 }
78
79 LY_ARRAY_FOR(path, u) {
80 /* new node */
81 if (!inherit_prefix || (mod != path[u].node->module)) {
82 mod = path[u].node->module;
83 ret = ly_strcat(&result, "/%s:%s", lyplg_type_get_prefix(mod, format, prefix_data), path[u].node->name);
84 } else {
85 ret = ly_strcat(&result, "/%s", path[u].node->name);
86 }
87 LY_CHECK_GOTO(ret, cleanup);
88
89 /* node predicates */
90 LY_ARRAY_FOR(path[u].predicates, v) {
91 struct ly_path_predicate *pred = &path[u].predicates[v];
92
93 switch (path[u].pred_type) {
94 case LY_PATH_PREDTYPE_NONE:
95 break;
96 case LY_PATH_PREDTYPE_POSITION:
97 /* position predicate */
98 ret = ly_strcat(&result, "[%" PRIu64 "]", pred->position);
99 break;
100 case LY_PATH_PREDTYPE_LIST:
101 /* key-predicate */
102 strval = pred->value.realtype->plugin->print(path[u].node->module->ctx, &pred->value, format, prefix_data,
103 &d, NULL);
104
105 /* default quote */
106 quot = '\'';
107 if (strchr(strval, quot)) {
108 quot = '"';
109 }
110 if (inherit_prefix) {
111 /* always the same prefix as the parent */
112 ret = ly_strcat(&result, "[%s=%c%s%c]", pred->key->name, quot, strval, quot);
113 } else {
114 ret = ly_strcat(&result, "[%s:%s=%c%s%c]", lyplg_type_get_prefix(pred->key->module, format, prefix_data),
115 pred->key->name, quot, strval, quot);
116 }
117 if (d) {
118 free((char *)strval);
119 }
120 break;
121 case LY_PATH_PREDTYPE_LEAFLIST:
122 /* leaf-list-predicate */
123 strval = pred->value.realtype->plugin->print(path[u].node->module->ctx, &pred->value, format, prefix_data,
124 &d, NULL);
125
126 /* default quote */
127 quot = '\'';
128 if (strchr(strval, quot)) {
129 quot = '"';
130 }
131 ret = ly_strcat(&result, "[.=%c%s%c]", quot, strval, quot);
132 if (d) {
133 free((char *)strval);
134 }
135 break;
136 }
137
138 LY_CHECK_GOTO(ret, cleanup);
139 }
140 }
141
142cleanup:
143 if (ret) {
144 free(result);
145 } else {
146 *str = result;
147 }
148 return ret;
149}
150
154static LY_ERR
155lyplg_type_store_node_instanceid(const struct ly_ctx *ctx, const struct lysc_type *type, const void *value, size_t value_len,
156 uint32_t options, LY_VALUE_FORMAT format, void *prefix_data, uint32_t hints, const struct lysc_node *ctx_node,
157 struct lyd_value *storage, struct lys_glob_unres *unres, struct ly_err_item **err)
158{
159 LY_ERR ret = LY_SUCCESS;
160 struct lyxp_expr *exp = NULL;
161 uint32_t prefix_opt = 0;
162 struct ly_path *path = NULL;
163 char *canon;
164
165 /* init storage */
166 memset(storage, 0, sizeof *storage);
167 storage->realtype = type;
168
169 /* check hints */
170 ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
171 LY_CHECK_GOTO(ret, cleanup);
172
173 if ((((char *)value)[0] == '/') && (value_len == 1)) {
174 /* special path */
175 goto store;
176 }
177
178 switch (format) {
179 case LY_VALUE_SCHEMA:
181 case LY_VALUE_XML:
182 prefix_opt = LY_PATH_PREFIX_MANDATORY;
183 break;
184 case LY_VALUE_CANON:
185 case LY_VALUE_LYB:
186 case LY_VALUE_JSON:
187 case LY_VALUE_STR_NS:
188 prefix_opt = LY_PATH_PREFIX_STRICT_INHERIT;
189 break;
190 }
191
192 /* parse the value */
193 ret = ly_path_parse(ctx, ctx_node, value, value_len, 0, LY_PATH_BEGIN_ABSOLUTE, prefix_opt, LY_PATH_PRED_SIMPLE, &exp);
194 if (ret) {
195 ret = ly_err_new(err, LY_EVALID, LYVE_DATA, NULL, NULL,
196 "Invalid instance-identifier \"%.*s\" value - syntax error.", (int)value_len, (char *)value);
197 goto cleanup;
198 }
199
200 if (options & LYPLG_TYPE_STORE_IMPLEMENT) {
201 /* implement all prefixes */
202 LY_CHECK_GOTO(ret = lys_compile_expr_implement(ctx, exp, format, prefix_data, 1, unres, NULL), cleanup);
203 }
204
205 /* resolve it on schema tree, use JSON format instead of LYB because for this type they are equal but for some
206 * nested types (such as numbers in predicates in the path) LYB would be invalid */
207 ret = ly_path_compile(ctx, NULL, ctx_node, NULL, exp, (ctx_node && (ctx_node->flags & LYS_IS_OUTPUT)) ?
208 LY_PATH_OPER_OUTPUT : LY_PATH_OPER_INPUT, LY_PATH_TARGET_MANY, 1, (format == LY_VALUE_LYB) ?
209 LY_VALUE_JSON : format, prefix_data, &path);
210 if (ret) {
211 ret = ly_err_new(err, ret, LYVE_DATA, NULL, NULL,
212 "Invalid instance-identifier \"%.*s\" value - semantic error.", (int)value_len, (char *)value);
213 goto cleanup;
214 }
215
216store:
217 /* store value */
218 storage->target = path;
219
220 /* store canonical value */
221 if (format == LY_VALUE_CANON) {
222 if (options & LYPLG_TYPE_STORE_DYNAMIC) {
223 ret = lydict_insert_zc(ctx, (char *)value, &storage->_canonical);
224 options &= ~LYPLG_TYPE_STORE_DYNAMIC;
225 LY_CHECK_GOTO(ret, cleanup);
226 } else {
227 ret = lydict_insert(ctx, value, value_len, &storage->_canonical);
228 LY_CHECK_GOTO(ret, cleanup);
229 }
230 } else {
231 /* JSON format with prefix is the canonical one */
232 ret = node_instanceid_path2str(path, LY_VALUE_JSON, NULL, &canon);
233 LY_CHECK_GOTO(ret, cleanup);
234
235 ret = lydict_insert_zc(ctx, canon, &storage->_canonical);
236 LY_CHECK_GOTO(ret, cleanup);
237 }
238
239cleanup:
240 lyxp_expr_free(ctx, exp);
241 if (options & LYPLG_TYPE_STORE_DYNAMIC) {
242 free((void *)value);
243 }
244
245 if (ret) {
246 lyplg_type_free_instanceid(ctx, storage);
247 }
248 return ret;
249}
250
254static const void *
255lyplg_type_print_node_instanceid(const struct ly_ctx *UNUSED(ctx), const struct lyd_value *value, LY_VALUE_FORMAT format,
256 void *prefix_data, ly_bool *dynamic, size_t *value_len)
257{
258 char *ret;
259
260 if ((format == LY_VALUE_CANON) || (format == LY_VALUE_JSON) || (format == LY_VALUE_LYB)) {
261 if (dynamic) {
262 *dynamic = 0;
263 }
264 if (value_len) {
265 *value_len = strlen(value->_canonical);
266 }
267 return value->_canonical;
268 }
269
270 /* print the value in the specific format */
271 if (node_instanceid_path2str(value->target, format, prefix_data, &ret)) {
272 return NULL;
273 }
274 *dynamic = 1;
275 if (value_len) {
276 *value_len = strlen(ret);
277 }
278 return ret;
279}
280
289 {
290 .module = "ietf-netconf-acm",
291 .revision = "2012-02-22",
292 .name = "node-instance-identifier",
293
294 .plugin.id = "libyang 2 - node-instance-identifier, version 1",
295 .plugin.store = lyplg_type_store_node_instanceid,
296 .plugin.validate = NULL,
297 .plugin.compare = lyplg_type_compare_instanceid,
298 .plugin.sort = NULL,
299 .plugin.print = lyplg_type_print_node_instanceid,
300 .plugin.duplicate = lyplg_type_dup_instanceid,
301 .plugin.free = lyplg_type_free_instanceid,
302 .plugin.lyb_data_len = -1,
303 },
304 {
305 .module = "ietf-netconf-acm",
306 .revision = "2018-02-14",
307 .name = "node-instance-identifier",
308
309 .plugin.id = "libyang 2 - node-instance-identifier, version 1",
310 .plugin.store = lyplg_type_store_node_instanceid,
311 .plugin.validate = NULL,
312 .plugin.compare = lyplg_type_compare_instanceid,
313 .plugin.sort = NULL,
314 .plugin.print = lyplg_type_print_node_instanceid,
315 .plugin.duplicate = lyplg_type_dup_instanceid,
316 .plugin.free = lyplg_type_free_instanceid,
317 .plugin.lyb_data_len = -1,
318 },
319 {0}
320};
libyang context handler.
LIBYANG_API_DECL LY_ERR lydict_insert(const struct ly_ctx *ctx, const char *value, size_t len, const char **str_p)
Insert string into dictionary. If the string is already present, only a reference counter is incremen...
LIBYANG_API_DECL LY_ERR lydict_insert_zc(const struct ly_ctx *ctx, char *value, const char **str_p)
Insert string into dictionary - zerocopy version. If the string is already present,...
LY_ERR
libyang's error codes returned by the libyang functions.
Definition: log.h:244
@ LYVE_DATA
Definition: log.h:281
@ LY_EVALID
Definition: log.h:252
@ LY_SUCCESS
Definition: log.h:245
Libyang full error structure.
Definition: log.h:289
const char * module
LIBYANG_API_DECL LY_ERR ly_err_new(struct ly_err_item **err, LY_ERR ecode, LY_VECODE vecode, char *path, char *apptag, const char *err_format,...) _FORMAT_PRINTF(6
Create and fill error structure.
LIBYANG_API_DECL const char * lyplg_type_get_prefix(const struct lys_module *mod, LY_VALUE_FORMAT format, void *prefix_data)
Get format-specific prefix for a module.
LIBYANG_API_DECL LY_ERR lyplg_type_check_hints(uint32_t hints, const char *value, size_t value_len, LY_DATA_TYPE type, int *base, struct ly_err_item **err)
Check that the type is suitable for the parser's hints (if any) in the specified format.
LIBYANG_API_DECL LY_ERR lyplg_type_dup_instanceid(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup)
Implementation of lyplg_type_dup_clb for the built-in instance-identifier type.
Definition: instanceid.c:328
LIBYANG_API_DECL LY_ERR lyplg_type_compare_instanceid(const struct lyd_value *val1, const struct lyd_value *val2)
Implementation of lyplg_type_compare_clb for the built-in instance-identifier type.
Definition: instanceid.c:244
LIBYANG_API_DECL void lyplg_type_free_instanceid(const struct ly_ctx *ctx, struct lyd_value *value)
Implementation of lyplg_type_free_clb for the built-in instance-identifier type.
Definition: instanceid.c:351
#define LYPLG_TYPE_STORE_DYNAMIC
#define LYPLG_TYPE_STORE_IMPLEMENT
LY_DATA_TYPE basetype
Definition: tree_schema.h:1536
uint16_t flags
Definition: tree_schema.h:1652
Available YANG schema tree structures representing YANG module.
Definition: tree_schema.h:2341
Compiled YANG data node.
Definition: tree_schema.h:1650
#define LYS_IS_OUTPUT
Definition: tree_schema.h:954
#define LY_ARRAY_FOR(ARRAY,...)
Sized-array iterator (for-loop).
Definition: tree.h:167
LY_VALUE_FORMAT
All kinds of supported value formats and prefix mappings to modules.
Definition: tree.h:235
#define LY_ARRAY_COUNT_TYPE
Type (i.e. size) of the sized array's size counter.
Definition: tree.h:104
@ LY_VALUE_JSON
Definition: tree.h:240
@ LY_VALUE_SCHEMA
Definition: tree.h:237
@ LY_VALUE_CANON
Definition: tree.h:236
@ LY_VALUE_XML
Definition: tree.h:239
@ LY_VALUE_STR_NS
Definition: tree.h:242
@ LY_VALUE_SCHEMA_RESOLVED
Definition: tree.h:238
@ LY_VALUE_LYB
Definition: tree.h:241
The main libyang public header.
uint8_t ly_bool
Type to indicate boolean value.
Definition: log.h:34
const struct lyplg_type_record plugins_node_instanceid[]
Plugin information for instance-identifier type implementation.
API for (user) types plugins.
const struct lysc_type * realtype
Definition: tree_data.h:564
const char * _canonical
Definition: tree_data.h:561
YANG data representation.
Definition: tree_data.h:560