libyang 2.1.80
libyang is YANG data modelling language parser and toolkit written (and providing API) in C.
Loading...
Searching...
No Matches
union.c
Go to the documentation of this file.
1
15#define _GNU_SOURCE /* strdup */
16
17#include "plugins_types.h"
18
19#include <assert.h>
20#include <stdint.h>
21#include <stdlib.h>
22#include <string.h>
23
24#include "libyang.h"
25
26/* additional internal headers for some useful simple macros */
27#include "common.h"
28#include "compat.h"
29#include "plugins_internal.h" /* LY_TYPE_*_STR */
30
46#define IDX_SIZE 4
47
58static LY_ERR
59union_subvalue_assignment(const void *value, size_t value_len, void **original, size_t *orig_len, uint32_t *options)
60{
61 LY_ERR ret = LY_SUCCESS;
62
63 if (*options & LYPLG_TYPE_STORE_DYNAMIC) {
64 /* The allocated value is stored and spend. */
65 *original = (void *)value;
66 *options &= ~LYPLG_TYPE_STORE_DYNAMIC;
67 } else if (value_len) {
68 /* Make copy of the value. */
69 *original = calloc(1, value_len);
70 LY_CHECK_ERR_RET(!*original, ret = LY_EMEM, ret);
71 memcpy(*original, value, value_len);
72 } else {
73 /* Empty value. */
74 *original = strdup("");
75 LY_CHECK_ERR_RET(!*original, ret = LY_EMEM, ret);
76 }
77 *orig_len = value_len;
78
79 return ret;
80}
81
91static LY_ERR
92lyb_union_validate(const void *lyb_data, size_t lyb_data_len, const struct lysc_type_union *type_u, struct ly_err_item **err)
93{
94 LY_ERR ret = LY_SUCCESS;
95 uint64_t type_idx = 0;
96
97 /* Basic validation. */
98 if (lyb_data_len < IDX_SIZE) {
99 ret = ly_err_new(err, LY_EVALID, LYVE_DATA, NULL, NULL, "Invalid LYB union value size %zu (expected at least 4).",
100 lyb_data_len);
101 return ret;
102 }
103
104 /* Get index in correct byte order. */
105 memcpy(&type_idx, lyb_data, IDX_SIZE);
106 type_idx = le64toh(type_idx);
107 if (type_idx >= LY_ARRAY_COUNT(type_u->types)) {
108 ret = ly_err_new(err, LY_EVALID, LYVE_DATA, NULL, NULL,
109 "Invalid LYB union type index %" PRIu64 " (type count %" LY_PRI_ARRAY_COUNT_TYPE ").",
110 type_idx, LY_ARRAY_COUNT(type_u->types));
111 return ret;
112 }
113
114 return ret;
115}
116
127static void
128lyb_parse_union(const void *lyb_data, size_t lyb_data_len, uint32_t *type_idx, const void **lyb_value, size_t *lyb_value_len)
129{
130 uint64_t num = 0;
131
132 assert(lyb_data && !(lyb_value && !lyb_value_len));
133
134 if (type_idx) {
135 memcpy(&num, lyb_data, IDX_SIZE);
136 num = le64toh(num);
137
138 *type_idx = num;
139 }
140
141 if (lyb_value && lyb_value_len && lyb_data_len) {
142 /* Get lyb_value and its length. */
143 if (lyb_data_len == IDX_SIZE) {
144 *lyb_value_len = 0;
145 *lyb_value = "";
146 } else {
147 *lyb_value_len = lyb_data_len - IDX_SIZE;
148 *lyb_value = (char *)lyb_data + IDX_SIZE;
149 }
150 }
151}
152
166static LY_ERR
167union_store_type(const struct ly_ctx *ctx, struct lysc_type *type, struct lyd_value_union *subvalue,
168 ly_bool resolve, const struct lyd_node *ctx_node, const struct lyd_node *tree, struct lys_glob_unres *unres,
169 struct ly_err_item **err)
170{
171 LY_ERR ret;
172 const void *value = NULL;
173 size_t value_len = 0;
174
175 if (subvalue->format == LY_VALUE_LYB) {
176 lyb_parse_union(subvalue->original, subvalue->orig_len, NULL, &value, &value_len);
177 } else {
178 value = subvalue->original;
179 value_len = subvalue->orig_len;
180 }
181
182 ret = type->plugin->store(ctx, type, value, value_len, 0, subvalue->format, subvalue->prefix_data, subvalue->hints,
183 subvalue->ctx_node, &subvalue->value, unres, err);
184 if ((ret != LY_SUCCESS) && (ret != LY_EINCOMPLETE)) {
185 /* clear any leftover/freed garbage */
186 memset(&subvalue->value, 0, sizeof subvalue->value);
187 return ret;
188 }
189
190 if (resolve && (ret == LY_EINCOMPLETE)) {
191 /* we need the value resolved */
192 ret = type->plugin->validate(ctx, type, ctx_node, tree, &subvalue->value, err);
193 if (ret) {
194 /* resolve failed, we need to free the stored value */
195 type->plugin->free(ctx, &subvalue->value);
196 }
197 }
198
199 return ret;
200}
201
216static LY_ERR
217union_find_type(const struct ly_ctx *ctx, struct lysc_type **types, struct lyd_value_union *subvalue,
218 ly_bool resolve, const struct lyd_node *ctx_node, const struct lyd_node *tree, uint32_t *type_idx,
219 struct lys_glob_unres *unres, struct ly_err_item **err)
220{
221 LY_ERR ret = LY_SUCCESS;
223 uint32_t temp_lo = 0;
224
225 if (!types || !LY_ARRAY_COUNT(types)) {
226 return LY_EINVAL;
227 }
228
229 *err = NULL;
230
231 /* turn logging temporarily off */
232 ly_temp_log_options(&temp_lo);
233
234 /* use the first usable subtype to store the value */
235 for (u = 0; u < LY_ARRAY_COUNT(types); ++u) {
236 ret = union_store_type(ctx, types[u], subvalue, resolve, ctx_node, tree, unres, err);
237 if ((ret == LY_SUCCESS) || (ret == LY_EINCOMPLETE)) {
238 break;
239 }
240
241 ly_err_free(*err);
242 *err = NULL;
243 }
244
245 if (u == LY_ARRAY_COUNT(types)) {
246 ret = ly_err_new(err, LY_EVALID, LYVE_DATA, NULL, NULL, "Invalid union value \"%.*s\" - no matching subtype found.",
247 (int)subvalue->orig_len, (char *)subvalue->original);
248 } else if (type_idx) {
249 *type_idx = u;
250 }
251
252 /* restore logging */
254 return ret;
255}
256
271static LY_ERR
272lyb_fill_subvalue(const struct ly_ctx *ctx, struct lysc_type_union *type_u, const void *lyb_data, size_t lyb_data_len,
273 void *prefix_data, struct lyd_value_union *subvalue, uint32_t *options, struct lys_glob_unres *unres,
274 struct ly_err_item **err)
275{
276 LY_ERR ret;
277 uint32_t type_idx;
278 const void *lyb_value = NULL;
279 size_t lyb_value_len = 0;
280
281 ret = lyb_union_validate(lyb_data, lyb_data_len, type_u, err);
282 LY_CHECK_RET(ret);
283
284 /* parse lyb_data and set the lyb_value and lyb_value_len */
285 lyb_parse_union(lyb_data, lyb_data_len, &type_idx, &lyb_value, &lyb_value_len);
286 LY_CHECK_RET(ret);
287
288 /* store lyb_data to subvalue */
289 ret = union_subvalue_assignment(lyb_data, lyb_data_len, &subvalue->original, &subvalue->orig_len, options);
290 LY_CHECK_RET(ret);
291
292 if (lyb_value) {
293 /* resolve prefix_data and set format */
294 ret = lyplg_type_prefix_data_new(ctx, lyb_value, lyb_value_len, LY_VALUE_LYB, prefix_data, &subvalue->format,
295 &subvalue->prefix_data);
296 LY_CHECK_RET(ret);
297 assert(subvalue->format == LY_VALUE_LYB);
298 } else {
299 /* lyb_parse_union() did not find lyb_value, just set format */
300 subvalue->format = LY_VALUE_LYB;
301 }
302
303 /* use the specific type to store the value */
304 ret = union_store_type(ctx, type_u->types[type_idx], subvalue, 0, NULL, NULL, unres, err);
305
306 return ret;
307}
308
309LIBYANG_API_DEF LY_ERR
310lyplg_type_store_union(const struct ly_ctx *ctx, const struct lysc_type *type, const void *value, size_t value_len,
311 uint32_t options, LY_VALUE_FORMAT format, void *prefix_data, uint32_t hints, const struct lysc_node *ctx_node,
312 struct lyd_value *storage, struct lys_glob_unres *unres, struct ly_err_item **err)
313{
314 LY_ERR ret = LY_SUCCESS, r;
315 struct lysc_type_union *type_u = (struct lysc_type_union *)type;
316 struct lyd_value_union *subvalue;
317
318 *err = NULL;
319
320 /* init storage */
321 memset(storage, 0, sizeof *storage);
322 LYPLG_TYPE_VAL_INLINE_PREPARE(storage, subvalue);
323 LY_CHECK_ERR_GOTO(!subvalue, ret = LY_EMEM, cleanup);
324 storage->realtype = type;
325 subvalue->hints = hints;
326 subvalue->ctx_node = ctx_node;
327
328 if (format == LY_VALUE_LYB) {
329 ret = lyb_fill_subvalue(ctx, type_u, value, value_len, prefix_data, subvalue, &options, unres, err);
330 LY_CHECK_GOTO((ret != LY_SUCCESS) && (ret != LY_EINCOMPLETE), cleanup);
331 } else {
332 /* Store @p value to subvalue. */
333 ret = union_subvalue_assignment(value, value_len, &subvalue->original, &subvalue->orig_len, &options);
334 LY_CHECK_GOTO(ret, cleanup);
335
336 /* store format-specific data for later prefix resolution */
337 ret = lyplg_type_prefix_data_new(ctx, value, value_len, format, prefix_data, &subvalue->format,
338 &subvalue->prefix_data);
339 LY_CHECK_GOTO(ret, cleanup);
340
341 /* use the first usable subtype to store the value */
342 ret = union_find_type(ctx, type_u->types, subvalue, 0, NULL, NULL, NULL, unres, err);
343 LY_CHECK_GOTO((ret != LY_SUCCESS) && (ret != LY_EINCOMPLETE), cleanup);
344 }
345
346 /* store canonical value, if any (use the specific type value) */
347 r = lydict_insert(ctx, subvalue->value._canonical, 0, &storage->_canonical);
348 LY_CHECK_ERR_GOTO(r, ret = r, cleanup);
349
350cleanup:
351 if (options & LYPLG_TYPE_STORE_DYNAMIC) {
352 free((void *)value);
353 }
354
355 if ((ret != LY_SUCCESS) && (ret != LY_EINCOMPLETE)) {
356 lyplg_type_free_union(ctx, storage);
357 }
358 return ret;
359}
360
361LIBYANG_API_DEF LY_ERR
362lyplg_type_validate_union(const struct ly_ctx *ctx, const struct lysc_type *type, const struct lyd_node *ctx_node,
363 const struct lyd_node *tree, struct lyd_value *storage, struct ly_err_item **err)
364{
365 LY_ERR ret = LY_SUCCESS;
366 struct lysc_type_union *type_u = (struct lysc_type_union *)type;
367 struct lyd_value_union *subvalue = storage->subvalue;
368 uint32_t type_idx;
369
370 *err = NULL;
371
372 /* because of types that do not store their own type as realtype (leafref), we are not able to call their
373 * validate callback (there is no way to get the type TODO could be added to struct lyd_value_union), so
374 * we have to perform union value storing again from scratch */
375 subvalue->value.realtype->plugin->free(ctx, &subvalue->value);
376
377 if (subvalue->format == LY_VALUE_LYB) {
378 /* use the specific type to store the value */
379 lyb_parse_union(subvalue->original, 0, &type_idx, NULL, NULL);
380 ret = union_store_type(ctx, type_u->types[type_idx], subvalue, 1, ctx_node, tree, NULL, err);
381 LY_CHECK_RET(ret);
382 } else {
383 /* use the first usable subtype to store the value */
384 ret = union_find_type(ctx, type_u->types, subvalue, 1, ctx_node, tree, NULL, NULL, err);
385 LY_CHECK_RET(ret);
386 }
387
388 /* success, update the canonical value, if any generated */
389 lydict_remove(ctx, storage->_canonical);
390 LY_CHECK_RET(lydict_insert(ctx, subvalue->value._canonical, 0, &storage->_canonical));
391 return LY_SUCCESS;
392}
393
394LIBYANG_API_DEF LY_ERR
395lyplg_type_compare_union(const struct lyd_value *val1, const struct lyd_value *val2)
396{
397 if (val1->realtype != val2->realtype) {
398 return LY_ENOT;
399 }
400
401 if (val1->subvalue->value.realtype != val2->subvalue->value.realtype) {
402 return LY_ENOT;
403 }
404 return val1->subvalue->value.realtype->plugin->compare(&val1->subvalue->value, &val2->subvalue->value);
405}
406
419static const void *
420lyb_union_print(const struct ly_ctx *ctx, struct lysc_type_union *type_u, struct lyd_value_union *subvalue,
421 void *prefix_data, size_t *value_len)
422{
423 void *ret = NULL;
424 LY_ERR r;
425 struct ly_err_item *err;
426 uint64_t num = 0;
427 uint32_t type_idx = 0;
428 ly_bool dynamic;
429 size_t pval_len;
430 void *pval;
431
432 /* Find out the index number (type_idx). The call should succeed
433 * because the union_find_type() has already been called in the
434 * lyplg_type_store_union().
435 */
436 if (!ctx) {
437 assert(subvalue->ctx_node);
438 ctx = subvalue->ctx_node->module->ctx;
439 }
440 subvalue->value.realtype->plugin->free(ctx, &subvalue->value);
441 r = union_find_type(ctx, type_u->types, subvalue, 0, NULL, NULL, &type_idx, NULL, &err);
442 LY_CHECK_RET((r != LY_SUCCESS) && (r != LY_EINCOMPLETE), NULL);
443
444 /* Print subvalue in LYB format. */
445 pval = (void *)subvalue->value.realtype->plugin->print(NULL, &subvalue->value, LY_VALUE_LYB, prefix_data, &dynamic,
446 &pval_len);
447 LY_CHECK_RET(!pval, NULL);
448
449 /* Create LYB data. */
450 *value_len = IDX_SIZE + pval_len;
451 ret = malloc(*value_len);
452 LY_CHECK_RET(!ret, NULL);
453
454 num = type_idx;
455 num = htole64(num);
456 memcpy(ret, &num, IDX_SIZE);
457 memcpy((char *)ret + IDX_SIZE, pval, pval_len);
458
459 if (dynamic) {
460 free(pval);
461 }
462
463 return ret;
464}
465
466LIBYANG_API_DEF const void *
467lyplg_type_print_union(const struct ly_ctx *ctx, const struct lyd_value *value, LY_VALUE_FORMAT format,
468 void *prefix_data, ly_bool *dynamic, size_t *value_len)
469{
470 const void *ret;
471 struct lyd_value_union *subvalue = value->subvalue;
472 struct lysc_type_union *type_u = (struct lysc_type_union *)value->realtype;
473 size_t lyb_data_len = 0;
474
475 if ((format == LY_VALUE_LYB) && (subvalue->format == LY_VALUE_LYB)) {
476 /* The return value is already ready. */
477 *dynamic = 0;
478 if (value_len) {
479 *value_len = subvalue->orig_len;
480 }
481 return subvalue->original;
482 } else if ((format == LY_VALUE_LYB) && (subvalue->format != LY_VALUE_LYB)) {
483 /* The return LYB data must be created. */
484 *dynamic = 1;
485 ret = lyb_union_print(ctx, type_u, subvalue, prefix_data, &lyb_data_len);
486 if (value_len) {
487 *value_len = lyb_data_len;
488 }
489 return ret;
490 }
491
492 assert(format != LY_VALUE_LYB);
493 ret = (void *)subvalue->value.realtype->plugin->print(ctx, &subvalue->value, format, prefix_data, dynamic, value_len);
494 if (!value->_canonical && (format == LY_VALUE_CANON)) {
495 /* the canonical value is supposed to be stored now */
496 lydict_insert(ctx, subvalue->value._canonical, 0, (const char **)&value->_canonical);
497 }
498
499 return ret;
500}
501
502LIBYANG_API_DEF LY_ERR
503lyplg_type_dup_union(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup)
504{
505 LY_ERR ret = LY_SUCCESS;
506 struct lyd_value_union *orig_val = original->subvalue, *dup_val;
507
508 /* init dup value */
509 memset(dup, 0, sizeof *dup);
510 dup->realtype = original->realtype;
511
512 ret = lydict_insert(ctx, original->_canonical, 0, &dup->_canonical);
513 LY_CHECK_GOTO(ret, cleanup);
514
515 dup_val = calloc(1, sizeof *dup_val);
516 LY_CHECK_ERR_GOTO(!dup_val, LOGMEM(ctx); ret = LY_EMEM, cleanup);
517 dup->subvalue = dup_val;
518
519 ret = orig_val->value.realtype->plugin->duplicate(ctx, &orig_val->value, &dup_val->value);
520 LY_CHECK_GOTO(ret, cleanup);
521
522 if (orig_val->orig_len) {
523 dup_val->original = calloc(1, orig_val->orig_len);
524 LY_CHECK_ERR_GOTO(!dup_val->original, LOGMEM(ctx); ret = LY_EMEM, cleanup);
525 memcpy(dup_val->original, orig_val->original, orig_val->orig_len);
526 } else {
527 dup_val->original = strdup("");
528 LY_CHECK_ERR_GOTO(!dup_val->original, LOGMEM(ctx); ret = LY_EMEM, cleanup);
529 }
530 dup_val->orig_len = orig_val->orig_len;
531
532 dup_val->format = orig_val->format;
533 dup_val->ctx_node = orig_val->ctx_node;
534 dup_val->hints = orig_val->hints;
535 ret = lyplg_type_prefix_data_dup(ctx, orig_val->format, orig_val->prefix_data, &dup_val->prefix_data);
536 LY_CHECK_GOTO(ret, cleanup);
537
538cleanup:
539 if (ret) {
540 lyplg_type_free_union(ctx, dup);
541 }
542 return ret;
543}
544
545LIBYANG_API_DEF void
546lyplg_type_free_union(const struct ly_ctx *ctx, struct lyd_value *value)
547{
548 struct lyd_value_union *val;
549
551 value->_canonical = NULL;
552 LYD_VALUE_GET(value, val);
553 if (val) {
554 if (val->value.realtype) {
555 val->value.realtype->plugin->free(ctx, &val->value);
556 }
558 free(val->original);
559
561 }
562}
563
572 {
573 .module = "",
574 .revision = NULL,
575 .name = LY_TYPE_UNION_STR,
576
577 .plugin.id = "libyang 2 - union,version 1",
578 .plugin.store = lyplg_type_store_union,
579 .plugin.validate = lyplg_type_validate_union,
580 .plugin.compare = lyplg_type_compare_union,
581 .plugin.sort = NULL,
582 .plugin.print = lyplg_type_print_union,
583 .plugin.duplicate = lyplg_type_dup_union,
584 .plugin.free = lyplg_type_free_union,
585 .plugin.lyb_data_len = -1,
586 },
587 {0}
588};
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 ...
LY_ERR
libyang's error codes returned by the libyang functions.
Definition log.h:251
@ LYVE_DATA
Definition log.h:288
@ LY_EINVAL
Definition log.h:255
@ LY_EMEM
Definition log.h:253
@ LY_ENOT
Definition log.h:265
@ LY_EVALID
Definition log.h:259
@ LY_SUCCESS
Definition log.h:252
@ LY_EINCOMPLETE
Definition log.h:261
Libyang full error structure.
Definition log.h:296
LIBYANG_API_DECL void ly_temp_log_options(uint32_t *opts)
Set temporary thread-safe logger options overwriting those set by ly_log_options().
const char *const char * revision
lyplg_type_print_clb print
lyplg_type_store_clb store
lyplg_type_compare_clb compare
lyplg_type_validate_clb validate
lyplg_type_dup_clb duplicate
lyplg_type_free_clb free
#define LYPLG_TYPE_VAL_INLINE_PREPARE(storage, type_val)
Prepare value memory for storing a specific type value, may be allocated dynamically.
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 LY_ERR LIBYANG_API_DECL void ly_err_free(void *ptr)
Destructor for the error records created with ly_err_new().
#define LYPLG_TYPE_VAL_INLINE_DESTROY(type_val)
Destroy a prepared value.
LIBYANG_API_DECL LY_ERR lyplg_type_prefix_data_new(const struct ly_ctx *ctx, const void *value, size_t value_len, LY_VALUE_FORMAT format, const void *prefix_data, LY_VALUE_FORMAT *format_p, void **prefix_data_p)
Store used prefixes in a string into an internal libyang structure used in lyd_value.
LIBYANG_API_DECL LY_ERR lyplg_type_prefix_data_dup(const struct ly_ctx *ctx, LY_VALUE_FORMAT format, const void *orig, void **dup)
Duplicate prefix data.
LIBYANG_API_DECL void lyplg_type_prefix_data_free(LY_VALUE_FORMAT format, void *prefix_data)
Free internal prefix data.
LIBYANG_API_DEF void lyplg_type_free_union(const struct ly_ctx *ctx, struct lyd_value *value)
Implementation of lyplg_type_free_clb for the built-in union type.
Definition union.c:546
LIBYANG_API_DEF LY_ERR lyplg_type_compare_union(const struct lyd_value *val1, const struct lyd_value *val2)
Implementation of lyplg_type_compare_clb for the built-in union type.
Definition union.c:395
LIBYANG_API_DEF const void * lyplg_type_print_union(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 union type.
Definition union.c:467
LIBYANG_API_DEF LY_ERR lyplg_type_validate_union(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 union type.
Definition union.c:362
LIBYANG_API_DEF LY_ERR lyplg_type_store_union(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 union type.
Definition union.c:310
LIBYANG_API_DEF LY_ERR lyplg_type_dup_union(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup)
Implementation of lyplg_type_dup_clb for the built-in union type.
Definition union.c:503
#define LYPLG_TYPE_STORE_DYNAMIC
struct lyplg_type * plugin
struct lysc_type ** types
Compiled YANG data node.
#define LY_ARRAY_COUNT(ARRAY)
Get the number of records in the ARRAY.
Definition tree.h:148
LY_VALUE_FORMAT
All kinds of supported value formats and prefix mappings to modules.
Definition tree.h:234
#define LY_PRI_ARRAY_COUNT_TYPE
Printing format specifier macro for LY_ARRAY_SIZE_TYPE values.
Definition tree.h:109
#define LY_ARRAY_COUNT_TYPE
Type (i.e. size) of the sized array's size counter.
Definition tree.h:104
@ LY_VALUE_CANON
Definition tree.h:235
@ LY_VALUE_LYB
Definition tree.h:240
The main libyang public header.
uint8_t ly_bool
Type to indicate boolean value.
Definition log.h:35
API for (user) types plugins.
const struct lysc_type * realtype
Definition tree_data.h:564
void * prefix_data
Definition tree_data.h:624
uint32_t hints
Definition tree_data.h:620
#define LYD_VALUE_GET(value, type_val)
Get the value in format specific to the type.
Definition tree_data.h:603
struct lyd_value value
Definition tree_data.h:616
const char * _canonical
Definition tree_data.h:561
LY_VALUE_FORMAT format
Definition tree_data.h:621
const struct lysc_node * ctx_node
Definition tree_data.h:625
Generic structure for a data node.
Definition tree_data.h:781
YANG data representation.
Definition tree_data.h:560
Special lyd_value structure for built-in union values.
Definition tree_data.h:615
#define LOGMEM(CTX)
Definition tree_edit.h:22
#define IDX_SIZE
Size in bytes of the index in the LYB Binary Format.
Definition union.c:46
const struct lyplg_type_record plugins_union[]
Plugin information for union type implementation.
Definition union.c:571