30#include "plugins_internal.h"
44static void lyplg_type_free_union(
const struct ly_ctx *ctx,
struct lyd_value *value);
49#define LYPLG_UNION_TYPE_IDX_SIZE 1
61union_validate_value_lyb(
const void *lyb_data, uint64_t lyb_data_size_bits,
const struct lysc_type_union *type_u,
64 uint32_t type_idx = 0;
74 type_idx = le32toh(type_idx);
77 "Invalid LYB union type index %" PRIu32
" (type count %" LYA_PRI_COUNT_T ").",
95union_parse_value_lyb(
const void *lyb_data, uint64_t lyb_data_size_bits, uint32_t *type_idx,
const void **lyb_value,
96 uint64_t *lyb_value_size_bits)
109 if (lyb_value && lyb_value_size_bits && lyb_data_size_bits) {
112 *lyb_value_size_bits = 0;
134union_create_value_lyb(
const struct ly_ctx *ctx, uint32_t type_idx,
const struct lyd_value *value,
void **lyb_value,
139 const void *pval = NULL;
140 uint64_t pval_size_bits, lyb_bits = 0;
163 num = htole32(type_idx);
173 *lyb_size_bits = lyb_bits;
190union_update_lref_err(
struct ly_err_item *err,
const struct lysc_type *type,
const void *value, uint64_t value_size_bits)
205 err->
apptag = strdup(
"instance-required");
208 valstr = strndup((
const char *)value, value_size_bits / 8);
209 LY_CHECK_ERR_RET(!valstr, LOGMEM(NULL),
LY_EMEM);
215 LY_CHECK_ERR_RET(r == -1, LOGMEM(NULL),
LY_EMEM);
238union_subvalue_get_input_value(
const struct ly_ctx *ctx,
const struct lysc_type_union *type_u, uint32_t type_idx,
248 *value_size_bits = 0;
256 if (ti != type_idx) {
263 union_update_lref_err(*err, type_u->
types[ti], *value, *value_size_bits);
271 assert(!(*value_size_bits % 8));
275 *value = strndup(*value, *value_size_bits / 8);
278 type_plg->
free(ctx, &storage);
283 *format = subvalue->
format;
289 *format = subvalue->
format;
319union_store_type(
const struct ly_ctx *ctx,
const struct lysc_type *type,
const void *value, uint64_t value_size_bits,
322 struct lys_glob_unres *unres,
struct ly_err_item **err)
330 type_plg = LYSC_GET_TYPE_PLG(type->
plugin_ref);
338 rc = type_plg->
store(ctx, type, value, value_size_bits, options, format, prefix_data, hints, ctx_snode, storage,
342 union_update_lref_err(*err, type, value, value_size_bits);
348 rc = type_plg->
validate_tree(ctx, type, ctx_node, tree, storage, err);
351 type_plg->
free(ctx, storage);
362 memset(storage, 0,
sizeof *storage);
384union_read_store_type(
const struct ly_ctx *ctx,
const struct lysc_type_union *type_u, uint32_t type_idx,
390 uint64_t value_size_bits;
396 r = union_subvalue_get_input_value(ctx, type_u, type_idx, subvalue, &value, &value_size_bits, &dynamic, &format,
410 rc = union_store_type(ctx, type_u->
types[type_idx], value, value_size_bits, options, format, prefix_data,
433 uint32_t options,
const struct lyd_node *ctx_node,
const struct lyd_node *tree, uint32_t *type_idx,
434 struct lys_glob_unres *unres,
struct ly_err_item **err)
439 uint32_t *prev_lo, temp_lo = 0;
440 char *
msg = NULL, *err_app_tag = NULL;
456 rc = union_read_store_type(ctx, type_u, u, subvalue, options, ctx_node, tree, unres, &e);
468 msg_len = asprintf(&msg,
"Invalid LYB union value - no matching subtype found:\n");
470 msg_len = asprintf(&msg,
"Invalid union value \"%.*s\" - no matching subtype found:\n",
474 LY_CHECK_ERR_GOTO(!errs, rc =
LY_EMEM, cleanup);
485 if (errs[u]->apptag) {
487 err_app_tag = strdup(errs[u]->apptag);
488 LY_CHECK_ERR_GOTO(!err_app_tag, rc =
LY_EMEM, cleanup);
490 }
else if (strcmp(errs[u]->apptag, err_app_tag)) {
497 msg = ly_realloc(msg, msg_len + 4 + strlen(type_plg->
id) + 2 + strlen(errs[u]->msg) + 2);
498 LY_CHECK_ERR_GOTO(!msg, rc =
LY_EMEM, cleanup);
499 msg_len += sprintf(msg + msg_len,
" %s: %s\n", type_plg->
id, errs[u]->msg);
502 if (!use_err_app_tag) {
508 }
else if (type_idx) {
542union_prepare_subvalue(
const struct ly_ctx *ctx,
const struct lysc_type *type,
const void *value, uint64_t value_size_bits,
549 memset(storage, 0,
sizeof *storage);
554 (*subvalue)->hints = hints;
555 (*subvalue)->ctx_node = ctx_node;
559 (*subvalue)->original = (
void *)value;
561 }
else if (value_size_bits) {
566 (*subvalue)->original = strdup(
"");
569 (*subvalue)->orig_size_bits = value_size_bits;
574 (format ==
LY_VALUE_LYB) ? NULL : prefix_data, &(*subvalue)->format, &(*subvalue)->prefix_data);
578lyplg_type_store_union(
const struct ly_ctx *ctx,
const struct lysc_type *type,
const void *value, uint64_t value_size_bits,
585 uint32_t type_idx = 0;
592 rc = union_prepare_subvalue(ctx, type, value, value_size_bits, &options, format, prefix_data, hints,
593 ctx_node, storage, &subvalue, err);
594 LY_CHECK_GOTO(rc, cleanup);
598 rc = union_validate_value_lyb(value, value_size_bits, type_u, err);
599 LY_CHECK_GOTO(rc, cleanup);
600 union_parse_value_lyb(value, 0, &type_idx, NULL, NULL);
603 rc = union_read_store_type(ctx, type_u, type_idx, subvalue, options, NULL, NULL, unres, err);
607 rc = union_find_type(ctx, type_u, subvalue, options & ~
LYPLG_TYPE_STORE_ONLY, NULL, NULL, NULL, unres, err);
611 rc = union_find_type(ctx, type_u, subvalue, options, NULL, NULL, NULL, unres, err);
618 LY_CHECK_ERR_GOTO(r, rc = r, cleanup);
626 lyplg_type_free_union(ctx, storage);
633 const void *value, uint64_t value_size_bits, uint32_t options,
LY_VALUE_FORMAT format,
void *prefix_data,
640 uint64_t lyb_size_bits;
645 memset(storage, 0,
sizeof *storage);
649 LY_CHECK_ERR_GOTO(!subvalue, rc =
LY_EMEM, cleanup);
657 r = union_create_value_lyb(ctx, type_idx, &subvalue->
value, &lyb, &lyb_size_bits, err);
658 LY_CHECK_ERR_GOTO(r, rc = r, cleanup);
669 LY_CHECK_ERR_GOTO(r, rc = r, cleanup);
678 lyplg_type_free_union(ctx, storage);
679 memset(storage, 0,
sizeof *storage);
702 LY_CHECK_RET(realtype_plg->
duplicate(ctx, &subvalue->
value, &orig));
703 realtype_plg->
free(ctx, &subvalue->
value);
707 union_parse_value_lyb(subvalue->
original, 0, &type_idx, NULL, NULL);
709 if (union_read_store_type(ctx, type_u, type_idx, subvalue, 0, ctx_node, tree, NULL, err)) {
720 rc = union_find_type(ctx, type_u, subvalue, 0, ctx_node, tree, NULL, NULL, err);
721 LY_CHECK_GOTO(rc, cleanup);
732 subvalue->
value = orig;
747 &val1->subvalue->value, &val2->subvalue->value);
759 &val1->subvalue->value, &val2->subvalue->value);
772 if (type == val1->subvalue->value.
realtype) {
775 }
else if (type == val2->subvalue->value.
realtype) {
797 uint64_t *value_size_bits)
802 uint32_t type_idx = 0;
815 LY_CHECK_RET(realtype_plg->
duplicate(ctx, &subvalue->
value, &orig), NULL);
816 realtype_plg->
free(ctx, &subvalue->
value);
819 r = union_find_type(ctx, type_u, subvalue, 0, NULL, NULL, &type_idx, NULL, &err);
823 r = union_find_type(ctx, type_u, subvalue,
LYPLG_TYPE_STORE_ONLY, NULL, NULL, &type_idx, NULL, &err);
829 r = union_create_value_lyb(NULL, type_idx, &subvalue->
value, &ret, value_size_bits, &err);
831 LY_CHECK_ERR_RET(r, subvalue->
value = orig, NULL);
835 realtype_plg->
free(ctx, &subvalue->
value);
836 subvalue->
value = orig;
842 void *prefix_data,
ly_bool *dynamic, uint64_t *value_size_bits)
847 uint64_t lyb_data_size_bits = 0;
852 if (value_size_bits) {
859 ret = union_print_value_lyb(ctx, type_u, subvalue, &lyb_data_size_bits);
860 if (value_size_bits) {
861 *value_size_bits = lyb_data_size_bits;
868 format, prefix_data, dynamic, value_size_bits);
884 memset(dup, 0,
sizeof *dup);
888 LY_CHECK_GOTO(ret, cleanup);
890 dup_val = calloc(1,
sizeof *dup_val);
891 LY_CHECK_ERR_GOTO(!dup_val, LOGMEM(ctx); ret =
LY_EMEM, cleanup);
892 dup->subvalue = dup_val;
895 LY_CHECK_GOTO(ret, cleanup);
899 LY_CHECK_ERR_GOTO(!dup_val->original, LOGMEM(ctx); ret =
LY_EMEM, cleanup);
902 dup_val->original = strdup(
"");
903 LY_CHECK_ERR_GOTO(!dup_val->original, LOGMEM(ctx); ret =
LY_EMEM, cleanup);
907 dup_val->format = orig_val->
format;
908 dup_val->ctx_node = orig_val->
ctx_node;
909 dup_val->hints = orig_val->
hints;
911 LY_CHECK_GOTO(ret, cleanup);
915 lyplg_type_free_union(ctx, dup);
950 .name = LY_TYPE_UNION_STR,
952 .plugin.id =
"ly2 union",
954 .plugin.store = lyplg_type_store_union,
955 .plugin.validate_value = NULL,
956 .plugin.validate_tree = lyplg_type_validate_tree_union,
957 .plugin.compare = lyplg_type_compare_union,
958 .plugin.sort = lyplg_type_sort_union,
959 .plugin.print = lyplg_type_print_union,
960 .plugin.duplicate = lyplg_type_dup_union,
961 .plugin.free = lyplg_type_free_union,
#define LYA_PRI_COUNT_T
Printing format specifier macro for LYA_COUNT_T values.
#define LYA_COUNT(ARRAY)
Get the number of records in the ARRAY.
#define LYA_FOR(ARRAY, INDEX)
Helper macro to go through sized-arrays with a numeric iterator.
#define LYA_COUNT_T
Type (i.e. size) of the sized array's size counter.
LIBYANG_API_DECL LY_ERR lydict_dup(const struct ly_ctx *ctx, const char *value, const char **str_p)
Duplicate string in dictionary. Only a reference counter is incremented.
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
libyang's error codes returned by the libyang functions.
Libyang full error structure.
LIBYANG_API_DECL uint32_t * ly_temp_log_options(uint32_t *opts)
Set temporary thread-safe (thread-specific) logger options overwriting those set by ly_log_options().
lyplg_type_store_clb store
lyplg_type_dup_clb duplicate
lyplg_type_validate_tree_clb validate_tree
#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 void ly_err_free(void *ptr)
Destructor for the error records created with ly_err_new().
LIBYANG_API_DEF LY_ERR lyplg_type_store_union_idx(const struct ly_ctx *ctx, const struct lysc_type *type, uint32_t type_idx, const void *value, uint64_t value_size_bits, uint32_t options, LY_VALUE_FORMAT format, void *prefix_data, uint32_t hints, const struct lysc_node *ctx_node, struct lyd_value *storage, struct ly_err_item **err)
Store a union value with a specific member type index, keeping that member resolved (pinned),...
#define LYPLG_TYPE_VAL_INLINE_DESTROY(type_val)
Destroy a prepared value.
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.
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 an error structure.
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 LYPLG_BITS2BYTES(bits)
Convert bits to bytes.
LIBYANG_API_DECL LY_ERR LIBYANG_API_DECL LY_ERR ly_err_new_no_mem(struct ly_err_item **err)
Create and fill an error structure with a no-memory error.
LIBYANG_API_DECL void lyplg_type_prefix_data_free(LY_VALUE_FORMAT format, void *prefix_data)
Free internal prefix data.
Hold type-specific functions for various operations with the data values.
LIBYANG_API_DECL void lyplg_type_lyb_size_variable_bits(const struct lysc_type *type, enum lyplg_lyb_size_type *size_type, uint64_t *fixed_size_bits)
Implementation of lyplg_type_lyb_size_clb for a type with variable length in bits.
#define LYPLG_TYPE_STORE_DYNAMIC
#define LYPLG_TYPE_STORE_IMPLEMENT
#define LYPLG_TYPE_STORE_ONLY
struct lys_module * module
struct lysc_type * realtype
struct lysc_type ** types
LIBYANG_API_DECL const char * lyxp_get_expr(const struct lyxp_expr *path)
Getter for original XPath expression from a parsed expression.
uint8_t ly_bool
Type to indicate boolean value.
API for (user) types plugins.
const struct lysc_type * realtype
#define LYD_VALUE_GET(value, type_val)
Get the value in format specific to the type.
const struct lysc_node * ctx_node
Generic structure for a data node.
YANG data representation.
Special lyd_value structure for built-in union values.
#define LYPLG_UNION_TYPE_IDX_SIZE
Size in bytes of the used type index in the LYB Binary Format.
const struct lyplg_type_record plugins_union[]
Plugin information for union type implementation.
LY_VALUE_FORMAT
All kinds of supported value formats and prefix mappings to modules.