libyang  3.13.6
libyang is YANG data modelling language parser and toolkit written (and providing API) in C.
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 
164 static LY_ERR
165 union_update_lref_err(struct ly_err_item *err, const struct lysc_type *type, const void *value, size_t value_len)
166 {
167  const struct lysc_type_leafref *lref;
168  char *valstr = NULL;
169  int r;
170 
171  if (!err || (type->basetype != LY_TYPE_LEAFREF)) {
172  /* nothing to do */
173  return LY_SUCCESS;
174  }
175 
176  lref = (const struct lysc_type_leafref *)type;
177 
178  /* update error-app-tag */
179  free(err->apptag);
180  err->apptag = strdup("instance-required");
181  LY_CHECK_ERR_RET(!err->apptag, LOGMEM(NULL), LY_EMEM);
182 
183  valstr = strndup((const char *)value, value_len);
184  LY_CHECK_ERR_RET(!valstr, LOGMEM(NULL), LY_EMEM);
185 
186  /* update error-message */
187  free(err->msg);
188  r = asprintf(&err->msg, LY_ERRMSG_NOLREF_VAL, valstr, lyxp_get_expr(lref->path));
189  free(valstr);
190  LY_CHECK_ERR_RET(r == -1, LOGMEM(NULL), LY_EMEM);
191 
192  return LY_SUCCESS;
193 }
194 
210 static LY_ERR
211 union_store_type(const struct ly_ctx *ctx, struct lysc_type_union *type_u, uint32_t type_idx, struct lyd_value_union *subvalue,
212  uint32_t options, ly_bool validate, const struct lyd_node *ctx_node, const struct lyd_node *tree,
213  struct lys_glob_unres *unres, struct ly_err_item **err)
214 {
215  LY_ERR rc = LY_SUCCESS;
216  struct lysc_type *type = type_u->types[type_idx];
217  const void *value = NULL;
218  size_t value_len = 0;
219  ly_bool dynamic = 0;
220  LY_VALUE_FORMAT format;
221  void *prefix_data;
222  uint32_t opts = 0, ti;
223 
224  *err = NULL;
225 
226  if (subvalue->format == LY_VALUE_LYB) {
227  lyb_parse_union(subvalue->original, subvalue->orig_len, &ti, &value, &value_len);
228  if (ti != type_idx) {
229  /* value of another type, first store the value properly and then use its JSON value for parsing */
230  rc = type_u->types[ti]->plugin->store(ctx, type_u->types[ti], value, value_len, LYPLG_TYPE_STORE_ONLY,
231  subvalue->format, subvalue->prefix_data, subvalue->hints, subvalue->ctx_node, &subvalue->value, unres, err);
232  if (rc && (rc != LY_EINCOMPLETE)) {
233  /* clear any leftover/freed garbage */
234  memset(&subvalue->value, 0, sizeof subvalue->value);
235 
236  /* if this is a leafref, lets make sure we propagate the appropriate error, and not a type validation failure */
237  union_update_lref_err(*err, type_u->types[ti], value, value_len);
238  goto cleanup;
239  }
240 
241  assert(subvalue->value.realtype);
242  value = subvalue->value.realtype->plugin->print(ctx, &subvalue->value, LY_VALUE_JSON, NULL, &dynamic, &value_len);
243 
244  /* to avoid leaks, free subvalue->value, but we need the value, which may be stored there */
245  if (!dynamic) {
246  value = strndup(value, value_len);
247  dynamic = 1;
248  }
249  type_u->types[ti]->plugin->free(ctx, &subvalue->value);
250 
251  format = LY_VALUE_JSON;
252  prefix_data = NULL;
253  } else {
254  format = subvalue->format;
255  prefix_data = subvalue->prefix_data;
256  }
257  } else {
258  value = subvalue->original;
259  value_len = subvalue->orig_len;
260  format = subvalue->format;
261  prefix_data = subvalue->prefix_data;
262  }
263 
264  if (options & LYPLG_TYPE_STORE_ONLY) {
265  opts |= LYPLG_TYPE_STORE_ONLY;
266  }
267 
268  rc = type->plugin->store(ctx, type, value, value_len, opts, format, prefix_data, subvalue->hints,
269  subvalue->ctx_node, &subvalue->value, unres, err);
270  if (rc && (rc != LY_EINCOMPLETE)) {
271  /* clear any leftover/freed garbage */
272  memset(&subvalue->value, 0, sizeof subvalue->value);
273 
274  /* if this is a leafref, lets make sure we propagate the appropriate error, and not a type validation failure */
275  union_update_lref_err(*err, type, value, value_len);
276  goto cleanup;
277  }
278 
279  if (validate && (rc == LY_EINCOMPLETE)) {
280  /* we need the value validated */
281  rc = type->plugin->validate(ctx, type, ctx_node, tree, &subvalue->value, err);
282  if (rc) {
283  /* validate failed, we need to free the stored value */
284  type->plugin->free(ctx, &subvalue->value);
285  goto cleanup;
286  }
287  }
288 
289 cleanup:
290  if (dynamic) {
291  free((void *)value);
292  }
293  return rc;
294 }
295 
311 static LY_ERR
312 union_find_type(const struct ly_ctx *ctx, struct lysc_type_union *type_u, struct lyd_value_union *subvalue,
313  uint32_t options, ly_bool resolve, const struct lyd_node *ctx_node, const struct lyd_node *tree,
314  uint32_t *type_idx, struct lys_glob_unres *unres, struct ly_err_item **err)
315 {
316  LY_ERR ret = LY_SUCCESS;
318  struct ly_err_item **errs = NULL, *e;
319  uint32_t *prev_lo, temp_lo = 0;
320  char *msg = NULL, *err_app_tag = NULL;
321  int msg_len = 0;
322  ly_bool use_err_app_tag = 0;
323 
324  *err = NULL;
325 
326  /* alloc errors */
327  errs = calloc(LY_ARRAY_COUNT(type_u->types), sizeof *errs);
328  LY_CHECK_RET(!errs, LY_EMEM);
329 
330  /* turn logging temporarily off */
331  prev_lo = ly_temp_log_options(&temp_lo);
332 
333  /* use the first usable subtype to store the value */
334  for (u = 0; u < LY_ARRAY_COUNT(type_u->types); ++u) {
335  ret = union_store_type(ctx, type_u, u, subvalue, options, resolve, ctx_node, tree, unres, &e);
336  if ((ret == LY_SUCCESS) || (ret == LY_EINCOMPLETE)) {
337  break;
338  }
339 
340  errs[u] = e;
341  }
342 
343  if (u == LY_ARRAY_COUNT(type_u->types)) {
344  /* create the full error */
345  if (subvalue->format == LY_VALUE_LYB) {
346  msg_len = asprintf(&msg, "Invalid LYB union value - no matching subtype found:\n");
347  } else {
348  msg_len = asprintf(&msg, "Invalid union value \"%.*s\" - no matching subtype found:\n",
349  (int)subvalue->orig_len, (char *)subvalue->original);
350  }
351  if (msg_len == -1) {
352  LY_CHECK_ERR_GOTO(!errs, ret = LY_EMEM, cleanup);
353  /* for further actions in function msg_len is just 0 */
354  msg_len = 0;
355  }
356  for (u = 0; u < LY_ARRAY_COUNT(type_u->types); ++u) {
357  if (!errs[u]) {
358  /* no error for some reason */
359  continue;
360  }
361 
362  /* use an app-tag if all the types set it or set none */
363  if (errs[u]->apptag) {
364  if (!err_app_tag) {
365  err_app_tag = strdup(errs[u]->apptag);
366  LY_CHECK_ERR_GOTO(!err_app_tag, ret = LY_EMEM, cleanup);
367  use_err_app_tag = 1;
368  } else if (strcmp(errs[u]->apptag, err_app_tag)) {
369  use_err_app_tag = 0;
370  }
371  }
372 
373  msg = ly_realloc(msg, msg_len + 4 + strlen(type_u->types[u]->plugin->id) + 2 + strlen(errs[u]->msg) + 2);
374  LY_CHECK_ERR_GOTO(!msg, ret = LY_EMEM, cleanup);
375  msg_len += sprintf(msg + msg_len, " %s: %s\n", type_u->types[u]->plugin->id, errs[u]->msg);
376  }
377 
378  if (!use_err_app_tag) {
379  free(err_app_tag);
380  err_app_tag = NULL;
381  }
382  ret = ly_err_new(err, LY_EVALID, LYVE_DATA, NULL, err_app_tag, "%s", msg);
383  } else if (type_idx) {
384  *type_idx = u;
385  }
386 
387 cleanup:
388  for (u = 0; u < LY_ARRAY_COUNT(type_u->types); ++u) {
389  ly_err_free(errs[u]);
390  }
391  free(errs);
392  free(msg);
393  ly_temp_log_options(prev_lo);
394  return ret;
395 }
396 
411 static LY_ERR
412 lyb_fill_subvalue(const struct ly_ctx *ctx, struct lysc_type_union *type_u, const void *lyb_data, size_t lyb_data_len,
413  void *prefix_data, struct lyd_value_union *subvalue, uint32_t *options, struct lys_glob_unres *unres,
414  struct ly_err_item **err)
415 {
416  LY_ERR ret;
417  uint32_t type_idx;
418  const void *lyb_value = NULL;
419  size_t lyb_value_len = 0;
420 
421  ret = lyb_union_validate(lyb_data, lyb_data_len, type_u, err);
422  LY_CHECK_RET(ret);
423 
424  /* parse lyb_data and set the lyb_value and lyb_value_len */
425  lyb_parse_union(lyb_data, lyb_data_len, &type_idx, &lyb_value, &lyb_value_len);
426  LY_CHECK_RET(ret);
427 
428  /* store lyb_data to subvalue */
429  ret = union_subvalue_assignment(lyb_data, lyb_data_len, &subvalue->original, &subvalue->orig_len, options);
430  LY_CHECK_RET(ret);
431 
432  if (lyb_value) {
433  /* resolve prefix_data and set format */
434  ret = lyplg_type_prefix_data_new(ctx, lyb_value, lyb_value_len, LY_VALUE_LYB, prefix_data, &subvalue->format,
435  &subvalue->prefix_data);
436  LY_CHECK_RET(ret);
437  assert(subvalue->format == LY_VALUE_LYB);
438  } else {
439  /* lyb_parse_union() did not find lyb_value, just set format */
440  subvalue->format = LY_VALUE_LYB;
441  }
442 
443  /* use the specific type to store the value */
444  ret = union_store_type(ctx, type_u, type_idx, subvalue, *options, 0, NULL, NULL, unres, err);
445 
446  return ret;
447 }
448 
449 LIBYANG_API_DEF LY_ERR
450 lyplg_type_store_union(const struct ly_ctx *ctx, const struct lysc_type *type, const void *value, size_t value_len,
451  uint32_t options, LY_VALUE_FORMAT format, void *prefix_data, uint32_t hints, const struct lysc_node *ctx_node,
452  struct lyd_value *storage, struct lys_glob_unres *unres, struct ly_err_item **err)
453 {
454  LY_ERR ret = LY_SUCCESS, r;
455  struct lysc_type_union *type_u = (struct lysc_type_union *)type;
456  struct lyd_value_union *subvalue;
457 
458  *err = NULL;
459 
460  /* init storage */
461  memset(storage, 0, sizeof *storage);
462  LYPLG_TYPE_VAL_INLINE_PREPARE(storage, subvalue);
463  LY_CHECK_ERR_GOTO(!subvalue, ret = LY_EMEM, cleanup);
464  storage->realtype = type;
465  subvalue->hints = hints;
466  subvalue->ctx_node = ctx_node;
467 
468  if (format == LY_VALUE_LYB) {
469  ret = lyb_fill_subvalue(ctx, type_u, value, value_len, prefix_data, subvalue, &options, unres, err);
470  LY_CHECK_GOTO((ret != LY_SUCCESS) && (ret != LY_EINCOMPLETE), cleanup);
471  } else {
472  /* to correctly resolve the union type, we need to always validate the value */
473  options &= ~LYPLG_TYPE_STORE_ONLY;
474 
475  /* store value to subvalue */
476  ret = union_subvalue_assignment(value, value_len, &subvalue->original, &subvalue->orig_len, &options);
477  LY_CHECK_GOTO(ret, cleanup);
478 
479  /* store format-specific data for later prefix resolution */
480  ret = lyplg_type_prefix_data_new(ctx, value, value_len, format, prefix_data, &subvalue->format,
481  &subvalue->prefix_data);
482  LY_CHECK_GOTO(ret, cleanup);
483 
484  /* use the first usable subtype to store the value */
485  ret = union_find_type(ctx, type_u, subvalue, options, 0, NULL, NULL, NULL, unres, err);
486  LY_CHECK_GOTO((ret != LY_SUCCESS) && (ret != LY_EINCOMPLETE), cleanup);
487  }
488 
489  /* store canonical value, if any (use the specific type value) */
490  r = lydict_insert(ctx, subvalue->value._canonical, 0, &storage->_canonical);
491  LY_CHECK_ERR_GOTO(r, ret = r, cleanup);
492 
493 cleanup:
494  if (options & LYPLG_TYPE_STORE_DYNAMIC) {
495  free((void *)value);
496  }
497 
498  if ((ret != LY_SUCCESS) && (ret != LY_EINCOMPLETE)) {
499  lyplg_type_free_union(ctx, storage);
500  }
501  return ret;
502 }
503 
504 LIBYANG_API_DEF LY_ERR
505 lyplg_type_validate_union(const struct ly_ctx *ctx, const struct lysc_type *type, const struct lyd_node *ctx_node,
506  const struct lyd_node *tree, struct lyd_value *storage, struct ly_err_item **err)
507 {
508  LY_ERR rc = LY_SUCCESS;
509  struct lysc_type_union *type_u = (struct lysc_type_union *)type;
510  struct lyd_value_union *subvalue = storage->subvalue;
511  struct lyd_value orig = {0};
512  uint32_t type_idx;
513  ly_bool validated = 0;
514 
515  *err = NULL;
516 
517  /* because of types that do not store their own type as realtype (leafref), we are not able to call their
518  * validate callback (there is no way to get the type) but even if possible, the value may be invalid
519  * for the type, so we may have to perform union value storing again from scratch, but keep a value backup */
520  LY_CHECK_RET(subvalue->value.realtype->plugin->duplicate(ctx, &subvalue->value, &orig));
521  subvalue->value.realtype->plugin->free(ctx, &subvalue->value);
522 
523  if (subvalue->format == LY_VALUE_LYB) {
524  /* use the specific type to store and validate the value */
525  lyb_parse_union(subvalue->original, 0, &type_idx, NULL, NULL);
526 
527  if (union_store_type(ctx, type_u, type_idx, subvalue, 0, 1, ctx_node, tree, NULL, err)) {
528  /* validation failed, we need to try storing the value again */
529  ly_err_free(*err);
530  *err = NULL;
531  } else {
532  validated = 1;
533  }
534  }
535 
536  if (!validated) {
537  /* use the first usable subtype to store and validate the value */
538  rc = union_find_type(ctx, type_u, subvalue, 0, 1, ctx_node, tree, NULL, NULL, err);
539  if (rc) {
540  /* validation failed, restore the previous value */
541  subvalue->value = orig;
542  return rc;
543  }
544  }
545 
546  /* update the canonical value, if any generated */
547  lydict_remove(ctx, storage->_canonical);
548  LY_CHECK_RET(lydict_insert(ctx, subvalue->value._canonical, 0, &storage->_canonical));
549 
550  /* free backup value */
551  orig.realtype->plugin->free(ctx, &orig);
552  return LY_SUCCESS;
553 }
554 
555 LIBYANG_API_DEF LY_ERR
556 lyplg_type_compare_union(const struct ly_ctx *ctx, const struct lyd_value *val1, const struct lyd_value *val2)
557 {
558  if (val1->subvalue->value.realtype != val2->subvalue->value.realtype) {
559  return LY_ENOT;
560  }
561  return val1->subvalue->value.realtype->plugin->compare(ctx, &val1->subvalue->value, &val2->subvalue->value);
562 }
563 
564 LIBYANG_API_DEF int
565 lyplg_type_sort_union(const struct ly_ctx *ctx, const struct lyd_value *val1, const struct lyd_value *val2)
566 {
567  int rc;
569  struct lysc_type **types, *type;
570 
571  if (val1->subvalue->value.realtype == val2->subvalue->value.realtype) {
572  return val1->subvalue->value.realtype->plugin->sort(ctx, &val1->subvalue->value, &val2->subvalue->value);
573  }
574 
575  /* compare according to the order of types */
576  rc = 0;
577  types = ((struct lysc_type_union *)val1->realtype)->types;
578  LY_ARRAY_FOR(types, u) {
579  if (types[u]->basetype == LY_TYPE_LEAFREF) {
580  type = ((struct lysc_type_leafref *)types[u])->realtype;
581  } else {
582  type = types[u];
583  }
584 
585  if (type == val1->subvalue->value.realtype) {
586  rc = 1;
587  break;
588  } else if (type == val2->subvalue->value.realtype) {
589  rc = -1;
590  break;
591  }
592  }
593  assert(rc);
594 
595  return rc;
596 }
597 
610 static const void *
611 lyb_union_print(const struct ly_ctx *ctx, struct lysc_type_union *type_u, struct lyd_value_union *subvalue,
612  void *prefix_data, size_t *value_len)
613 {
614  void *ret = NULL;
615  LY_ERR r;
616  struct ly_err_item *err;
617  uint64_t num = 0;
618  uint32_t type_idx = 0;
619  ly_bool dynamic;
620  size_t pval_len;
621  void *pval;
622 
623  /* Find out the index number (type_idx). The call should succeed
624  * because the union_find_type() has already been called in the
625  * lyplg_type_store_union().
626  */
627  if (!ctx) {
628  assert(subvalue->ctx_node);
629  ctx = subvalue->ctx_node->module->ctx;
630  }
631  subvalue->value.realtype->plugin->free(ctx, &subvalue->value);
632  r = union_find_type(ctx, type_u, subvalue, 0, 0, NULL, NULL, &type_idx, NULL, &err);
633  ly_err_free(err);
634  LY_CHECK_RET((r != LY_SUCCESS) && (r != LY_EINCOMPLETE), NULL);
635 
636  /* Print subvalue in LYB format. */
637  pval = (void *)subvalue->value.realtype->plugin->print(NULL, &subvalue->value, LY_VALUE_LYB, prefix_data, &dynamic,
638  &pval_len);
639  LY_CHECK_RET(!pval, NULL);
640 
641  /* Create LYB data. */
642  *value_len = TYPE_IDX_SIZE + pval_len;
643  ret = malloc(*value_len);
644  LY_CHECK_RET(!ret, NULL);
645 
646  num = type_idx;
647  num = htole64(num);
648  memcpy(ret, &num, TYPE_IDX_SIZE);
649  memcpy((char *)ret + TYPE_IDX_SIZE, pval, pval_len);
650 
651  if (dynamic) {
652  free(pval);
653  }
654 
655  return ret;
656 }
657 
658 LIBYANG_API_DEF const void *
659 lyplg_type_print_union(const struct ly_ctx *ctx, const struct lyd_value *value, LY_VALUE_FORMAT format,
660  void *prefix_data, ly_bool *dynamic, size_t *value_len)
661 {
662  const void *ret;
663  struct lyd_value_union *subvalue = value->subvalue;
664  struct lysc_type_union *type_u = (struct lysc_type_union *)value->realtype;
665  size_t lyb_data_len = 0;
666 
667  if ((format == LY_VALUE_LYB) && (subvalue->format == LY_VALUE_LYB)) {
668  /* The return value is already ready. */
669  *dynamic = 0;
670  if (value_len) {
671  *value_len = subvalue->orig_len;
672  }
673  return subvalue->original;
674  } else if ((format == LY_VALUE_LYB) && (subvalue->format != LY_VALUE_LYB)) {
675  /* The return LYB data must be created. */
676  *dynamic = 1;
677  ret = lyb_union_print(ctx, type_u, subvalue, prefix_data, &lyb_data_len);
678  if (value_len) {
679  *value_len = lyb_data_len;
680  }
681  return ret;
682  }
683 
684  assert(format != LY_VALUE_LYB);
685  ret = (void *)subvalue->value.realtype->plugin->print(ctx, &subvalue->value, format, prefix_data, dynamic, value_len);
686  if (!value->_canonical && (format == LY_VALUE_CANON)) {
687  /* the canonical value is supposed to be stored now */
688  lydict_insert(ctx, subvalue->value._canonical, 0, (const char **)&value->_canonical);
689  }
690 
691  return ret;
692 }
693 
694 LIBYANG_API_DEF LY_ERR
695 lyplg_type_dup_union(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup)
696 {
697  LY_ERR ret = LY_SUCCESS;
698  struct lyd_value_union *orig_val = original->subvalue, *dup_val;
699 
700  /* init dup value */
701  memset(dup, 0, sizeof *dup);
702  dup->realtype = original->realtype;
703 
704  ret = lydict_insert(ctx, original->_canonical, 0, &dup->_canonical);
705  LY_CHECK_GOTO(ret, cleanup);
706 
707  dup_val = calloc(1, sizeof *dup_val);
708  LY_CHECK_ERR_GOTO(!dup_val, LOGMEM(ctx); ret = LY_EMEM, cleanup);
709  dup->subvalue = dup_val;
710 
711  ret = orig_val->value.realtype->plugin->duplicate(ctx, &orig_val->value, &dup_val->value);
712  LY_CHECK_GOTO(ret, cleanup);
713 
714  if (orig_val->orig_len) {
715  dup_val->original = calloc(1, orig_val->orig_len);
716  LY_CHECK_ERR_GOTO(!dup_val->original, LOGMEM(ctx); ret = LY_EMEM, cleanup);
717  memcpy(dup_val->original, orig_val->original, orig_val->orig_len);
718  } else {
719  dup_val->original = strdup("");
720  LY_CHECK_ERR_GOTO(!dup_val->original, LOGMEM(ctx); ret = LY_EMEM, cleanup);
721  }
722  dup_val->orig_len = orig_val->orig_len;
723 
724  dup_val->format = orig_val->format;
725  dup_val->ctx_node = orig_val->ctx_node;
726  dup_val->hints = orig_val->hints;
727  ret = lyplg_type_prefix_data_dup(ctx, orig_val->format, orig_val->prefix_data, &dup_val->prefix_data);
728  LY_CHECK_GOTO(ret, cleanup);
729 
730 cleanup:
731  if (ret) {
732  lyplg_type_free_union(ctx, dup);
733  }
734  return ret;
735 }
736 
737 LIBYANG_API_DEF void
738 lyplg_type_free_union(const struct ly_ctx *ctx, struct lyd_value *value)
739 {
740  struct lyd_value_union *val;
741 
743  value->_canonical = NULL;
744  LYD_VALUE_GET(value, val);
745  if (val) {
746  if (val->value.realtype) {
747  val->value.realtype->plugin->free(ctx, &val->value);
748  }
750  free(val->original);
751 
753  }
754 }
755 
763 const struct lyplg_type_record plugins_union[] = {
764  {
765  .module = "",
766  .revision = NULL,
767  .name = LY_TYPE_UNION_STR,
768 
769  .plugin.id = "libyang 2 - union,version 1",
770  .plugin.store = lyplg_type_store_union,
771  .plugin.validate = lyplg_type_validate_union,
772  .plugin.compare = lyplg_type_compare_union,
773  .plugin.sort = lyplg_type_sort_union,
774  .plugin.print = lyplg_type_print_union,
775  .plugin.duplicate = lyplg_type_dup_union,
776  .plugin.free = lyplg_type_free_union,
777  .plugin.lyb_data_len = -1,
778  },
779  {0}
780 };
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 err
Definition: log.h:284
char * apptag
Definition: log.h:290
char * msg
Definition: log.h:286
LY_ERR
libyang's error codes returned by the libyang functions.
Definition: log.h:237
@ LYVE_DATA
Definition: log.h:274
@ LY_EMEM
Definition: log.h:239
@ LY_ENOT
Definition: log.h:251
@ LY_EVALID
Definition: log.h:245
@ LY_SUCCESS
Definition: log.h:238
@ LY_EINCOMPLETE
Definition: log.h:247
Libyang full error structure.
Definition: log.h:282
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().
const char * module
lyplg_type_print_clb print
lyplg_type_store_clb store
lyplg_type_compare_clb compare
lyplg_type_validate_clb validate
const char * id
lyplg_type_dup_clb duplicate
lyplg_type_free_clb free
lyplg_type_sort_clb sort
#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 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 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.
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:738
LIBYANG_API_DEF 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:556
LIBYANG_API_DEF 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:565
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:505
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:450
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:695
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:659
#define LYPLG_TYPE_STORE_DYNAMIC
#define LYPLG_TYPE_STORE_ONLY
LY_DATA_TYPE basetype
Definition: tree_schema.h:1287
struct lyxp_expr * path
Definition: tree_schema.h:1366
struct lys_module * module
Definition: tree_schema.h:1425
struct lyplg_type * plugin
Definition: tree_schema.h:1286
struct lysc_type ** types
Definition: tree_schema.h:1400
struct ly_ctx * ctx
Definition: tree_schema.h:2138
LY_DATA_TYPE basetype
Definition: tree_schema.h:1397
LIBYANG_API_DECL const char * lyxp_get_expr(const struct lyxp_expr *path)
Getter for original XPath expression from a parsed expression.
Compiled YANG data node.
Definition: tree_schema.h:1421
#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_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_TYPE_LEAFREF
Definition: tree.h:217
@ LY_VALUE_JSON
Definition: tree.h:239
@ 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:28
API for (user) types plugins.
const struct lysc_type * realtype
Definition: tree_data.h:571
void * original
Definition: tree_data.h:625
void * prefix_data
Definition: tree_data.h:631
uint32_t hints
Definition: tree_data.h:627
#define LYD_VALUE_GET(value, type_val)
Get the value in format specific to the type.
Definition: tree_data.h:610
size_t orig_len
Definition: tree_data.h:626
struct lyd_value value
Definition: tree_data.h:623
const char * _canonical
Definition: tree_data.h:568
LY_VALUE_FORMAT format
Definition: tree_data.h:628
const struct lysc_node * ctx_node
Definition: tree_data.h:632
Generic structure for a data node.
Definition: tree_data.h:795
YANG data representation.
Definition: tree_data.h:567
Special lyd_value structure for built-in union values.
Definition: tree_data.h:622
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 LOGMEM(CTX)
Definition: tree_edit.h:22
#define TYPE_IDX_SIZE
Size in bytes of the used type 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:763