libyang  2.1.80
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, &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 
309 LIBYANG_API_DEF LY_ERR
310 lyplg_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 
350 cleanup:
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 
361 LIBYANG_API_DEF LY_ERR
362 lyplg_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 
394 LIBYANG_API_DEF LY_ERR
395 lyplg_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 
419 static const void *
420 lyb_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 
466 LIBYANG_API_DEF const void *
467 lyplg_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 
502 LIBYANG_API_DEF LY_ERR
503 lyplg_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 
538 cleanup:
539  if (ret) {
540  lyplg_type_free_union(ctx, dup);
541  }
542  return ret;
543 }
544 
545 LIBYANG_API_DEF void
546 lyplg_type_free_union(const struct ly_ctx *ctx, struct lyd_value *value)
547 {
548  struct lyd_value_union *val;
549 
550  lydict_remove(ctx, value->_canonical);
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 };
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:2101
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:467
#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:395
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:546
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:571
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:310
#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:362
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:503
libyang context handler.
struct lyd_value value
Definition: tree_data.h:616
Definition: log.h:258