libyang  4.0.6
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 
16 #define _GNU_SOURCE /* strdup */
17 
18 #include "plugins_types.h"
19 
20 #include <assert.h>
21 #include <stdint.h>
22 #include <stdlib.h>
23 #include <string.h>
24 
25 #include "libyang.h"
26 
27 /* additional internal headers for some useful simple macros */
28 #include "compat.h"
29 #include "ly_common.h"
30 #include "lyb.h"
31 #include "plugins_internal.h" /* LY_TYPE_*_STR */
32 
45 static void lyplg_type_free_union(const struct ly_ctx *ctx, struct lyd_value *value);
46 
50 #define LYPLG_UNION_TYPE_IDX_SIZE 1
51 
62 static LY_ERR
63 union_subvalue_assignment(const void *value, uint32_t value_size_bits, void **original, uint32_t *orig_size_bits,
64  uint32_t *options)
65 {
66  LY_ERR ret = LY_SUCCESS;
67 
68  if (*options & LYPLG_TYPE_STORE_DYNAMIC) {
69  /* The allocated value is stored and spend. */
70  *original = (void *)value;
71  *options &= ~LYPLG_TYPE_STORE_DYNAMIC;
72  } else if (value_size_bits) {
73  /* Make a copy of the value. */
74  *original = calloc(1, LYPLG_BITS2BYTES(value_size_bits));
75  LY_CHECK_ERR_RET(!*original, ret = LY_EMEM, ret);
76  memcpy(*original, value, LYPLG_BITS2BYTES(value_size_bits));
77  } else {
78  /* Empty value. */
79  *original = strdup("");
80  LY_CHECK_ERR_RET(!*original, ret = LY_EMEM, ret);
81  }
82  *orig_size_bits = value_size_bits;
83 
84  return ret;
85 }
86 
96 static LY_ERR
97 lyb_union_validate(const void *lyb_data, uint32_t lyb_data_size_bits, const struct lysc_type_union *type_u,
98  struct ly_err_item **err)
99 {
100  uint32_t type_idx = 0;
101 
102  /* basic validation */
103  if (lyb_data_size_bits < LYPLG_UNION_TYPE_IDX_SIZE * 8) {
104  return ly_err_new(err, LY_EVALID, LYVE_DATA, NULL, NULL, "Invalid LYB union value size %" PRIu32
105  " b (expected at least %" PRIu8 " b).", lyb_data_size_bits, LYPLG_UNION_TYPE_IDX_SIZE * 8);
106  }
107 
108  /* get index in correct byte order */
109  memcpy(&type_idx, lyb_data, LYPLG_UNION_TYPE_IDX_SIZE);
110  type_idx = le32toh(type_idx);
111  if (type_idx >= LY_ARRAY_COUNT(type_u->types)) {
112  return ly_err_new(err, LY_EVALID, LYVE_DATA, NULL, NULL,
113  "Invalid LYB union type index %" PRIu32 " (type count %" LY_PRI_ARRAY_COUNT_TYPE ").",
114  type_idx, LY_ARRAY_COUNT(type_u->types));
115  }
116 
117  return LY_SUCCESS;
118 }
119 
130 static void
131 lyb_parse_union(const void *lyb_data, uint32_t lyb_data_size_bits, uint32_t *type_idx, const void **lyb_value,
132  uint32_t *lyb_value_size_bits)
133 {
134  uint32_t num = 0;
135 
136  assert(lyb_data && !(lyb_value && !lyb_value_size_bits));
137 
138  if (type_idx) {
139  memcpy(&num, lyb_data, LYPLG_UNION_TYPE_IDX_SIZE);
140  num = le32toh(num);
141 
142  *type_idx = num;
143  }
144 
145  if (lyb_value && lyb_value_size_bits && lyb_data_size_bits) {
146  /* Get lyb_value and its length. */
147  if (lyb_data_size_bits == LYPLG_UNION_TYPE_IDX_SIZE * 8) {
148  *lyb_value_size_bits = 0;
149  *lyb_value = "";
150  } else {
151  *lyb_value_size_bits = lyb_data_size_bits - LYPLG_UNION_TYPE_IDX_SIZE * 8;
152  *lyb_value = (char *)lyb_data + LYPLG_UNION_TYPE_IDX_SIZE;
153  }
154  }
155 }
156 
168 static LY_ERR
169 union_update_lref_err(struct ly_err_item *err, const struct lysc_type *type, const void *value, uint32_t value_size_bits)
170 {
171  const struct lysc_type_leafref *lref;
172  char *valstr = NULL;
173  int r;
174 
175  if (!err || (type->basetype != LY_TYPE_LEAFREF)) {
176  /* nothing to do */
177  return LY_SUCCESS;
178  }
179 
180  lref = (const struct lysc_type_leafref *)type;
181 
182  /* update error-app-tag */
183  free(err->apptag);
184  err->apptag = strdup("instance-required");
185  LY_CHECK_ERR_RET(!err->apptag, LOGMEM(NULL), LY_EMEM);
186 
187  valstr = strndup((const char *)value, value_size_bits / 8);
188  LY_CHECK_ERR_RET(!valstr, LOGMEM(NULL), LY_EMEM);
189 
190  /* update error-message */
191  free(err->msg);
192  r = asprintf(&err->msg, LY_ERRMSG_NOLREF_VAL, valstr, lyxp_get_expr(lref->path));
193  free(valstr);
194  LY_CHECK_ERR_RET(r == -1, LOGMEM(NULL), LY_EMEM);
195 
196  return LY_SUCCESS;
197 }
198 
215 static LY_ERR
216 union_store_type(const struct ly_ctx *ctx, struct lysc_type_union *type_u, uint32_t type_idx, struct lyd_value_union *subvalue,
217  uint32_t options, ly_bool validate_tree, const struct lyd_node *ctx_node, const struct lyd_node *tree,
218  const struct lysc_ext_instance *top_ext, struct lys_glob_unres *unres, struct ly_err_item **err)
219 {
220  LY_ERR rc = LY_SUCCESS;
221  struct lysc_type *type = type_u->types[type_idx];
222  const void *value = NULL;
223  ly_bool dynamic = 0;
224  LY_VALUE_FORMAT format;
225  void *prefix_data;
226  uint32_t value_size_bits = 0, opts = 0, ti;
227  struct lyplg_type *type_plg;
228 
229  *err = NULL;
230 
231  if (subvalue->format == LY_VALUE_LYB) {
232  lyb_parse_union(subvalue->original, subvalue->orig_size_bits, &ti, &value, &value_size_bits);
233  if (ti != type_idx) {
234  /* value of another type, first store the value properly and then use its JSON value for parsing */
235  type_plg = LYSC_GET_TYPE_PLG(type_u->types[ti]->plugin_ref);
236  rc = type_plg->store(ctx, type_u->types[ti], value, value_size_bits, LYPLG_TYPE_STORE_ONLY,
237  subvalue->format, subvalue->prefix_data, subvalue->hints, subvalue->ctx_node, subvalue->top_ext,
238  &subvalue->value, unres, err);
239  if ((rc != LY_SUCCESS) && (rc != LY_EINCOMPLETE)) {
240  /* clear any leftover/freed garbage */
241  memset(&subvalue->value, 0, sizeof subvalue->value);
242 
243  /* if this is a leafref, lets make sure we propagate the appropriate error, and not a type validation failure */
244  union_update_lref_err(*err, type_u->types[ti], value, value_size_bits);
245  goto cleanup;
246  }
247 
248  assert(subvalue->value.realtype);
249  value = LYSC_GET_TYPE_PLG(subvalue->value.realtype->plugin_ref)->print(ctx, &subvalue->value,
250  LY_VALUE_JSON, NULL, &dynamic, &value_size_bits);
251  assert(!(value_size_bits % 8));
252 
253  /* to avoid leaks, free subvalue->value, but we need the value, which may be stored there */
254  if (!dynamic) {
255  value = strndup(value, value_size_bits / 8);
256  dynamic = 1;
257  }
258  type_plg->free(ctx, &subvalue->value);
259 
260  format = LY_VALUE_JSON;
261  prefix_data = NULL;
262  } else {
263  format = subvalue->format;
264  prefix_data = subvalue->prefix_data;
265  }
266  } else {
267  value = subvalue->original;
268  value_size_bits = subvalue->orig_size_bits;
269  format = subvalue->format;
270  prefix_data = subvalue->prefix_data;
271  }
272 
273  if (options & LYPLG_TYPE_STORE_ONLY) {
274  opts |= LYPLG_TYPE_STORE_ONLY;
275  }
276 
277  type_plg = LYSC_GET_TYPE_PLG(type->plugin_ref);
278 
279  rc = type_plg->store(ctx, type, value, value_size_bits, opts, format, prefix_data, subvalue->hints,
280  subvalue->ctx_node, subvalue->top_ext, &subvalue->value, unres, err);
281  if ((rc != LY_SUCCESS) && (rc != LY_EINCOMPLETE)) {
282  /* clear any leftover/freed garbage */
283  memset(&subvalue->value, 0, sizeof subvalue->value);
284 
285  /* if this is a leafref, lets make sure we propagate the appropriate error, and not a type validation failure */
286  union_update_lref_err(*err, type, value, value_size_bits);
287  goto cleanup;
288  }
289 
290  if (validate_tree && type_plg->validate_tree) {
291  /* we need the value validated in the data tree */
292  rc = type_plg->validate_tree(ctx, type, ctx_node, tree, top_ext, &subvalue->value, err);
293  if (rc) {
294  /* validate failed, we need to free the stored value */
295  type_plg->free(ctx, &subvalue->value);
296  goto cleanup;
297  }
298  }
299 
300 cleanup:
301  if (dynamic) {
302  free((void *)value);
303  }
304  return rc;
305 }
306 
323 static LY_ERR
324 union_find_type(const struct ly_ctx *ctx, struct lysc_type_union *type_u, struct lyd_value_union *subvalue,
325  uint32_t options, ly_bool validate_tree, const struct lyd_node *ctx_node, const struct lyd_node *tree,
326  const struct lysc_ext_instance *top_ext, uint32_t *type_idx, struct lys_glob_unres *unres, struct ly_err_item **err)
327 {
328  LY_ERR ret = LY_SUCCESS;
330  struct ly_err_item **errs = NULL, *e;
331  uint32_t *prev_lo, temp_lo = 0;
332  char *msg = NULL, *err_app_tag = NULL;
333  int msg_len = 0;
334  ly_bool use_err_app_tag = 0;
335  struct lyplg_type *type_plg;
336 
337  *err = NULL;
338 
339  /* alloc errors */
340  errs = calloc(LY_ARRAY_COUNT(type_u->types), sizeof *errs);
341  LY_CHECK_RET(!errs, LY_EMEM);
342 
343  /* turn logging temporarily off */
344  prev_lo = ly_temp_log_options(&temp_lo);
345 
346  /* use the first usable subtype to store the value */
347  for (u = 0; u < LY_ARRAY_COUNT(type_u->types); ++u) {
348  ret = union_store_type(ctx, type_u, u, subvalue, options, validate_tree, ctx_node, tree, top_ext, unres, &e);
349  if ((ret == LY_SUCCESS) || (ret == LY_EINCOMPLETE)) {
350  break;
351  }
352 
353  errs[u] = e;
354  }
355 
356  if (u == LY_ARRAY_COUNT(type_u->types)) {
357  /* create the full error */
358  if (subvalue->format == LY_VALUE_LYB) {
359  msg_len = asprintf(&msg, "Invalid LYB union value - no matching subtype found:\n");
360  } else {
361  msg_len = asprintf(&msg, "Invalid union value \"%.*s\" - no matching subtype found:\n",
362  (int)subvalue->orig_size_bits / 8, (char *)subvalue->original);
363  }
364  if (msg_len == -1) {
365  LY_CHECK_ERR_GOTO(!errs, ret = LY_EMEM, cleanup);
366  /* for further actions in function msg_len is just 0 */
367  msg_len = 0;
368  }
369  for (u = 0; u < LY_ARRAY_COUNT(type_u->types); ++u) {
370  if (!errs[u]) {
371  /* no error for some reason */
372  continue;
373  }
374 
375  /* use an app-tag if all the types set it or set none */
376  if (errs[u]->apptag) {
377  if (!err_app_tag) {
378  err_app_tag = strdup(errs[u]->apptag);
379  LY_CHECK_ERR_GOTO(!err_app_tag, ret = LY_EMEM, cleanup);
380  use_err_app_tag = 1;
381  } else if (strcmp(errs[u]->apptag, err_app_tag)) {
382  use_err_app_tag = 0;
383  }
384  }
385 
386  type_plg = LYSC_GET_TYPE_PLG(type_u->types[u]->plugin_ref);
387 
388  msg = ly_realloc(msg, msg_len + 4 + strlen(type_plg->id) + 2 + strlen(errs[u]->msg) + 2);
389  LY_CHECK_ERR_GOTO(!msg, ret = LY_EMEM, cleanup);
390  msg_len += sprintf(msg + msg_len, " %s: %s\n", type_plg->id, errs[u]->msg);
391  }
392 
393  if (!use_err_app_tag) {
394  free(err_app_tag);
395  err_app_tag = NULL;
396  }
397  ret = ly_err_new(err, LY_EVALID, LYVE_DATA, NULL, err_app_tag, "%s", msg);
398  err_app_tag = NULL;
399  } else if (type_idx) {
400  *type_idx = u;
401  }
402 
403 cleanup:
404  for (u = 0; u < LY_ARRAY_COUNT(type_u->types); ++u) {
405  ly_err_free(errs[u]);
406  }
407  free(errs);
408  free(msg);
409  free(err_app_tag);
410  ly_temp_log_options(prev_lo);
411  return ret;
412 }
413 
428 static LY_ERR
429 lyb_fill_subvalue(const struct ly_ctx *ctx, struct lysc_type_union *type_u, const void *lyb_data, uint32_t lyb_data_size_bits,
430  void *prefix_data, struct lyd_value_union *subvalue, uint32_t *options, struct lys_glob_unres *unres,
431  struct ly_err_item **err)
432 {
433  LY_ERR ret;
434  uint32_t lyb_value_size_bits = 0, type_idx;
435  const void *lyb_value = NULL;
436 
437  ret = lyb_union_validate(lyb_data, lyb_data_size_bits, type_u, err);
438  LY_CHECK_RET(ret);
439 
440  /* parse lyb_data and set the lyb_value and lyb_value_size_bits */
441  lyb_parse_union(lyb_data, lyb_data_size_bits, &type_idx, &lyb_value, &lyb_value_size_bits);
442 
443  /* store lyb_data to subvalue */
444  ret = union_subvalue_assignment(lyb_data, lyb_data_size_bits, &subvalue->original, &subvalue->orig_size_bits, options);
445  LY_CHECK_RET(ret);
446 
447  if (lyb_value) {
448  /* resolve prefix_data and set format */
449  ret = lyplg_type_prefix_data_new(ctx, lyb_value, LYPLG_BITS2BYTES(lyb_value_size_bits), LY_VALUE_LYB,
450  prefix_data, &subvalue->format, &subvalue->prefix_data);
451  LY_CHECK_RET(ret);
452  assert(subvalue->format == LY_VALUE_LYB);
453  } else {
454  /* lyb_parse_union() did not find lyb_value, just set format */
455  subvalue->format = LY_VALUE_LYB;
456  }
457 
458  /* use the specific type to store the value */
459  ret = union_store_type(ctx, type_u, type_idx, subvalue, *options, 0, NULL, NULL, NULL, unres, err);
460 
461  return ret;
462 }
463 
464 static LY_ERR
465 lyplg_type_store_union(const struct ly_ctx *ctx, const struct lysc_type *type, const void *value, uint32_t value_size_bits,
466  uint32_t options, LY_VALUE_FORMAT format, void *prefix_data, uint32_t hints, const struct lysc_node *ctx_node,
467  const struct lysc_ext_instance *top_ext, struct lyd_value *storage, struct lys_glob_unres *unres,
468  struct ly_err_item **err)
469 {
470  LY_ERR ret = LY_SUCCESS, r;
471  struct lysc_type_union *type_u = (struct lysc_type_union *)type;
472  struct lyd_value_union *subvalue;
473 
474  *err = NULL;
475 
476  /* init storage */
477  memset(storage, 0, sizeof *storage);
478  LYPLG_TYPE_VAL_INLINE_PREPARE(storage, subvalue);
479  LY_CHECK_ERR_GOTO(!subvalue, ret = LY_EMEM, cleanup);
480  storage->realtype = type;
481  subvalue->hints = hints;
482  subvalue->ctx_node = ctx_node;
483  subvalue->top_ext = top_ext;
484 
485  if (format == LY_VALUE_LYB) {
486  ret = lyb_fill_subvalue(ctx, type_u, value, value_size_bits, prefix_data, subvalue, &options, unres, err);
487  LY_CHECK_GOTO((ret != LY_SUCCESS) && (ret != LY_EINCOMPLETE), cleanup);
488  } else {
489  /* store value to subvalue */
490  ret = union_subvalue_assignment(value, value_size_bits, &subvalue->original, &subvalue->orig_size_bits, &options);
491  LY_CHECK_GOTO(ret, cleanup);
492 
493  /* store format-specific data for later prefix resolution */
494  ret = lyplg_type_prefix_data_new(ctx, value, LYPLG_BITS2BYTES(value_size_bits), format, prefix_data,
495  &subvalue->format, &subvalue->prefix_data);
496  LY_CHECK_GOTO(ret, cleanup);
497 
498  /* use the first usable and valid subtype to store the value */
499  ret = union_find_type(ctx, type_u, subvalue, options & ~LYPLG_TYPE_STORE_ONLY, 0, NULL, NULL, NULL, NULL, unres,
500  err);
501  if (ret && (ret != LY_EINCOMPLETE) && (options & LYPLG_TYPE_STORE_ONLY)) {
502  /* we tried to find the actual type by validating the value but no type matched, so try to find any type */
503  ly_err_free(*err);
504  *err = NULL;
505  ret = union_find_type(ctx, type_u, subvalue, options, 0, NULL, NULL, NULL, NULL, unres, err);
506  }
507  LY_CHECK_GOTO(ret && (ret != LY_EINCOMPLETE), cleanup);
508  }
509 
510  /* store canonical value, if any (use the specific type value) */
511  r = lydict_insert(ctx, subvalue->value._canonical, 0, &storage->_canonical);
512  LY_CHECK_ERR_GOTO(r, ret = r, cleanup);
513 
514 cleanup:
515  if (options & LYPLG_TYPE_STORE_DYNAMIC) {
516  free((void *)value);
517  }
518 
519  if ((ret != LY_SUCCESS) && (ret != LY_EINCOMPLETE)) {
520  lyplg_type_free_union(ctx, storage);
521  }
522  return ret;
523 }
524 
525 static LY_ERR
526 lyplg_type_validate_tree_union(const struct ly_ctx *ctx, const struct lysc_type *type, const struct lyd_node *ctx_node,
527  const struct lyd_node *tree, const struct lysc_ext_instance *top_ext, struct lyd_value *storage,
528  struct ly_err_item **err)
529 {
530  LY_ERR rc = LY_SUCCESS;
531  struct lysc_type_union *type_u = (struct lysc_type_union *)type;
532  struct lyd_value_union *subvalue = storage->subvalue;
533  struct lyd_value orig = {0};
534  uint32_t type_idx;
535  ly_bool validated = 0;
536  struct lyplg_type *subvalue_type_plg;
537 
538  *err = NULL;
539 
540  /* because of types that do not store their own type as realtype (leafref), we are not able to call their
541  * validate callback (there is no way to get the type) but even if possible, the value may be invalid
542  * for the type, so we may have to perform union value storing again from scratch, but keep a value backup */
543  subvalue_type_plg = LYSC_GET_TYPE_PLG(subvalue->value.realtype->plugin_ref);
544  LY_CHECK_RET(subvalue_type_plg->duplicate(ctx, &subvalue->value, &orig));
545  subvalue_type_plg->free(ctx, &subvalue->value);
546 
547  if (subvalue->format == LY_VALUE_LYB) {
548  /* use the specific type to store and validate the value */
549  lyb_parse_union(subvalue->original, 0, &type_idx, NULL, NULL);
550 
551  if (union_store_type(ctx, type_u, type_idx, subvalue, 0, 1, ctx_node, tree, top_ext, NULL, err)) {
552  /* validation failed, we need to try storing the value again */
553  ly_err_free(*err);
554  *err = NULL;
555  } else {
556  validated = 1;
557  }
558  }
559 
560  if (!validated) {
561  /* use the first usable subtype to store and validate the value */
562  rc = union_find_type(ctx, type_u, subvalue, 0, 1, ctx_node, tree, top_ext, NULL, NULL, err);
563  if (rc) {
564  /* validation failed, restore the previous value */
565  subvalue->value = orig;
566  return rc;
567  }
568  }
569 
570  /* update the canonical value, if any generated */
571  lydict_remove(ctx, storage->_canonical);
572  LY_CHECK_RET(lydict_insert(ctx, subvalue->value._canonical, 0, &storage->_canonical));
573 
574  /* free backup value */
575  LYSC_GET_TYPE_PLG(orig.realtype->plugin_ref)->free(ctx, &orig);
576  return LY_SUCCESS;
577 }
578 
579 static LY_ERR
580 lyplg_type_compare_union(const struct ly_ctx *ctx, const struct lyd_value *val1, const struct lyd_value *val2)
581 {
582  if (val1->subvalue->value.realtype != val2->subvalue->value.realtype) {
583  return LY_ENOT;
584  }
585  return LYSC_GET_TYPE_PLG(val1->subvalue->value.realtype->plugin_ref)->compare(ctx,
586  &val1->subvalue->value, &val2->subvalue->value);
587 }
588 
589 static int
590 lyplg_type_sort_union(const struct ly_ctx *ctx, const struct lyd_value *val1, const struct lyd_value *val2)
591 {
592  int rc;
594  struct lysc_type **types, *type;
595 
596  if (val1->subvalue->value.realtype == val2->subvalue->value.realtype) {
597  return LYSC_GET_TYPE_PLG(val1->subvalue->value.realtype->plugin_ref)->sort(ctx,
598  &val1->subvalue->value, &val2->subvalue->value);
599  }
600 
601  /* compare according to the order of types */
602  rc = 0;
603  types = ((struct lysc_type_union *)val1->realtype)->types;
604  LY_ARRAY_FOR(types, u) {
605  if (types[u]->basetype == LY_TYPE_LEAFREF) {
606  type = ((struct lysc_type_leafref *)types[u])->realtype;
607  } else {
608  type = types[u];
609  }
610 
611  if (type == val1->subvalue->value.realtype) {
612  rc = 1;
613  break;
614  } else if (type == val2->subvalue->value.realtype) {
615  rc = -1;
616  break;
617  }
618  }
619  assert(rc);
620 
621  return rc;
622 }
623 
636 static const void *
637 lyb_union_print(const struct ly_ctx *ctx, struct lysc_type_union *type_u, struct lyd_value_union *subvalue,
638  void *prefix_data, uint32_t *value_size_bits)
639 {
640  void *ret = NULL;
641  LY_ERR r;
642  struct ly_err_item *err;
643  uint32_t num = 0, pval_size_bits, type_idx = 0;
644  ly_bool dynamic;
645  void *pval;
646 
647  /* learn the type index, must succeed because have been called before */
648  if (!ctx) {
649  assert(subvalue->ctx_node);
650  ctx = subvalue->ctx_node->module->ctx;
651  }
652  LYSC_GET_TYPE_PLG(subvalue->value.realtype->plugin_ref)->free(ctx, &subvalue->value);
653  r = union_find_type(ctx, type_u, subvalue, 0, 0, NULL, NULL, NULL, &type_idx, NULL, &err);
654  ly_err_free(err);
655  LY_CHECK_RET((r != LY_SUCCESS) && (r != LY_EINCOMPLETE), NULL);
656 
657  /* print subvalue in LYB format */
658  pval = (void *)LYSC_GET_TYPE_PLG(subvalue->value.realtype->plugin_ref)->print(NULL, &subvalue->value, LY_VALUE_LYB,
659  prefix_data, &dynamic, &pval_size_bits);
660  LY_CHECK_RET(!pval, NULL);
661 
662  /* create LYB data */
663  *value_size_bits = LYPLG_UNION_TYPE_IDX_SIZE * 8 + pval_size_bits;
664  ret = malloc(LYPLG_BITS2BYTES(*value_size_bits));
665  LY_CHECK_RET(!ret, NULL);
666 
667  num = htole32(type_idx);
668  memcpy(ret, &num, LYPLG_UNION_TYPE_IDX_SIZE);
669  memcpy((char *)ret + LYPLG_UNION_TYPE_IDX_SIZE, pval, LYPLG_BITS2BYTES(pval_size_bits));
670 
671  if (dynamic) {
672  free(pval);
673  }
674 
675  return ret;
676 }
677 
678 static const void *
679 lyplg_type_print_union(const struct ly_ctx *ctx, const struct lyd_value *value, LY_VALUE_FORMAT format,
680  void *prefix_data, ly_bool *dynamic, uint32_t *value_size_bits)
681 {
682  const void *ret;
683  struct lyd_value_union *subvalue = value->subvalue;
684  struct lysc_type_union *type_u = (struct lysc_type_union *)value->realtype;
685  uint32_t lyb_data_size_bits = 0;
686 
687  if ((format == LY_VALUE_LYB) && (subvalue->format == LY_VALUE_LYB)) {
688  /* The return value is already ready. */
689  *dynamic = 0;
690  if (value_size_bits) {
691  *value_size_bits = subvalue->orig_size_bits;
692  }
693  return subvalue->original;
694  } else if ((format == LY_VALUE_LYB) && (subvalue->format != LY_VALUE_LYB)) {
695  /* The return LYB data must be created. */
696  *dynamic = 1;
697  ret = lyb_union_print(ctx, type_u, subvalue, prefix_data, &lyb_data_size_bits);
698  if (value_size_bits) {
699  *value_size_bits = lyb_data_size_bits;
700  }
701  return ret;
702  }
703 
704  assert(format != LY_VALUE_LYB);
705  ret = (void *)LYSC_GET_TYPE_PLG(subvalue->value.realtype->plugin_ref)->print(ctx, &subvalue->value,
706  format, prefix_data, dynamic, value_size_bits);
707  if (!value->_canonical && (format == LY_VALUE_CANON)) {
708  /* the canonical value is supposed to be stored now */
709  lydict_insert(ctx, subvalue->value._canonical, 0, (const char **)&value->_canonical);
710  }
711 
712  return ret;
713 }
714 
715 static LY_ERR
716 lyplg_type_dup_union(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup)
717 {
718  LY_ERR ret = LY_SUCCESS;
719  struct lyd_value_union *orig_val = original->subvalue, *dup_val;
720 
721  /* init dup value */
722  memset(dup, 0, sizeof *dup);
723  dup->realtype = original->realtype;
724 
725  ret = lydict_insert(ctx, original->_canonical, 0, &dup->_canonical);
726  LY_CHECK_GOTO(ret, cleanup);
727 
728  dup_val = calloc(1, sizeof *dup_val);
729  LY_CHECK_ERR_GOTO(!dup_val, LOGMEM(ctx); ret = LY_EMEM, cleanup);
730  dup->subvalue = dup_val;
731 
732  ret = LYSC_GET_TYPE_PLG(orig_val->value.realtype->plugin_ref)->duplicate(ctx, &orig_val->value, &dup_val->value);
733  LY_CHECK_GOTO(ret, cleanup);
734 
735  if (orig_val->orig_size_bits) {
736  dup_val->original = calloc(1, LYPLG_BITS2BYTES(orig_val->orig_size_bits));
737  LY_CHECK_ERR_GOTO(!dup_val->original, LOGMEM(ctx); ret = LY_EMEM, cleanup);
738  memcpy(dup_val->original, orig_val->original, LYPLG_BITS2BYTES(orig_val->orig_size_bits));
739  } else {
740  dup_val->original = strdup("");
741  LY_CHECK_ERR_GOTO(!dup_val->original, LOGMEM(ctx); ret = LY_EMEM, cleanup);
742  }
743  dup_val->orig_size_bits = orig_val->orig_size_bits;
744 
745  dup_val->format = orig_val->format;
746  dup_val->ctx_node = orig_val->ctx_node;
747  dup_val->hints = orig_val->hints;
748  ret = lyplg_type_prefix_data_dup(ctx, orig_val->format, orig_val->prefix_data, &dup_val->prefix_data);
749  LY_CHECK_GOTO(ret, cleanup);
750 
751 cleanup:
752  if (ret) {
753  lyplg_type_free_union(ctx, dup);
754  }
755  return ret;
756 }
757 
758 static void
759 lyplg_type_free_union(const struct ly_ctx *ctx, struct lyd_value *value)
760 {
761  struct lyd_value_union *val;
762 
763  lydict_remove(ctx, value->_canonical);
764  value->_canonical = NULL;
765  LYD_VALUE_GET(value, val);
766  if (val) {
767  if (val->value.realtype) {
768  LYSC_GET_TYPE_PLG(val->value.realtype->plugin_ref)->free(ctx, &val->value);
769  }
771  free(val->original);
772 
774  }
775 }
776 
785  {
786  .module = "",
787  .revision = NULL,
788  .name = LY_TYPE_UNION_STR,
789 
790  .plugin.id = "ly2 union",
791  .plugin.lyb_size = lyplg_type_lyb_size_variable_bits,
792  .plugin.store = lyplg_type_store_union,
793  .plugin.validate_value = NULL,
794  .plugin.validate_tree = lyplg_type_validate_tree_union,
795  .plugin.compare = lyplg_type_compare_union,
796  .plugin.sort = lyplg_type_sort_union,
797  .plugin.print = lyplg_type_print_union,
798  .plugin.duplicate = lyplg_type_dup_union,
799  .plugin.free = lyplg_type_free_union,
800  },
801  {0}
802 };
LIBYANG_API_DECL void lyplg_type_lyb_size_variable_bits(const struct lysc_type *type, enum lyplg_lyb_size_type *size_type, uint32_t *fixed_size_bits)
Implementation of lyplg_type_lyb_size_clb for a type with variable length in bits.
struct lysc_type * realtype
Definition: tree_data.h:567
Compiled YANG data node.
Definition: tree_schema.h:1434
#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:2185
memset(value->fixed_mem, 0, LYD_VALUE_FIXED_MEM_SIZE)
const char * id
LY_DATA_TYPE basetype
Definition: tree_schema.h:1410
Hold type-specific functions for various operations with the data values.
Generic structure for a data node.
Definition: tree_data.h:792
YANG extension compiled instance.
Definition: plugins_exts.h:436
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().
LY_ERR
libyang&#39;s error codes returned by the libyang functions.
Definition: log.h:240
uint8_t ly_bool
Type to indicate boolean value.
Definition: log.h:28
lyplg_type_free_clb free
LY_ERR err
Definition: log.h:287
#define LYPLG_UNION_TYPE_IDX_SIZE
Size in bytes of the used type index in the LYB Binary Format.
Definition: union.c:50
Definition: log.h:254
#define LYPLG_TYPE_STORE_DYNAMIC
void * original
Definition: tree_data.h:621
uintptr_t plugin_ref
Definition: tree_schema.h:1299
#define LOGMEM(CTX)
Definition: tree_edit.h:22
LIBYANG_API_DECL LY_ERR lyplg_type_prefix_data_new(const struct ly_ctx *ctx, const void *value, uint32_t value_size, 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.
char * apptag
Definition: log.h:293
char * msg
Definition: log.h:289
struct lysc_node * ctx_node
Definition: tree_data.h:628
struct lysc_type ** types
Definition: tree_schema.h:1413
LYPLG_TYPE_VAL_INLINE_DESTROY(val)
Definition: log.h:242
The main libyang public header.
lyplg_type_validate_tree_clb validate_tree
YANG data representation.
Definition: tree_data.h:563
const char * _canonical
Definition: tree_data.h:564
lyplg_type_store_clb store
struct lyxp_expr * path
Definition: tree_schema.h:1379
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:606
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:784
uint32_t hints
Definition: tree_data.h:623
uint32_t orig_size_bits
Definition: tree_data.h:622
void * prefix_data
Definition: tree_data.h:627
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...
Definition: log.h:248
lyplg_type_dup_clb duplicate
const char * module
LIBYANG_API_DECL LY_ERR lyplg_type_prefix_data_dup(const struct ly_ctx *ctx, LY_VALUE_FORMAT format, const void *orig, void **dup)
Duplicate prefix data.
#define LY_ARRAY_COUNT(ARRAY)
Get the number of records in the ARRAY.
Definition: tree.h:148
LIBYANG_API_DECL void lyplg_type_prefix_data_free(LY_VALUE_FORMAT format, void *prefix_data)
Free internal prefix data.
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:1438
if((v1->size!=v2->size)||memcmp(v1->data, v2->data, v1->size))
Definition: binary.c:384
LY_VALUE_FORMAT
All kinds of supported value formats and prefix mappings to modules.
Definition: tree.h:234
LIBYANG_API_DECL const char * lyxp_get_expr(const struct lyxp_expr *path)
Getter for original XPath expression from a parsed expression.
#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:1300
Special lyd_value structure for built-in union values.
Definition: tree_data.h:618
API for (user) types plugins.
LY_VALUE_FORMAT format
Definition: tree_data.h:624
libyang context handler.
#define LYPLG_BITS2BYTES(bits)
Convert bits to bytes.
struct lyd_value value
Definition: tree_data.h:619
struct lysc_ext_instance * top_ext
Definition: tree_data.h:629
#define LYPLG_TYPE_STORE_ONLY
assert(!value->_canonical)