libyang  3.9.1
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 
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  }
354  for (u = 0; u < LY_ARRAY_COUNT(type_u->types); ++u) {
355  if (!errs[u]) {
356  /* no error for some reason */
357  continue;
358  }
359 
360  /* use an app-tag if all the types set it or set none */
361  if (errs[u]->apptag) {
362  if (!err_app_tag) {
363  err_app_tag = strdup(errs[u]->apptag);
364  LY_CHECK_ERR_GOTO(!err_app_tag, ret = LY_EMEM, cleanup);
365  use_err_app_tag = 1;
366  } else if (strcmp(errs[u]->apptag, err_app_tag)) {
367  use_err_app_tag = 0;
368  }
369  }
370 
371  msg = ly_realloc(msg, msg_len + 4 + strlen(type_u->types[u]->plugin->id) + 2 + strlen(errs[u]->msg) + 2);
372  LY_CHECK_ERR_GOTO(!msg, ret = LY_EMEM, cleanup);
373  msg_len += sprintf(msg + msg_len, " %s: %s\n", type_u->types[u]->plugin->id, errs[u]->msg);
374  }
375 
376  if (!use_err_app_tag) {
377  free(err_app_tag);
378  err_app_tag = NULL;
379  }
380  ret = ly_err_new(err, LY_EVALID, LYVE_DATA, NULL, err_app_tag, "%s", msg);
381  } else if (type_idx) {
382  *type_idx = u;
383  }
384 
385 cleanup:
386  for (u = 0; u < LY_ARRAY_COUNT(type_u->types); ++u) {
387  ly_err_free(errs[u]);
388  }
389  free(errs);
390  free(msg);
391  ly_temp_log_options(prev_lo);
392  return ret;
393 }
394 
409 static LY_ERR
410 lyb_fill_subvalue(const struct ly_ctx *ctx, struct lysc_type_union *type_u, const void *lyb_data, size_t lyb_data_len,
411  void *prefix_data, struct lyd_value_union *subvalue, uint32_t *options, struct lys_glob_unres *unres,
412  struct ly_err_item **err)
413 {
414  LY_ERR ret;
415  uint32_t type_idx;
416  const void *lyb_value = NULL;
417  size_t lyb_value_len = 0;
418 
419  ret = lyb_union_validate(lyb_data, lyb_data_len, type_u, err);
420  LY_CHECK_RET(ret);
421 
422  /* parse lyb_data and set the lyb_value and lyb_value_len */
423  lyb_parse_union(lyb_data, lyb_data_len, &type_idx, &lyb_value, &lyb_value_len);
424  LY_CHECK_RET(ret);
425 
426  /* store lyb_data to subvalue */
427  ret = union_subvalue_assignment(lyb_data, lyb_data_len, &subvalue->original, &subvalue->orig_len, options);
428  LY_CHECK_RET(ret);
429 
430  if (lyb_value) {
431  /* resolve prefix_data and set format */
432  ret = lyplg_type_prefix_data_new(ctx, lyb_value, lyb_value_len, LY_VALUE_LYB, prefix_data, &subvalue->format,
433  &subvalue->prefix_data);
434  LY_CHECK_RET(ret);
435  assert(subvalue->format == LY_VALUE_LYB);
436  } else {
437  /* lyb_parse_union() did not find lyb_value, just set format */
438  subvalue->format = LY_VALUE_LYB;
439  }
440 
441  /* use the specific type to store the value */
442  ret = union_store_type(ctx, type_u, type_idx, subvalue, *options, 0, NULL, NULL, unres, err);
443 
444  return ret;
445 }
446 
447 LIBYANG_API_DEF LY_ERR
448 lyplg_type_store_union(const struct ly_ctx *ctx, const struct lysc_type *type, const void *value, size_t value_len,
449  uint32_t options, LY_VALUE_FORMAT format, void *prefix_data, uint32_t hints, const struct lysc_node *ctx_node,
450  struct lyd_value *storage, struct lys_glob_unres *unres, struct ly_err_item **err)
451 {
452  LY_ERR ret = LY_SUCCESS, r;
453  struct lysc_type_union *type_u = (struct lysc_type_union *)type;
454  struct lyd_value_union *subvalue;
455 
456  *err = NULL;
457 
458  /* init storage */
459  memset(storage, 0, sizeof *storage);
460  LYPLG_TYPE_VAL_INLINE_PREPARE(storage, subvalue);
461  LY_CHECK_ERR_GOTO(!subvalue, ret = LY_EMEM, cleanup);
462  storage->realtype = type;
463  subvalue->hints = hints;
464  subvalue->ctx_node = ctx_node;
465 
466  if (format == LY_VALUE_LYB) {
467  ret = lyb_fill_subvalue(ctx, type_u, value, value_len, prefix_data, subvalue, &options, unres, err);
468  LY_CHECK_GOTO((ret != LY_SUCCESS) && (ret != LY_EINCOMPLETE), cleanup);
469  } else {
470  /* to correctly resolve the union type, we need to always validate the value */
471  options &= ~LYPLG_TYPE_STORE_ONLY;
472 
473  /* store value to subvalue */
474  ret = union_subvalue_assignment(value, value_len, &subvalue->original, &subvalue->orig_len, &options);
475  LY_CHECK_GOTO(ret, cleanup);
476 
477  /* store format-specific data for later prefix resolution */
478  ret = lyplg_type_prefix_data_new(ctx, value, value_len, format, prefix_data, &subvalue->format,
479  &subvalue->prefix_data);
480  LY_CHECK_GOTO(ret, cleanup);
481 
482  /* use the first usable subtype to store the value */
483  ret = union_find_type(ctx, type_u, subvalue, options, 0, NULL, NULL, NULL, unres, err);
484  LY_CHECK_GOTO((ret != LY_SUCCESS) && (ret != LY_EINCOMPLETE), cleanup);
485  }
486 
487  /* store canonical value, if any (use the specific type value) */
488  r = lydict_insert(ctx, subvalue->value._canonical, 0, &storage->_canonical);
489  LY_CHECK_ERR_GOTO(r, ret = r, cleanup);
490 
491 cleanup:
492  if (options & LYPLG_TYPE_STORE_DYNAMIC) {
493  free((void *)value);
494  }
495 
496  if ((ret != LY_SUCCESS) && (ret != LY_EINCOMPLETE)) {
497  lyplg_type_free_union(ctx, storage);
498  }
499  return ret;
500 }
501 
502 LIBYANG_API_DEF LY_ERR
503 lyplg_type_validate_union(const struct ly_ctx *ctx, const struct lysc_type *type, const struct lyd_node *ctx_node,
504  const struct lyd_node *tree, struct lyd_value *storage, struct ly_err_item **err)
505 {
506  LY_ERR rc = LY_SUCCESS;
507  struct lysc_type_union *type_u = (struct lysc_type_union *)type;
508  struct lyd_value_union *subvalue = storage->subvalue;
509  struct lyd_value orig = {0};
510  uint32_t type_idx;
511  ly_bool validated = 0;
512 
513  *err = NULL;
514 
515  /* because of types that do not store their own type as realtype (leafref), we are not able to call their
516  * validate callback (there is no way to get the type) but even if possible, the value may be invalid
517  * for the type, so we may have to perform union value storing again from scratch, but keep a value backup */
518  LY_CHECK_RET(subvalue->value.realtype->plugin->duplicate(ctx, &subvalue->value, &orig));
519  subvalue->value.realtype->plugin->free(ctx, &subvalue->value);
520 
521  if (subvalue->format == LY_VALUE_LYB) {
522  /* use the specific type to store and validate the value */
523  lyb_parse_union(subvalue->original, 0, &type_idx, NULL, NULL);
524 
525  if (union_store_type(ctx, type_u, type_idx, subvalue, 0, 1, ctx_node, tree, NULL, err)) {
526  /* validation failed, we need to try storing the value again */
527  ly_err_free(*err);
528  *err = NULL;
529  } else {
530  validated = 1;
531  }
532  }
533 
534  if (!validated) {
535  /* use the first usable subtype to store and validate the value */
536  rc = union_find_type(ctx, type_u, subvalue, 0, 1, ctx_node, tree, NULL, NULL, err);
537  if (rc) {
538  /* validation failed, restore the previous value */
539  subvalue->value = orig;
540  return rc;
541  }
542  }
543 
544  /* update the canonical value, if any generated */
545  lydict_remove(ctx, storage->_canonical);
546  LY_CHECK_RET(lydict_insert(ctx, subvalue->value._canonical, 0, &storage->_canonical));
547 
548  /* free backup value */
549  orig.realtype->plugin->free(ctx, &orig);
550  return LY_SUCCESS;
551 }
552 
553 LIBYANG_API_DEF LY_ERR
554 lyplg_type_compare_union(const struct ly_ctx *ctx, const struct lyd_value *val1, const struct lyd_value *val2)
555 {
556  if (val1->subvalue->value.realtype != val2->subvalue->value.realtype) {
557  return LY_ENOT;
558  }
559  return val1->subvalue->value.realtype->plugin->compare(ctx, &val1->subvalue->value, &val2->subvalue->value);
560 }
561 
562 LIBYANG_API_DEF int
563 lyplg_type_sort_union(const struct ly_ctx *ctx, const struct lyd_value *val1, const struct lyd_value *val2)
564 {
565  int rc;
567  struct lysc_type **types, *type;
568 
569  if (val1->subvalue->value.realtype == val2->subvalue->value.realtype) {
570  return val1->subvalue->value.realtype->plugin->sort(ctx, &val1->subvalue->value, &val2->subvalue->value);
571  }
572 
573  /* compare according to the order of types */
574  rc = 0;
575  types = ((struct lysc_type_union *)val1->realtype)->types;
576  LY_ARRAY_FOR(types, u) {
577  if (types[u]->basetype == LY_TYPE_LEAFREF) {
578  type = ((struct lysc_type_leafref *)types[u])->realtype;
579  } else {
580  type = types[u];
581  }
582 
583  if (type == val1->subvalue->value.realtype) {
584  rc = 1;
585  break;
586  } else if (type == val2->subvalue->value.realtype) {
587  rc = -1;
588  break;
589  }
590  }
591  assert(rc);
592 
593  return rc;
594 }
595 
608 static const void *
609 lyb_union_print(const struct ly_ctx *ctx, struct lysc_type_union *type_u, struct lyd_value_union *subvalue,
610  void *prefix_data, size_t *value_len)
611 {
612  void *ret = NULL;
613  LY_ERR r;
614  struct ly_err_item *err;
615  uint64_t num = 0;
616  uint32_t type_idx = 0;
617  ly_bool dynamic;
618  size_t pval_len;
619  void *pval;
620 
621  /* Find out the index number (type_idx). The call should succeed
622  * because the union_find_type() has already been called in the
623  * lyplg_type_store_union().
624  */
625  if (!ctx) {
626  assert(subvalue->ctx_node);
627  ctx = subvalue->ctx_node->module->ctx;
628  }
629  subvalue->value.realtype->plugin->free(ctx, &subvalue->value);
630  r = union_find_type(ctx, type_u, subvalue, 0, 0, NULL, NULL, &type_idx, NULL, &err);
631  ly_err_free(err);
632  LY_CHECK_RET((r != LY_SUCCESS) && (r != LY_EINCOMPLETE), NULL);
633 
634  /* Print subvalue in LYB format. */
635  pval = (void *)subvalue->value.realtype->plugin->print(NULL, &subvalue->value, LY_VALUE_LYB, prefix_data, &dynamic,
636  &pval_len);
637  LY_CHECK_RET(!pval, NULL);
638 
639  /* Create LYB data. */
640  *value_len = TYPE_IDX_SIZE + pval_len;
641  ret = malloc(*value_len);
642  LY_CHECK_RET(!ret, NULL);
643 
644  num = type_idx;
645  num = htole64(num);
646  memcpy(ret, &num, TYPE_IDX_SIZE);
647  memcpy((char *)ret + TYPE_IDX_SIZE, pval, pval_len);
648 
649  if (dynamic) {
650  free(pval);
651  }
652 
653  return ret;
654 }
655 
656 LIBYANG_API_DEF const void *
657 lyplg_type_print_union(const struct ly_ctx *ctx, const struct lyd_value *value, LY_VALUE_FORMAT format,
658  void *prefix_data, ly_bool *dynamic, size_t *value_len)
659 {
660  const void *ret;
661  struct lyd_value_union *subvalue = value->subvalue;
662  struct lysc_type_union *type_u = (struct lysc_type_union *)value->realtype;
663  size_t lyb_data_len = 0;
664 
665  if ((format == LY_VALUE_LYB) && (subvalue->format == LY_VALUE_LYB)) {
666  /* The return value is already ready. */
667  *dynamic = 0;
668  if (value_len) {
669  *value_len = subvalue->orig_len;
670  }
671  return subvalue->original;
672  } else if ((format == LY_VALUE_LYB) && (subvalue->format != LY_VALUE_LYB)) {
673  /* The return LYB data must be created. */
674  *dynamic = 1;
675  ret = lyb_union_print(ctx, type_u, subvalue, prefix_data, &lyb_data_len);
676  if (value_len) {
677  *value_len = lyb_data_len;
678  }
679  return ret;
680  }
681 
682  assert(format != LY_VALUE_LYB);
683  ret = (void *)subvalue->value.realtype->plugin->print(ctx, &subvalue->value, format, prefix_data, dynamic, value_len);
684  if (!value->_canonical && (format == LY_VALUE_CANON)) {
685  /* the canonical value is supposed to be stored now */
686  lydict_insert(ctx, subvalue->value._canonical, 0, (const char **)&value->_canonical);
687  }
688 
689  return ret;
690 }
691 
692 LIBYANG_API_DEF LY_ERR
693 lyplg_type_dup_union(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup)
694 {
695  LY_ERR ret = LY_SUCCESS;
696  struct lyd_value_union *orig_val = original->subvalue, *dup_val;
697 
698  /* init dup value */
699  memset(dup, 0, sizeof *dup);
700  dup->realtype = original->realtype;
701 
702  ret = lydict_insert(ctx, original->_canonical, 0, &dup->_canonical);
703  LY_CHECK_GOTO(ret, cleanup);
704 
705  dup_val = calloc(1, sizeof *dup_val);
706  LY_CHECK_ERR_GOTO(!dup_val, LOGMEM(ctx); ret = LY_EMEM, cleanup);
707  dup->subvalue = dup_val;
708 
709  ret = orig_val->value.realtype->plugin->duplicate(ctx, &orig_val->value, &dup_val->value);
710  LY_CHECK_GOTO(ret, cleanup);
711 
712  if (orig_val->orig_len) {
713  dup_val->original = calloc(1, orig_val->orig_len);
714  LY_CHECK_ERR_GOTO(!dup_val->original, LOGMEM(ctx); ret = LY_EMEM, cleanup);
715  memcpy(dup_val->original, orig_val->original, orig_val->orig_len);
716  } else {
717  dup_val->original = strdup("");
718  LY_CHECK_ERR_GOTO(!dup_val->original, LOGMEM(ctx); ret = LY_EMEM, cleanup);
719  }
720  dup_val->orig_len = orig_val->orig_len;
721 
722  dup_val->format = orig_val->format;
723  dup_val->ctx_node = orig_val->ctx_node;
724  dup_val->hints = orig_val->hints;
725  ret = lyplg_type_prefix_data_dup(ctx, orig_val->format, orig_val->prefix_data, &dup_val->prefix_data);
726  LY_CHECK_GOTO(ret, cleanup);
727 
728 cleanup:
729  if (ret) {
730  lyplg_type_free_union(ctx, dup);
731  }
732  return ret;
733 }
734 
735 LIBYANG_API_DEF void
736 lyplg_type_free_union(const struct ly_ctx *ctx, struct lyd_value *value)
737 {
738  struct lyd_value_union *val;
739 
740  lydict_remove(ctx, value->_canonical);
741  value->_canonical = NULL;
742  LYD_VALUE_GET(value, val);
743  if (val) {
744  if (val->value.realtype) {
745  val->value.realtype->plugin->free(ctx, &val->value);
746  }
748  free(val->original);
749 
751  }
752 }
753 
762  {
763  .module = "",
764  .revision = NULL,
765  .name = LY_TYPE_UNION_STR,
766 
767  .plugin.id = "libyang 2 - union,version 1",
768  .plugin.store = lyplg_type_store_union,
769  .plugin.validate = lyplg_type_validate_union,
770  .plugin.compare = lyplg_type_compare_union,
771  .plugin.sort = lyplg_type_sort_union,
772  .plugin.print = lyplg_type_print_union,
773  .plugin.duplicate = lyplg_type_dup_union,
774  .plugin.free = lyplg_type_free_union,
775  .plugin.lyb_data_len = -1,
776  },
777  {0}
778 };
struct lysc_type * realtype
Definition: tree_data.h:580
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:2158
memset(value->fixed_mem, 0, LYD_VALUE_FIXED_MEM_SIZE)
const char * id
struct lyplg_type * plugin
Definition: tree_schema.h:1304
LY_DATA_TYPE basetype
Definition: tree_schema.h:1415
Generic structure for a data node.
Definition: tree_data.h:804
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:657
Definition: log.h:242
LY_ERR err
Definition: log.h:287
#define LYPLG_TYPE_STORE_DYNAMIC
void * original
Definition: tree_data.h:634
size_t orig_len
Definition: tree_data.h:635
#define LOGMEM(CTX)
Definition: tree_edit.h:22
char * apptag
Definition: log.h:293
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:736
struct lysc_node * ctx_node
Definition: tree_data.h:641
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:576
const char * _canonical
Definition: tree_data.h:577
lyplg_type_store_clb store
struct lyxp_expr * path
Definition: tree_schema.h:1384
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:619
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:761
uint32_t hints
Definition: tree_data.h:636
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:448
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:554
void * prefix_data
Definition: tree_data.h:640
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:563
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
LIBYANG_API_DECL const char * lyxp_get_expr(const struct lyxp_expr *path)
Getter for original XPath expression from a parsed expression.
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.
LY_DATA_TYPE basetype
Definition: tree_schema.h:1305
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:503
#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:631
API for (user) types plugins.
LY_VALUE_FORMAT format
Definition: tree_data.h:637
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:693
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:632
#define LYPLG_TYPE_STORE_ONLY
Definition: log.h:254
assert(!value->_canonical)