libyang 2.1.128
libyang is YANG data modelling language parser and toolkit written (and providing API) in C.
Loading...
Searching...
No Matches
instanceid.c
Go to the documentation of this file.
1
14#define _GNU_SOURCE /* strdup */
15
16#include "plugins_types.h"
17
18#include <stdint.h>
19#include <stdlib.h>
20
21#include "libyang.h"
22
23/* additional internal headers for some useful simple macros */
24#include "common.h"
25#include "compat.h"
26#include "path.h"
27#include "plugins_internal.h" /* LY_TYPE_*_STR */
28
37
47static LY_ERR
48instanceid_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, *local_mod = NULL;
54 struct ly_set *mods = NULL;
55 ly_bool inherit_prefix = 0, d;
56 const char *strval;
57
58 switch (format) {
59 case LY_VALUE_XML:
60 /* null the local module so that all the prefixes are printed */
61 mods = prefix_data;
62 local_mod = mods->objs[0];
63 mods->objs[0] = NULL;
64
65 /* fallthrough */
66 case LY_VALUE_SCHEMA:
68 /* everything is prefixed */
69 inherit_prefix = 0;
70 break;
71 case LY_VALUE_CANON:
72 case LY_VALUE_JSON:
73 case LY_VALUE_LYB:
74 case LY_VALUE_STR_NS:
75 /* the same prefix is inherited and skipped */
76 inherit_prefix = 1;
77 break;
78 }
79
80 LY_ARRAY_FOR(path, u) {
81 /* new node */
82 if (!inherit_prefix || (mod != path[u].node->module)) {
83 mod = path[u].node->module;
84 ret = ly_strcat(&result, "/%s:%s", lyplg_type_get_prefix(mod, format, prefix_data), path[u].node->name);
85 } else {
86 ret = ly_strcat(&result, "/%s", path[u].node->name);
87 }
88 LY_CHECK_GOTO(ret, cleanup);
89
90 /* node predicates */
91 LY_ARRAY_FOR(path[u].predicates, v) {
92 struct ly_path_predicate *pred = &path[u].predicates[v];
93
94 switch (pred->type) {
95 case LY_PATH_PREDTYPE_POSITION:
96 /* position predicate */
97 ret = ly_strcat(&result, "[%" PRIu64 "]", pred->position);
98 break;
99 case LY_PATH_PREDTYPE_LIST:
100 /* key-predicate */
101 strval = pred->value.realtype->plugin->print(path[u].node->module->ctx, &pred->value, format, prefix_data,
102 &d, NULL);
103
104 /* default quote */
105 quot = '\'';
106 if (strchr(strval, quot)) {
107 quot = '"';
108 }
109 if (inherit_prefix) {
110 /* always the same prefix as the parent */
111 ret = ly_strcat(&result, "[%s=%c%s%c]", pred->key->name, quot, strval, quot);
112 } else {
113 ret = ly_strcat(&result, "[%s:%s=%c%s%c]", lyplg_type_get_prefix(pred->key->module, format, prefix_data),
114 pred->key->name, quot, strval, quot);
115 }
116 if (d) {
117 free((char *)strval);
118 }
119 break;
120 case LY_PATH_PREDTYPE_LEAFLIST:
121 /* leaf-list-predicate */
122 strval = pred->value.realtype->plugin->print(path[u].node->module->ctx, &pred->value, format, prefix_data,
123 &d, NULL);
124
125 /* default quote */
126 quot = '\'';
127 if (strchr(strval, quot)) {
128 quot = '"';
129 }
130 ret = ly_strcat(&result, "[.=%c%s%c]", quot, strval, quot);
131 if (d) {
132 free((char *)strval);
133 }
134 break;
135 case LY_PATH_PREDTYPE_LIST_VAR:
136 LOGINT(path[u].node->module->ctx);
137 ret = LY_EINT;
138 goto cleanup;
139 }
140
141 LY_CHECK_GOTO(ret, cleanup);
142 }
143 }
144
145cleanup:
146 if (local_mod) {
147 mods->objs[0] = (void *)local_mod;
148 }
149 if (ret) {
150 free(result);
151 } else {
152 *str = result;
153 }
154 return ret;
155}
156
157LIBYANG_API_DEF LY_ERR
158lyplg_type_store_instanceid(const struct ly_ctx *ctx, const struct lysc_type *type, const void *value, size_t value_len,
159 uint32_t options, LY_VALUE_FORMAT format, void *prefix_data, uint32_t hints, const struct lysc_node *ctx_node,
160 struct lyd_value *storage, struct lys_glob_unres *unres, struct ly_err_item **err)
161{
162 LY_ERR ret = LY_SUCCESS;
163 struct lysc_type_instanceid *type_inst = (struct lysc_type_instanceid *)type;
164 struct ly_path *path;
165 char *canon;
166
167 /* init storage */
168 memset(storage, 0, sizeof *storage);
169 storage->realtype = type;
170
171 /* check hints */
172 ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
173 LY_CHECK_GOTO(ret, cleanup);
174
175 /* compile instance-identifier into path */
176 if (format == LY_VALUE_LYB) {
177 /* value in LYB format is the same as in JSON format. */
178 ret = lyplg_type_lypath_new(ctx, value, value_len, options, LY_VALUE_JSON, prefix_data, ctx_node,
179 unres, &path, err);
180 } else {
181 ret = lyplg_type_lypath_new(ctx, value, value_len, options, format, prefix_data, ctx_node,
182 unres, &path, err);
183 }
184 LY_CHECK_GOTO(ret, cleanup);
185
186 /* store value */
187 storage->target = path;
188
189 /* check status */
190 ret = lyplg_type_lypath_check_status(ctx_node, path, format, prefix_data, err);
191 LY_CHECK_GOTO(ret, cleanup);
192
193 /* store canonical value */
194 if (format == LY_VALUE_CANON) {
195 if (options & LYPLG_TYPE_STORE_DYNAMIC) {
196 ret = lydict_insert_zc(ctx, (char *)value, &storage->_canonical);
197 options &= ~LYPLG_TYPE_STORE_DYNAMIC;
198 LY_CHECK_GOTO(ret, cleanup);
199 } else {
200 ret = lydict_insert(ctx, value, value_len, &storage->_canonical);
201 LY_CHECK_GOTO(ret, cleanup);
202 }
203 } else {
204 /* JSON format with prefix is the canonical one */
205 ret = instanceid_path2str(path, LY_VALUE_JSON, NULL, &canon);
206 LY_CHECK_GOTO(ret, cleanup);
207
208 ret = lydict_insert_zc(ctx, canon, &storage->_canonical);
209 LY_CHECK_GOTO(ret, cleanup);
210 }
211
212cleanup:
213 if (options & LYPLG_TYPE_STORE_DYNAMIC) {
214 free((void *)value);
215 }
216
217 if (ret) {
218 lyplg_type_free_instanceid(ctx, storage);
219 }
220 if (!ret && type_inst->require_instance) {
221 /* needs to be resolved */
222 return LY_EINCOMPLETE;
223 } else {
224 return ret;
225 }
226}
227
228LIBYANG_API_DEF LY_ERR
229lyplg_type_validate_instanceid(const struct ly_ctx *ctx, const struct lysc_type *UNUSED(type),
230 const struct lyd_node *ctx_node, const struct lyd_node *tree, struct lyd_value *storage,
231 struct ly_err_item **err)
232{
233 LY_ERR ret = LY_SUCCESS;
234 struct lysc_type_instanceid *type_inst = (struct lysc_type_instanceid *)storage->realtype;
235 const char *value;
236 char *path;
237
238 *err = NULL;
239
240 if (!type_inst->require_instance) {
241 /* redundant to resolve */
242 return LY_SUCCESS;
243 }
244
245 /* find the target in data */
246 if ((ret = ly_path_eval(storage->target, tree, NULL, NULL))) {
247 value = lyplg_type_print_instanceid(ctx, storage, LY_VALUE_CANON, NULL, NULL, NULL);
248 path = lyd_path(ctx_node, LYD_PATH_STD, NULL, 0);
249 return ly_err_new(err, ret, LYVE_DATA, path, strdup("instance-required"), LY_ERRMSG_NOINST, value);
250 }
251
252 return LY_SUCCESS;
253}
254
255LIBYANG_API_DEF LY_ERR
256lyplg_type_compare_instanceid(const struct lyd_value *val1, const struct lyd_value *val2)
257{
259
260 if (val1->realtype != val2->realtype) {
261 return LY_ENOT;
262 }
263
264 if (val1 == val2) {
265 return LY_SUCCESS;
266 } else if (LY_ARRAY_COUNT(val1->target) != LY_ARRAY_COUNT(val2->target)) {
267 return LY_ENOT;
268 }
269
270 LY_ARRAY_FOR(val1->target, u) {
271 struct ly_path *s1 = &val1->target[u];
272 struct ly_path *s2 = &val2->target[u];
273
274 if ((s1->node != s2->node) || (s1->predicates && (LY_ARRAY_COUNT(s1->predicates) != LY_ARRAY_COUNT(s2->predicates)))) {
275 return LY_ENOT;
276 }
277 LY_ARRAY_FOR(s1->predicates, v) {
278 struct ly_path_predicate *pred1 = &s1->predicates[v];
279 struct ly_path_predicate *pred2 = &s2->predicates[v];
280
281 if (pred1->type != pred2->type) {
282 return LY_ENOT;
283 }
284
285 switch (pred1->type) {
286 case LY_PATH_PREDTYPE_POSITION:
287 /* position predicate */
288 if (pred1->position != pred2->position) {
289 return LY_ENOT;
290 }
291 break;
292 case LY_PATH_PREDTYPE_LIST:
293 /* key-predicate */
294 if ((pred1->key != pred2->key) ||
295 ((struct lysc_node_leaf *)pred1->key)->type->plugin->compare(&pred1->value, &pred2->value)) {
296 return LY_ENOT;
297 }
298 break;
299 case LY_PATH_PREDTYPE_LEAFLIST:
300 /* leaf-list predicate */
301 if (((struct lysc_node_leaflist *)s1->node)->type->plugin->compare(&pred1->value, &pred2->value)) {
302 return LY_ENOT;
303 }
304 break;
305 case LY_PATH_PREDTYPE_LIST_VAR:
306 /* key-predicate with a variable */
307 if ((pred1->key != pred2->key) || strcmp(pred1->variable, pred2->variable)) {
308 return LY_ENOT;
309 }
310 break;
311 }
312 }
313 }
314
315 return LY_SUCCESS;
316}
317
318LIBYANG_API_DEF const void *
319lyplg_type_print_instanceid(const struct ly_ctx *UNUSED(ctx), const struct lyd_value *value, LY_VALUE_FORMAT format,
320 void *prefix_data, ly_bool *dynamic, size_t *value_len)
321{
322 char *ret;
323
324 if ((format == LY_VALUE_CANON) || (format == LY_VALUE_JSON) || (format == LY_VALUE_LYB)) {
325 if (dynamic) {
326 *dynamic = 0;
327 }
328 if (value_len) {
329 *value_len = strlen(value->_canonical);
330 }
331 return value->_canonical;
332 }
333
334 /* print the value in the specific format */
335 if (instanceid_path2str(value->target, format, prefix_data, &ret)) {
336 return NULL;
337 }
338 *dynamic = 1;
339 if (value_len) {
340 *value_len = strlen(ret);
341 }
342 return ret;
343}
344
345LIBYANG_API_DEF LY_ERR
346lyplg_type_dup_instanceid(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup)
347{
348 LY_ERR ret;
349
350 memset(dup, 0, sizeof *dup);
351
352 /* canonical value */
353 ret = lydict_insert(ctx, original->_canonical, 0, &dup->_canonical);
354 LY_CHECK_GOTO(ret, error);
355
356 /* copy path */
357 ret = ly_path_dup(ctx, original->target, &dup->target);
358 LY_CHECK_GOTO(ret, error);
359
360 dup->realtype = original->realtype;
361 return LY_SUCCESS;
362
363error:
365 return ret;
366}
367
368LIBYANG_API_DEF void
369lyplg_type_free_instanceid(const struct ly_ctx *ctx, struct lyd_value *value)
370{
371 lydict_remove(ctx, value->_canonical);
372 value->_canonical = NULL;
373 ly_path_free(ctx, value->target);
374}
375
384 {
385 .module = "",
386 .revision = NULL,
387 .name = LY_TYPE_INST_STR,
388
389 .plugin.id = "libyang 2 - instance-identifier, version 1",
390 .plugin.store = lyplg_type_store_instanceid,
391 .plugin.validate = lyplg_type_validate_instanceid,
392 .plugin.compare = lyplg_type_compare_instanceid,
393 .plugin.sort = NULL,
394 .plugin.print = lyplg_type_print_instanceid,
395 .plugin.duplicate = lyplg_type_dup_instanceid,
396 .plugin.free = lyplg_type_free_instanceid,
397 .plugin.lyb_data_len = -1,
398 },
399 {0}
400};
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_remove(const struct ly_ctx *ctx, const char *value)
Remove specified string from the dictionary. It decrement reference counter for the string and if it ...
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:251
@ LYVE_DATA
Definition log.h:288
@ LY_ENOT
Definition log.h:265
@ LY_EINT
Definition log.h:258
@ LY_SUCCESS
Definition log.h:252
@ LY_EINCOMPLETE
Definition log.h:261
Libyang full error structure.
Definition log.h:296
Structure to hold a set of (not necessary somehow connected) objects. Usually used for lyd_node,...
Definition set.h:46
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_lypath_check_status(const struct lysc_node *ctx_node, const struct ly_path *path, LY_VALUE_FORMAT format, void *prefix_data, struct ly_err_item **err)
Check that the lypath instance-identifier value is allowed based on the status of the nodes.
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_lypath_new(const struct ly_ctx *ctx, const char *value, size_t value_len, uint32_t options, LY_VALUE_FORMAT format, void *prefix_data, const struct lysc_node *ctx_node, struct lys_glob_unres *unres, struct ly_path **path, struct ly_err_item **err)
Helper function to create internal schema path representation for instance-identifier value represent...
LIBYANG_API_DECL LY_ERR lyplg_type_validate_instanceid(const struct ly_ctx *ctx, const struct lysc_type *type, const struct lyd_node *ctx_node, const struct lyd_node *tree, struct lyd_value *storage, struct ly_err_item **err)
Implementation of lyplg_type_validate_clb for the built-in instance-identifier type.
LIBYANG_API_DEF LY_ERR lyplg_type_store_instanceid(const struct ly_ctx *ctx, const struct lysc_type *type, const void *value, size_t value_len, uint32_t options, LY_VALUE_FORMAT format, void *prefix_data, uint32_t hints, const struct lysc_node *ctx_node, struct lyd_value *storage, struct lys_glob_unres *unres, struct ly_err_item **err)
Implementation of lyplg_type_store_clb for the built-in instance-identifier type.
Definition instanceid.c:158
LIBYANG_API_DEF 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:346
LIBYANG_API_DEF 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:256
LIBYANG_API_DECL const void * lyplg_type_print_instanceid(const struct ly_ctx *ctx, const struct lyd_value *value, LY_VALUE_FORMAT format, void *prefix_data, ly_bool *dynamic, size_t *value_len)
Implementation of lyplg_type_print_clb for the built-in instance-identifier type.
LIBYANG_API_DEF 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:369
#define LYPLG_TYPE_STORE_DYNAMIC
LY_DATA_TYPE basetype
Available YANG schema tree structures representing YANG module.
Compiled YANG data node.
#define LY_ARRAY_COUNT(ARRAY)
Get the number of records in the ARRAY.
Definition tree.h:148
#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:234
#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:239
@ LY_VALUE_SCHEMA
Definition tree.h:236
@ LY_VALUE_CANON
Definition tree.h:235
@ LY_VALUE_XML
Definition tree.h:238
@ LY_VALUE_STR_NS
Definition tree.h:241
@ LY_VALUE_SCHEMA_RESOLVED
Definition tree.h:237
@ LY_VALUE_LYB
Definition tree.h:240
LIBYANG_API_DEF const void * lyplg_type_print_instanceid(const struct ly_ctx *UNUSED(ctx), const struct lyd_value *value, LY_VALUE_FORMAT format, void *prefix_data, ly_bool *dynamic, size_t *value_len)
Definition instanceid.c:319
LIBYANG_API_DEF LY_ERR lyplg_type_validate_instanceid(const struct ly_ctx *ctx, const struct lysc_type *UNUSED(type), const struct lyd_node *ctx_node, const struct lyd_node *tree, struct lyd_value *storage, struct ly_err_item **err)
Definition instanceid.c:229
const struct lyplg_type_record plugins_instanceid[]
Plugin information for instance-identifier type implementation.
Definition instanceid.c:383
The main libyang public header.
uint8_t ly_bool
Type to indicate boolean value.
Definition log.h:35
API for (user) types plugins.
LIBYANG_API_DECL char * lyd_path(const struct lyd_node *node, LYD_PATH_TYPE pathtype, char *buffer, size_t buflen)
Generate path of the given node in the requested format.
@ LYD_PATH_STD
Definition tree_data.h:2273
const struct lysc_type * realtype
Definition tree_data.h:564
const char * _canonical
Definition tree_data.h:561
Generic structure for a data node.
Definition tree_data.h:781
YANG data representation.
Definition tree_data.h:560