Loading...
Searching...
No Matches
union.c
Go to the documentation of this file.
#define _GNU_SOURCE /* strdup */
#include "plugins_types.h"
#include <assert.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "libyang.h"
/* additional internal headers for some useful simple macros */
#include "compat.h"
#include "ly_common.h"
#include "plugins_internal.h" /* LY_TYPE_*_STR */
#define TYPE_IDX_SIZE 4
static LY_ERR
union_subvalue_assignment(const void *value, size_t value_len, void **original, size_t *orig_len, uint32_t *options)
{
LY_ERR ret = LY_SUCCESS;
if (*options & LYPLG_TYPE_STORE_DYNAMIC) {
/* The allocated value is stored and spend. */
*original = (void *)value;
*options &= ~LYPLG_TYPE_STORE_DYNAMIC;
} else if (value_len) {
/* Make copy of the value. */
*original = calloc(1, value_len);
LY_CHECK_ERR_RET(!*original, ret = LY_EMEM, ret);
memcpy(*original, value, value_len);
} else {
/* Empty value. */
*original = strdup("");
LY_CHECK_ERR_RET(!*original, ret = LY_EMEM, ret);
}
*orig_len = value_len;
return ret;
}
static LY_ERR
lyb_union_validate(const void *lyb_data, size_t lyb_data_len, const struct lysc_type_union *type_u, struct ly_err_item **err)
{
LY_ERR ret = LY_SUCCESS;
uint64_t type_idx = 0;
/* Basic validation. */
if (lyb_data_len < TYPE_IDX_SIZE) {
ret = ly_err_new(err, LY_EVALID, LYVE_DATA, NULL, NULL, "Invalid LYB union value size %zu (expected at least 4).",
lyb_data_len);
return ret;
}
/* Get index in correct byte order. */
memcpy(&type_idx, lyb_data, TYPE_IDX_SIZE);
type_idx = le64toh(type_idx);
if (type_idx >= LY_ARRAY_COUNT(type_u->types)) {
ret = ly_err_new(err, LY_EVALID, LYVE_DATA, NULL, NULL,
"Invalid LYB union type index %" PRIu64 " (type count %" LY_PRI_ARRAY_COUNT_TYPE ").",
type_idx, LY_ARRAY_COUNT(type_u->types));
return ret;
}
return ret;
}
static void
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)
{
uint64_t num = 0;
assert(lyb_data && !(lyb_value && !lyb_value_len));
if (type_idx) {
memcpy(&num, lyb_data, TYPE_IDX_SIZE);
num = le64toh(num);
*type_idx = num;
}
if (lyb_value && lyb_value_len && lyb_data_len) {
/* Get lyb_value and its length. */
if (lyb_data_len == TYPE_IDX_SIZE) {
*lyb_value_len = 0;
*lyb_value = "";
} else {
*lyb_value_len = lyb_data_len - TYPE_IDX_SIZE;
*lyb_value = (char *)lyb_data + TYPE_IDX_SIZE;
}
}
}
static LY_ERR
union_update_lref_err(struct ly_err_item *err, const struct lysc_type *type, const void *value, size_t value_len)
{
const struct lysc_type_leafref *lref;
char *valstr = NULL;
int r;
if (!err || (type->basetype != LY_TYPE_LEAFREF)) {
/* nothing to do */
return LY_SUCCESS;
}
lref = (const struct lysc_type_leafref *)type;
/* update error-app-tag */
free(err->apptag);
err->apptag = strdup("instance-required");
LY_CHECK_ERR_RET(!err->apptag, LOGMEM(NULL), LY_EMEM);
valstr = strndup((const char *)value, value_len);
LY_CHECK_ERR_RET(!valstr, LOGMEM(NULL), LY_EMEM);
/* update error-message */
free(err->msg);
r = asprintf(&err->msg, LY_ERRMSG_NOLREF_VAL, valstr, lyxp_get_expr(lref->path));
free(valstr);
LY_CHECK_ERR_RET(r == -1, LOGMEM(NULL), LY_EMEM);
return LY_SUCCESS;
}
static LY_ERR
union_store_type(const struct ly_ctx *ctx, struct lysc_type_union *type_u, uint32_t type_idx, struct lyd_value_union *subvalue,
uint32_t options, ly_bool validate, const struct lyd_node *ctx_node, const struct lyd_node *tree,
struct lys_glob_unres *unres, struct ly_err_item **err)
{
LY_ERR rc = LY_SUCCESS;
struct lysc_type *type = type_u->types[type_idx];
const void *value = NULL;
size_t value_len = 0;
ly_bool dynamic = 0;
LY_VALUE_FORMAT format;
void *prefix_data;
uint32_t opts = 0, ti;
*err = NULL;
if (subvalue->format == LY_VALUE_LYB) {
lyb_parse_union(subvalue->original, subvalue->orig_len, &ti, &value, &value_len);
if (ti != type_idx) {
/* value of another type, first store the value properly and then use its JSON value for parsing */
rc = type_u->types[ti]->plugin->store(ctx, type_u->types[ti], value, value_len, LYPLG_TYPE_STORE_ONLY,
subvalue->format, subvalue->prefix_data, subvalue->hints, subvalue->ctx_node, &subvalue->value, unres, err);
if (rc && (rc != LY_EINCOMPLETE)) {
/* clear any leftover/freed garbage */
memset(&subvalue->value, 0, sizeof subvalue->value);
/* if this is a leafref, lets make sure we propagate the appropriate error, and not a type validation failure */
union_update_lref_err(*err, type_u->types[ti], value, value_len);
goto cleanup;
}
assert(subvalue->value.realtype);
value = subvalue->value.realtype->plugin->print(ctx, &subvalue->value, LY_VALUE_JSON, NULL, &dynamic, &value_len);
/* to avoid leaks, free subvalue->value, but we need the value, which may be stored there */
if (!dynamic) {
value = strndup(value, value_len);
dynamic = 1;
}
type_u->types[ti]->plugin->free(ctx, &subvalue->value);
format = LY_VALUE_JSON;
prefix_data = NULL;
} else {
format = subvalue->format;
prefix_data = subvalue->prefix_data;
}
} else {
value = subvalue->original;
value_len = subvalue->orig_len;
format = subvalue->format;
prefix_data = subvalue->prefix_data;
}
if (options & LYPLG_TYPE_STORE_ONLY) {
opts |= LYPLG_TYPE_STORE_ONLY;
}
rc = type->plugin->store(ctx, type, value, value_len, opts, format, prefix_data, subvalue->hints,
subvalue->ctx_node, &subvalue->value, unres, err);
if (rc && (rc != LY_EINCOMPLETE)) {
/* clear any leftover/freed garbage */
memset(&subvalue->value, 0, sizeof subvalue->value);
/* if this is a leafref, lets make sure we propagate the appropriate error, and not a type validation failure */
union_update_lref_err(*err, type, value, value_len);
goto cleanup;
}
if (validate && (rc == LY_EINCOMPLETE)) {
/* we need the value validated */
rc = type->plugin->validate(ctx, type, ctx_node, tree, &subvalue->value, err);
if (rc) {
/* validate failed, we need to free the stored value */
type->plugin->free(ctx, &subvalue->value);
goto cleanup;
}
}
cleanup:
if (dynamic) {
free((void *)value);
}
return rc;
}
static LY_ERR
union_find_type(const struct ly_ctx *ctx, struct lysc_type_union *type_u, struct lyd_value_union *subvalue,
uint32_t options, ly_bool resolve, const struct lyd_node *ctx_node, const struct lyd_node *tree,
uint32_t *type_idx, struct lys_glob_unres *unres, struct ly_err_item **err)
{
LY_ERR ret = LY_SUCCESS;
LY_ARRAY_COUNT_TYPE u;
struct ly_err_item **errs = NULL, *e;
uint32_t *prev_lo, temp_lo = 0;
char *msg = NULL, *err_app_tag = NULL;
int msg_len = 0;
ly_bool use_err_app_tag = 0;
*err = NULL;
/* alloc errors */
errs = calloc(LY_ARRAY_COUNT(type_u->types), sizeof *errs);
LY_CHECK_RET(!errs, LY_EMEM);
/* turn logging temporarily off */
prev_lo = ly_temp_log_options(&temp_lo);
/* use the first usable subtype to store the value */
for (u = 0; u < LY_ARRAY_COUNT(type_u->types); ++u) {
ret = union_store_type(ctx, type_u, u, subvalue, options, resolve, ctx_node, tree, unres, &e);
if ((ret == LY_SUCCESS) || (ret == LY_EINCOMPLETE)) {
break;
}
errs[u] = e;
}
if (u == LY_ARRAY_COUNT(type_u->types)) {
/* create the full error */
if (subvalue->format == LY_VALUE_LYB) {
msg_len = asprintf(&msg, "Invalid LYB union value - no matching subtype found:\n");
} else {
msg_len = asprintf(&msg, "Invalid union value \"%.*s\" - no matching subtype found:\n",
(int)subvalue->orig_len, (char *)subvalue->original);
}
if (msg_len == -1) {
LY_CHECK_ERR_GOTO(!errs, ret = LY_EMEM, cleanup);
/* for further actions in function msg_len is just 0 */
msg_len = 0;
}
for (u = 0; u < LY_ARRAY_COUNT(type_u->types); ++u) {
if (!errs[u]) {
/* no error for some reason */
continue;
}
/* use an app-tag if all the types set it or set none */
if (errs[u]->apptag) {
if (!err_app_tag) {
err_app_tag = strdup(errs[u]->apptag);
LY_CHECK_ERR_GOTO(!err_app_tag, ret = LY_EMEM, cleanup);
use_err_app_tag = 1;
} else if (strcmp(errs[u]->apptag, err_app_tag)) {
use_err_app_tag = 0;
}
}
msg = ly_realloc(msg, msg_len + 4 + strlen(type_u->types[u]->plugin->id) + 2 + strlen(errs[u]->msg) + 2);
LY_CHECK_ERR_GOTO(!msg, ret = LY_EMEM, cleanup);
msg_len += sprintf(msg + msg_len, " %s: %s\n", type_u->types[u]->plugin->id, errs[u]->msg);
}
if (!use_err_app_tag) {
free(err_app_tag);
err_app_tag = NULL;
}
ret = ly_err_new(err, LY_EVALID, LYVE_DATA, NULL, err_app_tag, "%s", msg);
} else if (type_idx) {
*type_idx = u;
}
cleanup:
for (u = 0; u < LY_ARRAY_COUNT(type_u->types); ++u) {
ly_err_free(errs[u]);
}
free(errs);
free(msg);
ly_temp_log_options(prev_lo);
return ret;
}
static LY_ERR
lyb_fill_subvalue(const struct ly_ctx *ctx, struct lysc_type_union *type_u, const void *lyb_data, size_t lyb_data_len,
void *prefix_data, struct lyd_value_union *subvalue, uint32_t *options, struct lys_glob_unres *unres,
struct ly_err_item **err)
{
LY_ERR ret;
uint32_t type_idx;
const void *lyb_value = NULL;
size_t lyb_value_len = 0;
ret = lyb_union_validate(lyb_data, lyb_data_len, type_u, err);
LY_CHECK_RET(ret);
/* parse lyb_data and set the lyb_value and lyb_value_len */
lyb_parse_union(lyb_data, lyb_data_len, &type_idx, &lyb_value, &lyb_value_len);
LY_CHECK_RET(ret);
/* store lyb_data to subvalue */
ret = union_subvalue_assignment(lyb_data, lyb_data_len, &subvalue->original, &subvalue->orig_len, options);
LY_CHECK_RET(ret);
if (lyb_value) {
/* resolve prefix_data and set format */
ret = lyplg_type_prefix_data_new(ctx, lyb_value, lyb_value_len, LY_VALUE_LYB, prefix_data, &subvalue->format,
&subvalue->prefix_data);
LY_CHECK_RET(ret);
assert(subvalue->format == LY_VALUE_LYB);
} else {
/* lyb_parse_union() did not find lyb_value, just set format */
subvalue->format = LY_VALUE_LYB;
}
/* use the specific type to store the value */
ret = union_store_type(ctx, type_u, type_idx, subvalue, *options, 0, NULL, NULL, unres, err);
return ret;
}
LIBYANG_API_DEF LY_ERR
lyplg_type_store_union(const struct ly_ctx *ctx, const struct lysc_type *type, const void *value, size_t value_len,
uint32_t options, LY_VALUE_FORMAT format, void *prefix_data, uint32_t hints, const struct lysc_node *ctx_node,
struct lyd_value *storage, struct lys_glob_unres *unres, struct ly_err_item **err)
{
LY_ERR ret = LY_SUCCESS, r;
struct lysc_type_union *type_u = (struct lysc_type_union *)type;
struct lyd_value_union *subvalue;
*err = NULL;
/* init storage */
memset(storage, 0, sizeof *storage);
LYPLG_TYPE_VAL_INLINE_PREPARE(storage, subvalue);
LY_CHECK_ERR_GOTO(!subvalue, ret = LY_EMEM, cleanup);
storage->realtype = type;
subvalue->hints = hints;
subvalue->ctx_node = ctx_node;
if (format == LY_VALUE_LYB) {
ret = lyb_fill_subvalue(ctx, type_u, value, value_len, prefix_data, subvalue, &options, unres, err);
LY_CHECK_GOTO((ret != LY_SUCCESS) && (ret != LY_EINCOMPLETE), cleanup);
} else {
/* to correctly resolve the union type, we need to always validate the value */
options &= ~LYPLG_TYPE_STORE_ONLY;
/* store value to subvalue */
ret = union_subvalue_assignment(value, value_len, &subvalue->original, &subvalue->orig_len, &options);
LY_CHECK_GOTO(ret, cleanup);
/* store format-specific data for later prefix resolution */
ret = lyplg_type_prefix_data_new(ctx, value, value_len, format, prefix_data, &subvalue->format,
&subvalue->prefix_data);
LY_CHECK_GOTO(ret, cleanup);
/* use the first usable subtype to store the value */
ret = union_find_type(ctx, type_u, subvalue, options, 0, NULL, NULL, NULL, unres, err);
LY_CHECK_GOTO((ret != LY_SUCCESS) && (ret != LY_EINCOMPLETE), cleanup);
}
/* store canonical value, if any (use the specific type value) */
r = lydict_insert(ctx, subvalue->value._canonical, 0, &storage->_canonical);
LY_CHECK_ERR_GOTO(r, ret = r, cleanup);
cleanup:
if (options & LYPLG_TYPE_STORE_DYNAMIC) {
free((void *)value);
}
if ((ret != LY_SUCCESS) && (ret != LY_EINCOMPLETE)) {
lyplg_type_free_union(ctx, storage);
}
return ret;
}
LIBYANG_API_DEF LY_ERR
lyplg_type_validate_union(const struct ly_ctx *ctx, const struct lysc_type *type, const struct lyd_node *ctx_node,
const struct lyd_node *tree, struct lyd_value *storage, struct ly_err_item **err)
{
LY_ERR rc = LY_SUCCESS;
struct lysc_type_union *type_u = (struct lysc_type_union *)type;
struct lyd_value_union *subvalue = storage->subvalue;
struct lyd_value orig = {0};
uint32_t type_idx;
ly_bool validated = 0;
*err = NULL;
/* because of types that do not store their own type as realtype (leafref), we are not able to call their
* validate callback (there is no way to get the type) but even if possible, the value may be invalid
* for the type, so we may have to perform union value storing again from scratch, but keep a value backup */
LY_CHECK_RET(subvalue->value.realtype->plugin->duplicate(ctx, &subvalue->value, &orig));
subvalue->value.realtype->plugin->free(ctx, &subvalue->value);
if (subvalue->format == LY_VALUE_LYB) {
/* use the specific type to store and validate the value */
lyb_parse_union(subvalue->original, 0, &type_idx, NULL, NULL);
if (union_store_type(ctx, type_u, type_idx, subvalue, 0, 1, ctx_node, tree, NULL, err)) {
/* validation failed, we need to try storing the value again */
ly_err_free(*err);
*err = NULL;
} else {
validated = 1;
}
}
if (!validated) {
/* use the first usable subtype to store and validate the value */
rc = union_find_type(ctx, type_u, subvalue, 0, 1, ctx_node, tree, NULL, NULL, err);
if (rc) {
/* validation failed, restore the previous value */
subvalue->value = orig;
return rc;
}
}
/* update the canonical value, if any generated */
lydict_remove(ctx, storage->_canonical);
LY_CHECK_RET(lydict_insert(ctx, subvalue->value._canonical, 0, &storage->_canonical));
/* free backup value */
orig.realtype->plugin->free(ctx, &orig);
return LY_SUCCESS;
}
LIBYANG_API_DEF LY_ERR
lyplg_type_compare_union(const struct ly_ctx *ctx, const struct lyd_value *val1, const struct lyd_value *val2)
{
if (val1->subvalue->value.realtype != val2->subvalue->value.realtype) {
return LY_ENOT;
}
return val1->subvalue->value.realtype->plugin->compare(ctx, &val1->subvalue->value, &val2->subvalue->value);
}
LIBYANG_API_DEF int
lyplg_type_sort_union(const struct ly_ctx *ctx, const struct lyd_value *val1, const struct lyd_value *val2)
{
int rc;
LY_ARRAY_COUNT_TYPE u;
struct lysc_type **types, *type;
if (val1->subvalue->value.realtype == val2->subvalue->value.realtype) {
return val1->subvalue->value.realtype->plugin->sort(ctx, &val1->subvalue->value, &val2->subvalue->value);
}
/* compare according to the order of types */
rc = 0;
types = ((struct lysc_type_union *)val1->realtype)->types;
LY_ARRAY_FOR(types, u) {
if (types[u]->basetype == LY_TYPE_LEAFREF) {
type = ((struct lysc_type_leafref *)types[u])->realtype;
} else {
type = types[u];
}
if (type == val1->subvalue->value.realtype) {
rc = 1;
break;
} else if (type == val2->subvalue->value.realtype) {
rc = -1;
break;
}
}
assert(rc);
return rc;
}
static const void *
lyb_union_print(const struct ly_ctx *ctx, struct lysc_type_union *type_u, struct lyd_value_union *subvalue,
void *prefix_data, size_t *value_len)
{
void *ret = NULL;
LY_ERR r;
struct ly_err_item *err;
uint64_t num = 0;
uint32_t type_idx = 0;
ly_bool dynamic;
size_t pval_len;
void *pval;
/* Find out the index number (type_idx). The call should succeed
* because the union_find_type() has already been called in the
* lyplg_type_store_union().
*/
if (!ctx) {
assert(subvalue->ctx_node);
ctx = subvalue->ctx_node->module->ctx;
}
subvalue->value.realtype->plugin->free(ctx, &subvalue->value);
r = union_find_type(ctx, type_u, subvalue, 0, 0, NULL, NULL, &type_idx, NULL, &err);
ly_err_free(err);
LY_CHECK_RET((r != LY_SUCCESS) && (r != LY_EINCOMPLETE), NULL);
/* Print subvalue in LYB format. */
pval = (void *)subvalue->value.realtype->plugin->print(NULL, &subvalue->value, LY_VALUE_LYB, prefix_data, &dynamic,
&pval_len);
LY_CHECK_RET(!pval, NULL);
/* Create LYB data. */
*value_len = TYPE_IDX_SIZE + pval_len;
ret = malloc(*value_len);
LY_CHECK_RET(!ret, NULL);
num = type_idx;
num = htole64(num);
memcpy(ret, &num, TYPE_IDX_SIZE);
memcpy((char *)ret + TYPE_IDX_SIZE, pval, pval_len);
if (dynamic) {
free(pval);
}
return ret;
}
LIBYANG_API_DEF const void *
lyplg_type_print_union(const struct ly_ctx *ctx, const struct lyd_value *value, LY_VALUE_FORMAT format,
void *prefix_data, ly_bool *dynamic, size_t *value_len)
{
const void *ret;
struct lyd_value_union *subvalue = value->subvalue;
struct lysc_type_union *type_u = (struct lysc_type_union *)value->realtype;
size_t lyb_data_len = 0;
if ((format == LY_VALUE_LYB) && (subvalue->format == LY_VALUE_LYB)) {
/* The return value is already ready. */
*dynamic = 0;
if (value_len) {
*value_len = subvalue->orig_len;
}
return subvalue->original;
} else if ((format == LY_VALUE_LYB) && (subvalue->format != LY_VALUE_LYB)) {
/* The return LYB data must be created. */
*dynamic = 1;
ret = lyb_union_print(ctx, type_u, subvalue, prefix_data, &lyb_data_len);
if (value_len) {
*value_len = lyb_data_len;
}
return ret;
}
assert(format != LY_VALUE_LYB);
ret = (void *)subvalue->value.realtype->plugin->print(ctx, &subvalue->value, format, prefix_data, dynamic, value_len);
if (!value->_canonical && (format == LY_VALUE_CANON)) {
/* the canonical value is supposed to be stored now */
lydict_insert(ctx, subvalue->value._canonical, 0, (const char **)&value->_canonical);
}
return ret;
}
LIBYANG_API_DEF LY_ERR
lyplg_type_dup_union(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup)
{
LY_ERR ret = LY_SUCCESS;
struct lyd_value_union *orig_val = original->subvalue, *dup_val;
/* init dup value */
memset(dup, 0, sizeof *dup);
dup->realtype = original->realtype;
ret = lydict_insert(ctx, original->_canonical, 0, &dup->_canonical);
LY_CHECK_GOTO(ret, cleanup);
dup_val = calloc(1, sizeof *dup_val);
LY_CHECK_ERR_GOTO(!dup_val, LOGMEM(ctx); ret = LY_EMEM, cleanup);
dup->subvalue = dup_val;
ret = orig_val->value.realtype->plugin->duplicate(ctx, &orig_val->value, &dup_val->value);
LY_CHECK_GOTO(ret, cleanup);
if (orig_val->orig_len) {
dup_val->original = calloc(1, orig_val->orig_len);
LY_CHECK_ERR_GOTO(!dup_val->original, LOGMEM(ctx); ret = LY_EMEM, cleanup);
memcpy(dup_val->original, orig_val->original, orig_val->orig_len);
} else {
dup_val->original = strdup("");
LY_CHECK_ERR_GOTO(!dup_val->original, LOGMEM(ctx); ret = LY_EMEM, cleanup);
}
dup_val->orig_len = orig_val->orig_len;
dup_val->format = orig_val->format;
dup_val->ctx_node = orig_val->ctx_node;
dup_val->hints = orig_val->hints;
ret = lyplg_type_prefix_data_dup(ctx, orig_val->format, orig_val->prefix_data, &dup_val->prefix_data);
LY_CHECK_GOTO(ret, cleanup);
cleanup:
if (ret) {
lyplg_type_free_union(ctx, dup);
}
return ret;
}
LIBYANG_API_DEF void
lyplg_type_free_union(const struct ly_ctx *ctx, struct lyd_value *value)
{
struct lyd_value_union *val;
lydict_remove(ctx, value->_canonical);
value->_canonical = NULL;
LYD_VALUE_GET(value, val);
if (val) {
if (val->value.realtype) {
val->value.realtype->plugin->free(ctx, &val->value);
}
lyplg_type_prefix_data_free(val->format, val->prefix_data);
free(val->original);
LYPLG_TYPE_VAL_INLINE_DESTROY(val);
}
}
const struct lyplg_type_record plugins_union[] = {
{
.module = "",
.revision = NULL,
.name = LY_TYPE_UNION_STR,
.plugin.id = "libyang 2 - union,version 1",
.plugin.store = lyplg_type_store_union,
.plugin.validate = lyplg_type_validate_union,
.plugin.compare = lyplg_type_compare_union,
.plugin.sort = lyplg_type_sort_union,
.plugin.print = lyplg_type_print_union,
.plugin.duplicate = lyplg_type_dup_union,
.plugin.free = lyplg_type_free_union,
.plugin.lyb_data_len = -1,
},
{0}
};
ly_ctx
libyang context handler.
lydict_insert
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...
lydict_remove
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_item::err
LY_ERR err
Definition log.h:284
ly_err_item::apptag
char * apptag
Definition log.h:290
ly_err_item::msg
char * msg
Definition log.h:286
LY_ERR
LY_ERR
libyang's error codes returned by the libyang functions.
Definition log.h:237
LYVE_DATA
@ LYVE_DATA
Definition log.h:274
LY_EMEM
@ LY_EMEM
Definition log.h:239
LY_ENOT
@ LY_ENOT
Definition log.h:251
LY_EVALID
@ LY_EVALID
Definition log.h:245
LY_SUCCESS
@ LY_SUCCESS
Definition log.h:238
LY_EINCOMPLETE
@ LY_EINCOMPLETE
Definition log.h:247
ly_err_item
Libyang full error structure.
Definition log.h:282
ly_temp_log_options
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().
lyplg_type_record::revision
const char *const char * revision
Definition plugins_types.h:638
lyplg_type::print
lyplg_type_print_clb print
Definition plugins_types.h:628
lyplg_type::store
lyplg_type_store_clb store
Definition plugins_types.h:624
lyplg_type::compare
lyplg_type_compare_clb compare
Definition plugins_types.h:626
lyplg_type::validate
lyplg_type_validate_clb validate
Definition plugins_types.h:625
lyplg_type::id
const char * id
Definition plugins_types.h:622
lyplg_type::duplicate
lyplg_type_dup_clb duplicate
Definition plugins_types.h:629
lyplg_type::free
lyplg_type_free_clb free
Definition plugins_types.h:630
lyplg_type::sort
lyplg_type_sort_clb sort
Definition plugins_types.h:627
LYPLG_TYPE_VAL_INLINE_PREPARE
#define LYPLG_TYPE_VAL_INLINE_PREPARE(storage, type_val)
Prepare value memory for storing a specific type value, may be allocated dynamically.
Definition plugins_types.h:194
ly_err_free
LIBYANG_API_DECL LY_ERR LIBYANG_API_DECL void ly_err_free(void *ptr)
Destructor for the error records created with ly_err_new().
LYPLG_TYPE_VAL_INLINE_DESTROY
#define LYPLG_TYPE_VAL_INLINE_DESTROY(type_val)
Destroy a prepared value.
Definition plugins_types.h:206
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.
lyplg_type_prefix_data_new
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.
lyplg_type_prefix_data_dup
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.
lyplg_type_prefix_data_free
LIBYANG_API_DECL void lyplg_type_prefix_data_free(LY_VALUE_FORMAT format, void *prefix_data)
Free internal prefix data.
lyplg_type_record
Definition plugins_types.h:635
lyplg_type_free_union
LIBYANG_API_DEF void lyplg_type_free_union(const struct ly_ctx *ctx, struct lyd_value *value)
Implementation of lyplg_type_free_clb for the built-in union type.
Definition union.c:738
lyplg_type_compare_union
LIBYANG_API_DEF LY_ERR lyplg_type_compare_union(const struct ly_ctx *ctx, const struct lyd_value *val1, const struct lyd_value *val2)
Implementation of lyplg_type_compare_clb for the built-in union type.
Definition union.c:556
lyplg_type_print_union
LIBYANG_API_DEF const void * lyplg_type_print_union(const struct ly_ctx *ctx, const struct lyd_value *value, LY_VALUE_FORMAT format, void *prefix_data, ly_bool *dynamic, size_t *value_len)
Implementation of lyplg_type_print_clb for the built-in union type.
Definition union.c:659
lyplg_type_sort_union
LIBYANG_API_DEF int lyplg_type_sort_union(const struct ly_ctx *ctx, const struct lyd_value *val1, const struct lyd_value *val2)
Implementation of lyplg_type_sort_clb for the built-in union type.
Definition union.c:565
lyplg_type_validate_union
LIBYANG_API_DEF LY_ERR lyplg_type_validate_union(const struct ly_ctx *ctx, const struct lysc_type *type, const struct lyd_node *ctx_node, const struct lyd_node *tree, struct lyd_value *storage, struct ly_err_item **err)
Implementation of lyplg_type_validate_clb for the built-in union type.
Definition union.c:505
lyplg_type_store_union
LIBYANG_API_DEF LY_ERR lyplg_type_store_union(const struct ly_ctx *ctx, const struct lysc_type *type, const void *value, size_t value_len, uint32_t options, LY_VALUE_FORMAT format, void *prefix_data, uint32_t hints, const struct lysc_node *ctx_node, struct lyd_value *storage, struct lys_glob_unres *unres, struct ly_err_item **err)
Implementation of lyplg_type_store_clb for the built-in union type.
Definition union.c:450
lyplg_type_dup_union
LIBYANG_API_DEF LY_ERR lyplg_type_dup_union(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup)
Implementation of lyplg_type_dup_clb for the built-in union type.
Definition union.c:695
LYPLG_TYPE_STORE_DYNAMIC
#define LYPLG_TYPE_STORE_DYNAMIC
Definition plugins_types.h:471
LYPLG_TYPE_STORE_ONLY
#define LYPLG_TYPE_STORE_ONLY
Definition plugins_types.h:478
lysc_type::basetype
LY_DATA_TYPE basetype
Definition tree_schema.h:1287
lysc_type_leafref::path
struct lyxp_expr * path
Definition tree_schema.h:1366
lysc_type::plugin
struct lyplg_type * plugin
Definition tree_schema.h:1286
lysc_type_union::types
struct lysc_type ** types
Definition tree_schema.h:1400
lysc_type_union::basetype
LY_DATA_TYPE basetype
Definition tree_schema.h:1397
lyxp_get_expr
LIBYANG_API_DECL const char * lyxp_get_expr(const struct lyxp_expr *path)
Getter for original XPath expression from a parsed expression.
lysc_node
Compiled YANG data node.
Definition tree_schema.h:1421
lysc_type
Definition tree_schema.h:1283
lysc_type_leafref
Definition tree_schema.h:1359
lysc_type_union
Definition tree_schema.h:1393
LY_ARRAY_COUNT
#define LY_ARRAY_COUNT(ARRAY)
Get the number of records in the ARRAY.
Definition tree.h:148
LY_ARRAY_FOR
#define LY_ARRAY_FOR(ARRAY,...)
Sized-array iterator (for-loop).
Definition tree.h:167
LY_VALUE_FORMAT
LY_VALUE_FORMAT
All kinds of supported value formats and prefix mappings to modules.
Definition tree.h:234
LY_PRI_ARRAY_COUNT_TYPE
#define LY_PRI_ARRAY_COUNT_TYPE
Printing format specifier macro for LY_ARRAY_SIZE_TYPE values.
Definition tree.h:109
LY_ARRAY_COUNT_TYPE
#define LY_ARRAY_COUNT_TYPE
Type (i.e. size) of the sized array's size counter.
Definition tree.h:104
LY_TYPE_LEAFREF
@ LY_TYPE_LEAFREF
Definition tree.h:217
LY_VALUE_JSON
@ LY_VALUE_JSON
Definition tree.h:239
LY_VALUE_CANON
@ LY_VALUE_CANON
Definition tree.h:235
LY_VALUE_LYB
@ LY_VALUE_LYB
Definition tree.h:240
libyang.h
The main libyang public header.
ly_bool
uint8_t ly_bool
Type to indicate boolean value.
Definition log.h:35
plugins_types.h
API for (user) types plugins.
lyd_value::realtype
const struct lysc_type * realtype
Definition tree_data.h:571
lyd_value_union::original
void * original
Definition tree_data.h:625
lyd_value_union::prefix_data
void * prefix_data
Definition tree_data.h:631
lyd_value_union::hints
uint32_t hints
Definition tree_data.h:627
LYD_VALUE_GET
#define LYD_VALUE_GET(value, type_val)
Get the value in format specific to the type.
Definition tree_data.h:610
lyd_value_union::orig_len
size_t orig_len
Definition tree_data.h:626
lyd_value_union::value
struct lyd_value value
Definition tree_data.h:623
lyd_value::_canonical
const char * _canonical
Definition tree_data.h:568
lyd_value_union::format
LY_VALUE_FORMAT format
Definition tree_data.h:628
lyd_value_union::ctx_node
const struct lysc_node * ctx_node
Definition tree_data.h:632
lyd_node
Generic structure for a data node.
Definition tree_data.h:795
lyd_value
YANG data representation.
Definition tree_data.h:567
lyd_value_union
Special lyd_value structure for built-in union values.
Definition tree_data.h:622
ly_realloc
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,...
LOGMEM
#define LOGMEM(CTX)
Definition tree_edit.h:22
TYPE_IDX_SIZE
#define TYPE_IDX_SIZE
Size in bytes of the used type index in the LYB Binary Format.
Definition union.c:46
plugins_union
const struct lyplg_type_record plugins_union[]
Plugin information for union type implementation.
Definition union.c:763