libyang  3.12.2
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  /* 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 
742  lydict_remove(ctx, value->_canonical);
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 
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 };
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:659
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:738
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:763
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:450
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:556
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:565
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:505
#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:695
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)