libyang  2.1.30
libyang is YANG data modelling language parser and toolkit written (and providing API) in C.
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
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 
58 static LY_ERR
59 union_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 
91 static LY_ERR
92 lyb_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 
127 static void
128 lyb_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 
166 static LY_ERR
167 union_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 
216 static LY_ERR
217 union_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 */
253  ly_temp_log_options(NULL);
254  return ret;
255 }
256 
271 static LY_ERR
272 lyb_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,
290  &subvalue->original, &subvalue->orig_len, options);
291  LY_CHECK_RET(ret);
292 
293  if (lyb_value) {
294  /* Resolve prefix_data and set format. */
295  ret = lyplg_type_prefix_data_new(ctx, lyb_value, lyb_value_len, LY_VALUE_LYB, prefix_data, &subvalue->format,
296  &subvalue->prefix_data);
297  LY_CHECK_RET(ret);
298  assert(subvalue->format == LY_VALUE_LYB);
299  } else {
300  /* The lyb_parse_union() did not find lyb_value.
301  * Just set format.
302  */
303  subvalue->format = LY_VALUE_LYB;
304  }
305 
306  /* Use the specific type to store the value. */
307  ret = union_store_type(ctx, type_u->types[type_idx], subvalue, 0, NULL, NULL, unres, err);
308 
309  return ret;
310 }
311 
312 LIBYANG_API_DEF LY_ERR
313 lyplg_type_store_union(const struct ly_ctx *ctx, const struct lysc_type *type, const void *value, size_t value_len,
314  uint32_t options, LY_VALUE_FORMAT format, void *prefix_data, uint32_t hints, const struct lysc_node *ctx_node,
315  struct lyd_value *storage, struct lys_glob_unres *unres, struct ly_err_item **err)
316 {
317  LY_ERR ret = LY_SUCCESS, r;
318  struct lysc_type_union *type_u = (struct lysc_type_union *)type;
319  struct lyd_value_union *subvalue;
320 
321  *err = NULL;
322 
323  /* init storage */
324  memset(storage, 0, sizeof *storage);
325  LYPLG_TYPE_VAL_INLINE_PREPARE(storage, subvalue);
326  LY_CHECK_ERR_GOTO(!subvalue, ret = LY_EMEM, cleanup);
327  storage->realtype = type;
328  subvalue->hints = hints;
329  subvalue->ctx_node = ctx_node;
330 
331  if (format == LY_VALUE_LYB) {
332  ret = lyb_fill_subvalue(ctx, type_u, value, value_len,
333  prefix_data, subvalue, &options, unres, err);
334  LY_CHECK_GOTO((ret != LY_SUCCESS) && (ret != LY_EINCOMPLETE), cleanup);
335  } else {
336  /* Store @p value to subvalue. */
337  ret = union_subvalue_assignment(value, value_len,
338  &subvalue->original, &subvalue->orig_len, &options);
339  LY_CHECK_GOTO(ret, cleanup);
340 
341  /* store format-specific data for later prefix resolution */
342  ret = lyplg_type_prefix_data_new(ctx, value, value_len, format, prefix_data, &subvalue->format,
343  &subvalue->prefix_data);
344  LY_CHECK_GOTO(ret, cleanup);
345 
346  /* use the first usable subtype to store the value */
347  ret = union_find_type(ctx, type_u->types, subvalue, 0, NULL, NULL, NULL, unres, err);
348  LY_CHECK_GOTO((ret != LY_SUCCESS) && (ret != LY_EINCOMPLETE), cleanup);
349  }
350 
351  /* store canonical value, if any (use the specific type value) */
352  r = lydict_insert(ctx, subvalue->value._canonical, 0, &storage->_canonical);
353  LY_CHECK_ERR_GOTO(r, ret = r, cleanup);
354 
355 cleanup:
356  if (options & LYPLG_TYPE_STORE_DYNAMIC) {
357  free((void *)value);
358  }
359 
360  if ((ret != LY_SUCCESS) && (ret != LY_EINCOMPLETE)) {
361  lyplg_type_free_union(ctx, storage);
362  }
363  return ret;
364 }
365 
366 LIBYANG_API_DEF LY_ERR
367 lyplg_type_validate_union(const struct ly_ctx *ctx, const struct lysc_type *type, const struct lyd_node *ctx_node,
368  const struct lyd_node *tree, struct lyd_value *storage, struct ly_err_item **err)
369 {
370  LY_ERR ret = LY_SUCCESS;
371  struct lysc_type_union *type_u = (struct lysc_type_union *)type;
372  struct lyd_value_union *subvalue = storage->subvalue;
373 
374  *err = NULL;
375 
376  /* because of types that do not store their own type as realtype (leafref), we are not able to call their
377  * validate callback (there is no way to get the type TODO could be added to struct lyd_value_union), so
378  * we have to perform union value storing again from scratch */
379  subvalue->value.realtype->plugin->free(ctx, &subvalue->value);
380 
381  /* use the first usable subtype to store the value */
382  ret = union_find_type(ctx, type_u->types, subvalue, 1, ctx_node, tree, NULL, NULL, err);
383  LY_CHECK_RET(ret);
384 
385  /* success, update the canonical value, if any generated */
386  lydict_remove(ctx, storage->_canonical);
387  LY_CHECK_RET(lydict_insert(ctx, subvalue->value._canonical, 0, &storage->_canonical));
388  return LY_SUCCESS;
389 }
390 
391 LIBYANG_API_DEF LY_ERR
392 lyplg_type_compare_union(const struct lyd_value *val1, const struct lyd_value *val2)
393 {
394  if (val1->realtype != val2->realtype) {
395  return LY_ENOT;
396  }
397 
398  if (val1->subvalue->value.realtype != val2->subvalue->value.realtype) {
399  return LY_ENOT;
400  }
401  return val1->subvalue->value.realtype->plugin->compare(&val1->subvalue->value, &val2->subvalue->value);
402 }
403 
416 static const void *
417 lyb_union_print(const struct ly_ctx *ctx, struct lysc_type_union *type_u, struct lyd_value_union *subvalue,
418  void *prefix_data, size_t *value_len)
419 {
420  void *ret = NULL;
421  LY_ERR retval;
422  struct ly_err_item *err;
423  uint64_t num = 0;
424  uint32_t type_idx;
425  ly_bool dynamic;
426  size_t pval_len;
427  void *pval;
428 
429  /* Find out the index number (type_idx). The call should succeed
430  * because the union_find_type() has already been called in the
431  * lyplg_type_store_union().
432  */
433  if (!ctx) {
434  assert(subvalue->ctx_node);
435  ctx = subvalue->ctx_node->module->ctx;
436  }
437  subvalue->value.realtype->plugin->free(ctx, &subvalue->value);
438  retval = union_find_type(ctx, type_u->types, subvalue, 0, NULL, NULL, &type_idx, NULL, &err);
439  LY_CHECK_RET((retval != LY_SUCCESS) && (retval != LY_EINCOMPLETE), NULL);
440 
441  /* Print subvalue in LYB format. */
442  pval = (void *)subvalue->value.realtype->plugin->print(NULL, &subvalue->value, LY_VALUE_LYB, prefix_data, &dynamic,
443  &pval_len);
444  LY_CHECK_RET(!pval, NULL);
445 
446  /* Create LYB data. */
447  *value_len = IDX_SIZE + pval_len;
448  ret = malloc(*value_len);
449  LY_CHECK_RET(!ret, NULL);
450 
451  num = type_idx;
452  num = htole64(num);
453  memcpy(ret, &num, IDX_SIZE);
454  memcpy((char *)ret + IDX_SIZE, pval, pval_len);
455 
456  if (dynamic) {
457  free(pval);
458  }
459 
460  return ret;
461 }
462 
463 LIBYANG_API_DEF const void *
464 lyplg_type_print_union(const struct ly_ctx *ctx, const struct lyd_value *value, LY_VALUE_FORMAT format,
465  void *prefix_data, ly_bool *dynamic, size_t *value_len)
466 {
467  const void *ret;
468  struct lyd_value_union *subvalue = value->subvalue;
469  struct lysc_type_union *type_u = (struct lysc_type_union *)value->realtype;
470  size_t lyb_data_len = 0;
471 
472  if ((format == LY_VALUE_LYB) && (subvalue->format == LY_VALUE_LYB)) {
473  /* The return value is already ready. */
474  *dynamic = 0;
475  if (value_len) {
476  *value_len = subvalue->orig_len;
477  }
478  return subvalue->original;
479  } else if ((format == LY_VALUE_LYB) && (subvalue->format != LY_VALUE_LYB)) {
480  /* The return LYB data must be created. */
481  *dynamic = 1;
482  ret = lyb_union_print(ctx, type_u, subvalue, prefix_data, &lyb_data_len);
483  if (value_len) {
484  *value_len = lyb_data_len;
485  }
486  return ret;
487  }
488 
489  assert(format != LY_VALUE_LYB);
490  ret = (void *)subvalue->value.realtype->plugin->print(ctx, &subvalue->value, format, prefix_data, dynamic, value_len);
491  if (!value->_canonical && (format == LY_VALUE_CANON)) {
492  /* the canonical value is supposed to be stored now */
493  lydict_insert(ctx, subvalue->value._canonical, 0, (const char **)&value->_canonical);
494  }
495 
496  return ret;
497 }
498 
499 LIBYANG_API_DEF LY_ERR
500 lyplg_type_dup_union(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup)
501 {
502  LY_ERR ret = LY_SUCCESS;
503  struct lyd_value_union *orig_val = original->subvalue, *dup_val;
504 
505  /* init dup value */
506  memset(dup, 0, sizeof *dup);
507  dup->realtype = original->realtype;
508 
509  ret = lydict_insert(ctx, original->_canonical, 0, &dup->_canonical);
510  LY_CHECK_GOTO(ret, cleanup);
511 
512  dup_val = calloc(1, sizeof *dup_val);
513  LY_CHECK_ERR_GOTO(!dup_val, LOGMEM(ctx); ret = LY_EMEM, cleanup);
514  dup->subvalue = dup_val;
515 
516  ret = orig_val->value.realtype->plugin->duplicate(ctx, &orig_val->value, &dup_val->value);
517  LY_CHECK_GOTO(ret, cleanup);
518 
519  if (orig_val->orig_len) {
520  dup_val->original = calloc(1, orig_val->orig_len);
521  LY_CHECK_ERR_GOTO(!dup_val->original, LOGMEM(ctx); ret = LY_EMEM, cleanup);
522  memcpy(dup_val->original, orig_val->original, orig_val->orig_len);
523  } else {
524  dup_val->original = strdup("");
525  LY_CHECK_ERR_GOTO(!dup_val->original, LOGMEM(ctx); ret = LY_EMEM, cleanup);
526  }
527  dup_val->orig_len = orig_val->orig_len;
528 
529  dup_val->format = orig_val->format;
530  dup_val->ctx_node = orig_val->ctx_node;
531  dup_val->hints = orig_val->hints;
532  ret = lyplg_type_prefix_data_dup(ctx, orig_val->format, orig_val->prefix_data, &dup_val->prefix_data);
533  LY_CHECK_GOTO(ret, cleanup);
534 
535 cleanup:
536  if (ret) {
537  lyplg_type_free_union(ctx, dup);
538  }
539  return ret;
540 }
541 
542 LIBYANG_API_DEF void
543 lyplg_type_free_union(const struct ly_ctx *ctx, struct lyd_value *value)
544 {
545  struct lyd_value_union *val;
546 
547  lydict_remove(ctx, value->_canonical);
548  value->_canonical = NULL;
549  LYD_VALUE_GET(value, val);
550  if (val) {
551  if (val->value.realtype) {
552  val->value.realtype->plugin->free(ctx, &val->value);
553  }
555  free(val->original);
556 
558  }
559 }
560 
569  {
570  .module = "",
571  .revision = NULL,
572  .name = LY_TYPE_UNION_STR,
573 
574  .plugin.id = "libyang 2 - union,version 1",
575  .plugin.store = lyplg_type_store_union,
576  .plugin.validate = lyplg_type_validate_union,
577  .plugin.compare = lyplg_type_compare_union,
578  .plugin.sort = NULL,
579  .plugin.print = lyplg_type_print_union,
580  .plugin.duplicate = lyplg_type_dup_union,
581  .plugin.free = lyplg_type_free_union,
582  .plugin.lyb_data_len = -1,
583  },
584  {0}
585 };
struct lysc_type * realtype
Definition: tree_data.h:564
Compiled YANG data node.
Definition: tree_schema.h:1414
#define LY_PRI_ARRAY_COUNT_TYPE
Printing format specifier macro for LY_ARRAY_SIZE_TYPE values.
Definition: tree.h:109
struct ly_ctx * ctx
Definition: tree_schema.h:2098
struct lyplg_type * plugin
Definition: tree_schema.h:1298
Generic structure for a data node.
Definition: tree_data.h:781
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.
Definition: log.h:256
uint8_t ly_bool
Type to indicate boolean value.
Definition: log.h:28
lyplg_type_free_clb free
LIBYANG_API_DECL 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:464
#define LYPLG_TYPE_STORE_DYNAMIC
void * original
Definition: tree_data.h:618
size_t orig_len
Definition: tree_data.h:619
#define LOGMEM(CTX)
Definition: tree_edit.h:22
LIBYANG_API_DECL void ly_temp_log_options(uint32_t *opts)
Set temporary thread-safe logger options overwriting those set by ly_log_options().
LIBYANG_API_DECL 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:392
LIBYANG_API_DECL 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:543
struct lysc_node * ctx_node
Definition: tree_data.h:625
struct lysc_type ** types
Definition: tree_schema.h:1395
The main libyang public header.
YANG data representation.
Definition: tree_data.h:560
const char * _canonical
Definition: tree_data.h:561
lyplg_type_store_clb store
Libyang full error structure.
Definition: log.h:299
Definition: log.h:291
#define LYD_VALUE_GET(value, type_val)
Get the value in format specific to the type.
Definition: tree_data.h:603
LIBYANG_API_DECL LY_ERR LIBYANG_API_DECL void ly_err_free(void *ptr)
Destructor for the error records created with ly_err_new().
Definition: log.h:262
struct lyplg_type_record plugins_union[]
Plugin information for union type implementation.
Definition: union.c:568
uint32_t hints
Definition: tree_data.h:620
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_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:313
#define IDX_SIZE
Size in bytes of the index in the LYB Binary Format.
Definition: union.c:46
void * prefix_data
Definition: tree_data.h:624
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(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...
lyplg_type_dup_clb duplicate
const char * module
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.
#define LY_ARRAY_COUNT(ARRAY)
Get the number of records in the ARRAY.
Definition: tree.h:148
LIBYANG_API_DECL void lyplg_type_prefix_data_free(LY_VALUE_FORMAT format, void *prefix_data)
Free internal prefix data.
#define LY_ARRAY_COUNT_TYPE
Type (i.e. size) of the sized array&#39;s size counter.
Definition: tree.h:104
Definition: log.h:268
struct lys_module * module
Definition: tree_schema.h:1418
#define LYPLG_TYPE_VAL_INLINE_DESTROY(type_val)
Destroy a prepared value.
LY_VALUE_FORMAT
All kinds of supported value formats and prefix mappings to modules.
Definition: tree.h:234
lyplg_type_print_clb print
lyplg_type_validate_clb validate
#define LYPLG_TYPE_VAL_INLINE_PREPARE(storage, type_val)
Prepare value memory for storing a specific type value, may be allocated dynamically.
LY_ERR
libyang&#39;s error codes returned by the libyang functions.
Definition: log.h:254
LIBYANG_API_DECL 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:367
lyplg_type_compare_clb compare
Special lyd_value structure for built-in union values.
Definition: tree_data.h:615
API for (user) types plugins.
LY_VALUE_FORMAT format
Definition: tree_data.h:621
LIBYANG_API_DECL 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:500
libyang context handler.
struct lyd_value value
Definition: tree_data.h:616
Definition: log.h:258