libyang  3.7.5
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 "compat.h"
28 #include "ly_common.h"
29 #include "plugins_internal.h" /* LY_TYPE_*_STR */
30 
46 #define TYPE_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 < TYPE_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, TYPE_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, TYPE_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 == TYPE_IDX_SIZE) {
144  *lyb_value_len = 0;
145  *lyb_value = "";
146  } else {
147  *lyb_value_len = lyb_data_len - TYPE_IDX_SIZE;
148  *lyb_value = (char *)lyb_data + TYPE_IDX_SIZE;
149  }
150  }
151 }
152 
168 static LY_ERR
169 union_store_type(const struct ly_ctx *ctx, struct lysc_type_union *type_u, uint32_t type_idx, struct lyd_value_union *subvalue,
170  uint32_t options, ly_bool validate, const struct lyd_node *ctx_node, const struct lyd_node *tree,
171  struct lys_glob_unres *unres, struct ly_err_item **err)
172 {
173  LY_ERR rc = LY_SUCCESS;
174  struct lysc_type *type = type_u->types[type_idx];
175  const void *value = NULL;
176  size_t value_len = 0;
177  ly_bool dynamic = 0;
178  LY_VALUE_FORMAT format;
179  void *prefix_data;
180  uint32_t opts = 0, ti;
181 
182  *err = NULL;
183 
184  if (subvalue->format == LY_VALUE_LYB) {
185  lyb_parse_union(subvalue->original, subvalue->orig_len, &ti, &value, &value_len);
186  if (ti != type_idx) {
187  /* value of another type, first store the value properly and then use its JSON value for parsing */
188  rc = type_u->types[ti]->plugin->store(ctx, type_u->types[ti], value, value_len, LYPLG_TYPE_STORE_ONLY,
189  subvalue->format, subvalue->prefix_data, subvalue->hints, subvalue->ctx_node, &subvalue->value, unres, err);
190  if ((rc != LY_SUCCESS) && (rc != LY_EINCOMPLETE)) {
191  /* clear any leftover/freed garbage */
192  memset(&subvalue->value, 0, sizeof subvalue->value);
193  return rc;
194  }
195 
196  assert(subvalue->value.realtype);
197  value = subvalue->value.realtype->plugin->print(ctx, &subvalue->value, LY_VALUE_JSON, NULL, &dynamic, &value_len);
198 
199  /* to avoid leaks, free subvalue->value, but we need the value, which may be stored there */
200  if (!dynamic) {
201  value = strndup(value, value_len);
202  dynamic = 1;
203  }
204  type_u->types[ti]->plugin->free(ctx, &subvalue->value);
205 
206  format = LY_VALUE_JSON;
207  prefix_data = NULL;
208  } else {
209  format = subvalue->format;
210  prefix_data = subvalue->prefix_data;
211  }
212  } else {
213  value = subvalue->original;
214  value_len = subvalue->orig_len;
215  format = subvalue->format;
216  prefix_data = subvalue->prefix_data;
217  }
218 
219  if (options & LYPLG_TYPE_STORE_ONLY) {
220  opts |= LYPLG_TYPE_STORE_ONLY;
221  }
222  if (dynamic) {
223  opts |= LYPLG_TYPE_STORE_DYNAMIC;
224  }
225 
226  rc = type->plugin->store(ctx, type, value, value_len, opts, format, prefix_data, subvalue->hints,
227  subvalue->ctx_node, &subvalue->value, unres, err);
228  if ((rc != LY_SUCCESS) && (rc != LY_EINCOMPLETE)) {
229  /* clear any leftover/freed garbage */
230  memset(&subvalue->value, 0, sizeof subvalue->value);
231  return rc;
232  }
233 
234  if (validate && (rc == LY_EINCOMPLETE)) {
235  /* we need the value validated */
236  rc = type->plugin->validate(ctx, type, ctx_node, tree, &subvalue->value, err);
237  if (rc) {
238  /* validate failed, we need to free the stored value */
239  type->plugin->free(ctx, &subvalue->value);
240  }
241  }
242 
243  return rc;
244 }
245 
261 static LY_ERR
262 union_find_type(const struct ly_ctx *ctx, struct lysc_type_union *type_u, struct lyd_value_union *subvalue,
263  uint32_t options, ly_bool resolve, const struct lyd_node *ctx_node, const struct lyd_node *tree,
264  uint32_t *type_idx, struct lys_glob_unres *unres, struct ly_err_item **err)
265 {
266  LY_ERR ret = LY_SUCCESS;
268  struct ly_err_item **errs = NULL, *e;
269  uint32_t *prev_lo, temp_lo = 0;
270  char *msg = NULL;
271  int msg_len = 0;
272 
273  *err = NULL;
274 
275  /* alloc errors */
276  errs = calloc(LY_ARRAY_COUNT(type_u->types), sizeof *errs);
277  LY_CHECK_RET(!errs, LY_EMEM);
278 
279  /* turn logging temporarily off */
280  prev_lo = ly_temp_log_options(&temp_lo);
281 
282  /* use the first usable subtype to store the value */
283  for (u = 0; u < LY_ARRAY_COUNT(type_u->types); ++u) {
284  ret = union_store_type(ctx, type_u, u, subvalue, options, resolve, ctx_node, tree, unres, &e);
285  if ((ret == LY_SUCCESS) || (ret == LY_EINCOMPLETE)) {
286  break;
287  }
288 
289  errs[u] = e;
290  }
291 
292  if (u == LY_ARRAY_COUNT(type_u->types)) {
293  /* create the full error */
294  if (subvalue->format == LY_VALUE_LYB) {
295  msg_len = asprintf(&msg, "Invalid LYB union value - no matching subtype found:\n");
296  } else {
297  msg_len = asprintf(&msg, "Invalid union value \"%.*s\" - no matching subtype found:\n",
298  (int)subvalue->orig_len, (char *)subvalue->original);
299  }
300  if (msg_len == -1) {
301  LY_CHECK_ERR_GOTO(!errs, ret = LY_EMEM, cleanup);
302  }
303  for (u = 0; u < LY_ARRAY_COUNT(type_u->types); ++u) {
304  if (!errs[u]) {
305  /* no error for some reason */
306  continue;
307  }
308 
309  msg = ly_realloc(msg, msg_len + 4 + strlen(type_u->types[u]->plugin->id) + 2 + strlen(errs[u]->msg) + 2);
310  LY_CHECK_ERR_GOTO(!msg, ret = LY_EMEM, cleanup);
311  msg_len += sprintf(msg + msg_len, " %s: %s\n", type_u->types[u]->plugin->id, errs[u]->msg);
312  }
313 
314  ret = ly_err_new(err, LY_EVALID, LYVE_DATA, NULL, NULL, "%s", msg);
315  } else if (type_idx) {
316  *type_idx = u;
317  }
318 
319 cleanup:
320  for (u = 0; u < LY_ARRAY_COUNT(type_u->types); ++u) {
321  ly_err_free(errs[u]);
322  }
323  free(errs);
324  free(msg);
325  ly_temp_log_options(prev_lo);
326  return ret;
327 }
328 
343 static LY_ERR
344 lyb_fill_subvalue(const struct ly_ctx *ctx, struct lysc_type_union *type_u, const void *lyb_data, size_t lyb_data_len,
345  void *prefix_data, struct lyd_value_union *subvalue, uint32_t *options, struct lys_glob_unres *unres,
346  struct ly_err_item **err)
347 {
348  LY_ERR ret;
349  uint32_t type_idx;
350  const void *lyb_value = NULL;
351  size_t lyb_value_len = 0;
352 
353  ret = lyb_union_validate(lyb_data, lyb_data_len, type_u, err);
354  LY_CHECK_RET(ret);
355 
356  /* parse lyb_data and set the lyb_value and lyb_value_len */
357  lyb_parse_union(lyb_data, lyb_data_len, &type_idx, &lyb_value, &lyb_value_len);
358  LY_CHECK_RET(ret);
359 
360  /* store lyb_data to subvalue */
361  ret = union_subvalue_assignment(lyb_data, lyb_data_len, &subvalue->original, &subvalue->orig_len, options);
362  LY_CHECK_RET(ret);
363 
364  if (lyb_value) {
365  /* resolve prefix_data and set format */
366  ret = lyplg_type_prefix_data_new(ctx, lyb_value, lyb_value_len, LY_VALUE_LYB, prefix_data, &subvalue->format,
367  &subvalue->prefix_data);
368  LY_CHECK_RET(ret);
369  assert(subvalue->format == LY_VALUE_LYB);
370  } else {
371  /* lyb_parse_union() did not find lyb_value, just set format */
372  subvalue->format = LY_VALUE_LYB;
373  }
374 
375  /* use the specific type to store the value */
376  ret = union_store_type(ctx, type_u, type_idx, subvalue, *options, 0, NULL, NULL, unres, err);
377 
378  return ret;
379 }
380 
381 LIBYANG_API_DEF LY_ERR
382 lyplg_type_store_union(const struct ly_ctx *ctx, const struct lysc_type *type, const void *value, size_t value_len,
383  uint32_t options, LY_VALUE_FORMAT format, void *prefix_data, uint32_t hints, const struct lysc_node *ctx_node,
384  struct lyd_value *storage, struct lys_glob_unres *unres, struct ly_err_item **err)
385 {
386  LY_ERR ret = LY_SUCCESS, r;
387  struct lysc_type_union *type_u = (struct lysc_type_union *)type;
388  struct lyd_value_union *subvalue;
389 
390  *err = NULL;
391 
392  /* init storage */
393  memset(storage, 0, sizeof *storage);
394  LYPLG_TYPE_VAL_INLINE_PREPARE(storage, subvalue);
395  LY_CHECK_ERR_GOTO(!subvalue, ret = LY_EMEM, cleanup);
396  storage->realtype = type;
397  subvalue->hints = hints;
398  subvalue->ctx_node = ctx_node;
399 
400  if (format == LY_VALUE_LYB) {
401  ret = lyb_fill_subvalue(ctx, type_u, value, value_len, prefix_data, subvalue, &options, unres, err);
402  LY_CHECK_GOTO((ret != LY_SUCCESS) && (ret != LY_EINCOMPLETE), cleanup);
403  } else {
404  /* to correctly resolve the union type, we need to always validate the value */
405  options &= ~LYPLG_TYPE_STORE_ONLY;
406 
407  /* store value to subvalue */
408  ret = union_subvalue_assignment(value, value_len, &subvalue->original, &subvalue->orig_len, &options);
409  LY_CHECK_GOTO(ret, cleanup);
410 
411  /* store format-specific data for later prefix resolution */
412  ret = lyplg_type_prefix_data_new(ctx, value, value_len, format, prefix_data, &subvalue->format,
413  &subvalue->prefix_data);
414  LY_CHECK_GOTO(ret, cleanup);
415 
416  /* use the first usable subtype to store the value */
417  ret = union_find_type(ctx, type_u, subvalue, options, 0, NULL, NULL, NULL, unres, err);
418  LY_CHECK_GOTO((ret != LY_SUCCESS) && (ret != LY_EINCOMPLETE), cleanup);
419  }
420 
421  /* store canonical value, if any (use the specific type value) */
422  r = lydict_insert(ctx, subvalue->value._canonical, 0, &storage->_canonical);
423  LY_CHECK_ERR_GOTO(r, ret = r, cleanup);
424 
425 cleanup:
426  if (options & LYPLG_TYPE_STORE_DYNAMIC) {
427  free((void *)value);
428  }
429 
430  if ((ret != LY_SUCCESS) && (ret != LY_EINCOMPLETE)) {
431  lyplg_type_free_union(ctx, storage);
432  }
433  return ret;
434 }
435 
436 LIBYANG_API_DEF LY_ERR
437 lyplg_type_validate_union(const struct ly_ctx *ctx, const struct lysc_type *type, const struct lyd_node *ctx_node,
438  const struct lyd_node *tree, struct lyd_value *storage, struct ly_err_item **err)
439 {
440  LY_ERR rc = LY_SUCCESS;
441  struct lysc_type_union *type_u = (struct lysc_type_union *)type;
442  struct lyd_value_union *subvalue = storage->subvalue;
443  struct lyd_value orig = {0};
444  uint32_t type_idx;
445  ly_bool validated = 0;
446 
447  *err = NULL;
448 
449  /* because of types that do not store their own type as realtype (leafref), we are not able to call their
450  * validate callback (there is no way to get the type) but even if possible, the value may be invalid
451  * for the type, so we may have to perform union value storing again from scratch, but keep a value backup */
452  LY_CHECK_RET(subvalue->value.realtype->plugin->duplicate(ctx, &subvalue->value, &orig));
453  subvalue->value.realtype->plugin->free(ctx, &subvalue->value);
454 
455  if (subvalue->format == LY_VALUE_LYB) {
456  /* use the specific type to store and validate the value */
457  lyb_parse_union(subvalue->original, 0, &type_idx, NULL, NULL);
458 
459  if (union_store_type(ctx, type_u, type_idx, subvalue, 0, 1, ctx_node, tree, NULL, err)) {
460  /* validation failed, we need to try storing the value again */
461  ly_err_free(*err);
462  *err = NULL;
463  } else {
464  validated = 1;
465  }
466  }
467 
468  if (!validated) {
469  /* use the first usable subtype to store and validate the value */
470  rc = union_find_type(ctx, type_u, subvalue, 0, 1, ctx_node, tree, NULL, NULL, err);
471  if (rc) {
472  /* validation failed, restore the previous value */
473  subvalue->value = orig;
474  return rc;
475  }
476  }
477 
478  /* update the canonical value, if any generated */
479  lydict_remove(ctx, storage->_canonical);
480  LY_CHECK_RET(lydict_insert(ctx, subvalue->value._canonical, 0, &storage->_canonical));
481 
482  /* free backup value */
483  orig.realtype->plugin->free(ctx, &orig);
484  return LY_SUCCESS;
485 }
486 
487 LIBYANG_API_DEF LY_ERR
488 lyplg_type_compare_union(const struct ly_ctx *ctx, const struct lyd_value *val1, const struct lyd_value *val2)
489 {
490  if (val1->subvalue->value.realtype != val2->subvalue->value.realtype) {
491  return LY_ENOT;
492  }
493  return val1->subvalue->value.realtype->plugin->compare(ctx, &val1->subvalue->value, &val2->subvalue->value);
494 }
495 
496 LIBYANG_API_DEF int
497 lyplg_type_sort_union(const struct ly_ctx *ctx, const struct lyd_value *val1, const struct lyd_value *val2)
498 {
499  int rc = LY_SUCCESS;
501  struct lysc_type **types;
502 
503  if (val1->subvalue->value.realtype == val2->subvalue->value.realtype) {
504  return val1->subvalue->value.realtype->plugin->sort(ctx, &val1->subvalue->value, &val2->subvalue->value);
505  }
506 
507  /* compare according to the order of types */
508  types = ((struct lysc_type_union *)val1->realtype)->types;
509  LY_ARRAY_FOR(types, u) {
510  if (types[u] == val1->subvalue->value.realtype) {
511  rc = 1;
512  break;
513  } else if (types[u] == val2->subvalue->value.realtype) {
514  rc = -1;
515  break;
516  }
517  }
518  assert(rc != 0);
519 
520  return rc;
521 }
522 
535 static const void *
536 lyb_union_print(const struct ly_ctx *ctx, struct lysc_type_union *type_u, struct lyd_value_union *subvalue,
537  void *prefix_data, size_t *value_len)
538 {
539  void *ret = NULL;
540  LY_ERR r;
541  struct ly_err_item *err;
542  uint64_t num = 0;
543  uint32_t type_idx = 0;
544  ly_bool dynamic;
545  size_t pval_len;
546  void *pval;
547 
548  /* Find out the index number (type_idx). The call should succeed
549  * because the union_find_type() has already been called in the
550  * lyplg_type_store_union().
551  */
552  if (!ctx) {
553  assert(subvalue->ctx_node);
554  ctx = subvalue->ctx_node->module->ctx;
555  }
556  subvalue->value.realtype->plugin->free(ctx, &subvalue->value);
557  r = union_find_type(ctx, type_u, subvalue, 0, 0, NULL, NULL, &type_idx, NULL, &err);
558  ly_err_free(err);
559  LY_CHECK_RET((r != LY_SUCCESS) && (r != LY_EINCOMPLETE), NULL);
560 
561  /* Print subvalue in LYB format. */
562  pval = (void *)subvalue->value.realtype->plugin->print(NULL, &subvalue->value, LY_VALUE_LYB, prefix_data, &dynamic,
563  &pval_len);
564  LY_CHECK_RET(!pval, NULL);
565 
566  /* Create LYB data. */
567  *value_len = TYPE_IDX_SIZE + pval_len;
568  ret = malloc(*value_len);
569  LY_CHECK_RET(!ret, NULL);
570 
571  num = type_idx;
572  num = htole64(num);
573  memcpy(ret, &num, TYPE_IDX_SIZE);
574  memcpy((char *)ret + TYPE_IDX_SIZE, pval, pval_len);
575 
576  if (dynamic) {
577  free(pval);
578  }
579 
580  return ret;
581 }
582 
583 LIBYANG_API_DEF const void *
584 lyplg_type_print_union(const struct ly_ctx *ctx, const struct lyd_value *value, LY_VALUE_FORMAT format,
585  void *prefix_data, ly_bool *dynamic, size_t *value_len)
586 {
587  const void *ret;
588  struct lyd_value_union *subvalue = value->subvalue;
589  struct lysc_type_union *type_u = (struct lysc_type_union *)value->realtype;
590  size_t lyb_data_len = 0;
591 
592  if ((format == LY_VALUE_LYB) && (subvalue->format == LY_VALUE_LYB)) {
593  /* The return value is already ready. */
594  *dynamic = 0;
595  if (value_len) {
596  *value_len = subvalue->orig_len;
597  }
598  return subvalue->original;
599  } else if ((format == LY_VALUE_LYB) && (subvalue->format != LY_VALUE_LYB)) {
600  /* The return LYB data must be created. */
601  *dynamic = 1;
602  ret = lyb_union_print(ctx, type_u, subvalue, prefix_data, &lyb_data_len);
603  if (value_len) {
604  *value_len = lyb_data_len;
605  }
606  return ret;
607  }
608 
609  assert(format != LY_VALUE_LYB);
610  ret = (void *)subvalue->value.realtype->plugin->print(ctx, &subvalue->value, format, prefix_data, dynamic, value_len);
611  if (!value->_canonical && (format == LY_VALUE_CANON)) {
612  /* the canonical value is supposed to be stored now */
613  lydict_insert(ctx, subvalue->value._canonical, 0, (const char **)&value->_canonical);
614  }
615 
616  return ret;
617 }
618 
619 LIBYANG_API_DEF LY_ERR
620 lyplg_type_dup_union(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup)
621 {
622  LY_ERR ret = LY_SUCCESS;
623  struct lyd_value_union *orig_val = original->subvalue, *dup_val;
624 
625  /* init dup value */
626  memset(dup, 0, sizeof *dup);
627  dup->realtype = original->realtype;
628 
629  ret = lydict_insert(ctx, original->_canonical, 0, &dup->_canonical);
630  LY_CHECK_GOTO(ret, cleanup);
631 
632  dup_val = calloc(1, sizeof *dup_val);
633  LY_CHECK_ERR_GOTO(!dup_val, LOGMEM(ctx); ret = LY_EMEM, cleanup);
634  dup->subvalue = dup_val;
635 
636  ret = orig_val->value.realtype->plugin->duplicate(ctx, &orig_val->value, &dup_val->value);
637  LY_CHECK_GOTO(ret, cleanup);
638 
639  if (orig_val->orig_len) {
640  dup_val->original = calloc(1, orig_val->orig_len);
641  LY_CHECK_ERR_GOTO(!dup_val->original, LOGMEM(ctx); ret = LY_EMEM, cleanup);
642  memcpy(dup_val->original, orig_val->original, orig_val->orig_len);
643  } else {
644  dup_val->original = strdup("");
645  LY_CHECK_ERR_GOTO(!dup_val->original, LOGMEM(ctx); ret = LY_EMEM, cleanup);
646  }
647  dup_val->orig_len = orig_val->orig_len;
648 
649  dup_val->format = orig_val->format;
650  dup_val->ctx_node = orig_val->ctx_node;
651  dup_val->hints = orig_val->hints;
652  ret = lyplg_type_prefix_data_dup(ctx, orig_val->format, orig_val->prefix_data, &dup_val->prefix_data);
653  LY_CHECK_GOTO(ret, cleanup);
654 
655 cleanup:
656  if (ret) {
657  lyplg_type_free_union(ctx, dup);
658  }
659  return ret;
660 }
661 
662 LIBYANG_API_DEF void
663 lyplg_type_free_union(const struct ly_ctx *ctx, struct lyd_value *value)
664 {
665  struct lyd_value_union *val;
666 
667  lydict_remove(ctx, value->_canonical);
668  value->_canonical = NULL;
669  LYD_VALUE_GET(value, val);
670  if (val) {
671  if (val->value.realtype) {
672  val->value.realtype->plugin->free(ctx, &val->value);
673  }
675  free(val->original);
676 
678  }
679 }
680 
689  {
690  .module = "",
691  .revision = NULL,
692  .name = LY_TYPE_UNION_STR,
693 
694  .plugin.id = "libyang 2 - union,version 1",
695  .plugin.store = lyplg_type_store_union,
696  .plugin.validate = lyplg_type_validate_union,
697  .plugin.compare = lyplg_type_compare_union,
698  .plugin.sort = lyplg_type_sort_union,
699  .plugin.print = lyplg_type_print_union,
700  .plugin.duplicate = lyplg_type_dup_union,
701  .plugin.free = lyplg_type_free_union,
702  .plugin.lyb_data_len = -1,
703  },
704  {0}
705 };
struct lysc_type * realtype
Definition: tree_data.h:579
Compiled YANG data node.
Definition: tree_schema.h:1439
#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:2132
memset(value->fixed_mem, 0, LYD_VALUE_FIXED_MEM_SIZE)
const char * id
struct lyplg_type * plugin
Definition: tree_schema.h:1304
Generic structure for a data node.
Definition: tree_data.h:803
LIBYANG_API_DECL uint32_t * ly_temp_log_options(uint32_t *opts)
Set temporary thread-safe logger options overwriting those set by ly_log_options().
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:584
Definition: log.h:242
LY_ERR err
Definition: log.h:287
#define LYPLG_TYPE_STORE_DYNAMIC
void * original
Definition: tree_data.h:633
size_t orig_len
Definition: tree_data.h:634
#define LOGMEM(CTX)
Definition: tree_edit.h:22
char * msg
Definition: log.h:289
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:663
struct lysc_node * ctx_node
Definition: tree_data.h:640
struct lysc_type ** types
Definition: tree_schema.h:1418
LYPLG_TYPE_VAL_INLINE_DESTROY(val)
The main libyang public header.
YANG data representation.
Definition: tree_data.h:575
const char * _canonical
Definition: tree_data.h:576
lyplg_type_store_clb store
Libyang full error structure.
Definition: log.h:285
Definition: log.h:277
#define LYD_VALUE_GET(value, type_val)
Get the value in format specific to the type.
Definition: tree_data.h:618
LIBYANG_API_DECL LY_ERR LIBYANG_API_DECL void ly_err_free(void *ptr)
Destructor for the error records created with ly_err_new().
LIBYANG_API_DECL LY_ERR ly_err_new(struct ly_err_item **err, LY_ERR ecode, LY_VECODE vecode, char *data_path, char *apptag, const char *err_format,...) _FORMAT_PRINTF(6
Create and fill error structure.
struct lyplg_type_record plugins_union[]
Plugin information for union type implementation.
Definition: union.c:688
uint32_t hints
Definition: tree_data.h:635
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:382
LIBYANG_API_DECL LY_ERR lyplg_type_compare_union(const struct ly_ctx *ctx, 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:488
void * prefix_data
Definition: tree_data.h:639
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
lyplg_type_sort_clb sort
LIBYANG_API_DECL int lyplg_type_sort_union(const struct ly_ctx *ctx, const struct lyd_value *val1, const struct lyd_value *val2)
Implementation of lyplg_type_sort_clb for the built-in union type.
Definition: union.c:497
LIBYANG_API_DECL void lyplg_type_prefix_data_free(LY_VALUE_FORMAT format, void *prefix_data)
Free internal prefix data.
void * ly_realloc(void *ptr, size_t size)
Wrapper for realloc() call. The only difference is that if it fails to allocate the requested memory...
#define LY_ARRAY_FOR(ARRAY,...)
Sized-array iterator (for-loop).
Definition: tree.h:167
#define LY_ARRAY_COUNT_TYPE
Type (i.e. size) of the sized array&#39;s size counter.
Definition: tree.h:104
struct lys_module * module
Definition: tree_schema.h:1443
if((v1->size!=v2->size)||memcmp(v1->data, v2->data, v1->size))
Definition: binary.c:349
LY_VALUE_FORMAT
All kinds of supported value formats and prefix mappings to modules.
Definition: tree.h:234
lyplg_type_print_clb print
Definition: log.h:248
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.
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:437
#define TYPE_IDX_SIZE
Size in bytes of the used type index in the LYB Binary Format.
Definition: union.c:46
lyplg_type_compare_clb compare
Special lyd_value structure for built-in union values.
Definition: tree_data.h:630
API for (user) types plugins.
LY_VALUE_FORMAT format
Definition: tree_data.h:636
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:620
LY_ERR
libyang&#39;s error codes returned by the libyang functions.
Definition: log.h:240
libyang context handler.
struct lyd_value value
Definition: tree_data.h:631
#define LYPLG_TYPE_STORE_ONLY
Definition: log.h:254
assert(!value->_canonical)