1
0
Fork 0

Merging upstream version 3.4.2+dfsg.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-05 08:03:59 +01:00
parent 511f72b68b
commit 948b3e00b3
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
75 changed files with 1082 additions and 878 deletions

View file

@ -64,13 +64,13 @@ jobs:
build-cmd: "make"
}
- {
name: "Release, macOS 11, clang",
os: "macos-11",
name: "Release, macOS 14, clang",
os: "macos-14",
build-type: "Release",
cc: "clang",
options: "-DENABLE_TESTS=ON -DPATH_EXPECT=",
packager: "brew",
packages: "cmocka shunit2",
packages: "cmocka shunit2 tcl-tk",
snaps: "",
build-cmd: "make"
}

View file

@ -59,14 +59,14 @@ set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
# set version of the project
set(LIBYANG_MAJOR_VERSION 3)
set(LIBYANG_MINOR_VERSION 1)
set(LIBYANG_MICRO_VERSION 0)
set(LIBYANG_MINOR_VERSION 4)
set(LIBYANG_MICRO_VERSION 2)
set(LIBYANG_VERSION ${LIBYANG_MAJOR_VERSION}.${LIBYANG_MINOR_VERSION}.${LIBYANG_MICRO_VERSION})
# set version of the library
set(LIBYANG_MAJOR_SOVERSION 3)
set(LIBYANG_MINOR_SOVERSION 2)
set(LIBYANG_MICRO_SOVERSION 0)
set(LIBYANG_MINOR_SOVERSION 4)
set(LIBYANG_MICRO_SOVERSION 2)
set(LIBYANG_SOVERSION_FULL ${LIBYANG_MAJOR_SOVERSION}.${LIBYANG_MINOR_SOVERSION}.${LIBYANG_MICRO_SOVERSION})
set(LIBYANG_SOVERSION ${LIBYANG_MAJOR_SOVERSION})
@ -106,7 +106,8 @@ set(type_plugins
src/plugins_types/date_and_time.c
src/plugins_types/hex_string.c
src/plugins_types/xpath1.0.c
src/plugins_types/node_instanceid.c)
src/plugins_types/node_instanceid.c
src/plugins_types/time_period.c)
set(libsrc
src/ly_common.c
@ -471,7 +472,7 @@ endif()
# generate API/ABI report
if("${BUILD_TYPE_UPPER}" STREQUAL "ABICHECK")
lib_abi_check(yang "${headers}" ${LIBYANG_SOVERSION_FULL} 708a8bfad983a4095c8d4dc537a9d2a1d5ca65c5)
lib_abi_check(yang "${headers}" ${LIBYANG_SOVERSION_FULL} 670385f9595014dc9307615fa6e929b46dba026b)
endif()
# source code format target for Makefile

View file

@ -58,8 +58,6 @@ the `distro` directory.
* C compiler
* cmake >= 2.8.12
* libpcre2 >= 10.21 (including devel package)
* note, that PCRE is supposed to be compiled with unicode support (configure's options
`--enable-utf` and `--enable-unicode-properties`)
#### Optional

View file

@ -721,7 +721,7 @@ ly_ctx_unset_options(struct ly_ctx *ctx, uint16_t option)
ext = &mod->compiled->exts[u];
LY_ARRAY_FOR(ext->substmts, v) {
if (ext->substmts[v].stmt & LY_STMT_DATA_NODE_MASK) {
LY_LIST_FOR(*VOIDPTR2_C(ext->substmts[v].storage), root) {
LY_LIST_FOR(*ext->substmts[v].storage_p, root) {
lysc_tree_dfs_full(root, lysc_node_clear_priv_dfs_cb, NULL);
}
}

View file

@ -602,10 +602,10 @@ LIBYANG_API_DECL const struct lysp_submodule *ly_ctx_get_submodule2_latest(const
LIBYANG_API_DECL uint32_t ly_ctx_internal_modules_count(const struct ly_ctx *ctx);
/**
* @brief Try to find the model in the searchpaths of \p ctx and load it into it. If custom missing
* @brief Try to find the model in the searchpaths of @p ctx and load it into it. If custom missing
* module callback is set, it is used instead.
*
* The context itself is searched for the requested module first. If \p revision is not specified
* The context itself is searched for the requested module first. If @p revision is not specified
* (the module of the latest revision is requested) and there is implemented revision of the requested
* module in the context, this implemented revision is returned despite there might be a newer revision.
* This behavior is cause by the fact that it is not possible to have multiple implemented revisions of
@ -660,7 +660,7 @@ LIBYANG_API_DECL LY_ERR ly_ctx_get_yanglib_data(const struct ly_ctx *ctx, struct
* Note that the data stored by user into the ::lysc_node.priv pointer are kept
* untouched and the caller is responsible for freeing this private data.
*
* @param[in] ctx libyang context to destroy
* @param[in] ctx Context to destroy.
*/
LIBYANG_API_DECL void ly_ctx_destroy(struct ly_ctx *ctx);

View file

@ -104,9 +104,6 @@ lydict_resize_val_eq(void *val1_p, void *val2_p, ly_bool mod, void *UNUSED(cb_da
str1 = ((struct ly_dict_rec *)val1_p)->value;
str2 = ((struct ly_dict_rec *)val2_p)->value;
LY_CHECK_ERR_RET(!str1, LOGARG(NULL, val1_p), 0);
LY_CHECK_ERR_RET(!str2, LOGARG(NULL, val2_p), 0);
if (mod) {
/* used when inserting new values */
if (strcmp(str1, str2) == 0) {
@ -177,7 +174,7 @@ finish:
return ret;
}
LY_ERR
static LY_ERR
dict_insert(const struct ly_ctx *ctx, char *value, size_t len, ly_bool zerocopy, const char **str_p)
{
LY_ERR ret = LY_SUCCESS;
@ -221,9 +218,7 @@ dict_insert(const struct ly_ctx *ctx, char *value, size_t len, ly_bool zerocopy,
return ret;
}
if (str_p) {
*str_p = match->value;
}
return ret;
}
@ -269,3 +264,49 @@ lydict_insert_zc(const struct ly_ctx *ctx, char *value, const char **str_p)
return result;
}
static LY_ERR
dict_dup(const struct ly_ctx *ctx, char *value, const char **str_p)
{
LY_ERR ret = LY_SUCCESS;
struct ly_dict_rec *match = NULL, rec;
uint32_t hash;
/* set new callback to only compare memory addresses */
lyht_value_equal_cb prev = lyht_set_cb(ctx->dict.hash_tab, lydict_resize_val_eq);
LOGDBG(LY_LDGDICT, "duplicating %s", value);
hash = lyht_hash(value, strlen(value));
rec.value = value;
ret = lyht_find(ctx->dict.hash_tab, (void *)&rec, hash, (void **)&match);
if (ret == LY_SUCCESS) {
/* record found, increase refcount */
match->refcount++;
*str_p = match->value;
}
/* restore callback */
lyht_set_cb(ctx->dict.hash_tab, prev);
return ret;
}
LIBYANG_API_DEF LY_ERR
lydict_dup(const struct ly_ctx *ctx, const char *value, const char **str_p)
{
LY_ERR result;
LY_CHECK_ARG_RET(ctx, ctx, str_p, LY_EINVAL);
if (!value) {
*str_p = NULL;
return LY_SUCCESS;
}
pthread_mutex_lock((pthread_mutex_t *)&ctx->dict.lock);
result = dict_dup(ctx, (char *)value, str_p);
pthread_mutex_unlock((pthread_mutex_t *)&ctx->dict.lock);
return result;
}

View file

@ -113,6 +113,18 @@ LIBYANG_API_DECL LY_ERR lydict_insert_zc(const struct ly_ctx *ctx, char *value,
*/
LIBYANG_API_DECL LY_ERR lydict_remove(const struct ly_ctx *ctx, const char *value);
/**
* @brief Duplicate string in dictionary. Only a reference counter is incremented.
*
* @param[in] ctx libyang context handler
* @param[in] value NULL-terminated string to be duplicated in the dictionary (reference counter is incremented).
* @param[out] str_p Optional parameter to get pointer to the string corresponding to the @p value and stored in dictionary.
* @return LY_SUCCESS in case the string already exists in the dictionary.
* @return LY_ENOTFOUND in case the string was not found.
* @return LY_ERR on other errors
*/
LIBYANG_API_DECL LY_ERR lydict_dup(const struct ly_ctx *ctx, const char *value, const char **str_p);
/** @} dict */
#ifdef __cplusplus

View file

@ -179,6 +179,7 @@ lyht_free(struct ly_ht *ht, void (*val_free)(void *val_p))
*
* @param[in] ht Hash table to resize.
* @param[in] operation Operation to perform. 1 to enlarge, -1 to shrink, 0 to only rehash all records.
* @param[in] check Whether to check if the value has already been inserted or not.
* @return LY_ERR value.
*/
static LY_ERR
@ -247,7 +248,6 @@ lyht_resize(struct ly_ht *ht, int operation, int check)
* @param[in] hash Hash to find.
* @param[in] mod Whether the operation modifies the hash table (insert or remove) or not (find).
* @param[in] val_equal Callback for checking value equivalence.
* @param[out] crec_p Optional found first record.
* @param[out] col Optional collision number of @p rec_p, 0 for no collision.
* @param[out] rec_p Found exact matching record, may be a collision of @p crec_p.
* @return LY_ENOTFOUND if no record found,
@ -255,15 +255,12 @@ lyht_resize(struct ly_ht *ht, int operation, int check)
*/
static LY_ERR
lyht_find_rec(const struct ly_ht *ht, void *val_p, uint32_t hash, ly_bool mod, lyht_value_equal_cb val_equal,
struct ly_ht_rec **crec_p, uint32_t *col, struct ly_ht_rec **rec_p)
uint32_t *col, struct ly_ht_rec **rec_p)
{
uint32_t hlist_idx = hash & (ht->size - 1);
struct ly_ht_rec *rec;
uint32_t rec_idx;
if (crec_p) {
*crec_p = NULL;
}
if (col) {
*col = 0;
}
@ -271,9 +268,6 @@ lyht_find_rec(const struct ly_ht *ht, void *val_p, uint32_t hash, ly_bool mod, l
LYHT_ITER_HLIST_RECS(ht, hlist_idx, rec_idx, rec) {
if ((rec->hash == hash) && val_equal(val_p, &rec->val, mod, ht->cb_data)) {
if (crec_p) {
*crec_p = rec;
}
*rec_p = rec;
return LY_SUCCESS;
}
@ -292,7 +286,11 @@ lyht_find(const struct ly_ht *ht, void *val_p, uint32_t hash, void **match_p)
{
struct ly_ht_rec *rec;
lyht_find_rec(ht, val_p, hash, 0, ht->val_equal, NULL, NULL, &rec);
if (match_p) {
*match_p = NULL;
}
lyht_find_rec(ht, val_p, hash, 0, ht->val_equal, NULL, &rec);
if (rec && match_p) {
*match_p = rec->val;
@ -305,7 +303,7 @@ lyht_find_with_val_cb(const struct ly_ht *ht, void *val_p, uint32_t hash, lyht_v
{
struct ly_ht_rec *rec;
lyht_find_rec(ht, val_p, hash, 0, val_equal ? val_equal : ht->val_equal, NULL, NULL, &rec);
lyht_find_rec(ht, val_p, hash, 0, val_equal ? val_equal : ht->val_equal, NULL, &rec);
if (rec && match_p) {
*match_p = rec->val;
@ -317,12 +315,12 @@ LIBYANG_API_DEF LY_ERR
lyht_find_next_with_collision_cb(const struct ly_ht *ht, void *val_p, uint32_t hash,
lyht_value_equal_cb collision_val_equal, void **match_p)
{
struct ly_ht_rec *rec, *crec;
struct ly_ht_rec *rec;
uint32_t rec_idx;
uint32_t i;
/* find the record of the previously found value */
if (lyht_find_rec(ht, val_p, hash, 1, ht->val_equal, &crec, &i, &rec)) {
if (lyht_find_rec(ht, val_p, hash, 1, ht->val_equal, &i, &rec)) {
/* not found, cannot happen */
LOGINT_RET(NULL);
}
@ -373,7 +371,7 @@ _lyht_insert_with_resize_cb(struct ly_ht *ht, void *val_p, uint32_t hash, lyht_v
uint32_t rec_idx;
if (check) {
if (lyht_find_rec(ht, val_p, hash, 1, ht->val_equal, NULL, NULL, &rec) == LY_SUCCESS) {
if (lyht_find_rec(ht, val_p, hash, 1, ht->val_equal, NULL, &rec) == LY_SUCCESS) {
if (rec && match_p) {
*match_p = rec->val;
}
@ -459,7 +457,7 @@ lyht_remove_with_resize_cb(struct ly_ht *ht, void *val_p, uint32_t hash, lyht_va
uint32_t prev_rec_idx;
uint32_t rec_idx;
if (lyht_find_rec(ht, val_p, hash, 1, ht->val_equal, NULL, NULL, &found_rec)) {
if (lyht_find_rec(ht, val_p, hash, 1, ht->val_equal, NULL, &found_rec)) {
LOGARG(NULL, hash);
return LY_ENOTFOUND;
}

View file

@ -189,10 +189,15 @@ ly_err_get_rec(const struct ly_ctx *ctx)
/* prepare record */
rec.tid = pthread_self();
/* reuse lock */
/* LOCK */
pthread_mutex_lock((pthread_mutex_t *)&ctx->lyb_hash_lock);
/* get the pointer to the matching record */
if (lyht_find(ctx->err_ht, &rec, lyht_hash((void *)&rec.tid, sizeof rec.tid), (void **)&match)) {
return NULL;
}
lyht_find(ctx->err_ht, &rec, lyht_hash((void *)&rec.tid, sizeof rec.tid), (void **)&match);
/* UNLOCK */
pthread_mutex_unlock((pthread_mutex_t *)&ctx->lyb_hash_lock);
return match;
}

View file

@ -40,19 +40,53 @@
#include "version.h"
#include "xml.h"
LIBYANG_API_DEF struct ly_version ly_version_so = {
.major = LY_VERSION_MAJOR,
.minor = LY_VERSION_MINOR,
.micro = LY_VERSION_MICRO,
.str = LY_VERSION
};
LIBYANG_API_DEF uint32_t
ly_version_so_major(void)
{
return LY_VERSION_MAJOR;
}
LIBYANG_API_DEF struct ly_version ly_version_proj = {
.major = LY_PROJ_VERSION_MAJOR,
.minor = LY_PROJ_VERSION_MINOR,
.micro = LY_PROJ_VERSION_MICRO,
.str = LY_PROJ_VERSION
};
LIBYANG_API_DEF uint32_t
ly_version_so_minor(void)
{
return LY_VERSION_MINOR;
}
LIBYANG_API_DEF uint32_t
ly_version_so_micro(void)
{
return LY_VERSION_MICRO;
}
LIBYANG_API_DEF const char *
ly_version_so_str(void)
{
return LY_VERSION;
}
LIBYANG_API_DEF uint32_t
ly_version_proj_major(void)
{
return LY_PROJ_VERSION_MAJOR;
}
LIBYANG_API_DEF uint32_t
ly_version_proj_minor(void)
{
return LY_PROJ_VERSION_MINOR;
}
LIBYANG_API_DEF uint32_t
ly_version_proj_micro(void)
{
return LY_PROJ_VERSION_MICRO;
}
LIBYANG_API_DEF const char *
ly_version_proj_str(void)
{
return LY_PROJ_VERSION;
}
void *
ly_realloc(void *ptr, size_t size)

View file

@ -61,9 +61,6 @@ struct lysc_node;
#define GETMACRO6(_1, _2, _3, _4, _5, _6, NAME, ...) NAME
#define GETMACRO7(_1, _2, _3, _4, _5, _6, _7, NAME, ...) NAME
#define VOIDPTR_C(var) ((void *)(uintptr_t)(var))
#define VOIDPTR2_C(var) ((void **)(uintptr_t)(var))
/******************************************************************************
* Logger
*****************************************************************************/

View file

@ -3,7 +3,7 @@
* @author Michal Vasko <mvasko@cesnet.cz>
* @brief libyang common parser functions.
*
* Copyright (c) 2015 - 2022 CESNET, z.s.p.o.
* Copyright (c) 2015 - 2024 CESNET, z.s.p.o.
*
* This source code is licensed under BSD 3-Clause License (the "License").
* You may not use this file except in compliance with the License.
@ -70,22 +70,35 @@ lyd_parser_notif_eventtime_validate(const struct lyd_node *node)
{
LY_ERR rc = LY_SUCCESS;
struct ly_ctx *ctx = (struct ly_ctx *)LYD_CTX(node);
struct lysc_ctx cctx;
const struct lys_module *mod;
struct lysc_ctx cctx = {0};
const struct lys_module *mod1, *mod2;
const struct lysc_node *schema;
LY_ARRAY_COUNT_TYPE u;
struct ly_err_item *err = NULL;
struct lysp_type *type_p = NULL;
struct lysc_pattern **patterns = NULL;
const char *value;
/* find the used modules, we will either use a compiled leaf or compile the relevant type ourselves */
mod1 = ly_ctx_get_module_implemented(ctx, "notifications");
mod2 = ly_ctx_get_module_latest(ctx, "ietf-yang-types");
assert(mod2);
if (mod1 || !mod2->parsed) {
/* get date-and-time leaf */
schema = lys_find_path(LYD_CTX(node), NULL, "/notifications:notification/eventTime", 0);
LY_CHECK_RET(!schema, LY_ENOTFOUND);
/* validate the value */
value = lyd_get_value(node);
LY_CHECK_RET(lyd_value_validate(LYD_CTX(node), schema, value, strlen(value), NULL, NULL, NULL));
} else {
LYSC_CTX_INIT_CTX(cctx, ctx);
/* get date-and-time parsed type */
mod = ly_ctx_get_module_latest(ctx, "ietf-yang-types");
assert(mod);
LY_ARRAY_FOR(mod->parsed->typedefs, u) {
if (!strcmp(mod->parsed->typedefs[u].name, "date-and-time")) {
type_p = &mod->parsed->typedefs[u].type;
LY_ARRAY_FOR(mod2->parsed->typedefs, u) {
if (!strcmp(mod2->parsed->typedefs[u].name, "date-and-time")) {
type_p = &mod2->parsed->typedefs[u].type;
break;
}
}
@ -98,6 +111,7 @@ lyd_parser_notif_eventtime_validate(const struct lyd_node *node)
/* validate */
value = lyd_get_value(node);
rc = lyplg_type_validate_patterns(patterns, value, strlen(value), &err);
}
cleanup:
FREE_ARRAY(&cctx.free_ctx, patterns, lysc_pattern_free);
@ -3559,7 +3573,7 @@ lys_parse_ext_instance_stmt(struct lysp_ctx *pctx, struct lysp_ext_substmt *subs
{
LY_ERR rc = LY_SUCCESS;
if (!substmt->storage) {
if (!substmt->storage_p) {
/* nothing to parse, ignored */
goto cleanup;
}
@ -3587,7 +3601,7 @@ lys_parse_ext_instance_stmt(struct lysp_ctx *pctx, struct lysp_ext_substmt *subs
LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, (void **)&pnode, NULL), cleanup);
/* usually is a linked-list of all the parsed schema nodes */
pnodes_p = VOIDPTR_C(substmt->storage);
pnodes_p = (struct lysp_node **)substmt->storage_p;
while (*pnodes_p) {
pnodes_p = &(*pnodes_p)->next;
}
@ -3615,7 +3629,7 @@ lys_parse_ext_instance_stmt(struct lysp_ctx *pctx, struct lysp_ext_substmt *subs
case LY_STMT_TYPEDEF:
case LY_STMT_UNIQUE:
/* parse, sized array */
LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, VOIDPTR_C(substmt->storage), NULL), cleanup);
LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage_p, NULL), cleanup);
break;
case LY_STMT_ARGUMENT:
@ -3650,50 +3664,50 @@ lys_parse_ext_instance_stmt(struct lysp_ctx *pctx, struct lysp_ext_substmt *subs
case LY_STMT_YANG_VERSION:
case LY_STMT_YIN_ELEMENT:
/* single item */
if (*VOIDPTR2_C(substmt->storage)) {
if (*substmt->storage_p) {
LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
rc = LY_EVALID;
goto cleanup;
}
/* parse */
LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, VOIDPTR_C(substmt->storage), NULL), cleanup);
LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage_p, NULL), cleanup);
break;
case LY_STMT_CONFIG:
/* single item */
if ((*(uint16_t *)VOIDPTR2_C(substmt->storage)) & LYS_CONFIG_MASK) {
if ((*(uint16_t *)substmt->storage_p) & LYS_CONFIG_MASK) {
LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
rc = LY_EVALID;
goto cleanup;
}
/* parse */
LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, VOIDPTR_C(substmt->storage), NULL), cleanup);
LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage_p, NULL), cleanup);
break;
case LY_STMT_ORDERED_BY:
/* single item */
if ((*(uint16_t *)VOIDPTR2_C(substmt->storage)) & LYS_ORDBY_MASK) {
if ((*(uint16_t *)substmt->storage_p) & LYS_ORDBY_MASK) {
LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
rc = LY_EVALID;
goto cleanup;
}
/* parse */
LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, VOIDPTR_C(substmt->storage), NULL), cleanup);
LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage_p, NULL), cleanup);
break;
case LY_STMT_STATUS:
/* single item */
if ((*(uint16_t *)VOIDPTR2_C(substmt->storage)) & LYS_STATUS_MASK) {
if ((*(uint16_t *)substmt->storage_p) & LYS_STATUS_MASK) {
LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
rc = LY_EVALID;
goto cleanup;
}
/* parse */
LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, VOIDPTR_C(substmt->storage), NULL), cleanup);
LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage_p, NULL), cleanup);
break;
default:

View file

@ -53,6 +53,30 @@ lyd_xml_ctx_free(struct lyd_ctx *lydctx)
free(ctx);
}
/**
* @brief Log namespace error.
*
* @param[in] xmlctx XML context
* @param[in] prefix XML prefix.
* @param[in] prefix_len XML prefix length.
* @param[in] attr_name Current XML attribute name.
* @param[in] attr_len Current XML attribute name length.
*/
static void
lydxml_log_namespace_err(struct lyxml_ctx *xmlctx, const char *prefix, size_t prefix_len,
const char *attr_name, size_t attr_len)
{
if (prefix_len && attr_len) {
LOGVAL(xmlctx->ctx, LYVE_REFERENCE, "Unknown XML prefix \"%.*s\" at attribute \"%.*s\".",
(int)prefix_len, prefix, (int)attr_len, attr_name);
} else if (prefix_len) {
LOGVAL(xmlctx->ctx, LYVE_REFERENCE, "Unknown XML prefix \"%.*s\".",
(int)prefix_len, prefix);
} else {
LOGVAL(xmlctx->ctx, LYVE_REFERENCE, "Missing XML namespace.");
}
}
/**
* @brief Parse and create XML metadata.
*
@ -109,8 +133,10 @@ lydxml_metadata(struct lyd_xml_ctx *lydctx, const struct lysc_node *sparent, str
if (lydctx->parse_opts & LYD_PARSE_STRICT) {
LOGVAL(xmlctx->ctx, LYVE_REFERENCE, "Missing mandatory prefix for XML metadata \"%.*s\".",
(int)xmlctx->name_len, xmlctx->name);
ret = LY_EVALID;
goto cleanup;
/* If LYD_VALIDATE_MULTI_ERROR is set, then continue parsing, because otherwise the parser context
* will remain in a bad state, which will cause termination on some assert or undefined behavior.
*/
LY_DPARSER_ERR_GOTO(LY_EVALID, ret = LY_EVALID, lydctx, cleanup);
}
/* skip attr */
@ -123,8 +149,7 @@ lydxml_metadata(struct lyd_xml_ctx *lydctx, const struct lysc_node *sparent, str
/* get namespace of the attribute to find its annotation definition */
ns = lyxml_ns_get(&xmlctx->ns, xmlctx->prefix, xmlctx->prefix_len);
if (!ns) {
/* unknown namespace, XML error */
LOGVAL(xmlctx->ctx, LYVE_REFERENCE, "Unknown XML prefix \"%.*s\".", (int)xmlctx->prefix_len, xmlctx->prefix);
lydxml_log_namespace_err(xmlctx, xmlctx->prefix, xmlctx->prefix_len, xmlctx->name, xmlctx->name_len);
ret = LY_ENOTFOUND;
goto cleanup;
}
@ -215,7 +240,7 @@ lydxml_attrs(struct lyxml_ctx *xmlctx, struct lyd_attr **attr)
if (prefix_len) {
ns = lyxml_ns_get(&xmlctx->ns, prefix, prefix_len);
if (!ns) {
LOGVAL(xmlctx->ctx, LYVE_REFERENCE, "Unknown XML prefix \"%.*s\".", (int)prefix_len, prefix);
lydxml_log_namespace_err(xmlctx, prefix, prefix_len, name, name_len);
ret = LY_EVALID;
goto cleanup;
}
@ -441,7 +466,9 @@ lydxml_get_hints_opaq(const char *name, size_t name_len, const char *value, size
{
struct lyd_node_opaq *opaq;
char *ptr;
long num;
/* this needs to be at least 64bit, and it "should not" be an explicit int64_t
* because the code calls strtoll later on, which "might" return a bigger type */
long long num;
*hints = 0;
*anchor = NULL;
@ -453,11 +480,11 @@ lydxml_get_hints_opaq(const char *name, size_t name_len, const char *value, size
/* boolean value */
*hints |= LYD_VALHINT_BOOLEAN;
} else {
num = strtol(value, &ptr, 10);
num = strtoll(value, &ptr, 10);
if ((unsigned)(ptr - value) == value_len) {
/* number value */
*hints |= LYD_VALHINT_DECNUM;
if ((num < INT32_MIN) || (num > (long)UINT32_MAX)) {
if ((num < INT32_MIN) || (num > UINT32_MAX)) {
/* large number */
*hints |= LYD_VALHINT_NUM64;
}
@ -535,12 +562,7 @@ lydxml_subtree_get_snode(struct lyd_xml_ctx *lydctx, const struct lyd_node *pare
if (lydctx->int_opts & LYD_INTOPT_ANY) {
goto unknown_module;
}
if (prefix_len) {
LOGVAL(ctx, LYVE_REFERENCE, "Unknown XML prefix \"%.*s\".", (int)prefix_len, prefix);
} else {
LOGVAL(ctx, LYVE_REFERENCE, "Missing XML namespace.");
}
lydxml_log_namespace_err(xmlctx, prefix, prefix_len, NULL, 0);
return LY_EVALID;
}
@ -1056,14 +1078,13 @@ lydxml_subtree_r(struct lyd_xml_ctx *lydctx, struct lyd_node *parent, struct lyd
/* create metadata/attributes */
if (xmlctx->status == LYXML_ATTRIBUTE) {
if (snode) {
rc = lydxml_metadata(lydctx, snode, &meta);
LY_CHECK_GOTO(rc, cleanup);
r = lydxml_metadata(lydctx, snode, &meta);
} else {
assert(lydctx->parse_opts & LYD_PARSE_OPAQ);
rc = lydxml_attrs(xmlctx, &attr);
LY_CHECK_GOTO(rc, cleanup);
r = lydxml_attrs(xmlctx, &attr);
}
}
LY_DPARSER_ERR_GOTO(r, rc = r, lydctx, cleanup);
assert(xmlctx->status == LYXML_ELEM_CONTENT);
if (!snode) {
@ -1175,7 +1196,7 @@ lydxml_envelope(struct lyxml_ctx *xmlctx, const char *name, const char *uri, ly_
prefix_len = xmlctx->prefix_len;
ns = lyxml_ns_get(&xmlctx->ns, prefix, prefix_len);
if (!ns) {
LOGVAL(xmlctx->ctx, LYVE_REFERENCE, "Unknown XML prefix \"%.*s\".", (int)prefix_len, prefix);
lydxml_log_namespace_err(xmlctx, prefix, prefix_len, NULL, 0);
return LY_EVALID;
} else if (strcmp(ns->uri, uri)) {
/* different namespace */
@ -1399,7 +1420,7 @@ lydxml_opaq_r(struct lyxml_ctx *xmlctx, struct lyd_node *parent)
prefix_len = xmlctx->prefix_len;
ns = lyxml_ns_get(&xmlctx->ns, prefix, prefix_len);
if (!ns) {
LOGVAL(xmlctx->ctx, LYVE_REFERENCE, "Unknown XML prefix \"%.*s\".", (int)prefix_len, prefix);
lydxml_log_namespace_err(xmlctx, prefix, prefix_len, NULL, 0);
return LY_EVALID;
}

View file

@ -596,6 +596,7 @@ get_argument(struct lysp_yang_ctx *ctx, enum yang_arg arg, uint16_t *flags, char
size_t buf_len = 0;
uint8_t prefix = 0;
ly_bool str_end = 0;
int comment;
/* word buffer - dynamically allocated */
*word_b = NULL;
@ -627,18 +628,30 @@ get_argument(struct lysp_yang_ctx *ctx, enum yang_arg arg, uint16_t *flags, char
str_end = 1;
break;
case '/':
comment = 0;
if (ctx->in->current[1] == '/') {
/* one-line comment */
MOVE_INPUT(ctx, 2);
LY_CHECK_GOTO(ret = skip_comment(ctx, 1), error);
comment = 1;
} else if (ctx->in->current[1] == '*') {
/* block comment */
MOVE_INPUT(ctx, 2);
LY_CHECK_GOTO(ret = skip_comment(ctx, 2), error);
comment = 2;
} else {
/* not a comment after all */
LY_CHECK_GOTO(ret = buf_store_char(ctx, arg, word_p, word_len, word_b, &buf_len, 0, &prefix), error);
}
if (comment) {
if (*word_len) {
/* invalid comment sequence (RFC 7950 sec. 6.1.3.) */
LOGVAL_PARSER(ctx, LYVE_SYNTAX, "Invalid comment sequence \"%.2s\" in an unquoted string.", ctx->in->current);
ret = LY_EVALID;
goto error;
}
/* skip the comment */
MOVE_INPUT(ctx, 2);
LY_CHECK_GOTO(ret = skip_comment(ctx, comment), error);
}
break;
case ' ':
if (*word_len) {
@ -838,6 +851,8 @@ keyword_start:
/* fall through */
default:
MOVE_INPUT(ctx, 1);
/* fall through */
case '\0':
LOGVAL_PARSER(ctx, LY_VCODE_INSTREXP, (int)(ctx->in->current - word_start), word_start,
"a keyword followed by a separator");
return LY_EVALID;
@ -982,8 +997,16 @@ parse_ext(struct lysp_yang_ctx *ctx, const char *ext_name, size_t ext_name_len,
e->parent_stmt_index = parent_stmt_index;
YANG_READ_SUBSTMT_FOR_GOTO(ctx, kw, word, word_len, ret, cleanup) {
switch (kw) {
case LY_STMT_EXTENSION_INSTANCE:
LY_CHECK_GOTO(parse_ext(ctx, word, word_len, e, LY_STMT_EXTENSION_INSTANCE, 0, &e->exts), cleanup);
break;
default:
/* just store all the statements */
LY_CHECK_GOTO(ret = parse_ext_substmt(ctx, kw, word, word_len, &e->child), cleanup)
YANG_READ_SUBSTMT_NEXT_ITER(ctx, kw, word, word_len, NULL, ret, cleanup);
break;
}
YANG_READ_SUBSTMT_NEXT_ITER(ctx, kw, word, word_len, e->exts, ret, cleanup);
}
cleanup:

View file

@ -4,7 +4,7 @@
* @author Michal Vasko <mvasko@cesnet.cz>
* @brief YIN parser.
*
* Copyright (c) 2015 - 2022 CESNET, z.s.p.o.
* Copyright (c) 2015 - 2024 CESNET, z.s.p.o.
*
* This source code is licensed under BSD 3-Clause License (the "License").
* You may not use this file except in compliance with the License.
@ -3409,6 +3409,14 @@ yin_parse_extension_instance(struct lysp_yin_ctx *ctx, const void *parent, enum
if (ctx->xmlctx->ws_only) {
LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
while (ctx->xmlctx->status == LYXML_ELEMENT) {
/* BUG nested extensions will not be parsed because we are not able to dinsguish between them
* and the argument of this extension, in case there is one and its 'yin-element' is 'true'
stmt = yin_match_keyword(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix,
ctx->xmlctx->prefix_len, LY_STMT_EXTENSION_INSTANCE);
if (stmt == LY_STMT_EXTENSION_INSTANCE) {
LY_CHECK_RET(yin_parse_extension_instance(ctx, e, LY_STMT_EXTENSION_INSTANCE, 0, &e->exts));
} else { */
LY_CHECK_RET(yin_parse_element_generic(ctx, LY_STMT_EXTENSION_INSTANCE, &new_subelem));
if (!e->child) {
e->child = new_subelem;
@ -3420,6 +3428,9 @@ yin_parse_extension_instance(struct lysp_yin_ctx *ctx, const void *parent, enum
assert(ctx->xmlctx->status == LYXML_ELEM_CLOSE);
LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
}
/* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
LY_CHECK_RET(yin_unres_exts_add(ctx, e->exts));
} else if (ctx->xmlctx->value_len) {
/* invalid text content */
LOGVAL_PARSER(ctx, LYVE_SYNTAX, "Extension instance \"%s\" with unexpected text content \"%.*s\".", ext_name,

View file

@ -708,7 +708,7 @@ ly_path_compile_predicate(const struct ly_ctx *ctx, const struct lysc_node *cur_
/* store the value */
LOG_LOCSET(key, NULL);
ret = lyd_value_store(ctx, &p->value, ((struct lysc_node_leaf *)key)->type, val, val_len, 0, 0,
ret = lyd_value_store(ctx_node->module->ctx, &p->value, ((struct lysc_node_leaf *)key)->type, val, val_len, 0, 0,
NULL, format, prefix_data, LYD_HINT_DATA, key, NULL);
LOG_LOCBACK(1, 0);
LY_CHECK_ERR_GOTO(ret, p->value.realtype = NULL, cleanup);
@ -736,7 +736,7 @@ ly_path_compile_predicate(const struct ly_ctx *ctx, const struct lysc_node *cur_
/* names (keys) are unique - it was checked when parsing */
LOGVAL(ctx, LYVE_XPATH, "Predicate missing for a key of %s \"%s\" in path.",
lys_nodetype2str(ctx_node->nodetype), ctx_node->name);
ly_path_predicates_free(ctx, *predicates);
ly_path_predicates_free(ctx_node->module->ctx, *predicates);
*predicates = NULL;
ret = LY_EVALID;
goto cleanup;
@ -771,12 +771,10 @@ ly_path_compile_predicate(const struct ly_ctx *ctx, const struct lysc_node *cur_
}
/* store the value */
if (ctx_node) {
LOG_LOCSET(ctx_node, NULL);
}
ret = lyd_value_store(ctx, &p->value, ((struct lysc_node_leaflist *)ctx_node)->type, val, val_len, 0, 0,
ret = lyd_value_store(ctx_node->module->ctx, &p->value, ((struct lysc_node_leaflist *)ctx_node)->type, val, val_len, 0, 0,
NULL, format, prefix_data, LYD_HINT_DATA, ctx_node, NULL);
LOG_LOCBACK(ctx_node ? 1 : 0, 0);
LOG_LOCBACK(1, 0);
LY_CHECK_ERR_GOTO(ret, p->value.realtype = NULL, cleanup);
++(*tok_idx);
@ -1093,7 +1091,7 @@ ly_path_compile_deref(const struct ly_ctx *ctx, const struct lysc_node *ctx_node
}
lref = (const struct lysc_type_leafref *)deref_leaf_node->type;
LY_CHECK_GOTO(ret = ly_path_append(ctx, path2, path), cleanup);
ly_path_free(ctx, path2);
ly_path_free(path2);
path2 = NULL;
/* compile dereferenced leafref expression and append it to the path */
@ -1101,7 +1099,7 @@ ly_path_compile_deref(const struct ly_ctx *ctx, const struct lysc_node *ctx_node
&path2), cleanup);
node2 = path2[LY_ARRAY_COUNT(path2) - 1].node;
LY_CHECK_GOTO(ret = ly_path_append(ctx, path2, path), cleanup);
ly_path_free(ctx, path2);
ly_path_free(path2);
path2 = NULL;
/* properly parsed path must always continue with ')' and '/' */
@ -1125,9 +1123,9 @@ ly_path_compile_deref(const struct ly_ctx *ctx, const struct lysc_node *ctx_node
LY_CHECK_GOTO(ret = ly_path_append(ctx, path2, path), cleanup);
cleanup:
ly_path_free(ctx, path2);
ly_path_free(path2);
if (ret) {
ly_path_free(ctx, *path);
ly_path_free(*path);
*path = NULL;
}
return ret;
@ -1283,7 +1281,7 @@ _ly_path_compile(const struct ly_ctx *ctx, const struct lys_module *cur_mod, con
cleanup:
if (ret) {
ly_path_free(ctx, *path);
ly_path_free(*path);
*path = NULL;
}
LOG_LOCBACK(cur_node ? 1 : 0, 0);
@ -1488,7 +1486,7 @@ ly_path_predicates_free(const struct ly_ctx *ctx, struct ly_path_predicate *pred
}
void
ly_path_free(const struct ly_ctx *ctx, struct ly_path *path)
ly_path_free(struct ly_path *path)
{
LY_ARRAY_COUNT_TYPE u;
@ -1497,7 +1495,7 @@ ly_path_free(const struct ly_ctx *ctx, struct ly_path *path)
}
LY_ARRAY_FOR(path, u) {
ly_path_predicates_free(ctx, path[u].predicates);
ly_path_predicates_free(path[u].node->module->ctx, path[u].predicates);
}
LY_ARRAY_FREE(path);
}

View file

@ -257,9 +257,8 @@ void ly_path_predicates_free(const struct ly_ctx *ctx, struct ly_path_predicate
/**
* @brief Free ly_path structure.
*
* @param[in] ctx libyang context.
* @param[in] path The structure ([sized array](@ref sizedarrays)) to free.
*/
void ly_path_free(const struct ly_ctx *ctx, struct ly_path *path);
void ly_path_free(struct ly_path *path);
#endif /* LY_PATH_H_ */

View file

@ -80,6 +80,11 @@ extern const struct lyplg_type_record plugins_xpath10[];
*/
extern const struct lyplg_type_record plugins_node_instanceid[];
/*
* libnetconf2-netconf-server
*/
extern const struct lyplg_type_record plugins_time_period[];
/*
* lyds_tree
*/
@ -522,6 +527,9 @@ lyplg_init(ly_bool builtin_type_plugins_only)
LY_CHECK_GOTO(ret = plugins_insert(NULL, LYPLG_TYPE, plugins_hex_string), error);
LY_CHECK_GOTO(ret = plugins_insert(NULL, LYPLG_TYPE, plugins_xpath10), error);
/* libnetconf2-netconf-server */
LY_CHECK_GOTO(ret = plugins_insert(NULL, LYPLG_TYPE, plugins_time_period), error);
/* ietf-netconf-acm */
LY_CHECK_GOTO(ret = plugins_insert(NULL, LYPLG_TYPE, plugins_node_instanceid), error);

View file

@ -38,19 +38,22 @@ extern "C" {
* Furthermore, there are several internal plugins, implementing built-in data types and selected derived types and YANG
* extensions. These internal plugins uses the same API and can be taken as examples for implementing user plugins. Internal
* plugins are always loaded with the first created [context](@ref howtoContext) and unloaded with destroying the last one.
* The external plugins are in the same phase loaded from the default directories specified at compile time via cmake
* variables `PLUGINS_DIR` (where the `extensions` and `types` subdirectories are added for each plugin type) or separately
* via `PLUGINS_DIR_EXTENSIONS` and `PLUGINS_DIR_TYPES` for each plugin type. The default directories can be replaced runtime
* using environment variables `LIBYANG_TYPES_PLUGINS_DIR` and `LIBYANG_EXTENSIONS_PLUGINS_DIR`.
* The external plugins are in the same phase loaded as dynamic shared objects (shared libraries) from the default directories
* specified at compile time via cmake variables `PLUGINS_DIR` (where the `extensions` and `types` subdirectories are added
* for each plugin type) or separately via `PLUGINS_DIR_EXTENSIONS` and `PLUGINS_DIR_TYPES` for each plugin type. The default
* directories can be replaced runtime using environment variables `LIBYANG_TYPES_PLUGINS_DIR` and `LIBYANG_EXTENSIONS_PLUGINS_DIR`.
* There is also a separate function ::lyplg_add() to manually add a plugin (dynamic shared object) anytime later.
* Another option to manually add an external plugin is using the ::lyplg_add_extension_plugin() or ::lyplg_add_type_plugin()
* which is useful when loading a dynamic shared object is problematic. These functions allow for setting the necessary callbacks
* for the plugin at runtime.
*
* Order of the plugins determines their priority. libyang searches for the first match with the extension and type, so the
* firstly loaded plugin for the specific item is used. Since the internal plugins are loaded always before the external
* plugins, the internal plugins cannot be replaced.
*
* There is also a separate function ::lyplg_add() to add a plugin anytime later. Note, that such a plugin is being used
* after it is added with the lowest priority among other already loaded plugins. Also note that since all the plugins are
* unloaded with the destruction of the last context, creating a new context after that starts the standard plugins
* initiation and the manually added plugins are not loaded automatically.
* Note, that manually added plugin via lyplg_add*() function is added with the lowest priority among other already loaded plugins.
* Also note that since all the plugins are unloaded with the destruction of the last context, creating a new context after that
* starts the standard plugins initiation and the manually added plugins are not loaded automatically.
*
* The following pages contain description of the API for creating user plugins.
*

View file

@ -4,7 +4,7 @@
* @author Michal Vasko <mvasko@cesnet.cz>
* @brief helper functions for extension plugins
*
* Copyright (c) 2019 - 2022 CESNET, z.s.p.o.
* Copyright (c) 2019 - 2024 CESNET, z.s.p.o.
*
* This source code is licensed under BSD 3-Clause License (the "License").
* You may not use this file except in compliance with the License.
@ -81,34 +81,34 @@ cleanup:
* @brief Compile an instance extension statement.
*
* @param[in] ctx Compile context.
* @param[in] parsed Parsed ext instance substatement structure.
* @param[in] parsed_p Parsed ext instance substatement structure.
* @param[in] ext Compiled ext instance.
* @param[in] substmt Compled ext instance substatement info.
* @return LY_ERR value.
*/
static LY_ERR
lys_compile_ext_instance_stmt(struct lysc_ctx *ctx, uint64_t parsed, struct lysc_ext_instance *ext,
lys_compile_ext_instance_stmt(struct lysc_ctx *ctx, void **parsed_p, struct lysc_ext_instance *ext,
struct lysc_ext_substmt *substmt)
{
LY_ERR rc = LY_SUCCESS;
ly_bool length_restr = 0;
LY_DATA_TYPE basetype;
assert(parsed);
assert(*parsed_p);
/* compilation wthout any storage */
if (substmt->stmt == LY_STMT_IF_FEATURE) {
ly_bool enabled;
/* evaluate */
LY_CHECK_GOTO(rc = lys_eval_iffeatures(ctx->ctx, VOIDPTR_C(parsed), &enabled), cleanup);
LY_CHECK_GOTO(rc = lys_eval_iffeatures(ctx->ctx, *parsed_p, &enabled), cleanup);
if (!enabled) {
/* it is disabled, remove the whole extension instance */
rc = LY_ENOT;
}
}
if (!substmt->storage) {
if (!substmt->storage_p) {
/* nothing to store */
goto cleanup;
}
@ -133,7 +133,7 @@ lys_compile_ext_instance_stmt(struct lysc_ctx *ctx, uint64_t parsed, struct lysc
struct lysc_node *node;
lyplg_ext_get_storage(ext, LY_STMT_STATUS, sizeof flags, (const void **)&flags);
pnodes = VOIDPTR_C(parsed);
pnodes = *parsed_p;
/* compile nodes */
LY_LIST_FOR(pnodes, pnode) {
@ -163,7 +163,7 @@ lys_compile_ext_instance_stmt(struct lysc_ctx *ctx, uint64_t parsed, struct lysc
case LY_STMT_REFERENCE:
case LY_STMT_UNITS:
/* just make a copy */
LY_CHECK_GOTO(rc = lydict_insert(ctx->ctx, VOIDPTR_C(parsed), 0, VOIDPTR_C(substmt->storage)), cleanup);
LY_CHECK_GOTO(rc = lydict_insert(ctx->ctx, *parsed_p, 0, (const char **)substmt->storage_p), cleanup);
break;
case LY_STMT_BIT:
@ -175,7 +175,7 @@ lys_compile_ext_instance_stmt(struct lysc_ctx *ctx, uint64_t parsed, struct lysc
}
/* compile */
rc = lys_compile_type_enums(ctx, VOIDPTR_C(parsed), basetype, NULL, VOIDPTR_C(substmt->storage));
rc = lys_compile_type_enums(ctx, *parsed_p, basetype, NULL, (struct lysc_type_bitenum_item **)substmt->storage_p);
LY_CHECK_GOTO(rc, cleanup);
break;
@ -183,7 +183,7 @@ lys_compile_ext_instance_stmt(struct lysc_ctx *ctx, uint64_t parsed, struct lysc
uint16_t flags;
if (!(ctx->compile_opts & LYS_COMPILE_NO_CONFIG)) {
memcpy(&flags, &parsed, 2);
memcpy(&flags, parsed_p, 2);
if (flags & LYS_CONFIG_MASK) {
/* explicitly set */
flags |= LYS_SET_CONFIG;
@ -194,56 +194,56 @@ lys_compile_ext_instance_stmt(struct lysc_ctx *ctx, uint64_t parsed, struct lysc
/* default config */
flags = LYS_CONFIG_W;
}
memcpy(VOIDPTR_C(substmt->storage), &flags, 2);
memcpy(substmt->storage_p, &flags, 2);
} /* else leave zero */
break;
}
case LY_STMT_MUST: {
const struct lysp_restr *restrs = VOIDPTR_C(parsed);
const struct lysp_restr *restrs = *parsed_p;
/* sized array */
COMPILE_ARRAY_GOTO(ctx, restrs, *(struct lysc_must **)VOIDPTR_C(substmt->storage), lys_compile_must, rc, cleanup);
COMPILE_ARRAY_GOTO(ctx, restrs, *(struct lysc_must **)substmt->storage_p, lys_compile_must, rc, cleanup);
break;
}
case LY_STMT_WHEN: {
const uint16_t flags;
const struct lysp_when *when = VOIDPTR_C(parsed);
const struct lysp_when *when = *parsed_p;
/* read compiled status */
lyplg_ext_get_storage(ext, LY_STMT_STATUS, sizeof flags, (const void **)&flags);
/* compile */
LY_CHECK_GOTO(rc = lys_compile_when(ctx, when, flags, NULL, NULL, NULL, VOIDPTR_C(substmt->storage)), cleanup);
LY_CHECK_GOTO(rc = lys_compile_when(ctx, when, flags, NULL, NULL, NULL, (struct lysc_when **)substmt->storage_p), cleanup);
break;
}
case LY_STMT_FRACTION_DIGITS:
case LY_STMT_REQUIRE_INSTANCE:
/* just make a copy */
memcpy(VOIDPTR_C(substmt->storage), &parsed, 1);
memcpy(substmt->storage_p, parsed_p, 1);
break;
case LY_STMT_MANDATORY:
case LY_STMT_ORDERED_BY:
case LY_STMT_STATUS:
/* just make a copy */
memcpy(VOIDPTR_C(substmt->storage), &parsed, 2);
memcpy(substmt->storage_p, parsed_p, 2);
break;
case LY_STMT_MAX_ELEMENTS:
case LY_STMT_MIN_ELEMENTS:
/* just make a copy */
memcpy(VOIDPTR_C(substmt->storage), &parsed, 4);
memcpy(substmt->storage_p, parsed_p, 4);
break;
case LY_STMT_POSITION:
case LY_STMT_VALUE:
/* just make a copy */
memcpy(VOIDPTR_C(substmt->storage), &parsed, 8);
memcpy(substmt->storage_p, parsed_p, 8);
break;
case LY_STMT_IDENTITY:
/* compile */
rc = lys_identity_precompile(ctx, NULL, NULL, VOIDPTR_C(parsed), VOIDPTR_C(substmt->storage));
rc = lys_identity_precompile(ctx, NULL, NULL, *parsed_p, (struct lysc_ident **)substmt->storage_p);
LY_CHECK_GOTO(rc, cleanup);
break;
@ -252,36 +252,36 @@ lys_compile_ext_instance_stmt(struct lysc_ctx *ctx, uint64_t parsed, struct lysc
/* fallthrough */
case LY_STMT_RANGE:
/* compile, use uint64 default range */
rc = lys_compile_type_range(ctx, VOIDPTR_C(parsed), LY_TYPE_UINT64, length_restr, 0, NULL, VOIDPTR_C(substmt->storage));
rc = lys_compile_type_range(ctx, *parsed_p, LY_TYPE_UINT64, length_restr, 0, NULL, (struct lysc_range **)substmt->storage_p);
LY_CHECK_GOTO(rc, cleanup);
break;
case LY_STMT_PATTERN:
/* compile */
rc = lys_compile_type_patterns(ctx, VOIDPTR_C(parsed), NULL, VOIDPTR_C(substmt->storage));
rc = lys_compile_type_patterns(ctx, *parsed_p, NULL, (struct lysc_pattern ***)substmt->storage_p);
LY_CHECK_GOTO(rc, cleanup);
break;
case LY_STMT_TYPE: {
const uint16_t flags;
const char *units;
const struct lysp_type *ptype = VOIDPTR_C(parsed);
const struct lysp_type *ptype = *parsed_p;
/* read compiled info */
lyplg_ext_get_storage(ext, LY_STMT_STATUS, sizeof flags, (const void **)&flags);
lyplg_ext_get_storage(ext, LY_STMT_UNITS, sizeof units, (const void **)&units);
/* compile */
rc = lys_compile_type(ctx, NULL, flags, ext->def->name, ptype, VOIDPTR_C(substmt->storage), &units, NULL);
rc = lys_compile_type(ctx, NULL, flags, ext->def->name, ptype, (struct lysc_type **)substmt->storage_p, &units, NULL);
LY_CHECK_GOTO(rc, cleanup);
LY_ATOMIC_INC_BARRIER((*(struct lysc_type **)VOIDPTR_C(substmt->storage))->refcount);
LY_ATOMIC_INC_BARRIER((*(struct lysc_type **)substmt->storage_p)->refcount);
break;
}
case LY_STMT_EXTENSION_INSTANCE: {
struct lysp_ext_instance *extps = VOIDPTR_C(parsed);
struct lysp_ext_instance *extps = *parsed_p;
/* compile sized array */
COMPILE_EXTS_GOTO(ctx, extps, *(struct lysc_ext_instance **)VOIDPTR_C(substmt->storage), ext, rc, cleanup);
COMPILE_EXTS_GOTO(ctx, extps, *(struct lysc_ext_instance **)substmt->storage_p, ext, rc, cleanup);
break;
}
case LY_STMT_AUGMENT:
@ -330,7 +330,7 @@ lyplg_ext_compile_extension_instance(struct lysc_ctx *ctx, const struct lysp_ext
LY_ERR rc = LY_SUCCESS;
LY_ARRAY_COUNT_TYPE u, v;
enum ly_stmt stmtp;
uint64_t storagep;
void **storagep;
struct ly_set storagep_compiled = {0};
LY_CHECK_ARG_RET(ctx ? ctx->ctx : NULL, ctx, extp, ext, LY_EINVAL);
@ -340,9 +340,9 @@ lyplg_ext_compile_extension_instance(struct lysc_ctx *ctx, const struct lysp_ext
LY_ARRAY_FOR(extp->substmts, u) {
stmtp = extp->substmts[u].stmt;
storagep = *(uint64_t *)VOIDPTR_C(extp->substmts[u].storage);
storagep = extp->substmts[u].storage_p;
if (!storagep || ly_set_contains(&storagep_compiled, VOIDPTR_C(storagep), NULL)) {
if (!*storagep || ly_set_contains(&storagep_compiled, storagep, NULL)) {
/* nothing parsed or already compiled (for example, if it is a linked list of parsed nodes) */
continue;
}
@ -361,7 +361,7 @@ lyplg_ext_compile_extension_instance(struct lysc_ctx *ctx, const struct lysp_ext
}
/* compiled */
ly_set_add(&storagep_compiled, VOIDPTR_C(storagep), 1, NULL);
ly_set_add(&storagep_compiled, storagep, 1, NULL);
}
cleanup:
@ -420,7 +420,7 @@ lyplg_ext_sprinter_ctree_add_ext_nodes(const struct lyspr_tree_ctx *ctx, struct
uint32_t i;
struct lysc_node *schema;
LY_CHECK_ARG_RET2(NULL, ctx, ext, LY_EINVAL);
LY_CHECK_ARG_RET(NULL, ctx, ext, LY_EINVAL);
LY_ARRAY_FOR(ext->substmts, i) {
switch (ext->substmts[i].stmt) {
@ -437,7 +437,7 @@ lyplg_ext_sprinter_ctree_add_ext_nodes(const struct lyspr_tree_ctx *ctx, struct
case LY_STMT_LEAF:
case LY_STMT_LEAF_LIST:
case LY_STMT_LIST:
schema = *VOIDPTR2_C(ext->substmts[i].storage);
schema = *ext->substmts[i].storage_p;
if (schema) {
rc = lyplg_ext_sprinter_ctree_add_nodes(ctx, schema, clb);
return rc;
@ -458,7 +458,7 @@ lyplg_ext_sprinter_ptree_add_ext_nodes(const struct lyspr_tree_ctx *ctx, struct
uint32_t i;
struct lysp_node *schema;
LY_CHECK_ARG_RET2(NULL, ctx, ext, LY_EINVAL);
LY_CHECK_ARG_RET(NULL, ctx, ext, LY_EINVAL);
LY_ARRAY_FOR(ext->substmts, i) {
switch (ext->substmts[i].stmt) {
@ -475,7 +475,7 @@ lyplg_ext_sprinter_ptree_add_ext_nodes(const struct lyspr_tree_ctx *ctx, struct
case LY_STMT_LEAF:
case LY_STMT_LEAF_LIST:
case LY_STMT_LIST:
schema = *VOIDPTR2_C(ext->substmts[i].storage);
schema = *ext->substmts[i].storage_p;
if (schema) {
rc = lyplg_ext_sprinter_ptree_add_nodes(ctx, schema, clb);
return rc;
@ -494,7 +494,7 @@ lyplg_ext_sprinter_ctree_add_nodes(const struct lyspr_tree_ctx *ctx, struct lysc
{
struct lyspr_tree_schema *new;
LY_CHECK_ARG_RET1(NULL, ctx, LY_EINVAL);
LY_CHECK_ARG_RET(NULL, ctx, LY_EINVAL);
if (!nodes) {
return LY_SUCCESS;
@ -514,7 +514,7 @@ lyplg_ext_sprinter_ptree_add_nodes(const struct lyspr_tree_ctx *ctx, struct lysp
{
struct lyspr_tree_schema *new;
LY_CHECK_ARG_RET1(NULL, ctx, LY_EINVAL);
LY_CHECK_ARG_RET(NULL, ctx, LY_EINVAL);
if (!nodes) {
return LY_SUCCESS;
@ -531,7 +531,7 @@ lyplg_ext_sprinter_ptree_add_nodes(const struct lyspr_tree_ctx *ctx, struct lysp
LIBYANG_API_DECL LY_ERR
lyplg_ext_sprinter_tree_set_priv(const struct lyspr_tree_ctx *ctx, void *plugin_priv, void (*free_clb)(void *plugin_priv))
{
LY_CHECK_ARG_RET1(NULL, ctx, LY_EINVAL);
LY_CHECK_ARG_RET(NULL, ctx, LY_EINVAL);
((struct lyspr_tree_ctx *)ctx)->plugin_priv = plugin_priv;
((struct lyspr_tree_ctx *)ctx)->free_plugin_priv = free_clb;
@ -587,12 +587,12 @@ lyplg_ext_nodetype2stmt(uint16_t nodetype)
}
LY_ERR
lyplg_ext_get_storage_p(const struct lysc_ext_instance *ext, int stmt, uint64_t *storage_p)
lyplg_ext_get_storage_p(const struct lysc_ext_instance *ext, int stmt, void ***storage_pp)
{
LY_ARRAY_COUNT_TYPE u;
enum ly_stmt match = 0;
*storage_p = 0;
*storage_pp = NULL;
if (!(stmt & LY_STMT_NODE_MASK)) {
/* matching a non-node statement */
@ -601,7 +601,7 @@ lyplg_ext_get_storage_p(const struct lysc_ext_instance *ext, int stmt, uint64_t
LY_ARRAY_FOR(ext->substmts, u) {
if ((match && (ext->substmts[u].stmt == match)) || (!match && (ext->substmts[u].stmt & stmt))) {
*storage_p = ext->substmts[u].storage;
*storage_pp = ext->substmts[u].storage_p;
return LY_SUCCESS;
}
}
@ -613,14 +613,14 @@ LIBYANG_API_DEF LY_ERR
lyplg_ext_get_storage(const struct lysc_ext_instance *ext, int stmt, uint32_t storage_size, const void **storage)
{
LY_ERR rc = LY_SUCCESS;
uint64_t s;
void **s_p;
/* get pointer to the storage, is set even on error */
rc = lyplg_ext_get_storage_p(ext, stmt, &s);
rc = lyplg_ext_get_storage_p(ext, stmt, &s_p);
/* assign */
if (s) {
memcpy(storage, VOIDPTR_C(s), storage_size);
if (s_p) {
memcpy(storage, s_p, storage_size);
} else {
memset(storage, 0, storage_size);
}
@ -634,7 +634,9 @@ lyplg_ext_parsed_get_storage(const struct lysc_ext_instance *ext, int stmt, uint
LY_ARRAY_COUNT_TYPE u;
const struct lysp_ext_instance *extp = NULL;
enum ly_stmt match = 0;
uint64_t s = 0;
void **s_p = NULL;
LY_CHECK_ARG_RET(NULL, ext, ext->module->parsed, LY_EINVAL);
/* find the parsed ext instance */
LY_ARRAY_FOR(ext->module->parsed->exts, u) {
@ -655,14 +657,14 @@ lyplg_ext_parsed_get_storage(const struct lysc_ext_instance *ext, int stmt, uint
/* get the substatement */
LY_ARRAY_FOR(extp->substmts, u) {
if ((match && (extp->substmts[u].stmt == match)) || (!match && (extp->substmts[u].stmt & stmt))) {
s = extp->substmts[u].storage;
s_p = extp->substmts[u].storage_p;
break;
}
}
/* assign */
if (s) {
memcpy(storage, VOIDPTR_C(s), storage_size);
if (s_p) {
memcpy(storage, s_p, storage_size);
} else {
memset(storage, 0, storage_size);
}

View file

@ -109,7 +109,7 @@ extern "C" {
/**
* @brief Extensions API version
*/
#define LYPLG_EXT_API_VERSION 6
#define LYPLG_EXT_API_VERSION 8
/**
* @brief Mask for an operation statement.
@ -393,7 +393,7 @@ struct lysp_stmt {
*/
struct lysp_ext_substmt {
enum ly_stmt stmt; /**< parsed substatement */
uint64_t storage; /**< (pointer to) the parsed storage of the statement according to the specific
void **storage_p; /**< pointer to the parsed storage of the statement according to the specific
lys_ext_substmt::stmt */
};
@ -419,6 +419,7 @@ struct lysp_ext_instance {
parsed data ([sized array](@ref sizedarrays)) */
void *parsed; /**< private plugin parsed data */
struct lysp_stmt *child; /**< list of generic (unknown) YANG statements */
struct lysp_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
};
/**
@ -426,7 +427,7 @@ struct lysp_ext_instance {
*/
struct lysc_ext_substmt {
enum ly_stmt stmt; /**< compiled substatement */
uint64_t storage; /**< (pointer to) the compiled storage of the statement according to the specific
void **storage_p; /**< pointer to the compiled storage of the statement according to the specific
lys_ext_substmt::stmt */
};

View file

@ -79,27 +79,27 @@ annotation_parse(struct lysp_ctx *pctx, struct lysp_ext_instance *ext)
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[0].stmt = LY_STMT_IF_FEATURE;
ext->substmts[0].storage = (uint64_t)(uintptr_t)&ann_pdata->iffeatures;
ext->substmts[0].storage_p = (void **)&ann_pdata->iffeatures;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[1].stmt = LY_STMT_UNITS;
ext->substmts[1].storage = (uint64_t)(uintptr_t)&ann_pdata->units;
ext->substmts[1].storage_p = (void **)&ann_pdata->units;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[2].stmt = LY_STMT_STATUS;
ext->substmts[2].storage = (uint64_t)(uintptr_t)&ann_pdata->flags;
ext->substmts[2].storage_p = (void **)&ann_pdata->flags;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[3].stmt = LY_STMT_TYPE;
ext->substmts[3].storage = (uint64_t)(uintptr_t)&ann_pdata->type;
ext->substmts[3].storage_p = (void **)&ann_pdata->type;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[4].stmt = LY_STMT_DESCRIPTION;
ext->substmts[4].storage = (uint64_t)(uintptr_t)&ann_pdata->dsc;
ext->substmts[4].storage_p = (void **)&ann_pdata->dsc;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[5].stmt = LY_STMT_REFERENCE;
ext->substmts[5].storage = (uint64_t)(uintptr_t)&ann_pdata->ref;
ext->substmts[5].storage_p = (void **)&ann_pdata->ref;
if ((r = lyplg_ext_parse_extension_instance(pctx, ext))) {
return r;
@ -139,27 +139,27 @@ annotation_compile(struct lysc_ctx *cctx, const struct lysp_ext_instance *extp,
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[0].stmt = LY_STMT_IF_FEATURE;
ext->substmts[0].storage = 0;
ext->substmts[0].storage_p = NULL;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[1].stmt = LY_STMT_UNITS;
ext->substmts[1].storage = (uint64_t)(uintptr_t)&ann_cdata->units;
ext->substmts[1].storage_p = (void **)&ann_cdata->units;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[2].stmt = LY_STMT_STATUS;
ext->substmts[2].storage = (uint64_t)(uintptr_t)&ann_cdata->flags;
ext->substmts[2].storage_p = (void **)&ann_cdata->flags;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[3].stmt = LY_STMT_TYPE;
ext->substmts[3].storage = (uint64_t)(uintptr_t)&ann_cdata->type;
ext->substmts[3].storage_p = (void **)&ann_cdata->type;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[4].stmt = LY_STMT_DESCRIPTION;
ext->substmts[4].storage = (uint64_t)(uintptr_t)&ann_cdata->dsc;
ext->substmts[4].storage_p = (void **)&ann_cdata->dsc;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[5].stmt = LY_STMT_REFERENCE;
ext->substmts[5].storage = (uint64_t)(uintptr_t)&ann_cdata->ref;
ext->substmts[5].storage_p = (void **)&ann_cdata->ref;
ret = lyplg_ext_compile_extension_instance(cctx, extp, ext);
return ret;

View file

@ -90,60 +90,60 @@ structure_parse(struct lysp_ctx *pctx, struct lysp_ext_instance *ext)
/* parse substatements */
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[0].stmt = LY_STMT_MUST;
ext->substmts[0].storage = (uint64_t)(uintptr_t)&struct_pdata->musts;
ext->substmts[0].storage_p = (void **)&struct_pdata->musts;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[1].stmt = LY_STMT_STATUS;
ext->substmts[1].storage = (uint64_t)(uintptr_t)&struct_pdata->flags;
ext->substmts[1].storage_p = (void **)&struct_pdata->flags;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[2].stmt = LY_STMT_DESCRIPTION;
ext->substmts[2].storage = (uint64_t)(uintptr_t)&struct_pdata->dsc;
ext->substmts[2].storage_p = (void **)&struct_pdata->dsc;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[3].stmt = LY_STMT_REFERENCE;
ext->substmts[3].storage = (uint64_t)(uintptr_t)&struct_pdata->ref;
ext->substmts[3].storage_p = (void **)&struct_pdata->ref;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[4].stmt = LY_STMT_TYPEDEF;
ext->substmts[4].storage = (uint64_t)(uintptr_t)&struct_pdata->typedefs;
ext->substmts[4].storage_p = (void **)&struct_pdata->typedefs;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[5].stmt = LY_STMT_GROUPING;
ext->substmts[5].storage = (uint64_t)(uintptr_t)&struct_pdata->groupings;
ext->substmts[5].storage_p = (void **)&struct_pdata->groupings;
/* data-def-stmt */
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[6].stmt = LY_STMT_CONTAINER;
ext->substmts[6].storage = (uint64_t)(uintptr_t)&struct_pdata->child;
ext->substmts[6].storage_p = (void **)&struct_pdata->child;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[7].stmt = LY_STMT_LEAF;
ext->substmts[7].storage = (uint64_t)(uintptr_t)&struct_pdata->child;
ext->substmts[7].storage_p = (void **)&struct_pdata->child;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[8].stmt = LY_STMT_LEAF_LIST;
ext->substmts[8].storage = (uint64_t)(uintptr_t)&struct_pdata->child;
ext->substmts[8].storage_p = (void **)&struct_pdata->child;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[9].stmt = LY_STMT_LIST;
ext->substmts[9].storage = (uint64_t)(uintptr_t)&struct_pdata->child;
ext->substmts[9].storage_p = (void **)&struct_pdata->child;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[10].stmt = LY_STMT_CHOICE;
ext->substmts[10].storage = (uint64_t)(uintptr_t)&struct_pdata->child;
ext->substmts[10].storage_p = (void **)&struct_pdata->child;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[11].stmt = LY_STMT_ANYDATA;
ext->substmts[11].storage = (uint64_t)(uintptr_t)&struct_pdata->child;
ext->substmts[11].storage_p = (void **)&struct_pdata->child;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[12].stmt = LY_STMT_ANYXML;
ext->substmts[12].storage = (uint64_t)(uintptr_t)&struct_pdata->child;
ext->substmts[12].storage_p = (void **)&struct_pdata->child;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[13].stmt = LY_STMT_USES;
ext->substmts[13].storage = (uint64_t)(uintptr_t)&struct_pdata->child;
ext->substmts[13].storage_p = (void **)&struct_pdata->child;
rc = lyplg_ext_parse_extension_instance(pctx, ext);
return rc;
@ -190,60 +190,60 @@ structure_compile(struct lysc_ctx *cctx, const struct lysp_ext_instance *extp, s
LY_ARRAY_CREATE_GOTO(cctx->ctx, ext->substmts, 14, rc, emem);
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[0].stmt = LY_STMT_MUST;
ext->substmts[0].storage = (uint64_t)(uintptr_t)&struct_cdata->musts;
ext->substmts[0].storage_p = (void **)&struct_cdata->musts;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[1].stmt = LY_STMT_STATUS;
ext->substmts[1].storage = (uint64_t)(uintptr_t)&struct_cdata->flags;
ext->substmts[1].storage_p = (void **)&struct_cdata->flags;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[2].stmt = LY_STMT_DESCRIPTION;
ext->substmts[2].storage = (uint64_t)(uintptr_t)&struct_cdata->dsc;
ext->substmts[2].storage_p = (void **)&struct_cdata->dsc;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[3].stmt = LY_STMT_REFERENCE;
ext->substmts[3].storage = (uint64_t)(uintptr_t)&struct_cdata->ref;
ext->substmts[3].storage_p = (void **)&struct_cdata->ref;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[4].stmt = LY_STMT_TYPEDEF;
ext->substmts[4].storage = 0;
ext->substmts[4].storage_p = 0;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[5].stmt = LY_STMT_GROUPING;
ext->substmts[5].storage = 0;
ext->substmts[5].storage_p = 0;
/* data-def-stmt */
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[6].stmt = LY_STMT_CONTAINER;
ext->substmts[6].storage = (uint64_t)(uintptr_t)&struct_cdata->child;
ext->substmts[6].storage_p = (void **)&struct_cdata->child;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[7].stmt = LY_STMT_LEAF;
ext->substmts[7].storage = (uint64_t)(uintptr_t)&struct_cdata->child;
ext->substmts[7].storage_p = (void **)&struct_cdata->child;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[8].stmt = LY_STMT_LEAF_LIST;
ext->substmts[8].storage = (uint64_t)(uintptr_t)&struct_cdata->child;
ext->substmts[8].storage_p = (void **)&struct_cdata->child;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[9].stmt = LY_STMT_LIST;
ext->substmts[9].storage = (uint64_t)(uintptr_t)&struct_cdata->child;
ext->substmts[9].storage_p = (void **)&struct_cdata->child;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[10].stmt = LY_STMT_CHOICE;
ext->substmts[10].storage = (uint64_t)(uintptr_t)&struct_cdata->child;
ext->substmts[10].storage_p = (void **)&struct_cdata->child;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[11].stmt = LY_STMT_ANYDATA;
ext->substmts[11].storage = (uint64_t)(uintptr_t)&struct_cdata->child;
ext->substmts[11].storage_p = (void **)&struct_cdata->child;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[12].stmt = LY_STMT_ANYXML;
ext->substmts[12].storage = (uint64_t)(uintptr_t)&struct_cdata->child;
ext->substmts[12].storage_p = (void **)&struct_cdata->child;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[13].stmt = LY_STMT_USES;
ext->substmts[13].storage = (uint64_t)(uintptr_t)&struct_cdata->child;
ext->substmts[13].storage_p = (void **)&struct_cdata->child;
*lyplg_ext_compile_get_options(cctx) |= LYS_COMPILE_NO_CONFIG | LYS_COMPILE_NO_DISABLED;
rc = lyplg_ext_compile_extension_instance(cctx, extp, ext);
@ -339,53 +339,53 @@ structure_aug_parse(struct lysp_ctx *pctx, struct lysp_ext_instance *ext)
/* parse substatements */
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[0].stmt = LY_STMT_STATUS;
ext->substmts[0].storage = (uint64_t)(uintptr_t)&aug_pdata->flags;
ext->substmts[0].storage_p = (void **)&aug_pdata->flags;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[1].stmt = LY_STMT_DESCRIPTION;
ext->substmts[1].storage = (uint64_t)(uintptr_t)&aug_pdata->dsc;
ext->substmts[1].storage_p = (void **)&aug_pdata->dsc;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[2].stmt = LY_STMT_REFERENCE;
ext->substmts[2].storage = (uint64_t)(uintptr_t)&aug_pdata->ref;
ext->substmts[2].storage_p = (void **)&aug_pdata->ref;
/* data-def-stmt */
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[3].stmt = LY_STMT_CONTAINER;
ext->substmts[3].storage = (uint64_t)(uintptr_t)&aug_pdata->child;
ext->substmts[3].storage_p = (void **)&aug_pdata->child;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[4].stmt = LY_STMT_LEAF;
ext->substmts[4].storage = (uint64_t)(uintptr_t)&aug_pdata->child;
ext->substmts[4].storage_p = (void **)&aug_pdata->child;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[5].stmt = LY_STMT_LEAF_LIST;
ext->substmts[5].storage = (uint64_t)(uintptr_t)&aug_pdata->child;
ext->substmts[5].storage_p = (void **)&aug_pdata->child;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[6].stmt = LY_STMT_LIST;
ext->substmts[6].storage = (uint64_t)(uintptr_t)&aug_pdata->child;
ext->substmts[6].storage_p = (void **)&aug_pdata->child;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[7].stmt = LY_STMT_CHOICE;
ext->substmts[7].storage = (uint64_t)(uintptr_t)&aug_pdata->child;
ext->substmts[7].storage_p = (void **)&aug_pdata->child;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[8].stmt = LY_STMT_ANYDATA;
ext->substmts[8].storage = (uint64_t)(uintptr_t)&aug_pdata->child;
ext->substmts[8].storage_p = (void **)&aug_pdata->child;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[9].stmt = LY_STMT_ANYXML;
ext->substmts[9].storage = (uint64_t)(uintptr_t)&aug_pdata->child;
ext->substmts[9].storage_p = (void **)&aug_pdata->child;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[10].stmt = LY_STMT_USES;
ext->substmts[10].storage = (uint64_t)(uintptr_t)&aug_pdata->child;
ext->substmts[10].storage_p = (void **)&aug_pdata->child;
/* case */
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[11].stmt = LY_STMT_CASE;
ext->substmts[11].storage = (uint64_t)(uintptr_t)&aug_pdata->child;
ext->substmts[11].storage_p = (void **)&aug_pdata->child;
if ((rc = lyplg_ext_parse_extension_instance(pctx, ext))) {
return rc;
@ -394,7 +394,7 @@ structure_aug_parse(struct lysp_ctx *pctx, struct lysp_ext_instance *ext)
/* add fake parsed augment node */
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[12].stmt = LY_STMT_AUGMENT;
ext->substmts[12].storage = (uint64_t)(uintptr_t)&aug_pdata->aug;
ext->substmts[12].storage_p = (void **)&aug_pdata->aug;
aug_pdata->aug = calloc(1, sizeof *aug_pdata->aug);
if (!aug_pdata->aug) {
@ -476,7 +476,7 @@ structure_aug_sprinter_ptree(struct lysp_ext_instance *ext, const struct lyspr_t
assert(ctx);
aug = (struct lysp_node_augment **)(uintptr_t)ext->substmts[12].storage;
aug = (struct lysp_node_augment **)ext->substmts[12].storage_p;
rc = lyplg_ext_sprinter_ptree_add_nodes(ctx, (*aug)->child, structure_sprinter_pnode);
return rc;

View file

@ -58,15 +58,15 @@ yangdata_parse(struct lysp_ctx *pctx, struct lysp_ext_instance *ext)
LY_ARRAY_CREATE_GOTO(lyplg_ext_parse_get_cur_pmod(pctx)->mod->ctx, ext->substmts, 3, ret, emem);
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[0].stmt = LY_STMT_CONTAINER;
ext->substmts[0].storage = (uint64_t)(uintptr_t)&ext->parsed;
ext->substmts[0].storage_p = (void **)&ext->parsed;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[1].stmt = LY_STMT_CHOICE;
ext->substmts[1].storage = (uint64_t)(uintptr_t)&ext->parsed;
ext->substmts[1].storage_p = (void **)&ext->parsed;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[2].stmt = LY_STMT_USES;
ext->substmts[2].storage = (uint64_t)(uintptr_t)&ext->parsed;
ext->substmts[2].storage_p = (void **)&ext->parsed;
if ((ret = lyplg_ext_parse_extension_instance(pctx, ext))) {
return ret;
@ -96,15 +96,15 @@ yangdata_compile(struct lysc_ctx *cctx, const struct lysp_ext_instance *extp, st
LY_ARRAY_CREATE_GOTO(cctx->ctx, ext->substmts, 3, ret, emem);
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[0].stmt = LY_STMT_CONTAINER;
ext->substmts[0].storage = (uint64_t)(uintptr_t)&ext->compiled;
ext->substmts[0].storage_p = (void **)&ext->compiled;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[1].stmt = LY_STMT_CHOICE;
ext->substmts[1].storage = (uint64_t)(uintptr_t)&ext->compiled;
ext->substmts[1].storage_p = (void **)&ext->compiled;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[2].stmt = LY_STMT_USES;
ext->substmts[2].storage = (uint64_t)(uintptr_t)&ext->compiled;
ext->substmts[2].storage_p = (void **)&ext->compiled;
*lyplg_ext_compile_get_options(cctx) |= LYS_COMPILE_NO_CONFIG | LYS_COMPILE_NO_DISABLED;
ret = lyplg_ext_compile_extension_instance(cctx, extp, ext);

View file

@ -352,10 +352,16 @@ lyplg_type_print_simple(const struct ly_ctx *UNUSED(ctx), const struct lyd_value
LIBYANG_API_DEF LY_ERR
lyplg_type_dup_simple(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup)
{
LY_ERR r;
if ((r = lydict_dup(ctx, original->_canonical, &dup->_canonical))) {
/* in case of error NULL the values so that freeing does not fail */
memset(dup, 0, sizeof *dup);
LY_CHECK_RET(lydict_insert(ctx, original->_canonical, 0, &dup->_canonical));
return r;
}
memcpy(dup->fixed_mem, original->fixed_mem, sizeof dup->fixed_mem);
dup->realtype = original->realtype;
return LY_SUCCESS;
}
@ -831,8 +837,9 @@ lyplg_type_lypath_new(const struct ly_ctx *ctx, const char *value, size_t value_
uint32_t prefix_opt = 0;
struct ly_err_item *e;
const char *err_fmt = NULL;
uint16_t oper;
LY_CHECK_ARG_RET(ctx, ctx, value, ctx_node, path, err, LY_EINVAL);
LY_CHECK_ARG_RET(ctx, ctx, value, path, err, LY_EINVAL);
*path = NULL;
*err = NULL;
@ -871,8 +878,8 @@ lyplg_type_lypath_new(const struct ly_ctx *ctx, const char *value, size_t value_
}
/* resolve it on schema tree */
ret = ly_path_compile(ctx, NULL, ctx_node, NULL, exp, (ctx_node->flags & LYS_IS_OUTPUT) ?
LY_PATH_OPER_OUTPUT : LY_PATH_OPER_INPUT, LY_PATH_TARGET_SINGLE, 1, format, prefix_data, path);
oper = (ctx_node && (ctx_node->flags & LYS_IS_OUTPUT)) ? LY_PATH_OPER_OUTPUT : LY_PATH_OPER_INPUT;
ret = ly_path_compile(ctx, NULL, ctx_node, NULL, exp, oper, LY_PATH_TARGET_SINGLE, 1, format, prefix_data, path);
if (ret) {
err_fmt = "Invalid instance-identifier \"%.*s\" value - semantic error%s%s";
goto cleanup;
@ -888,7 +895,7 @@ cleanup:
ly_err_clean((struct ly_ctx *)ctx, e);
}
ly_path_free(ctx, *path);
ly_path_free(*path);
*path = NULL;
}
@ -896,9 +903,9 @@ cleanup:
}
LIBYANG_API_DEF void
lyplg_type_lypath_free(const struct ly_ctx *ctx, struct ly_path *path)
lyplg_type_lypath_free(const struct ly_ctx *UNUSED(ctx), struct ly_path *path)
{
ly_path_free(ctx, path);
ly_path_free(path);
}
LIBYANG_API_DEF LY_ERR
@ -1007,7 +1014,7 @@ lyplg_type_resolve_leafref_get_target_path(const struct lyxp_expr *path, const s
LY_CHECK_GOTO(lyxp_expr_parse(ctx_node->module->ctx, str_path, 0, 1, target_path), cleanup);
cleanup:
ly_path_free(ctx_node->module->ctx, p);
ly_path_free(p);
free(str_path);
return rc;
}

View file

@ -475,8 +475,10 @@ LIBYANG_API_DECL LY_ERR lyplg_type_print_xpath10_value(const struct lyd_value_xp
#define LYPLG_TYPE_STORE_IMPLEMENT 0x02 /**< If a foreign module is needed to be implemented to successfully instantiate
the value, make the module implemented. */
#define LYPLG_TYPE_STORE_IS_UTF8 0x04 /**< The value is guaranteed to be a valid UTF-8 string, if applicable for the type. */
#define LYPLG_TYPE_STORE_ONLY 0x08 /**< The value is stored only. The validation must be done using [validate](@ref lyplg_type_validate_clb) */
/** @} plugintypestoreopts */
#define LYPLG_TYPE_STORE_ONLY 0x08 /**< The value is stored only, type-specific validation is skipped (performed before) */
/**
* @} plugintypestoreopts
*/
/**
* @brief Callback to store the given @p value according to the given @p type.
@ -490,7 +492,9 @@ LIBYANG_API_DECL LY_ERR lyplg_type_print_xpath10_value(const struct lyd_value_xp
* @p value_len is always correct. All store functions have to free a dynamically allocated @p value in all
* cases (even on error).
*
* @param[in] ctx libyang context
* No unnecessary validation tasks should be performed by this callback and left for ::lyplg_type_validate_clb instead.
*
* @param[in] ctx libyang context.
* @param[in] type Type of the value being stored.
* @param[in] value Value to be stored.
* @param[in] value_len Length (number of bytes) of the given @p value.
@ -513,15 +517,14 @@ LIBYANG_API_DECL typedef LY_ERR (*lyplg_type_store_clb)(const struct ly_ctx *ctx
const struct lysc_node *ctx_node, struct lyd_value *storage, struct lys_glob_unres *unres, struct ly_err_item **err);
/**
* @brief Callback to validate the stored value in data.
* @brief Callback to validate the stored value in the accessible data tree.
*
* This callback is optional for types that can only be validated in a data tree. It must be called and succeed
* in case the ::lyplg_type_store_clb callback returned ::LY_EINCOMPLETE for the value to be valid. However, this
* callback can be called even in other cases (such as separate/repeated validation).
* This callback is optional and may not be defined for types that do not require the accessible data tree for
* validation (::lyplg_type_store_cb fully stores and validates the value).
*
* @param[in] ctx libyang context
* @param[in] ctx libyang context.
* @param[in] type Original type of the value (not necessarily the stored one) being validated.
* @param[in] ctx_node The value data context node for validation.
* @param[in] ctx_node Value data context node for validation.
* @param[in] tree External data tree (e.g. when validating RPC/Notification) with possibly referenced data.
* @param[in,out] storage Storage of the value successfully filled by ::lyplg_type_store_clb. May be modified.
* @param[out] err Optionally provided error information in case of failure. If not provided to the caller, a generic
@ -619,7 +622,7 @@ struct lyplg_type {
const char *id; /**< Plugin identification (mainly for distinguish incompatible versions when
used by external tools) */
lyplg_type_store_clb store; /**< store and canonize the value in the type-specific way */
lyplg_type_validate_clb validate; /**< optional, validate the value in the type-specific way in data */
lyplg_type_validate_clb validate; /**< optional, validate the value in the accessible data tree */
lyplg_type_compare_clb compare; /**< comparison callback to compare 2 values of the same type */
lyplg_type_sort_clb sort; /**< comparison callback for sorting values */
lyplg_type_print_clb print; /**< printer callback to get string representing the value */
@ -947,18 +950,6 @@ LIBYANG_API_DECL LY_ERR lyplg_type_store_instanceid(const struct ly_ctx *ctx, co
LIBYANG_API_DECL LY_ERR lyplg_type_validate_instanceid(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);
/**
* @brief Implementation of ::lyplg_type_compare_clb for the built-in instance-identifier type.
*/
LIBYANG_API_DECL LY_ERR lyplg_type_compare_instanceid(const struct ly_ctx *ctx, const struct lyd_value *val1,
const struct lyd_value *val2);
/**
* @brief Implementation of ::lyplg_type_sort_clb for the built-in instance-identifier type.
*/
LIBYANG_API_DEF int lyplg_type_sort_instanceid(const struct ly_ctx *ctx, const struct lyd_value *val1,
const struct lyd_value *val2);
/**
* @brief Implementation of ::lyplg_type_print_clb for the built-in instance-identifier type.
*/

View file

@ -42,8 +42,6 @@
*/
static const char b64_etable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static LY_ERR lyplg_type_validate_binary(const struct ly_ctx *UNUSED(ctx), const struct lysc_type *type, const struct lyd_node *UNUSED(ctx_node), const struct lyd_node *UNUSED(tree), struct lyd_value *storage, struct ly_err_item **err);
/**
* @brief Encode binary value into a base64 string value.
*
@ -260,6 +258,7 @@ lyplg_type_store_binary(const struct ly_ctx *ctx, const struct lysc_type *type,
struct ly_err_item **err)
{
LY_ERR ret = LY_SUCCESS;
struct lysc_type_bin *type_bin = (struct lysc_type_bin *)type;
struct lyd_value_binary *val;
/* init storage */
@ -312,16 +311,21 @@ lyplg_type_store_binary(const struct ly_ctx *ctx, const struct lysc_type *type,
ret = lydict_insert_zc(ctx, (char *)value, &storage->_canonical);
options &= ~LYPLG_TYPE_STORE_DYNAMIC;
LY_CHECK_GOTO(ret, cleanup);
/* value may have been freed */
value = storage->_canonical;
} else {
ret = lydict_insert(ctx, value_len ? value : "", value_len, &storage->_canonical);
LY_CHECK_GOTO(ret, cleanup);
}
if (!(options & LYPLG_TYPE_STORE_ONLY)) {
/* validate value */
ret = lyplg_type_validate_binary(ctx, type, NULL, NULL, storage, err);
/* validate length restriction of the binary value */
if (type_bin->length) {
ret = lyplg_type_validate_range(LY_TYPE_BINARY, type_bin->length, val->size, value, value_len, err);
LY_CHECK_GOTO(ret, cleanup);
}
}
cleanup:
if (options & LYPLG_TYPE_STORE_DYNAMIC) {
@ -334,33 +338,6 @@ cleanup:
return ret;
}
/**
* @brief Implementation of ::lyplg_type_validate_clb for the binary type.
*/
static LY_ERR
lyplg_type_validate_binary(const struct ly_ctx *ctx, const struct lysc_type *type, const struct lyd_node *UNUSED(ctx_node),
const struct lyd_node *UNUSED(tree), struct lyd_value *storage, struct ly_err_item **err)
{
struct lysc_type_bin *type_bin = (struct lysc_type_bin *)type;
struct lyd_value_binary *val;
const void *value;
size_t value_len;
LY_CHECK_ARG_RET(NULL, type, storage, err, LY_EINVAL);
val = LYPLG_TYPE_VAL_IS_DYN(val) ? (struct lyd_value_binary *)(storage->dyn_mem) : (struct lyd_value_binary *)(storage->fixed_mem);
value = lyd_value_get_canonical(ctx, storage);
value_len = strlen(value);
*err = NULL;
/* length restriction of the binary value */
if (type_bin->length) {
LY_CHECK_RET(lyplg_type_validate_range(LY_TYPE_BINARY, type_bin->length, val->size, value, value_len, err));
}
return LY_SUCCESS;
}
LIBYANG_API_DEF LY_ERR
lyplg_type_compare_binary(const struct ly_ctx *UNUSED(ctx), const struct lyd_value *val1, const struct lyd_value *val2)
{
@ -496,7 +473,7 @@ const struct lyplg_type_record plugins_binary[] = {
.plugin.id = "libyang 2 - binary, version 1",
.plugin.store = lyplg_type_store_binary,
.plugin.validate = lyplg_type_validate_binary,
.plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_binary,
.plugin.sort = lyplg_type_sort_binary,
.plugin.print = lyplg_type_print_binary,

View file

@ -53,7 +53,6 @@ lyplg_type_store_date_and_time(const struct ly_ctx *ctx, const struct lysc_type
struct ly_err_item **err)
{
LY_ERR ret = LY_SUCCESS;
struct lysc_type_str *type_dat = (struct lysc_type_str *)type;
struct lyd_value_date_and_time *val;
uint32_t i;
char c;
@ -102,20 +101,9 @@ lyplg_type_store_date_and_time(const struct ly_ctx *ctx, const struct lysc_type
ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
LY_CHECK_GOTO(ret, cleanup);
/* length restriction, there can be only ASCII chars */
if (type_dat->length) {
ret = lyplg_type_validate_range(LY_TYPE_STRING, type_dat->length, value_len, value, value_len, err);
LY_CHECK_GOTO(ret, cleanup);
}
/* date-and-time pattern */
ret = lyplg_type_validate_patterns(type_dat->patterns, value, value_len, err);
LY_CHECK_GOTO(ret, cleanup);
/* convert to UNIX time and fractions of second */
ret = ly_time_str2time(value, &val->time, &val->fractions_s);
if (ret) {
ret = ly_err_new(err, ret, 0, NULL, NULL, "%s", ly_last_logmsg());
/* convert to UNIX time and fractions of second, function must check for all the possible errors */
if (ly_time_str2time(value, &val->time, &val->fractions_s)) {
ret = ly_err_new(err, LY_EVALID, 0, NULL, NULL, "%s", ly_last_logmsg());
goto cleanup;
}

View file

@ -33,8 +33,6 @@
* | 8 | yes | `int64_t *` | little-endian value represented without floating point |
*/
static LY_ERR lyplg_type_validate_decimal64(const struct ly_ctx *UNUSED(ctx), const struct lysc_type *type, const struct lyd_node *UNUSED(ctx_node), const struct lyd_node *UNUSED(tree), struct lyd_value *storage, struct ly_err_item **err);
/**
* @brief Convert decimal64 number to canonical string.
*
@ -90,7 +88,7 @@ lyplg_type_store_decimal64(const struct ly_ctx *ctx, const struct lysc_type *typ
{
struct lysc_type_dec *type_dec = (struct lysc_type_dec *)type;
LY_ERR ret = LY_SUCCESS;
int64_t num;
int64_t num = 0;
char *canon;
/* init storage */
@ -144,9 +142,13 @@ lyplg_type_store_decimal64(const struct ly_ctx *ctx, const struct lysc_type *typ
if (!(options & LYPLG_TYPE_STORE_ONLY)) {
/* validate value */
ret = lyplg_type_validate_decimal64(ctx, type, NULL, NULL, storage, err);
if (type_dec->range) {
/* check range of the number */
ret = lyplg_type_validate_range(type->basetype, type_dec->range, num, storage->_canonical,
strlen(storage->_canonical), err);
LY_CHECK_GOTO(ret, cleanup);
}
}
cleanup:
if (options & LYPLG_TYPE_STORE_DYNAMIC) {
@ -159,31 +161,6 @@ cleanup:
return ret;
}
/**
* @brief Implementation of ::lyplg_type_validate_clb for the built-in decimal64 type.
*/
static LY_ERR
lyplg_type_validate_decimal64(const struct ly_ctx *UNUSED(ctx), const struct lysc_type *type, const struct lyd_node *UNUSED(ctx_node),
const struct lyd_node *UNUSED(tree), struct lyd_value *storage, struct ly_err_item **err)
{
LY_ERR ret;
struct lysc_type_dec *type_dec = (struct lysc_type_dec *)type;
int64_t num;
LY_CHECK_ARG_RET(NULL, type, storage, err, LY_EINVAL);
*err = NULL;
num = storage->dec64;
if (type_dec->range) {
/* check range of the number */
ret = lyplg_type_validate_range(type->basetype, type_dec->range, num, storage->_canonical,
strlen(storage->_canonical), err);
LY_CHECK_RET(ret);
}
return LY_SUCCESS;
}
LIBYANG_API_DEF LY_ERR
lyplg_type_compare_decimal64(const struct ly_ctx *UNUSED(ctx), const struct lyd_value *val1,
const struct lyd_value *val2)
@ -262,7 +239,7 @@ const struct lyplg_type_record plugins_decimal64[] = {
.plugin.id = "libyang 2 - decimal64, version 1",
.plugin.store = lyplg_type_store_decimal64,
.plugin.validate = lyplg_type_validate_decimal64,
.plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_decimal64,
.plugin.sort = lyplg_type_sort_decimal64,
.plugin.print = lyplg_type_print_decimal64,

View file

@ -55,17 +55,6 @@ lyplg_type_store_hex_string(const struct ly_ctx *ctx, const struct lysc_type *ty
ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
LY_CHECK_GOTO(ret, cleanup);
/* length restriction of the string */
if (type_str->length) {
/* value_len is in bytes, but we need number of characters here */
ret = lyplg_type_validate_range(LY_TYPE_STRING, type_str->length, ly_utf8len(value, value_len), value, value_len, err);
LY_CHECK_GOTO(ret, cleanup);
}
/* pattern restrictions */
ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err);
LY_CHECK_GOTO(ret, cleanup);
/* make a copy, it is needed for canonization */
if ((format != LY_VALUE_CANON) && !(options & LYPLG_TYPE_STORE_DYNAMIC)) {
value = strndup(value, value_len);
@ -83,12 +72,28 @@ lyplg_type_store_hex_string(const struct ly_ctx *ctx, const struct lysc_type *ty
ret = lydict_insert_zc(ctx, (char *)value, &storage->_canonical);
options &= ~LYPLG_TYPE_STORE_DYNAMIC;
LY_CHECK_GOTO(ret, cleanup);
/* value may have been freed */
value = storage->_canonical;
} else {
/* store directly */
ret = lydict_insert(ctx, value_len ? value : "", value_len, &storage->_canonical);
LY_CHECK_GOTO(ret, cleanup);
}
if (!(options & LYPLG_TYPE_STORE_ONLY)) {
/* validate length restriction of the string */
if (type_str->length) {
/* value_len is in bytes, but we need number of characters here */
ret = lyplg_type_validate_range(LY_TYPE_STRING, type_str->length, ly_utf8len(value, value_len), value, value_len, err);
LY_CHECK_GOTO(ret, cleanup);
}
/* validate pattern restrictions */
ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err);
LY_CHECK_GOTO(ret, cleanup);
}
cleanup:
if (options & LYPLG_TYPE_STORE_DYNAMIC) {
free((void *)value);

View file

@ -252,23 +252,14 @@ lyplg_type_validate_instanceid(const struct ly_ctx *ctx, const struct lysc_type
return LY_SUCCESS;
}
LIBYANG_API_DEF LY_ERR
lyplg_type_compare_instanceid(const struct ly_ctx *ctx, const struct lyd_value *val1, const struct lyd_value *val2)
{
return lyplg_type_compare_simple(ctx, val1, val2);
}
LIBYANG_API_DEF int
lyplg_type_sort_instanceid(const struct ly_ctx *ctx, const struct lyd_value *val1, const struct lyd_value *val2)
{
return lyplg_type_sort_simple(ctx, val1, val2);
}
LIBYANG_API_DEF const void *
lyplg_type_print_instanceid(const struct ly_ctx *UNUSED(ctx), const struct lyd_value *value, LY_VALUE_FORMAT format,
lyplg_type_print_instanceid(const struct ly_ctx *ctx, const struct lyd_value *value, LY_VALUE_FORMAT format,
void *prefix_data, ly_bool *dynamic, size_t *value_len)
{
char *ret;
char *ret = NULL;
struct ly_path *p = NULL;
const struct ly_path *target;
struct ly_err_item *err;
if ((format == LY_VALUE_CANON) || (format == LY_VALUE_JSON) || (format == LY_VALUE_LYB)) {
if (dynamic) {
@ -280,14 +271,34 @@ lyplg_type_print_instanceid(const struct ly_ctx *UNUSED(ctx), const struct lyd_v
return value->_canonical;
}
/* print the value in the specific format */
if (instanceid_path2str(value->target, format, prefix_data, &ret)) {
return NULL;
if (!value->target) {
/* schema default value, compile it first */
if (lyplg_type_lypath_new(ctx, value->_canonical, strlen(value->_canonical), 0, LY_VALUE_JSON, NULL, NULL,
NULL, &p, &err)) {
if (err) {
ly_err_print(ctx, err);
ly_err_free(err);
}
goto cleanup;
}
target = p;
} else {
target = value->target;
}
/* print the value in the specific format */
if (instanceid_path2str(target, format, prefix_data, &ret)) {
goto cleanup;
}
*dynamic = 1;
if (value_len) {
*value_len = strlen(ret);
}
cleanup:
ly_path_free(p);
return ret;
}
@ -295,6 +306,7 @@ LIBYANG_API_DEF LY_ERR
lyplg_type_dup_instanceid(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup)
{
LY_ERR ret;
struct ly_err_item *err;
memset(dup, 0, sizeof *dup);
@ -302,9 +314,21 @@ lyplg_type_dup_instanceid(const struct ly_ctx *ctx, const struct lyd_value *orig
ret = lydict_insert(ctx, original->_canonical, 0, &dup->_canonical);
LY_CHECK_GOTO(ret, error);
if (!original->target) {
/* schema default value, needs to be compiled */
if (lyplg_type_lypath_new(ctx, original->_canonical, strlen(original->_canonical), 0, LY_VALUE_JSON, NULL, NULL,
NULL, &dup->target, &err)) {
if (err) {
ly_err_print(ctx, err);
ly_err_free(err);
}
goto error;
}
} else {
/* copy path */
ret = ly_path_dup(ctx, original->target, &dup->target);
LY_CHECK_GOTO(ret, error);
}
dup->realtype = original->realtype;
return LY_SUCCESS;
@ -319,7 +343,7 @@ lyplg_type_free_instanceid(const struct ly_ctx *ctx, struct lyd_value *value)
{
lydict_remove(ctx, value->_canonical);
value->_canonical = NULL;
ly_path_free(ctx, value->target);
ly_path_free(value->target);
}
/**
@ -338,8 +362,8 @@ const struct lyplg_type_record plugins_instanceid[] = {
.plugin.id = "libyang 2 - instance-identifier, version 1",
.plugin.store = lyplg_type_store_instanceid,
.plugin.validate = lyplg_type_validate_instanceid,
.plugin.compare = lyplg_type_compare_instanceid,
.plugin.sort = lyplg_type_sort_instanceid,
.plugin.compare = lyplg_type_compare_simple,
.plugin.sort = lyplg_type_sort_simple,
.plugin.print = lyplg_type_print_instanceid,
.plugin.duplicate = lyplg_type_dup_instanceid,
.plugin.free = lyplg_type_free_instanceid,

View file

@ -36,9 +36,6 @@
* | 1/2/4/8 | yes | pointer to the specific integer type | little-endian integer value |
*/
static LY_ERR lyplg_type_validate_int(const struct ly_ctx *UNUSED(ctx), const struct lysc_type *type, const struct lyd_node *UNUSED(ctx_node), const struct lyd_node *UNUSED(tree), struct lyd_value *storage, struct ly_err_item **err);
static LY_ERR lyplg_type_validate_uint(const struct ly_ctx *UNUSED(ctx), const struct lysc_type *type, const struct lyd_node *UNUSED(ctx_node), const struct lyd_node *UNUSED(tree), struct lyd_value *storage, struct ly_err_item **err);
/**
* @brief LYB value size of each integer type.
*/
@ -53,6 +50,7 @@ lyplg_type_store_int(const struct ly_ctx *ctx, const struct lysc_type *type, con
const struct lysc_node *UNUSED(ctx_node), struct lyd_value *storage, struct lys_glob_unres *UNUSED(unres),
struct ly_err_item **err)
{
struct lysc_type_num *type_num = (struct lysc_type_num *)type;
LY_ERR ret = LY_SUCCESS;
int64_t num = 0;
int base = 1;
@ -157,10 +155,13 @@ lyplg_type_store_int(const struct ly_ctx *ctx, const struct lysc_type *type, con
}
if (!(options & LYPLG_TYPE_STORE_ONLY)) {
/* validate value */
ret = lyplg_type_validate_int(ctx, type, NULL, NULL, storage, err);
/* validate range of the number */
if (type_num->range) {
ret = lyplg_type_validate_range(type->basetype, type_num->range, num, storage->_canonical,
strlen(storage->_canonical), err);
LY_CHECK_GOTO(ret, cleanup);
}
}
cleanup:
if (options & LYPLG_TYPE_STORE_DYNAMIC) {
@ -173,48 +174,6 @@ cleanup:
return ret;
}
/**
* @brief Implementation of ::lyplg_type_validate_clb for the signed interger types.
*/
static LY_ERR
lyplg_type_validate_int(const struct ly_ctx *UNUSED(ctx), const struct lysc_type *type, const struct lyd_node *UNUSED(ctx_node),
const struct lyd_node *UNUSED(tree), struct lyd_value *storage, struct ly_err_item **err)
{
LY_ERR ret;
struct lysc_type_num *type_num = (struct lysc_type_num *)type;
int64_t num;
LY_CHECK_ARG_RET(NULL, type, storage, err, LY_EINVAL);
*err = NULL;
/* set the value (matters for big-endian) and get the correct int64 number */
switch (type->basetype) {
case LY_TYPE_INT8:
num = storage->int8;
break;
case LY_TYPE_INT16:
num = storage->int16;
break;
case LY_TYPE_INT32:
num = storage->int32;
break;
case LY_TYPE_INT64:
num = storage->int64;
break;
default:
return LY_EINVAL;
}
/* validate range of the number */
if (type_num->range) {
ret = lyplg_type_validate_range(type->basetype, type_num->range, num, storage->_canonical,
strlen(storage->_canonical), err);
LY_CHECK_RET(ret);
}
return LY_SUCCESS;
}
LIBYANG_API_DEF LY_ERR
lyplg_type_compare_int(const struct ly_ctx *UNUSED(ctx), const struct lyd_value *val1, const struct lyd_value *val2)
{
@ -357,6 +316,7 @@ lyplg_type_store_uint(const struct ly_ctx *ctx, const struct lysc_type *type, co
const struct lysc_node *UNUSED(ctx_node), struct lyd_value *storage, struct lys_glob_unres *UNUSED(unres),
struct ly_err_item **err)
{
struct lysc_type_num *type_num = (struct lysc_type_num *)type;
LY_ERR ret = LY_SUCCESS;
uint64_t num = 0;
int base = 0;
@ -441,10 +401,13 @@ lyplg_type_store_uint(const struct ly_ctx *ctx, const struct lysc_type *type, co
}
if (!(options & LYPLG_TYPE_STORE_ONLY)) {
/* validate value */
ret = lyplg_type_validate_uint(ctx, type, NULL, NULL, storage, err);
/* validate range of the number */
if (type_num->range) {
ret = lyplg_type_validate_range(type->basetype, type_num->range, num, storage->_canonical,
strlen(storage->_canonical), err);
LY_CHECK_GOTO(ret, cleanup);
}
}
cleanup:
if (options & LYPLG_TYPE_STORE_DYNAMIC) {
@ -457,48 +420,6 @@ cleanup:
return ret;
}
/**
* @brief Implementation of ::lyplg_type_validate_clb for the unsigned interger types.
*/
static LY_ERR
lyplg_type_validate_uint(const struct ly_ctx *UNUSED(ctx), const struct lysc_type *type, const struct lyd_node *UNUSED(ctx_node),
const struct lyd_node *UNUSED(tree), struct lyd_value *storage, struct ly_err_item **err)
{
LY_ERR ret;
struct lysc_type_num *type_num = (struct lysc_type_num *)type;
uint64_t num;
LY_CHECK_ARG_RET(NULL, type, storage, err, LY_EINVAL);
*err = NULL;
/* set the value (matters for big-endian) and get the correct int64 number */
switch (type->basetype) {
case LY_TYPE_UINT8:
num = storage->uint8;
break;
case LY_TYPE_UINT16:
num = storage->uint16;
break;
case LY_TYPE_UINT32:
num = storage->uint32;
break;
case LY_TYPE_UINT64:
num = storage->uint64;
break;
default:
return LY_EINVAL;
}
/* validate range of the number */
if (type_num->range) {
ret = lyplg_type_validate_range(type->basetype, type_num->range, num, storage->_canonical,
strlen(storage->_canonical), err);
LY_CHECK_RET(ret);
}
return LY_SUCCESS;
}
LIBYANG_API_DEF LY_ERR
lyplg_type_compare_uint(const struct ly_ctx *UNUSED(ctx), const struct lyd_value *val1, const struct lyd_value *val2)
{
@ -646,7 +567,7 @@ const struct lyplg_type_record plugins_integer[] = {
.plugin.id = "libyang 2 - integers, version 1",
.plugin.store = lyplg_type_store_uint,
.plugin.validate = lyplg_type_validate_uint,
.plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_uint,
.plugin.sort = lyplg_type_sort_uint,
.plugin.print = lyplg_type_print_uint,
@ -660,7 +581,7 @@ const struct lyplg_type_record plugins_integer[] = {
.plugin.id = "libyang 2 - integers, version 1",
.plugin.store = lyplg_type_store_uint,
.plugin.validate = lyplg_type_validate_uint,
.plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_uint,
.plugin.sort = lyplg_type_sort_uint,
.plugin.print = lyplg_type_print_uint,
@ -674,7 +595,7 @@ const struct lyplg_type_record plugins_integer[] = {
.plugin.id = "libyang 2 - integers, version 1",
.plugin.store = lyplg_type_store_uint,
.plugin.validate = lyplg_type_validate_uint,
.plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_uint,
.plugin.sort = lyplg_type_sort_uint,
.plugin.print = lyplg_type_print_uint,
@ -688,7 +609,7 @@ const struct lyplg_type_record plugins_integer[] = {
.plugin.id = "libyang 2 - integers, version 1",
.plugin.store = lyplg_type_store_uint,
.plugin.validate = lyplg_type_validate_uint,
.plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_uint,
.plugin.sort = lyplg_type_sort_uint,
.plugin.print = lyplg_type_print_uint,
@ -702,7 +623,7 @@ const struct lyplg_type_record plugins_integer[] = {
.plugin.id = "libyang 2 - integers, version 1",
.plugin.store = lyplg_type_store_int,
.plugin.validate = lyplg_type_validate_int,
.plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_int,
.plugin.sort = lyplg_type_sort_int,
.plugin.print = lyplg_type_print_int,
@ -716,7 +637,7 @@ const struct lyplg_type_record plugins_integer[] = {
.plugin.id = "libyang 2 - integers, version 1",
.plugin.store = lyplg_type_store_int,
.plugin.validate = lyplg_type_validate_int,
.plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_int,
.plugin.sort = lyplg_type_sort_int,
.plugin.print = lyplg_type_print_int,
@ -730,7 +651,7 @@ const struct lyplg_type_record plugins_integer[] = {
.plugin.id = "libyang 2 - integers, version 1",
.plugin.store = lyplg_type_store_int,
.plugin.validate = lyplg_type_validate_int,
.plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_int,
.plugin.sort = lyplg_type_sort_int,
.plugin.print = lyplg_type_print_int,
@ -744,7 +665,7 @@ const struct lyplg_type_record plugins_integer[] = {
.plugin.id = "libyang 2 - integers, version 1",
.plugin.store = lyplg_type_store_int,
.plugin.validate = lyplg_type_validate_int,
.plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_int,
.plugin.sort = lyplg_type_sort_int,
.plugin.print = lyplg_type_print_int,

View file

@ -171,6 +171,7 @@ lyplg_type_store_ipv4_address(const struct ly_ctx *ctx, const struct lysc_type *
ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
LY_CHECK_GOTO(ret, cleanup);
if (!(options & LYPLG_TYPE_STORE_ONLY)) {
/* length restriction of the string */
if (type_str->length) {
/* value_len is in bytes, but we need number of characters here */
@ -181,6 +182,7 @@ lyplg_type_store_ipv4_address(const struct ly_ctx *ctx, const struct lysc_type *
/* pattern restrictions */
ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err);
LY_CHECK_GOTO(ret, cleanup);
}
/* get the network-byte order address */
ret = ipv4address_str2ip(value, value_len, options, ctx, &val->addr, &val->zone, err);

View file

@ -57,7 +57,6 @@ lyplg_type_store_ipv4_address_no_zone(const struct ly_ctx *ctx, const struct lys
struct ly_err_item **err)
{
LY_ERR ret = LY_SUCCESS;
struct lysc_type_str *type_str = (struct lysc_type_str *)type;
struct lyd_value_ipv4_address_no_zone *val;
/* init storage */
@ -85,17 +84,6 @@ lyplg_type_store_ipv4_address_no_zone(const struct ly_ctx *ctx, const struct lys
ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
LY_CHECK_GOTO(ret, cleanup);
/* length restriction of the string */
if (type_str->length) {
/* value_len is in bytes, but we need number of characters here */
ret = lyplg_type_validate_range(LY_TYPE_STRING, type_str->length, ly_utf8len(value, value_len), value, value_len, err);
LY_CHECK_GOTO(ret, cleanup);
}
/* pattern restrictions */
ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err);
LY_CHECK_GOTO(ret, cleanup);
/* we always need a dynamic value */
if (!(options & LYPLG_TYPE_STORE_DYNAMIC)) {
value = strndup(value, value_len);
@ -104,7 +92,7 @@ lyplg_type_store_ipv4_address_no_zone(const struct ly_ctx *ctx, const struct lys
options |= LYPLG_TYPE_STORE_DYNAMIC;
}
/* get the network-byte order address */
/* get the network-byte order address, validates the value */
if (!inet_pton(AF_INET, value, &val->addr)) {
ret = ly_err_new(err, LY_EVALID, LYVE_DATA, NULL, NULL, "Failed to convert IPv4 address \"%s\".", (char *)value);
goto cleanup;

View file

@ -156,6 +156,7 @@ lyplg_type_store_ipv4_prefix(const struct ly_ctx *ctx, const struct lysc_type *t
ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
LY_CHECK_GOTO(ret, cleanup);
if (!(options & LYPLG_TYPE_STORE_ONLY)) {
/* length restriction of the string */
if (type_str->length) {
/* value_len is in bytes, but we need number of characters here */
@ -166,6 +167,7 @@ lyplg_type_store_ipv4_prefix(const struct ly_ctx *ctx, const struct lysc_type *t
/* pattern restrictions */
ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err);
LY_CHECK_GOTO(ret, cleanup);
}
/* get the mask in network-byte order */
ret = ipv4prefix_str2ip(value, value_len, &val->addr, &val->prefix, err);

View file

@ -172,6 +172,7 @@ lyplg_type_store_ipv6_address(const struct ly_ctx *ctx, const struct lysc_type *
ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
LY_CHECK_GOTO(ret, cleanup);
if (!(options & LYPLG_TYPE_STORE_ONLY)) {
/* length restriction of the string */
if (type_str->length) {
/* value_len is in bytes, but we need number of characters here */
@ -182,6 +183,7 @@ lyplg_type_store_ipv6_address(const struct ly_ctx *ctx, const struct lysc_type *
/* pattern restrictions */
ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err);
LY_CHECK_GOTO(ret, cleanup);
}
/* get the network-byte order address */
ret = ipv6address_str2ip(value, value_len, options, ctx, &val->addr, &val->zone, err);

View file

@ -96,7 +96,6 @@ lyplg_type_store_ipv6_address_no_zone(const struct ly_ctx *ctx, const struct lys
struct ly_err_item **err)
{
LY_ERR ret = LY_SUCCESS;
struct lysc_type_str *type_str = (struct lysc_type_str *)type;
struct lyd_value_ipv6_address_no_zone *val;
/* init storage */
@ -136,18 +135,7 @@ lyplg_type_store_ipv6_address_no_zone(const struct ly_ctx *ctx, const struct lys
ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
LY_CHECK_GOTO(ret, cleanup);
/* length restriction of the string */
if (type_str->length) {
/* value_len is in bytes, but we need number of characters here */
ret = lyplg_type_validate_range(LY_TYPE_STRING, type_str->length, ly_utf8len(value, value_len), value, value_len, err);
LY_CHECK_GOTO(ret, cleanup);
}
/* pattern restrictions */
ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err);
LY_CHECK_GOTO(ret, cleanup);
/* get the network-byte order address */
/* get the network-byte order address, validates the value */
ret = ipv6addressnozone_str2ip(value, value_len, options, &val->addr, err);
LY_CHECK_GOTO(ret, cleanup);

View file

@ -170,6 +170,7 @@ lyplg_type_store_ipv6_prefix(const struct ly_ctx *ctx, const struct lysc_type *t
ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
LY_CHECK_GOTO(ret, cleanup);
if (!(options & LYPLG_TYPE_STORE_ONLY)) {
/* length restriction of the string */
if (type_str->length) {
/* value_len is in bytes, but we need number of characters here */
@ -180,6 +181,7 @@ lyplg_type_store_ipv6_prefix(const struct ly_ctx *ctx, const struct lysc_type *t
/* pattern restrictions */
ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err);
LY_CHECK_GOTO(ret, cleanup);
}
/* get the mask in network-byte order */
ret = ipv6prefix_str2ip(value, value_len, &val->addr, &val->prefix, err);

View file

@ -41,19 +41,19 @@ lyplg_type_store_leafref(const struct ly_ctx *ctx, const struct lysc_type *type,
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;
LY_ERR rc = LY_SUCCESS;
struct lysc_type_leafref *type_lr = (struct lysc_type_leafref *)type;
assert(type_lr->realtype);
/* store the value as the real type of the leafref target */
ret = type_lr->realtype->plugin->store(ctx, type_lr->realtype, value, value_len, options, format, prefix_data,
rc = type_lr->realtype->plugin->store(ctx, type_lr->realtype, value, value_len, options, format, prefix_data,
hints, ctx_node, storage, unres, err);
if (ret == LY_EINCOMPLETE) {
if (rc == LY_EINCOMPLETE) {
/* it is irrelevant whether the target type needs some resolving */
ret = LY_SUCCESS;
rc = LY_SUCCESS;
}
LY_CHECK_RET(ret);
LY_CHECK_RET(rc);
if (type_lr->require_instance) {
/* needs to be resolved */
@ -67,7 +67,7 @@ LIBYANG_API_DEF LY_ERR
lyplg_type_validate_leafref(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 ret;
LY_ERR rc = LY_SUCCESS;
struct lysc_type_leafref *type_lr = (struct lysc_type_leafref *)type;
char *errmsg = NULL, *path;
struct ly_set *targets = NULL;
@ -80,24 +80,25 @@ lyplg_type_validate_leafref(const struct ly_ctx *ctx, const struct lysc_type *ty
return LY_SUCCESS;
}
ret = lyplg_type_resolve_leafref(type_lr, ctx_node, storage, tree, (ly_ctx_get_options(ctx) & LY_CTX_LEAFREF_LINKING) ? &targets : NULL, &errmsg);
if (ret != LY_SUCCESS) {
rc = lyplg_type_resolve_leafref(type_lr, ctx_node, storage, tree,
(ly_ctx_get_options(ctx) & LY_CTX_LEAFREF_LINKING) ? &targets : NULL, &errmsg);
if (rc) {
path = lyd_path(ctx_node, LYD_PATH_STD, NULL, 0);
ret = ly_err_new(err, LY_EVALID, LYVE_DATA, path, strdup("instance-required"), "%s", errmsg);
rc = ly_err_new(err, LY_EVALID, LYVE_DATA, path, strdup("instance-required"), "%s", errmsg);
free(errmsg);
goto cleanup;
}
if (ly_ctx_get_options(ctx) & LY_CTX_LEAFREF_LINKING) {
for (i = 0; i < targets->count; ++i) {
ret = lyd_link_leafref_node((struct lyd_node_term *)targets->dnodes[i], (struct lyd_node_term *)ctx_node);
LY_CHECK_GOTO(ret, cleanup);
rc = lyd_link_leafref_node((struct lyd_node_term *)targets->dnodes[i], (struct lyd_node_term *)ctx_node);
LY_CHECK_GOTO(rc, cleanup);
}
}
cleanup:
ly_set_free(targets, NULL);
return ret;
return rc;
}
LIBYANG_API_DEF LY_ERR

View file

@ -312,8 +312,8 @@ const struct lyplg_type_record plugins_node_instanceid[] = {
.plugin.id = "libyang 2 - node-instance-identifier, version 1",
.plugin.store = lyplg_type_store_node_instanceid,
.plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_instanceid,
.plugin.sort = lyplg_type_sort_instanceid,
.plugin.compare = lyplg_type_compare_simple,
.plugin.sort = lyplg_type_sort_simple,
.plugin.print = lyplg_type_print_node_instanceid,
.plugin.duplicate = lyplg_type_dup_instanceid,
.plugin.free = lyplg_type_free_instanceid,
@ -327,8 +327,8 @@ const struct lyplg_type_record plugins_node_instanceid[] = {
.plugin.id = "libyang 2 - node-instance-identifier, version 1",
.plugin.store = lyplg_type_store_node_instanceid,
.plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_instanceid,
.plugin.sort = lyplg_type_sort_instanceid,
.plugin.compare = lyplg_type_compare_simple,
.plugin.sort = lyplg_type_sort_simple,
.plugin.print = lyplg_type_print_node_instanceid,
.plugin.duplicate = lyplg_type_dup_instanceid,
.plugin.free = lyplg_type_free_instanceid,

View file

@ -34,8 +34,6 @@
* | string length | yes | `char *` | string itself |
*/
static LY_ERR lyplg_type_validate_string(const struct ly_ctx *UNUSED(ctx), const struct lysc_type *type, const struct lyd_node *UNUSED(ctx_node), const struct lyd_node *UNUSED(tree), struct lyd_value *storage, struct ly_err_item **err);
/**
* @brief Check string value for invalid characters.
*
@ -65,6 +63,7 @@ lyplg_type_store_string(const struct ly_ctx *ctx, const struct lysc_type *type,
const struct lysc_node *UNUSED(ctx_node), struct lyd_value *storage, struct lys_glob_unres *UNUSED(unres),
struct ly_err_item **err)
{
struct lysc_type_str *type_str = (struct lysc_type_str *)type;
LY_ERR ret = LY_SUCCESS;
/* init storage */
@ -86,14 +85,24 @@ lyplg_type_store_string(const struct ly_ctx *ctx, const struct lysc_type *type,
ret = lydict_insert_zc(ctx, (char *)value, &storage->_canonical);
options &= ~LYPLG_TYPE_STORE_DYNAMIC;
LY_CHECK_GOTO(ret, cleanup);
/* value may have been freed */
value = storage->_canonical;
} else {
ret = lydict_insert(ctx, value_len ? value : "", value_len, &storage->_canonical);
LY_CHECK_GOTO(ret, cleanup);
}
if (!(options & LYPLG_TYPE_STORE_ONLY)) {
/* validate value */
ret = lyplg_type_validate_string(ctx, type, NULL, NULL, storage, err);
/* length restriction of the string */
if (type_str->length) {
/* value_len is in bytes, but we need number of characters here */
ret = lyplg_type_validate_range(LY_TYPE_STRING, type_str->length, ly_utf8len(value, value_len), value, value_len, err);
LY_CHECK_GOTO(ret, cleanup);
}
/* pattern restrictions */
ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err);
LY_CHECK_GOTO(ret, cleanup);
}
@ -108,37 +117,6 @@ cleanup:
return ret;
}
/**
* @brief Implementation of ::lyplg_type_validate_clb for the string type.
*/
static LY_ERR
lyplg_type_validate_string(const struct ly_ctx *ctx, const struct lysc_type *type, const struct lyd_node *UNUSED(ctx_node),
const struct lyd_node *UNUSED(tree), struct lyd_value *storage, struct ly_err_item **err)
{
LY_ERR ret;
struct lysc_type_str *type_str = (struct lysc_type_str *)type;
const void *value;
size_t value_len;
LY_CHECK_ARG_RET(NULL, type, storage, err, LY_EINVAL);
value = lyd_value_get_canonical(ctx, storage);
value_len = strlen(value);
*err = NULL;
/* length restriction of the string */
if (type_str->length) {
/* value_len is in bytes, but we need number of characters here */
ret = lyplg_type_validate_range(LY_TYPE_STRING, type_str->length, ly_utf8len(value, value_len), value, value_len, err);
LY_CHECK_RET(ret);
}
/* pattern restrictions */
ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err);
LY_CHECK_RET(ret);
return LY_SUCCESS;
}
/**
* @brief Plugin information for string type implementation.
*
@ -154,7 +132,7 @@ const struct lyplg_type_record plugins_string[] = {
.plugin.id = "libyang 2 - string, version 1",
.plugin.store = lyplg_type_store_string,
.plugin.validate = lyplg_type_validate_string,
.plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_simple,
.plugin.sort = lyplg_type_sort_simple,
.plugin.print = lyplg_type_print_simple,

View file

@ -0,0 +1,100 @@
/**
* @file time_period.c
* @author Roman Janota <janota@cesnet.cz>
* @brief libnetconf2-netconf-server time-period type plugin.
*
* Copyright (c) 2024 CESNET, z.s.p.o.
*
* This source code is licensed under BSD 3-Clause License (the "License").
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*/
#include "plugins_types.h"
#include <stdlib.h>
#include <string.h>
#include "libyang.h"
#include "compat.h"
#include "ly_common.h"
#include "plugins_internal.h" /* LY_TYPE_*_STR */
/**
* @page howtoDataLYB LYB Binary Format
* @subsection howtoDataLYBTypesTimePeriod time-period (libnetconf2-netconf-server)
*
* | Size (B) | Mandatory | Type | Meaning |
* | :------ | :-------: | :--: | :-----: |
* | string length | yes | `char *` | time in either months, weeks, days, or hours |
*/
/**
* @brief Implementation of ::lyplg_type_sort_clb for libnetconf2-netconf-server time-period type.
*
* The values are sorted in descending order, i.e. the longest expiration time comes first.
*/
static int
lyplg_type_sort_time_period(const struct ly_ctx *ctx, const struct lyd_value *val1, const struct lyd_value *val2)
{
const char *value1, *value2;
char unit1, unit2;
long v1, v2;
value1 = lyd_value_get_canonical(ctx, val1);
value2 = lyd_value_get_canonical(ctx, val2);
/* get the units (last character) and the values (all characters except the last one) */
unit1 = value1[strlen(value1) - 1];
unit2 = value2[strlen(value2) - 1];
v1 = strtol(value1, NULL, 10);
v2 = strtol(value2, NULL, 10);
/* descending order */
if (unit1 == unit2) {
if (v1 > v2) {
return -1;
} else if (v1 == v2) {
return 0;
} else {
return 1;
}
} else if (unit1 == 'm') {
return -1;
} else if ((unit1 == 'w') && (unit2 != 'm')) {
return -1;
} else if ((unit1 == 'd') && (unit2 == 'h')) {
return -1;
} else {
return 1;
}
}
/**
* @brief Plugin information for time-period type implementation.
*
* Note that external plugins are supposed to use:
*
* LYPLG_TYPES = {
*/
const struct lyplg_type_record plugins_time_period[] = {
{
.module = "libnetconf2-netconf-server",
.revision = "2024-07-09",
.name = "time-period",
.plugin.id = "libyang 2 - time-period, version 1",
.plugin.store = lyplg_type_store_string,
.plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_simple,
.plugin.sort = lyplg_type_sort_time_period,
.plugin.print = lyplg_type_print_simple,
.plugin.duplicate = lyplg_type_dup_simple,
.plugin.free = lyplg_type_free_simple,
.plugin.lyb_data_len = -1,
},
{0}
};

View file

@ -493,7 +493,7 @@ lyplg_type_compare_union(const struct ly_ctx *ctx, const struct lyd_value *val1,
LIBYANG_API_DEF int
lyplg_type_sort_union(const struct ly_ctx *ctx, const struct lyd_value *val1, const struct lyd_value *val2)
{
int ret;
int rc = LY_SUCCESS;
LY_ARRAY_COUNT_TYPE u;
struct lysc_type **types;
@ -502,20 +502,19 @@ lyplg_type_sort_union(const struct ly_ctx *ctx, const struct lyd_value *val1, co
}
/* compare according to the order of types */
ret = 0;
types = ((struct lysc_type_union *)val1->realtype)->types;
LY_ARRAY_FOR(types, u) {
if (types[u] == val1->subvalue->value.realtype) {
ret = 1;
rc = 1;
break;
} else if (types[u] == val2->subvalue->value.realtype) {
ret = -1;
rc = -1;
break;
}
}
assert(ret != 0);
assert(rc != 0);
return ret;
return rc;
}
/**

View file

@ -248,7 +248,6 @@ lyplg_type_store_xpath10(const struct ly_ctx *ctx, const struct lysc_type *type,
struct lyd_value *storage, struct lys_glob_unres *UNUSED(unres), struct ly_err_item **err)
{
LY_ERR ret = LY_SUCCESS;
struct lysc_type_str *type_str = (struct lysc_type_str *)type;
struct lyd_value_xpath10 *val;
char *canon;
@ -262,17 +261,6 @@ lyplg_type_store_xpath10(const struct ly_ctx *ctx, const struct lysc_type *type,
ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
LY_CHECK_GOTO(ret, cleanup);
/* length restriction of the string */
if (type_str->length) {
/* value_len is in bytes, but we need number of characters here */
ret = lyplg_type_validate_range(LY_TYPE_STRING, type_str->length, ly_utf8len(value, value_len), value, value_len, err);
LY_CHECK_GOTO(ret, cleanup);
}
/* pattern restrictions */
ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err);
LY_CHECK_GOTO(ret, cleanup);
/* parse */
ret = lyxp_expr_parse(ctx, value_len ? value : "", value_len, 1, &val->exp);
LY_CHECK_GOTO(ret, cleanup);

View file

@ -1162,7 +1162,7 @@ yprp_inout(struct lys_ypr_ctx *pctx, const struct lysp_node_action_inout *inout,
ly_print_(pctx->out, "%*s%s {\n", INDENT, inout->name);
LEVEL++;
yprp_extension_instances(pctx, LY_STMT_MUST, 0, inout->exts, NULL);
yprp_extension_instances(pctx, lyplg_ext_nodetype2stmt(inout->nodetype), 0, inout->exts, NULL);
LY_ARRAY_FOR(inout->musts, u) {
yprp_restr(pctx, &inout->musts[u], LY_STMT_MUST, NULL);
}
@ -2563,7 +2563,7 @@ lyplg_ext_print_info_extension_instance(struct lyspr_ctx *ctx, const struct lysc
break;
}
LY_LIST_FOR(*VOIDPTR2_C(ext->substmts[u].storage), node) {
LY_LIST_FOR(*ext->substmts[u].storage_p, node) {
ypr_open(pctx->out, flag);
if (ext->substmts[u].stmt == LY_STMT_NOTIFICATION) {
yprc_notification(pctx, (struct lysc_node_notif *)node);
@ -2592,32 +2592,32 @@ lyplg_ext_print_info_extension_instance(struct lyspr_ctx *ctx, const struct lysc
case LY_STMT_PRESENCE:
case LY_STMT_REFERENCE:
case LY_STMT_UNITS:
if (*VOIDPTR2_C(ext->substmts[u].storage)) {
if (*ext->substmts[u].storage_p) {
ypr_open(pctx->out, flag);
ypr_substmt(pctx, ext->substmts[u].stmt, 0, *VOIDPTR2_C(ext->substmts[u].storage), 0, ext->exts);
ypr_substmt(pctx, ext->substmts[u].stmt, 0, *ext->substmts[u].storage_p, 0, ext->exts);
}
break;
case LY_STMT_BIT:
case LY_STMT_ENUM: {
const struct lysc_type_bitenum_item *items = *VOIDPTR2_C(ext->substmts[u].storage);
const struct lysc_type_bitenum_item *items = *ext->substmts[u].storage_p;
yprc_bits_enum(pctx, items, ext->substmts[u].stmt == LY_STMT_BIT ? LY_TYPE_BITS : LY_TYPE_ENUM, flag);
break;
}
case LY_STMT_CONFIG:
ypr_config(pctx, *(uint16_t *)VOIDPTR2_C(ext->substmts[u].storage), ext->exts, flag);
ypr_config(pctx, *(uint16_t *)ext->substmts[u].storage_p, ext->exts, flag);
break;
case LY_STMT_EXTENSION_INSTANCE:
yprc_extension_instances(pctx, LY_STMT_EXTENSION_INSTANCE, 0, *VOIDPTR2_C(ext->substmts[u].storage), flag);
yprc_extension_instances(pctx, LY_STMT_EXTENSION_INSTANCE, 0, *ext->substmts[u].storage_p, flag);
break;
case LY_STMT_FRACTION_DIGITS:
if (*VOIDPTR2_C(ext->substmts[u].storage)) {
if (*ext->substmts[u].storage_p) {
ypr_unsigned(pctx, LY_STMT_FRACTION_DIGITS, 0, ext->exts,
(long unsigned int)*VOIDPTR2_C(ext->substmts[u].storage), flag);
(long unsigned int)*ext->substmts[u].storage_p, flag);
}
break;
case LY_STMT_IDENTITY: {
const struct lysc_ident *idents = *VOIDPTR2_C(ext->substmts[u].storage);
const struct lysc_ident *idents = *ext->substmts[u].storage_p;
LY_ARRAY_FOR(idents, v) {
yprc_identity(pctx, &idents[v]);
@ -2625,15 +2625,15 @@ lyplg_ext_print_info_extension_instance(struct lyspr_ctx *ctx, const struct lysc
break;
}
case LY_STMT_LENGTH:
if (*VOIDPTR2_C(ext->substmts[u].storage)) {
yprc_range(pctx, *VOIDPTR2_C(ext->substmts[u].storage), LY_TYPE_STRING, flag);
if (*ext->substmts[u].storage_p) {
yprc_range(pctx, *ext->substmts[u].storage_p, LY_TYPE_STRING, flag);
}
break;
case LY_STMT_MANDATORY:
ypr_mandatory(pctx, *(uint16_t *)VOIDPTR_C(ext->substmts[u].storage), ext->exts, flag);
ypr_mandatory(pctx, *(uint16_t *)ext->substmts[u].storage_p, ext->exts, flag);
break;
case LY_STMT_MAX_ELEMENTS: {
uint32_t max = *(uint32_t *)VOIDPTR_C(ext->substmts[u].storage);
uint32_t max = *(uint32_t *)ext->substmts[u].storage_p;
if (max) {
ypr_unsigned(pctx, LY_STMT_MAX_ELEMENTS, 0, ext->exts, max, flag);
@ -2644,15 +2644,15 @@ lyplg_ext_print_info_extension_instance(struct lyspr_ctx *ctx, const struct lysc
break;
}
case LY_STMT_MIN_ELEMENTS:
ypr_unsigned(pctx, LY_STMT_MIN_ELEMENTS, 0, ext->exts, *(uint32_t *)VOIDPTR_C(ext->substmts[u].storage), flag);
ypr_unsigned(pctx, LY_STMT_MIN_ELEMENTS, 0, ext->exts, *(uint32_t *)ext->substmts[u].storage_p, flag);
break;
case LY_STMT_ORDERED_BY:
ypr_open(pctx->out, flag);
ypr_substmt(pctx, LY_STMT_ORDERED_BY, 0,
((*(uint16_t *)VOIDPTR_C(ext->substmts[u].storage)) & LYS_ORDBY_USER) ? "user" : "system", 0, ext->exts);
((*(uint16_t *)ext->substmts[u].storage_p) & LYS_ORDBY_USER) ? "user" : "system", 0, ext->exts);
break;
case LY_STMT_MUST: {
const struct lysc_must *musts = *VOIDPTR2_C(ext->substmts[u].storage);
const struct lysc_must *musts = *ext->substmts[u].storage_p;
LY_ARRAY_FOR(musts, v) {
yprc_must(pctx, &musts[v], flag);
@ -2660,7 +2660,7 @@ lyplg_ext_print_info_extension_instance(struct lyspr_ctx *ctx, const struct lysc
break;
}
case LY_STMT_PATTERN: {
const struct lysc_pattern *patterns = *VOIDPTR2_C(ext->substmts[u].storage);
const struct lysc_pattern *patterns = *ext->substmts[u].storage_p;
LY_ARRAY_FOR(patterns, v) {
yprc_pattern(pctx, &patterns[v], flag);
@ -2668,36 +2668,36 @@ lyplg_ext_print_info_extension_instance(struct lyspr_ctx *ctx, const struct lysc
break;
}
case LY_STMT_POSITION:
if (*VOIDPTR2_C(ext->substmts[u].storage)) {
ypr_unsigned(pctx, ext->substmts[u].stmt, 0, ext->exts, *(int64_t *)VOIDPTR_C(ext->substmts[u].storage), flag);
if (*ext->substmts[u].storage_p) {
ypr_unsigned(pctx, ext->substmts[u].stmt, 0, ext->exts, *(int64_t *)ext->substmts[u].storage_p, flag);
}
break;
case LY_STMT_VALUE:
if (*VOIDPTR2_C(ext->substmts[u].storage)) {
ypr_signed(pctx, ext->substmts[u].stmt, 0, ext->exts, *(int64_t *)VOIDPTR_C(ext->substmts[u].storage), flag);
if (*ext->substmts[u].storage_p) {
ypr_signed(pctx, ext->substmts[u].stmt, 0, ext->exts, *(int64_t *)ext->substmts[u].storage_p, flag);
}
break;
case LY_STMT_RANGE:
if (*VOIDPTR2_C(ext->substmts[u].storage)) {
yprc_range(pctx, *VOIDPTR2_C(ext->substmts[u].storage), LY_TYPE_UINT64, flag);
if (*ext->substmts[u].storage_p) {
yprc_range(pctx, *ext->substmts[u].storage_p, LY_TYPE_UINT64, flag);
}
break;
case LY_STMT_REQUIRE_INSTANCE:
ypr_open(pctx->out, flag);
ypr_substmt(pctx, LY_STMT_REQUIRE_INSTANCE, 0, *(uint8_t *)VOIDPTR_C(ext->substmts[u].storage) ? "true" : "false",
ypr_substmt(pctx, LY_STMT_REQUIRE_INSTANCE, 0, *(uint8_t *)ext->substmts[u].storage_p ? "true" : "false",
0, ext->exts);
break;
case LY_STMT_STATUS:
ypr_status(pctx, *(uint16_t *)VOIDPTR_C(ext->substmts[u].storage), ext->exts, flag);
ypr_status(pctx, *(uint16_t *)ext->substmts[u].storage_p, ext->exts, flag);
break;
case LY_STMT_TYPE:
if (*VOIDPTR2_C(ext->substmts[u].storage)) {
if (*ext->substmts[u].storage_p) {
ypr_open(pctx->out, flag);
yprc_type(pctx, *VOIDPTR2_C(ext->substmts[u].storage));
yprc_type(pctx, *ext->substmts[u].storage_p);
}
break;
case LY_STMT_WHEN:
yprc_when(pctx, *VOIDPTR2_C(ext->substmts[u].storage), flag);
yprc_when(pctx, *ext->substmts[u].storage_p, flag);
break;
case LY_STMT_AUGMENT:
case LY_STMT_BASE:

View file

@ -4,7 +4,7 @@
* @author Michal Vasko <mvasko@cesnet.cz>
* @brief Schema compilation.
*
* Copyright (c) 2015 - 2022 CESNET, z.s.p.o.
* Copyright (c) 2015 - 2024 CESNET, z.s.p.o.
*
* This source code is licensed under BSD 3-Clause License (the "License").
* You may not use this file except in compliance with the License.
@ -172,7 +172,10 @@ lys_compile_ext(struct lysc_ctx *ctx, struct lysp_ext_instance *extp, struct lys
/* compile extension if not already */
LY_CHECK_GOTO(ret = lys_compile_extension(ctx, extp, &ext->def), cleanup);
/* compile */
/* compile nested extensions */
COMPILE_EXTS_GOTO(ctx, extp->exts, ext->exts, ext, ret, cleanup);
/* compile this extension */
if (ext->def->plugin && ext->def->plugin->compile) {
if (ext->argument) {
lysc_update_path(ctx, ext->module, ext->argument);
@ -218,7 +221,7 @@ lys_identity_precompile(struct lysc_ctx *ctx_sc, struct ly_ctx *ctx, struct lysp
const struct lysp_ident *identities_p, struct lysc_ident **identities)
{
LY_ARRAY_COUNT_TYPE u;
struct lysc_ctx cctx;
struct lysc_ctx cctx = {0};
struct lysc_ident *ident;
LY_ERR ret = LY_SUCCESS;
@ -863,7 +866,7 @@ lys_compile_unres_leafref(struct lysc_ctx *ctx, const struct lysc_node *node, st
/* get the target node */
target = p[LY_ARRAY_COUNT(p) - 1].node;
ly_path_free(node->module->ctx, p);
ly_path_free(p);
if (!(target->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
LOGVAL(ctx->ctx, LYVE_REFERENCE, "Invalid leafref path \"%s\" - target node is %s instead of leaf or leaf-list.",
@ -960,6 +963,12 @@ lys_compile_unres_dflt(struct lysc_ctx *ctx, struct lysc_node *node, struct lysc
}
LY_ATOMIC_INC_BARRIER(((struct lysc_type *)storage->realtype)->refcount);
if (storage->realtype->basetype == LY_TYPE_INST) {
/* ly_path includes references to other nodes, in case they are in foreign modules, the context would
* need to be freed in specific order to avoid accessing freed memory, so just avoid storing it */
ly_path_free(storage->target);
storage->target = NULL;
}
return LY_SUCCESS;
}
@ -1453,7 +1462,7 @@ resolve_all:
ret = ly_path_compile_leafref(cctx.ctx, l->node, cctx.ext, lref->path,
(l->node->flags & LYS_IS_OUTPUT) ? LY_PATH_OPER_OUTPUT : LY_PATH_OPER_INPUT, LY_PATH_TARGET_MANY,
LY_VALUE_SCHEMA_RESOLVED, lref->prefixes, &path);
ly_path_free(l->node->module->ctx, path);
ly_path_free(path);
assert(ret != LY_ERECOMPILE);
if (ret) {
@ -1468,7 +1477,7 @@ resolve_all:
}
cleanup:
lysf_ctx_erase(&cctx.free_ctx);
assert(!cctx.free_ctx.ext_set.count);
return ret;
}
@ -1548,8 +1557,8 @@ lys_compile_depset_r(struct ly_ctx *ctx, struct ly_set *dep_set, struct lys_glob
}
cleanup:
assert(!fctx.ext_set.count);
lys_compile_unres_depset_erase(ctx, unres);
lysf_ctx_erase(&fctx);
return ret;
}
@ -1693,7 +1702,7 @@ lys_compile_unres_mod_erase(struct lysc_ctx *ctx, ly_bool error)
LY_ERR
lys_compile(struct lys_module *mod, struct lys_depset_unres *unres)
{
struct lysc_ctx ctx;
struct lysc_ctx ctx = {0};
struct lysc_module *mod_c = NULL;
struct lysp_module *sp;
struct lysp_submodule *submod;
@ -1814,7 +1823,7 @@ LY_ERR
lys_compile_identities(struct lys_module *mod)
{
LY_ERR rc = LY_SUCCESS;
struct lysc_ctx ctx;
struct lysc_ctx ctx = {0};
struct lysp_submodule *submod;
LY_ARRAY_COUNT_TYPE u;

View file

@ -67,7 +67,6 @@ struct lysc_ctx {
* @param[in] CTX libyang context.
*/
#define LYSC_CTX_INIT_CTX(CCTX, CTX) \
memset(&(CCTX), 0, sizeof (CCTX)); \
(CCTX).ctx = (CTX); \
(CCTX).path_len = 1; \
(CCTX).path[0] = '/'; \
@ -81,7 +80,6 @@ struct lysc_ctx {
* @param[in] EXT Ancestor extension instance.
*/
#define LYSC_CTX_INIT_PMOD(CCTX, PMOD, EXT) \
memset(&(CCTX), 0, sizeof (CCTX)); \
(CCTX).ctx = (PMOD)->mod->ctx; \
(CCTX).cur_mod = (PMOD)->mod; \
(CCTX).pmod = (PMOD); \
@ -164,9 +162,9 @@ struct lysc_unres_dflt {
* @param[out] DUP Where to store the result.
* @param[out] RET Where to store the return code.
*/
#define DUP_STRING(CTX, ORIG, DUP, RET) RET = lydict_insert(CTX, ORIG, 0, &(DUP))
#define DUP_STRING_RET(CTX, ORIG, DUP) LY_CHECK_RET(lydict_insert(CTX, ORIG, 0, &(DUP)))
#define DUP_STRING_GOTO(CTX, ORIG, DUP, RET, GOTO) LY_CHECK_GOTO(RET = lydict_insert(CTX, ORIG, 0, &(DUP)), GOTO)
#define DUP_STRING(CTX, ORIG, DUP, RET) RET = lydict_dup(CTX, ORIG, &(DUP))
#define DUP_STRING_RET(CTX, ORIG, DUP) LY_CHECK_RET(lydict_dup(CTX, ORIG, &(DUP)))
#define DUP_STRING_GOTO(CTX, ORIG, DUP, RET, GOTO) LY_CHECK_GOTO(RET = lydict_dup(CTX, ORIG, &(DUP)), GOTO)
#define DUP_ARRAY(CTX, ORIG_ARRAY, NEW_ARRAY, DUP_FUNC) \
if (ORIG_ARRAY) { \

View file

@ -2218,7 +2218,7 @@ lys_precompile_own_augments_mod(struct lysc_ctx *ctx, const struct lysp_module *
aug_p = NULL;
LY_ARRAY_FOR(pmod->exts[u].substmts, v) {
if (pmod->exts[u].substmts[v].stmt == LY_STMT_AUGMENT) {
aug_p = *VOIDPTR2_C(pmod->exts[u].substmts[v].storage);
aug_p = *(pmod->exts[u].substmts[v].storage_p);
break;
}
}
@ -2443,7 +2443,7 @@ lys_precompile_mod_augments_deviations(struct lysp_module *pmod, struct ly_set *
{
LY_ERR ret = LY_SUCCESS;
LY_ARRAY_COUNT_TYPE u, v;
struct lysc_ctx ctx;
struct lysc_ctx ctx = {0};
struct lys_module *m;
struct lysp_node_augment *aug;
struct ly_set set = {0};
@ -2488,7 +2488,7 @@ lys_precompile_mod_augments_deviations(struct lysp_module *pmod, struct ly_set *
aug = NULL;
LY_ARRAY_FOR(pmod->exts[u].substmts, v) {
if (pmod->exts[u].substmts[v].stmt == LY_STMT_AUGMENT) {
aug = *VOIDPTR2_C(pmod->exts[u].substmts[v].storage);
aug = *(pmod->exts[u].substmts[v].storage_p);
break;
}
}

View file

@ -1390,7 +1390,7 @@ lys_compile_type_patterns(struct lysc_ctx *ctx, const struct lysp_restr *pattern
if (patterns_p[u].arg.str[0] == LYSP_RESTR_PATTERN_NACK) {
(*pattern)->inverted = 1;
}
DUP_STRING_GOTO(ctx->ctx, &patterns_p[u].arg.str[1], (*pattern)->expr, ret, done);
LY_CHECK_GOTO(ret = lydict_insert(ctx->ctx, &patterns_p[u].arg.str[1], 0, &(*pattern)->expr), done);
DUP_STRING_GOTO(ctx->ctx, patterns_p[u].eapptag, (*pattern)->eapptag, ret, done);
DUP_STRING_GOTO(ctx->ctx, patterns_p[u].emsg, (*pattern)->emsg, ret, done);
DUP_STRING_GOTO(ctx->ctx, patterns_p[u].dsc, (*pattern)->dsc, ret, done);
@ -2582,10 +2582,10 @@ lys_compile_node_connect(struct lysc_ctx *ctx, struct lysc_node *parent, struct
}
} else {
/* top-level element */
struct lysc_node **list;
struct lysc_node **list = NULL;
if (ctx->ext) {
lyplg_ext_get_storage_p(ctx->ext, LY_STMT_DATA_NODE_MASK, (uint64_t *)&list);
lyplg_ext_get_storage_p(ctx->ext, LY_STMT_DATA_NODE_MASK, (void ***)&list);
} else if (node->nodetype == LYS_RPC) {
list = (struct lysc_node **)&ctx->cur_mod->compiled->rpcs;
} else if (node->nodetype == LYS_NOTIF) {
@ -2794,7 +2794,6 @@ lys_compile_node_action_inout(struct lysc_ctx *ctx, struct lysp_node *pnode, str
struct lysc_node_action_inout *inout = (struct lysc_node_action_inout *)node;
COMPILE_ARRAY_GOTO(ctx, inout_p->musts, inout->musts, lys_compile_must, ret, done);
COMPILE_EXTS_GOTO(ctx, inout_p->exts, inout->exts, inout, ret, done);
ctx->compile_opts |= (inout_p->nodetype == LYS_INPUT) ? LYS_COMPILE_RPC_INPUT : LYS_COMPILE_RPC_OUTPUT;
LY_LIST_FOR(inout_p->child, child_p) {

View file

@ -105,7 +105,7 @@ lys_identity_iffeature_value(const struct lysc_ident *ident)
const struct lysp_ident *idents_p, *found_ident = NULL;
struct lysp_include *includes;
assert(ident);
LY_CHECK_ARG_RET(NULL, ident, ident->module->parsed, LY_EINVAL);
/* Search parsed identity in the module. */
idents_p = ident->module->parsed->identities;
@ -146,6 +146,8 @@ lysp_feature_next(const struct lysp_feature *last, const struct lysp_module *pmo
{
struct lysp_feature *features;
LY_CHECK_ARG_RET(NULL, pmod, NULL);
if (!*idx) {
/* module features */
features = pmod->features;

View file

@ -1078,7 +1078,7 @@ lyd_insert_sibling(struct lyd_node *sibling, struct lyd_node *node, struct lyd_n
{
struct lyd_node *first_sibling;
LY_CHECK_ARG_RET(NULL, node, LY_EINVAL);
LY_CHECK_ARG_RET(NULL, node, sibling != node, LY_EINVAL);
if (sibling) {
LY_CHECK_RET(lyd_insert_check_schema(NULL, sibling->schema, node->schema));
@ -2148,6 +2148,11 @@ lyd_dup_r(const struct lyd_node *node, const struct ly_ctx *trg_ctx, struct lyd_
struct lyd_node *child;
if (options & LYD_DUP_RECURSIVE) {
/* create a hash table with the size of the previous hash table (duplicate) */
if (orig->children_ht) {
((struct lyd_node_inner *)dup)->children_ht = lyht_new(orig->children_ht->size, sizeof(struct lyd_node *), lyd_hash_table_val_equal, NULL, 1);
}
/* duplicate all the children */
LY_LIST_FOR(orig->child, child) {
LY_CHECK_GOTO(ret = lyd_dup_r(child, trg_ctx, dup, LYD_INSERT_NODE_LAST, NULL, options, NULL), error);
@ -2178,58 +2183,6 @@ error:
return ret;
}
/**
* @brief Duplicate a (leaf-)list and connect it into @p parent (if present) or last of @p first siblings.
*
* @param[in] orig Node to duplicate.
* @param[in] trg_ctx Target context for duplicated nodes.
* @param[in] parent Parent to insert into, NULL for top-level sibling.
* @param[in,out] first First sibling, NULL if no top-level sibling exist yet. Can be also NULL if @p parent is set.
* @param[in] options Bitmask of options flags, see @ref dupoptions.
* @param[out] dup_p Pointer where the created duplicated node is placed (besides connecting it to @p parent / @p first).
* @return LY_ERR value.
*/
static LY_ERR
lyd_dup_list(const struct lyd_node **orig, const struct ly_ctx *trg_ctx, struct lyd_node *parent,
struct lyd_node **first, uint32_t options, struct lyd_node **dup_p)
{
LY_ERR rc;
struct lyd_node *start, *leader, *dup;
const struct lysc_node *schema;
uint32_t insert_order;
/* duplicate leader */
start = (*orig)->next;
schema = (*orig)->schema;
rc = lyd_dup_r(*orig, trg_ctx, parent, LYD_INSERT_NODE_DEFAULT, first, options, &leader);
LY_CHECK_RET(rc);
if (!start || !start->schema || !LYD_NODE_IS_ALONE(leader)) {
/* no other instances */
if (dup_p) {
*dup_p = leader;
}
return LY_SUCCESS;
}
/* duplicate the rest of the nodes in the (leaf-)list */
insert_order = leader->next ? LYD_INSERT_NODE_LAST_BY_SCHEMA : LYD_INSERT_NODE_LAST;
LY_LIST_FOR(start, *orig) {
if (schema != (*orig)->schema) {
break;
}
rc = lyd_dup_r(*orig, trg_ctx, parent, insert_order, first, options, &dup);
LY_CHECK_GOTO(rc, cleanup);
}
cleanup:
if (dup_p) {
*dup_p = leader;
}
return rc;
}
/**
* @brief Get a parent node to connect duplicated subtree to.
*
@ -2317,6 +2270,8 @@ lyd_dup(const struct lyd_node *node, const struct ly_ctx *trg_ctx, struct lyd_no
struct lyd_node *local_parent = NULL; /* the direct parent node for the duplicated node(s) */
struct lyd_node *dup = NULL; /* duplicate node */
struct lyd_node *first_sibling = NULL; /* first sibling node */
const struct lyd_node *first_llist = NULL; /* first duplicated (leaf-)list node, if any */
uint32_t insert_order;
assert(node && trg_ctx);
@ -2339,19 +2294,35 @@ lyd_dup(const struct lyd_node *node, const struct ly_ctx *trg_ctx, struct lyd_no
rc = lyd_dup_r(orig, trg_ctx, NULL, LYD_INSERT_NODE_DEFAULT, &first_sibling, options, &dup);
LY_CHECK_GOTO(rc, error);
}
} else if (!nosiblings && orig->schema && (orig->schema->nodetype & (LYS_LIST | LYS_LEAFLIST))) {
/* duplicate the whole (leaf-)list */
rc = lyd_dup_list(&orig, trg_ctx, local_parent, &first_sibling, options, &dup);
LY_CHECK_GOTO(rc, error);
} else {
rc = lyd_dup_r(orig, trg_ctx, local_parent,
options & LYD_DUP_NO_LYDS ? LYD_INSERT_NODE_LAST_BY_SCHEMA : LYD_INSERT_NODE_DEFAULT,
&first_sibling, options, &dup);
/* decide insert order */
insert_order = (options & LYD_DUP_NO_LYDS) ? LYD_INSERT_NODE_LAST_BY_SCHEMA : LYD_INSERT_NODE_DEFAULT;
if (first_llist) {
if (orig->schema != first_llist->schema) {
/* all the (leaf-)list instances duplicated */
first_llist = NULL;
} else {
/* duplicating all the instances of a (leaf-)list, no need to change their order */
insert_order = LYD_INSERT_NODE_LAST;
}
} else if (orig->schema && (orig->schema->nodetype & (LYS_LIST | LYS_LEAFLIST))) {
/* duplicating the first (leaf-)list instance, duplicate the rest more efficiently */
first_llist = orig;
}
/* duplicate the node */
rc = lyd_dup_r(orig, trg_ctx, local_parent, insert_order, &first_sibling, options, &dup);
LY_CHECK_GOTO(rc, error);
if (first_llist && dup->next) {
/* orig was not the last node (because we are inserting into a parent with some previous instances),
* we must check find the order */
first_llist = NULL;
}
}
first_dup = first_dup ? first_dup : dup;
if (nosiblings || !orig) {
if (nosiblings) {
break;
}
}
@ -3624,7 +3595,7 @@ lyd_find_path(const struct lyd_node *ctx_node, const char *path, ly_bool output,
cleanup:
lyxp_expr_free(LYD_CTX(ctx_node), expr);
ly_path_free(LYD_CTX(ctx_node), lypath);
ly_path_free(lypath);
return ret;
}

View file

@ -1656,10 +1656,11 @@ ly_time_str2time(const char *value, time_t *time, char **fractions_s)
struct tm tm = {0};
uint32_t i, frac_len;
const char *frac;
char *ptr;
int64_t shift, shift_m;
time_t t;
LY_CHECK_ARG_RET(NULL, value, time, LY_EINVAL);
LY_CHECK_ARG_RET(NULL, value, strlen(value) > 17, time, LY_EINVAL);
tm.tm_year = atoi(&value[0]) - 1900;
tm.tm_mon = atoi(&value[5]) - 1;
@ -1698,6 +1699,10 @@ ly_time_str2time(const char *value, time_t *time, char **fractions_s)
++i;
frac = &value[i];
for (frac_len = 0; isdigit(frac[frac_len]); ++frac_len) {}
if (!frac_len) {
LOGERR(NULL, LY_EINVAL, "Missing date-and-time fractions after '.'.");
return LY_EINVAL;
}
i += frac_len;
} else {
@ -1709,15 +1714,20 @@ ly_time_str2time(const char *value, time_t *time, char **fractions_s)
/* zero shift */
shift = 0;
} else {
shift = strtol(&value[i], NULL, 10);
value += i;
shift = strtol(value, &ptr, 10);
if (shift > 23) {
LOGERR(NULL, LY_EINVAL, "Invalid date-and-time timezone hour \"%" PRIi64 "\".", shift);
return LY_EINVAL;
} else if (ptr[0] != ':') {
LOGERR(NULL, LY_EINVAL, "Invalid date-and-time timezone hour \"%s\".", value);
return LY_EINVAL;
}
shift = shift * 60 * 60; /* convert from hours to seconds */
shift_m = strtol(&value[i + 4], NULL, 10);
if (shift_m > 59) {
value = ptr + 1;
shift_m = strtol(value, NULL, 10);
if ((shift_m < 0) || (shift_m > 59)) {
LOGERR(NULL, LY_EINVAL, "Invalid date-and-time timezone minutes \"%" PRIi64 "\".", shift_m);
return LY_EINVAL;
}

View file

@ -84,7 +84,7 @@ lyd_hash(struct lyd_node *node)
*
* Implementation of ::lyht_value_equal_cb.
*/
static ly_bool
ly_bool
lyd_hash_table_val_equal(void *val1_p, void *val2_p, ly_bool mod, void *UNUSED(cb_data))
{
struct lyd_node *val1, *val2;

View file

@ -16,6 +16,7 @@
#ifndef LY_TREE_DATA_INTERNAL_H_
#define LY_TREE_DATA_INTERNAL_H_
#include "compat.h"
#include "log.h"
#include "plugins_types.h"
#include "tree_data.h"
@ -600,6 +601,13 @@ LY_ERR ly_value_validate(const struct ly_ctx *ctx, const struct lysc_node *node,
*/
LY_ERR lyd_hash(struct lyd_node *node);
/**
* @brief Compare callback for values in hash table.
*
* Implementation of ::lyht_value_equal_cb.
*/
ly_bool lyd_hash_table_val_equal(void *val1_p, void *val2_p, ly_bool mod, void *cb_data);
/**
* @brief Insert hash of the node into the hash table of its parent.
*

View file

@ -885,7 +885,7 @@ lyd_new_term(struct lyd_node *parent, const struct lys_module *module, const cha
return _lyd_new_term(parent, module, name, value, value ? strlen(value) : 0, options, node);
}
LIBYANG_API_DECL LY_ERR
LIBYANG_API_DEF LY_ERR
lyd_new_term_bin(struct lyd_node *parent, const struct lys_module *module, const char *name,
const void *value, size_t value_len, uint32_t options, struct lyd_node **node)
{
@ -1089,6 +1089,7 @@ lyd_new_opaq(struct lyd_node *parent, const struct ly_ctx *ctx, const char *name
const char *prefix, const char *module_name, struct lyd_node **node)
{
struct lyd_node *ret = NULL;
uint32_t hints = 0;
LY_CHECK_ARG_RET(ctx, parent || ctx, parent || node, name, module_name, !prefix || !strcmp(prefix, module_name), LY_EINVAL);
LY_CHECK_CTX_EQUAL_RET(ctx, parent ? LYD_CTX(parent) : NULL, LY_EINVAL);
@ -1098,10 +1099,12 @@ lyd_new_opaq(struct lyd_node *parent, const struct ly_ctx *ctx, const char *name
}
if (!value) {
value = "";
} else if (!strcmp(value, "[null]")) {
hints |= LYD_VALHINT_EMPTY;
}
LY_CHECK_RET(lyd_create_opaq(ctx, name, strlen(name), prefix, prefix ? strlen(prefix) : 0, module_name,
strlen(module_name), value, strlen(value), NULL, LY_VALUE_JSON, NULL, 0, &ret));
strlen(module_name), value, strlen(value), NULL, LY_VALUE_JSON, NULL, hints, &ret));
if (parent) {
lyd_insert_node(parent, NULL, ret, LYD_INSERT_NODE_LAST);
}
@ -1626,6 +1629,7 @@ lyd_new_path_(struct lyd_node *parent, const struct ly_ctx *ctx, const struct ly
ly_bool store_only = (options & LYD_NEW_VAL_STORE_ONLY) ? 1 : 0;
LY_ARRAY_COUNT_TYPE path_idx = 0, orig_count = 0;
LY_VALUE_FORMAT format;
uint32_t hints;
assert(parent || ctx);
assert(path && ((path[0] == '/') || parent));
@ -1728,9 +1732,13 @@ lyd_new_path_(struct lyd_node *parent, const struct ly_ctx *ctx, const struct ly
}
if (r && (r != LY_EINCOMPLETE)) {
/* creating opaque leaf-list */
hints = LYD_NODEHINT_LEAFLIST;
if (value && (format == LY_VALUE_JSON) && !ly_strncmp("[null]", value, value_len)) {
hints |= LYD_VALHINT_EMPTY;
}
LY_CHECK_GOTO(ret = lyd_create_opaq(ctx, schema->name, strlen(schema->name), NULL, 0,
schema->module->name, strlen(schema->module->name), value, value_len, NULL, format, NULL,
LYD_NODEHINT_LEAFLIST, &node), cleanup);
hints, &node), cleanup);
break;
}
}
@ -1765,8 +1773,12 @@ lyd_new_path_(struct lyd_node *parent, const struct ly_ctx *ctx, const struct ly
}
if (r && (r != LY_EINCOMPLETE)) {
/* creating opaque leaf */
hints = 0;
if (value && (format == LY_VALUE_JSON) && !ly_strncmp("[null]", value, value_len)) {
hints |= LYD_VALHINT_EMPTY;
}
LY_CHECK_GOTO(ret = lyd_create_opaq(ctx, schema->name, strlen(schema->name), NULL, 0,
schema->module->name, strlen(schema->module->name), value, value_len, NULL, format, NULL, 0, &node),
schema->module->name, strlen(schema->module->name), value, value_len, NULL, format, NULL, hints, &node),
cleanup);
break;
}
@ -1811,7 +1823,7 @@ cleanup:
LY_ARRAY_INCREMENT(p);
}
}
ly_path_free(ctx, p);
ly_path_free(p);
if (!ret) {
/* set out params only on success */
if (new_parent) {

View file

@ -644,7 +644,7 @@ lys_find_path_atoms(const struct ly_ctx *ctx, const struct lysc_node *ctx_node,
ret = lys_find_lypath_atoms(p, set);
cleanup:
ly_path_free(ctx, p);
ly_path_free(p);
lyxp_expr_free(ctx, expr);
return ret;
}
@ -679,7 +679,7 @@ lys_find_path(const struct ly_ctx *ctx, const struct lysc_node *ctx_node, const
snode = p[LY_ARRAY_COUNT(p) - 1].node;
cleanup:
ly_path_free(ctx, p);
ly_path_free(p);
lyxp_expr_free(ctx, expr);
return snode;
}
@ -1179,7 +1179,7 @@ lys_set_implemented(struct lys_module *mod, const char **features)
LY_ERR ret = LY_SUCCESS;
struct lys_glob_unres *unres = &mod->ctx->unres;
LY_CHECK_ARG_RET(NULL, mod, LY_EINVAL);
LY_CHECK_ARG_RET(NULL, mod, mod->parsed, LY_EINVAL);
/* implement */
ret = _lys_set_implemented(mod, features, unres);

View file

@ -768,7 +768,7 @@ lys_parse_localfile(struct ly_ctx *ctx, const char *name, const char *revision,
{
struct ly_in *in;
char *filepath = NULL;
LYS_INFORMAT format;
LYS_INFORMAT format = 0;
void *mod = NULL;
LY_ERR ret = LY_SUCCESS;
struct lysp_load_module_check_data check_data = {0};
@ -1829,7 +1829,7 @@ lysc_node_lref_target(const struct lysc_node *node)
/* get the target node */
target = p[LY_ARRAY_COUNT(p) - 1].node;
ly_path_free(node->module->ctx, p);
ly_path_free(p);
return target;
}

View file

@ -80,6 +80,8 @@ lysp_ext_instance_free(struct lysf_ctx *ctx, struct lysp_ext_instance *ext)
LY_LIST_FOR_SAFE(ext->child, next, stmt) {
lysp_stmt_free(ctx->ctx, stmt);
}
FREE_ARRAY(ctx, ext->exts, lysp_ext_instance_free);
}
/**
@ -1360,7 +1362,7 @@ lyplg_ext_pfree_instance_substatements(const struct ly_ctx *ctx, struct lysp_ext
ly_bool node_free;
LY_ARRAY_FOR(substmts, u) {
if (!substmts[u].storage) {
if (!substmts[u].storage_p) {
continue;
}
@ -1383,75 +1385,75 @@ lyplg_ext_pfree_instance_substatements(const struct ly_ctx *ctx, struct lysp_ext
case LY_STMT_USES: {
struct lysp_node *child, *child_next;
LY_LIST_FOR_SAFE(*VOIDPTR2_C(substmts[u].storage), child_next, child) {
LY_LIST_FOR_SAFE(*substmts[u].storage_p, child_next, child) {
node_free = (child->nodetype & (LYS_INPUT | LYS_OUTPUT)) ? 1 : 0;
lysp_node_free(&fctx, child);
if (node_free) {
free(child);
}
}
*VOIDPTR2_C(substmts[u].storage) = NULL;
*substmts[u].storage_p = NULL;
break;
}
case LY_STMT_BASE:
/* multiple strings */
FREE_ARRAY(ctx, **(const char ***)VOIDPTR2_C(substmts[u].storage), lydict_remove);
FREE_ARRAY(ctx, **(const char ***)substmts[u].storage_p, lydict_remove);
break;
case LY_STMT_BIT:
case LY_STMT_ENUM:
/* single enum */
lysp_type_enum_free(&fctx, *VOIDPTR2_C(substmts[u].storage));
lysp_type_enum_free(&fctx, *substmts[u].storage_p);
break;
case LY_STMT_DEVIATE:
/* single deviate */
lysp_deviate_free(&fctx, *VOIDPTR2_C(substmts[u].storage));
lysp_deviate_free(&fctx, *substmts[u].storage_p);
break;
case LY_STMT_DEVIATION:
/* single deviation */
lysp_deviation_free(&fctx, *VOIDPTR2_C(substmts[u].storage));
lysp_deviation_free(&fctx, *substmts[u].storage_p);
break;
case LY_STMT_EXTENSION:
/* single extension */
lysp_ext_free(&fctx, *VOIDPTR2_C(substmts[u].storage));
lysp_ext_free(&fctx, *substmts[u].storage_p);
break;
case LY_STMT_EXTENSION_INSTANCE:
/* multiple extension instances */
FREE_ARRAY(&fctx, *(struct lysp_ext_instance **)VOIDPTR2_C(substmts[u].storage), lysp_ext_instance_free);
FREE_ARRAY(&fctx, *(struct lysp_ext_instance **)substmts[u].storage_p, lysp_ext_instance_free);
break;
case LY_STMT_FEATURE:
/* multiple features */
FREE_ARRAY(&fctx, *(struct lysp_feature **)VOIDPTR2_C(substmts[u].storage), lysp_feature_free);
FREE_ARRAY(&fctx, *(struct lysp_feature **)substmts[u].storage_p, lysp_feature_free);
break;
case LY_STMT_IDENTITY:
/* multiple identities */
FREE_ARRAY(&fctx, *(struct lysp_ident **)VOIDPTR2_C(substmts[u].storage), lysp_ident_free);
FREE_ARRAY(&fctx, *(struct lysp_ident **)substmts[u].storage_p, lysp_ident_free);
break;
case LY_STMT_IMPORT:
/* multiple imports */
FREE_ARRAY(&fctx, *(struct lysp_import **)VOIDPTR2_C(substmts[u].storage), lysp_import_free);
FREE_ARRAY(&fctx, *(struct lysp_import **)substmts[u].storage_p, lysp_import_free);
break;
case LY_STMT_INCLUDE:
/* multiple includes */
FREE_ARRAY(&fctx, *(struct lysp_include **)VOIDPTR2_C(substmts[u].storage), lysp_include_free);
FREE_ARRAY(&fctx, *(struct lysp_include **)substmts[u].storage_p, lysp_include_free);
break;
case LY_STMT_REFINE:
/* multiple refines */
FREE_ARRAY(&fctx, *(struct lysp_refine **)VOIDPTR2_C(substmts[u].storage), lysp_refine_free);
FREE_ARRAY(&fctx, *(struct lysp_refine **)substmts[u].storage_p, lysp_refine_free);
break;
case LY_STMT_REVISION:
/* multiple revisions */
FREE_ARRAY(&fctx, *(struct lysp_revision **)VOIDPTR2_C(substmts[u].storage), lysp_revision_free);
FREE_ARRAY(&fctx, *(struct lysp_revision **)substmts[u].storage_p, lysp_revision_free);
break;
case LY_STMT_CONFIG:
@ -1485,7 +1487,7 @@ lyplg_ext_pfree_instance_substatements(const struct ly_ctx *ctx, struct lysp_ext
case LY_STMT_REVISION_DATE:
case LY_STMT_UNITS:
/* single string */
lydict_remove(ctx, *VOIDPTR2_C(substmts[u].storage));
lydict_remove(ctx, *substmts[u].storage_p);
break;
case LY_STMT_LENGTH:
@ -1493,34 +1495,34 @@ lyplg_ext_pfree_instance_substatements(const struct ly_ctx *ctx, struct lysp_ext
case LY_STMT_PATTERN:
case LY_STMT_RANGE:
/* multiple restrictions */
FREE_ARRAY(&fctx, *(struct lysp_restr **)VOIDPTR2_C(substmts[u].storage), lysp_restr_free);
FREE_ARRAY(&fctx, *(struct lysp_restr **)substmts[u].storage_p, lysp_restr_free);
break;
case LY_STMT_WHEN:
/* multiple whens */
FREE_ARRAY(&fctx, *(struct lysp_when **)VOIDPTR2_C(substmts[u].storage), lysp_when_free);
FREE_ARRAY(&fctx, *(struct lysp_when **)substmts[u].storage_p, lysp_when_free);
break;
case LY_STMT_PATH:
/* single expression */
lyxp_expr_free(ctx, *VOIDPTR2_C(substmts[u].storage));
lyxp_expr_free(ctx, *substmts[u].storage_p);
break;
case LY_STMT_DEFAULT:
case LY_STMT_IF_FEATURE:
case LY_STMT_UNIQUE:
/* multiple qnames */
FREE_ARRAY(ctx, *(struct lysp_qname **)VOIDPTR2_C(substmts[u].storage), lysp_qname_free);
FREE_ARRAY(ctx, *(struct lysp_qname **)substmts[u].storage_p, lysp_qname_free);
break;
case LY_STMT_TYPEDEF:
/* multiple typedefs */
FREE_ARRAY(&fctx, *(struct lysp_tpdf **)VOIDPTR2_C(substmts[u].storage), lysp_tpdf_free);
FREE_ARRAY(&fctx, *(struct lysp_tpdf **)substmts[u].storage_p, lysp_tpdf_free);
break;
case LY_STMT_TYPE: {
/* single type */
struct lysp_type **type_p = VOIDPTR_C(substmts[u].storage);
struct lysp_type **type_p = (struct lysp_type **)substmts[u].storage_p;
lysp_type_free(&fctx, *type_p);
free(*type_p);
@ -1529,7 +1531,7 @@ lyplg_ext_pfree_instance_substatements(const struct ly_ctx *ctx, struct lysp_ext
case LY_STMT_MODULE:
case LY_STMT_SUBMODULE:
/* single (sub)module */
lysp_module_free(&fctx, *VOIDPTR2_C(substmts[u].storage));
lysp_module_free(&fctx, *substmts[u].storage_p);
break;
default:
@ -1548,7 +1550,7 @@ lyplg_ext_cfree_instance_substatements(const struct ly_ctx *ctx, struct lysc_ext
ly_bool node_free;
LY_ARRAY_FOR(substmts, u) {
if (!substmts[u].storage) {
if (!substmts[u].storage_p) {
continue;
}
@ -1568,14 +1570,14 @@ lyplg_ext_cfree_instance_substatements(const struct ly_ctx *ctx, struct lysc_ext
case LY_STMT_LIST: {
struct lysc_node *child, *child_next;
LY_LIST_FOR_SAFE(*VOIDPTR2_C(substmts[u].storage), child_next, child) {
LY_LIST_FOR_SAFE(*substmts[u].storage_p, child_next, child) {
node_free = (child->nodetype & (LYS_INPUT | LYS_OUTPUT)) ? 1 : 0;
lysc_node_free_(&fctx, child);
if (node_free) {
free(child);
}
}
*VOIDPTR2_C(substmts[u].storage) = NULL;
*substmts[u].storage_p = NULL;
break;
}
case LY_STMT_USES:
@ -1605,7 +1607,7 @@ lyplg_ext_cfree_instance_substatements(const struct ly_ctx *ctx, struct lysc_ext
case LY_STMT_REFERENCE:
case LY_STMT_UNITS: {
/* single item */
const char *str = *VOIDPTR2_C(substmts[u].storage);
const char *str = *substmts[u].storage_p;
lydict_remove(ctx, str);
break;
@ -1613,7 +1615,7 @@ lyplg_ext_cfree_instance_substatements(const struct ly_ctx *ctx, struct lysc_ext
case LY_STMT_BIT:
case LY_STMT_ENUM: {
/* sized array */
struct lysc_type_bitenum_item *items = *VOIDPTR2_C(substmts[u].storage);
struct lysc_type_bitenum_item *items = *substmts[u].storage_p;
FREE_ARRAY(&fctx, items, lysc_enum_item_free);
break;
@ -1621,47 +1623,47 @@ lyplg_ext_cfree_instance_substatements(const struct ly_ctx *ctx, struct lysc_ext
case LY_STMT_LENGTH:
case LY_STMT_RANGE: {
/* single item */
struct lysc_range *range = *VOIDPTR2_C(substmts[u].storage);
struct lysc_range *range = *substmts[u].storage_p;
lysc_range_free(&fctx, range);
break;
}
case LY_STMT_MUST: {
/* sized array */
struct lysc_must *musts = *VOIDPTR2_C(substmts[u].storage);
struct lysc_must *musts = *substmts[u].storage_p;
FREE_ARRAY(&fctx, musts, lysc_must_free);
break;
}
case LY_STMT_WHEN:
/* single item, expects a pointer */
lysc_when_free(&fctx, VOIDPTR_C(substmts[u].storage));
lysc_when_free(&fctx, (struct lysc_when **)substmts[u].storage_p);
break;
case LY_STMT_PATTERN: {
/* sized array of pointers */
struct lysc_pattern **patterns = *VOIDPTR2_C(substmts[u].storage);
struct lysc_pattern **patterns = *substmts[u].storage_p;
FREE_ARRAY(&fctx, patterns, lysc_pattern_free);
break;
}
case LY_STMT_TYPE: {
/* single item */
struct lysc_type *type = *VOIDPTR2_C(substmts[u].storage);
struct lysc_type *type = *substmts[u].storage_p;
lysc_type_free(&fctx, type);
break;
}
case LY_STMT_IDENTITY: {
/* sized array */
struct lysc_ident *idents = *VOIDPTR2_C(substmts[u].storage);
struct lysc_ident *idents = *substmts[u].storage_p;
FREE_ARRAY(&fctx, idents, lysc_ident_free);
break;
}
case LY_STMT_EXTENSION_INSTANCE: {
/* sized array */
struct lysc_ext_instance *exts = *VOIDPTR2_C(substmts[u].storage);
struct lysc_ext_instance *exts = *substmts[u].storage_p;
FREE_ARRAY(&fctx, exts, lysc_ext_instance_free);
break;

View file

@ -726,11 +726,11 @@ uint8_t lys_stmt_flags(enum ly_stmt stmt);
* @param[in] ext Compiled ext instance.
* @param[in] stmt Compiled statement. Can be a mask when the first match is returned, it is expected the storage is
* the same for all the masked statements.
* @param[out] storage_p Pointer to a compiled ext instance substatement storage, NULL if was not compiled.
* @param[out] storage_pp Pointer to a compiled ext instance substatement storage, NULL if was not compiled.
* @return LY_SUCCESS on success.
* @return LY_ENOT if the substatement is not supported.
*/
LY_ERR lyplg_ext_get_storage_p(const struct lysc_ext_instance *ext, int stmt, uint64_t *storage_p);
LY_ERR lyplg_ext_get_storage_p(const struct lysc_ext_instance *ext, int stmt, void ***storage_pp);
/**
* @brief Warning if the filename does not match the expected module name and version

View file

@ -197,13 +197,14 @@ lyd_validate_node_when(const struct lyd_node *tree, const struct lyd_node *node,
* @param[in] np_cont_diff Whether to put NP container into diff or only its children.
* @param[in,out] node Optional current iteration node, update it if it is deleted.
* @param[in,out] node_when Optional set with nodes with "when" conditions, may be removed from.
* @param[in,out] node_types Optional set with unresolved type nodes, may be removed from.
* @param[in,out] diff Validation diff.
* @return 1 if @p node auto-deleted and updated to its next sibling.
* @return 0 if @p node was not auto-deleted.
*/
static ly_bool
lyd_validate_autodel_node_del(struct lyd_node **first, struct lyd_node *del, const struct lys_module *mod,
int np_cont_diff, struct lyd_node **node, struct ly_set *node_types, struct lyd_node **diff)
int np_cont_diff, struct lyd_node **node, struct ly_set *node_when, struct ly_set *node_types, struct lyd_node **diff)
{
struct lyd_node *iter;
ly_bool node_autodel = 0;
@ -228,6 +229,16 @@ lyd_validate_autodel_node_del(struct lyd_node **first, struct lyd_node *del, con
}
}
if (node_when && node_when->count) {
/* remove nested from node_when set */
LYD_TREE_DFS_BEGIN(del, iter) {
if ((del != iter) && ly_set_contains(node_when, iter, &idx)) {
ly_set_rm_index(node_when, idx, NULL);
}
LYD_TREE_DFS_END(del, iter);
}
}
if (node_types && node_types->count) {
/* remove from node_types set */
LYD_TREE_DFS_BEGIN(del, iter) {
@ -264,7 +275,7 @@ lyd_validate_unres_when(struct lyd_node **tree, const struct lys_module *mod, st
uint32_t xpath_options, struct ly_set *node_types, struct lyd_node **diff)
{
LY_ERR rc = LY_SUCCESS, r;
uint32_t i;
uint32_t i, count;
const struct lysc_when *disabled;
struct lyd_node *node = NULL;
@ -285,7 +296,12 @@ lyd_validate_unres_when(struct lyd_node **tree, const struct lys_module *mod, st
/* when false */
if (node->flags & LYD_WHEN_TRUE) {
/* autodelete */
lyd_validate_autodel_node_del(tree, node, mod, 1, NULL, node_types, diff);
count = node_when->count;
lyd_validate_autodel_node_del(tree, node, mod, 1, NULL, node_when, node_types, diff);
if (count > node_when->count) {
/* nested nodes removed, we lost the index */
ly_set_contains(node_when, node, &i);
}
} else if (val_opts & LYD_VALIDATE_OPERATIONAL) {
/* only a warning */
LOGWRN(LYD_CTX(node), "When condition \"%s\" not satisfied.", disabled->cond->expr);
@ -640,7 +656,7 @@ lyd_validate_autodel_leaflist_dflt(struct lyd_node **first, struct lyd_node **no
LYD_LIST_FOR_INST_SAFE(*first, schema, next, iter) {
if (iter->flags & LYD_DEFAULT) {
/* default instance found, remove it */
if (lyd_validate_autodel_node_del(first, iter, mod, 0, node, NULL, diff)) {
if (lyd_validate_autodel_node_del(first, iter, mod, 0, node, NULL, NULL, diff)) {
node_autodel = 1;
}
}
@ -685,7 +701,7 @@ lyd_validate_autodel_cont_leaf_dflt(struct lyd_node **first, struct lyd_node **n
LYD_LIST_FOR_INST_SAFE(*first, schema, next, iter) {
if (iter->flags & LYD_DEFAULT) {
/* default instance, remove it */
if (lyd_validate_autodel_node_del(first, iter, mod, 0, node, NULL, diff)) {
if (lyd_validate_autodel_node_del(first, iter, mod, 0, node, NULL, NULL, diff)) {
node_autodel = 1;
}
}
@ -695,7 +711,7 @@ lyd_validate_autodel_cont_leaf_dflt(struct lyd_node **first, struct lyd_node **n
LYD_LIST_FOR_INST(*first, schema, iter) {
if ((iter->flags & LYD_DEFAULT) && !(iter->flags & LYD_NEW)) {
/* old default instance, remove it */
if (lyd_validate_autodel_node_del(first, iter, mod, 0, node, NULL, diff)) {
if (lyd_validate_autodel_node_del(first, iter, mod, 0, node, NULL, NULL, diff)) {
node_autodel = 1;
}
break;
@ -753,7 +769,7 @@ lyd_validate_autodel_case_dflt(struct lyd_node **first, struct lyd_node **node,
if (!iter) {
/* there are only default nodes of the case meaning it does not exist and neither should any default nodes
* of the case, remove this one default node */
if (lyd_validate_autodel_node_del(first, *node, mod, 0, node, NULL, diff)) {
if (lyd_validate_autodel_node_del(first, *node, mod, 0, node, NULL, NULL, diff)) {
node_autodel = 1;
}
}

View file

@ -16,6 +16,8 @@
#ifndef LY_VERSION_H_
#define LY_VERSION_H_
#include "ly_config.h"
#ifdef __cplusplus
extern "C" {
#endif
@ -30,22 +32,61 @@ extern "C" {
#define LY_PROJ_VERSION_MICRO @LIBYANG_MICRO_VERSION@ /**< project micro version number */
#define LY_PROJ_VERSION "@LIBYANG_VERSION@" /**< project version string */
struct ly_version {
uint32_t major; /**< Major version number */
uint32_t minor; /**< Minor version number */
uint32_t micro; /**< Micro version number */
const char *str; /**< Version string */
};
/**
* @brief Get libyang major SO version.
*
* @return LY version.
*/
LIBYANG_API_DECL uint32_t ly_version_so_major(void);
/**
* @brief libyang SO version.
* @brief Get libyang minor SO version.
*
* @return LY version.
*/
LIBYANG_API_DECL extern struct ly_version ly_version_so;
LIBYANG_API_DECL uint32_t ly_version_so_minor(void);
/**
* @brief libyang project version.
* @brief Get libyang micro SO version.
*
* @return LY version.
*/
LIBYANG_API_DECL extern struct ly_version ly_version_proj;
LIBYANG_API_DECL uint32_t ly_version_so_micro(void);
/**
* @brief Get libyang string SO version.
*
* @return LY version.
*/
LIBYANG_API_DECL const char *ly_version_so_str(void);
/**
* @brief Get libyang major project version.
*
* @return LY version.
*/
LIBYANG_API_DECL uint32_t ly_version_proj_major(void);
/**
* @brief Get libyang minor project version.
*
* @return LY version.
*/
LIBYANG_API_DECL uint32_t ly_version_proj_minor(void);
/**
* @brief Get libyang micro project version.
*
* @return LY version.
*/
LIBYANG_API_DECL uint32_t ly_version_proj_micro(void);
/**
* @brief Get libyang string project version.
*
* @return LY version.
*/
LIBYANG_API_DECL const char *ly_version_proj_str(void);
#ifdef __cplusplus
}

View file

@ -330,7 +330,7 @@ print_set_debug(struct lyxp_set *set)
(lyd_child(item->node)->schema->nodetype == LYS_LEAF)) {
LOGDBG(LY_LDGXPATH, "\t%d (pos %u): ELEM %s (1st child val: %s)", i + 1, item->pos,
item->node->schema->name, lyd_get_value(lyd_child(item->node)));
} else if ((!item->node->schema && !lyd_child(item->node)) || (item->node->schema->nodetype == LYS_LEAFLIST)) {
} else if (lyd_get_value(item->node)) {
LOGDBG(LY_LDGXPATH, "\t%d (pos %u): ELEM %s (val: %s)", i + 1, item->pos,
LYD_NAME(item->node), lyd_get_value(item->node));
} else {
@ -4042,7 +4042,7 @@ xpath_deref(struct lyxp_set **args, uint32_t UNUSED(arg_count), struct lyxp_set
if (!r) {
/* get the target node */
target = p[LY_ARRAY_COUNT(p) - 1].node;
ly_path_free(set->ctx, p);
ly_path_free(p);
LY_CHECK_RET(lyxp_set_scnode_insert_node(set, target, LYXP_NODE_ELEM, LYXP_AXIS_SELF, NULL));
} /* else the target was found before but is disabled so it was removed */
@ -8272,7 +8272,9 @@ cleanup:
options &= ~LYXP_SKIP_EXPR;
}
lydict_remove(set->ctx, ncname_dict);
ly_path_predicates_free(set->ctx, predicates);
if (predicates) {
ly_path_predicates_free(scnode->module->ctx, predicates);
}
return rc;
}

View file

@ -80,7 +80,7 @@ module notifications {
}
}
/*container notification {
container notification {
description "internal struct to start a notification";
config false;
@ -90,6 +90,6 @@ module notifications {
}
// eventType and any data content goes here
}*/
}
}

View file

@ -580,6 +580,9 @@ test_dup_siblings_to_empty(struct test_state *state, struct timespec *ts_start,
TEST_END(ts_end);
/* need to remove the duplicated nodes if the test is repeated */
lyd_free_siblings(lyd_child(state->data1));
return LY_SUCCESS;
}

View file

@ -831,8 +831,8 @@ check_ext_instance_priv_parsed_is_set(struct lysc_ext_instance *ext)
LY_ARRAY_FOR(ext, u) {
substmts = ext[u].substmts;
LY_ARRAY_FOR(substmts, v) {
if (substmts && substmts[v].storage && (substmts[v].stmt & LY_STMT_DATA_NODE_MASK)) {
cnode = *(struct lysc_node **)substmts[v].storage;
if (substmts && substmts[v].storage_p && (substmts[v].stmt & LY_STMT_DATA_NODE_MASK)) {
cnode = *(struct lysc_node **)substmts[v].storage_p;
iter = check;
assert_int_equal(LY_SUCCESS, lysc_tree_dfs_full(cnode, check_node_priv_parsed_is_set, &iter));
}
@ -850,8 +850,8 @@ check_ext_instance_priv_parsed_not_set(struct lysc_ext_instance *ext)
LY_ARRAY_FOR(ext, u) {
substmts = ext[u].substmts;
LY_ARRAY_FOR(substmts, v) {
if (substmts && substmts[v].storage && (substmts[v].stmt & LY_STMT_DATA_NODE_MASK)) {
cnode = *(struct lysc_node **)substmts[v].storage;
if (substmts && substmts[v].storage_p && (substmts[v].stmt & LY_STMT_DATA_NODE_MASK)) {
cnode = *(struct lysc_node **)substmts[v].storage_p;
if (cnode) {
CHECK_POINTER((struct lysp_node *)cnode->priv, 0);
}

View file

@ -193,6 +193,18 @@ test_anyxml(void **state)
free(str);
CHECK_LYD_STRING(tree, LYD_PRINT_WITHSIBLINGS, data_expected);
lyd_free_all(tree);
data = "<anyx xmlns=\"urn:tests:a\"><x>1</x><x>0</x><x>-1</x><x>4294967295</x><x>4294967296</x><x>-2147483648</x><x>-2147483649</x></anyx>";
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
assert_non_null(tree);
tree = tree->next;
assert_int_equal(LY_SUCCESS, lyd_print_mem(&str, tree, LYD_XML, LYD_PRINT_SHRINK));
CHECK_STRING(str, data);
free(str);
assert_int_equal(LY_SUCCESS, lyd_print_mem(&str, tree, LYD_JSON, LYD_PRINT_SHRINK));
CHECK_STRING(str, "{\"a:anyx\":{\"x\":[1,0,-1,4294967295,\"4294967296\",-2147483648,\"-2147483649\"]}}");
free(str);
lyd_free_all(tree);
}
static void
@ -349,7 +361,7 @@ test_opaq(void **state)
" <c xmld:id=\"D\">1</c>\n"
"</a>\n",
LYD_XML, LYD_PARSE_OPAQ, LYD_VALIDATE_PRESENT, &tree));
CHECK_LOG_CTX("Unknown XML prefix \"xmld\".", "/a", 3);
CHECK_LOG_CTX("Unknown XML prefix \"xmld\" at attribute \"id\".", "/a", 3);
}
static void

View file

@ -409,7 +409,7 @@ test_target(void **state)
assert_string_equal(lyd_get_value(term->prev), "b");
lyd_free_all(tree);
ly_path_free(UTEST_LYCTX, path);
ly_path_free(path);
lyxp_expr_free(UTEST_LYCTX, exp);
}

View file

@ -130,6 +130,57 @@ test_insert_cont_leaflist(void **state)
lyd_free_all(cont);
}
static void
test_dup_sort(void **state)
{
const char *schema;
struct lys_module *mod;
struct lyd_node *cont, *cont2;
char *str;
schema = "module a {namespace urn:tests:a;prefix a;yang-version 1.1;revision 2014-05-08;"
"container cn { list lst {key \"k\"; leaf k {type uint32;}}}}";
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod);
assert_int_equal(lyd_new_inner(NULL, mod, "cn", 0, &cont), LY_SUCCESS);
assert_int_equal(lyd_new_list(cont, NULL, "lst", 0, NULL, "2"), LY_SUCCESS);
assert_int_equal(lyd_new_list(cont, NULL, "lst", 0, NULL, "5"), LY_SUCCESS);
assert_int_equal(lyd_new_list(cont, NULL, "lst", 0, NULL, "9"), LY_SUCCESS);
assert_int_equal(lyd_new_inner(NULL, mod, "cn", 0, &cont2), LY_SUCCESS);
assert_int_equal(lyd_new_list(cont2, NULL, "lst", 0, NULL, "1"), LY_SUCCESS);
assert_int_equal(lyd_new_list(cont2, NULL, "lst", 0, NULL, "3"), LY_SUCCESS);
assert_int_equal(lyd_new_list(cont2, NULL, "lst", 0, NULL, "8"), LY_SUCCESS);
assert_int_equal(lyd_dup_siblings(lyd_child(cont2), (struct lyd_node_inner *)cont, 0, NULL), LY_SUCCESS);
lyd_print_mem(&str, cont, LYD_XML, 0);
assert_string_equal(str,
"<cn xmlns=\"urn:tests:a\">\n"
" <lst>\n"
" <k>1</k>\n"
" </lst>\n"
" <lst>\n"
" <k>2</k>\n"
" </lst>\n"
" <lst>\n"
" <k>3</k>\n"
" </lst>\n"
" <lst>\n"
" <k>5</k>\n"
" </lst>\n"
" <lst>\n"
" <k>8</k>\n"
" </lst>\n"
" <lst>\n"
" <k>9</k>\n"
" </lst>\n"
"</cn>\n");
free(str);
lyd_free_all(cont);
lyd_free_all(cont2);
}
static void
test_try_user_order_func(void **state)
{
@ -1599,6 +1650,7 @@ main(void)
UTEST(test_insert_top_level_leaflist),
UTEST(test_insert_cont_list),
UTEST(test_insert_cont_leaflist),
UTEST(test_dup_sort),
UTEST(test_try_user_order_func),
UTEST(test_ordered_by_user),
UTEST(test_remove),

View file

@ -1712,7 +1712,7 @@ test_extension_compile(void **state)
LY_ARRAY_NEW_GOTO(UTEST_LYCTX, ext_p.substmts, substmtp, rc, cleanup);
substmtp->stmt = LY_STMT_ERROR_MESSAGE;
substmtp->storage = (uintptr_t)(void *)&ext_p.parsed;
substmtp->storage_p = &ext_p.parsed;
/* fake parse */
lydict_insert(UTEST_LYCTX, "my error", 0, (const char **)&ext_p.parsed);
@ -1721,7 +1721,7 @@ test_extension_compile(void **state)
LY_ARRAY_NEW_GOTO(UTEST_LYCTX, ext_c.substmts, substmt, rc, cleanup);
substmt->stmt = LY_STMT_ERROR_MESSAGE;
substmt->storage = (uintptr_t)(void *)&ext_c.compiled;
substmt->storage_p = &ext_c.compiled;
/*
* error-message

View file

@ -1233,6 +1233,7 @@ test_type_instanceid(void **state)
{
struct lys_module *mod;
struct lysc_type *type;
char *str;
assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, "module a {namespace urn:a;prefix a;typedef mytype {type instance-identifier {require-instance false;}}"
"leaf l1 {type instance-identifier {require-instance true;}}"
@ -1252,12 +1253,22 @@ test_type_instanceid(void **state)
assert_int_equal(LY_TYPE_INST, type->basetype);
assert_int_equal(1, ((struct lysc_type_instanceid *)type)->require_instance);
/* default value */
str = "module b1 {namespace urn:b1;prefix b1;"
"leaf l1 {type string;}}";
ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, str);
ly_ctx_set_options(UTEST_LYCTX, LY_CTX_REF_IMPLEMENTED);
assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, "module b2 {namespace urn:b2;prefix b2;"
"import b1 {prefix b1;}"
"leaf l1 {type instance-identifier; default \"/b1:l1\";}}", LYS_IN_YANG, NULL));
ly_ctx_set_options(UTEST_LYCTX, 0);
/* invalid cases */
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module aa {namespace urn:aa;prefix aa; leaf l {type instance-identifier {require-instance yes;}}}", LYS_IN_YANG, &mod));
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module aa {namespace urn:aa;prefix aa; leaf l {type instance-identifier {require-instance yes;}}}", LYS_IN_YANG, NULL));
CHECK_LOG_CTX("Parsing module \"aa\" failed.", NULL, 0);
CHECK_LOG_CTX("Invalid value \"yes\" of \"require-instance\".", NULL, 1);
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module aa {namespace urn:aa;prefix aa; leaf l {type instance-identifier {fraction-digits 1;}}}", LYS_IN_YANG, &mod));
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module aa {namespace urn:aa;prefix aa; leaf l {type instance-identifier {fraction-digits 1;}}}", LYS_IN_YANG, NULL));
CHECK_LOG_CTX("Invalid type restrictions for instance-identifier type.", "/aa:l", 0);
}

View file

@ -284,8 +284,6 @@ test_arg(void **state)
TEST_GET_ARGUMENT_SUCCESS("hello ", YCTX, Y_STR_ARG, "hello ", 5, " ", 1);
TEST_GET_ARGUMENT_SUCCESS("hello/*comment*/\n", YCTX, Y_STR_ARG, "hello/*comment*/\n", 5, "\n", 1);
TEST_GET_ARGUMENT_SUCCESS("\"hello\\n\\t\\\"\\\\\";", YCTX, Y_STR_ARG, "hello\n\t\"\\", 9, ";", 1);
free(buf);

View file

@ -112,14 +112,13 @@ test_data_xml(void **state)
TEST_SUCCESS_XML("a", "l", "2021-02-29T00:00:00-00:00", STRING, "2021-03-01T00:00:00-00:00");
TEST_ERROR_XML("a", "l", "2005-05-31T23:15:15.-08:00", LY_EVALID);
CHECK_LOG_CTX("Unsatisfied pattern - \"2005-05-31T23:15:15.-08:00\" does not conform to "
"\"\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d+)?(Z|[\\+\\-]\\d{2}:\\d{2})\".",
CHECK_LOG_CTX("Missing date-and-time fractions after '.'.",
"/a:l", 1);
TEST_ERROR_XML("a", "l", "2023-16-15T20:13:01+01:00", LY_EINVAL);
TEST_ERROR_XML("a", "l", "2023-16-15T20:13:01+01:00", LY_EVALID);
CHECK_LOG_CTX("Invalid date-and-time month \"15\".", "/a:l", 1);
TEST_ERROR_XML("a", "l", "2023-10-15T20:13:01+95:00", LY_EINVAL);
TEST_ERROR_XML("a", "l", "2023-10-15T20:13:01+95:00", LY_EVALID);
CHECK_LOG_CTX("Invalid date-and-time timezone hour \"95\".", "/a:l", 1);
/* hex-string */

View file

@ -1,33 +0,0 @@
source [expr {[info exists ::env(TESTS_DIR)] ? "$env(TESTS_DIR)/interactive/ly.tcl" : "ly.tcl"}]
set mdir $::env(YANG_MODULES_DIR)
test debug_dict {Check debug message DICT} {
-setup $ly_setup -cleanup $ly_cleanup -constraints {[yanglint_debug]} -body {
ly_cmd "verb debug"
ly_cmd "debug dict"
ly_cmd "load modleaf" "DICT"
}}
test debug_xpath {Check debug message XPATH} {
-setup $ly_setup -cleanup $ly_cleanup -constraints {[yanglint_debug]} -body {
ly_cmd "verb debug"
ly_cmd "debug xpath"
ly_cmd "load modmust" "XPATH"
}}
test debug_dep_sets {Check debug message DEPSETS} {
-setup $ly_setup -cleanup $ly_cleanup -constraints {[yanglint_debug]} -body {
ly_cmd "verb debug"
ly_cmd "debug dep-sets"
ly_cmd "load modleaf" "DEPSETS"
}}
test debug_depsets_xpath {Check debug message DEPSETS and XPATH} {
-setup $ly_setup -cleanup $ly_cleanup -constraints {[yanglint_debug]} -body {
ly_cmd "verb debug"
ly_cmd "debug dep-sets xpath"
ly_cmd "load modmust" "DEPSETS.*XPATH"
}}
cleanupTests

View file

@ -65,17 +65,3 @@ proc ly_exit {} {
send "exit\r"
expect eof
}
# Check if yanglint is configured as DEBUG.
# Return 1 on success.
proc yanglint_debug {} {
global TUT
# Call non-interactive yanglint with --help.
set output [exec -- $TUT "-h"]
# Find option --debug.
if { [regexp -- "--debug=GROUPS" $output] } {
return 1
} else {
return 0
}
}

View file

@ -224,7 +224,7 @@ get_schema_completion(const char *hint, char ***matches, unsigned int *match_cou
uint32_t idx;
const char *start;
char *end, *module_name = NULL, *path = NULL;
const struct lysc_node *parent, *last_node;
const struct lysc_node *parent, *last_node = NULL;
int rc = 0;
size_t len;