1
0
Fork 0

Adding 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:49 +01:00
parent cfcebb1a7d
commit 338ffded6d
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" build-cmd: "make"
} }
- { - {
name: "Release, macOS 11, clang", name: "Release, macOS 14, clang",
os: "macos-11", os: "macos-14",
build-type: "Release", build-type: "Release",
cc: "clang", cc: "clang",
options: "-DENABLE_TESTS=ON -DPATH_EXPECT=", options: "-DENABLE_TESTS=ON -DPATH_EXPECT=",
packager: "brew", packager: "brew",
packages: "cmocka shunit2", packages: "cmocka shunit2 tcl-tk",
snaps: "", snaps: "",
build-cmd: "make" build-cmd: "make"
} }

View file

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

View file

@ -58,8 +58,6 @@ the `distro` directory.
* C compiler * C compiler
* cmake >= 2.8.12 * cmake >= 2.8.12
* libpcre2 >= 10.21 (including devel package) * 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 #### Optional

View file

@ -721,7 +721,7 @@ ly_ctx_unset_options(struct ly_ctx *ctx, uint16_t option)
ext = &mod->compiled->exts[u]; ext = &mod->compiled->exts[u];
LY_ARRAY_FOR(ext->substmts, v) { LY_ARRAY_FOR(ext->substmts, v) {
if (ext->substmts[v].stmt & LY_STMT_DATA_NODE_MASK) { 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); 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); 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. * 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 * (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. * 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 * 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 * 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. * 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); 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; str1 = ((struct ly_dict_rec *)val1_p)->value;
str2 = ((struct ly_dict_rec *)val2_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) { if (mod) {
/* used when inserting new values */ /* used when inserting new values */
if (strcmp(str1, str2) == 0) { if (strcmp(str1, str2) == 0) {
@ -177,7 +174,7 @@ finish:
return ret; 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) dict_insert(const struct ly_ctx *ctx, char *value, size_t len, ly_bool zerocopy, const char **str_p)
{ {
LY_ERR ret = LY_SUCCESS; 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; return ret;
} }
if (str_p) {
*str_p = match->value; *str_p = match->value;
}
return ret; return ret;
} }
@ -269,3 +264,49 @@ lydict_insert_zc(const struct ly_ctx *ctx, char *value, const char **str_p)
return result; 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); 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 */ /** @} dict */
#ifdef __cplusplus #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] 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] 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. * @return LY_ERR value.
*/ */
static LY_ERR 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] hash Hash to find.
* @param[in] mod Whether the operation modifies the hash table (insert or remove) or not (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[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] 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. * @param[out] rec_p Found exact matching record, may be a collision of @p crec_p.
* @return LY_ENOTFOUND if no record found, * @return LY_ENOTFOUND if no record found,
@ -255,15 +255,12 @@ lyht_resize(struct ly_ht *ht, int operation, int check)
*/ */
static LY_ERR 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, 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); uint32_t hlist_idx = hash & (ht->size - 1);
struct ly_ht_rec *rec; struct ly_ht_rec *rec;
uint32_t rec_idx; uint32_t rec_idx;
if (crec_p) {
*crec_p = NULL;
}
if (col) { if (col) {
*col = 0; *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) { 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 ((rec->hash == hash) && val_equal(val_p, &rec->val, mod, ht->cb_data)) {
if (crec_p) {
*crec_p = rec;
}
*rec_p = rec; *rec_p = rec;
return LY_SUCCESS; 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; 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) { if (rec && match_p) {
*match_p = rec->val; *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; 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) { if (rec && match_p) {
*match_p = rec->val; *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_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) 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 rec_idx;
uint32_t i; uint32_t i;
/* find the record of the previously found value */ /* 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 */ /* not found, cannot happen */
LOGINT_RET(NULL); 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; uint32_t rec_idx;
if (check) { 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) { if (rec && match_p) {
*match_p = rec->val; *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 prev_rec_idx;
uint32_t 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); LOGARG(NULL, hash);
return LY_ENOTFOUND; return LY_ENOTFOUND;
} }

View file

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

View file

@ -40,19 +40,53 @@
#include "version.h" #include "version.h"
#include "xml.h" #include "xml.h"
LIBYANG_API_DEF struct ly_version ly_version_so = { LIBYANG_API_DEF uint32_t
.major = LY_VERSION_MAJOR, ly_version_so_major(void)
.minor = LY_VERSION_MINOR, {
.micro = LY_VERSION_MICRO, return LY_VERSION_MAJOR;
.str = LY_VERSION }
};
LIBYANG_API_DEF struct ly_version ly_version_proj = { LIBYANG_API_DEF uint32_t
.major = LY_PROJ_VERSION_MAJOR, ly_version_so_minor(void)
.minor = LY_PROJ_VERSION_MINOR, {
.micro = LY_PROJ_VERSION_MICRO, return LY_VERSION_MINOR;
.str = LY_PROJ_VERSION }
};
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 * void *
ly_realloc(void *ptr, size_t size) 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 GETMACRO6(_1, _2, _3, _4, _5, _6, NAME, ...) NAME
#define GETMACRO7(_1, _2, _3, _4, _5, _6, _7, 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 * Logger
*****************************************************************************/ *****************************************************************************/

View file

@ -3,7 +3,7 @@
* @author Michal Vasko <mvasko@cesnet.cz> * @author Michal Vasko <mvasko@cesnet.cz>
* @brief libyang common parser functions. * @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"). * 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 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; LY_ERR rc = LY_SUCCESS;
struct ly_ctx *ctx = (struct ly_ctx *)LYD_CTX(node); struct ly_ctx *ctx = (struct ly_ctx *)LYD_CTX(node);
struct lysc_ctx cctx; struct lysc_ctx cctx = {0};
const struct lys_module *mod; const struct lys_module *mod1, *mod2;
const struct lysc_node *schema;
LY_ARRAY_COUNT_TYPE u; LY_ARRAY_COUNT_TYPE u;
struct ly_err_item *err = NULL; struct ly_err_item *err = NULL;
struct lysp_type *type_p = NULL; struct lysp_type *type_p = NULL;
struct lysc_pattern **patterns = NULL; struct lysc_pattern **patterns = NULL;
const char *value; 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); LYSC_CTX_INIT_CTX(cctx, ctx);
/* get date-and-time parsed type */ /* get date-and-time parsed type */
mod = ly_ctx_get_module_latest(ctx, "ietf-yang-types"); LY_ARRAY_FOR(mod2->parsed->typedefs, u) {
assert(mod); if (!strcmp(mod2->parsed->typedefs[u].name, "date-and-time")) {
LY_ARRAY_FOR(mod->parsed->typedefs, u) { type_p = &mod2->parsed->typedefs[u].type;
if (!strcmp(mod->parsed->typedefs[u].name, "date-and-time")) {
type_p = &mod->parsed->typedefs[u].type;
break; break;
} }
} }
@ -98,6 +111,7 @@ lyd_parser_notif_eventtime_validate(const struct lyd_node *node)
/* validate */ /* validate */
value = lyd_get_value(node); value = lyd_get_value(node);
rc = lyplg_type_validate_patterns(patterns, value, strlen(value), &err); rc = lyplg_type_validate_patterns(patterns, value, strlen(value), &err);
}
cleanup: cleanup:
FREE_ARRAY(&cctx.free_ctx, patterns, lysc_pattern_free); 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; LY_ERR rc = LY_SUCCESS;
if (!substmt->storage) { if (!substmt->storage_p) {
/* nothing to parse, ignored */ /* nothing to parse, ignored */
goto cleanup; 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); LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, (void **)&pnode, NULL), cleanup);
/* usually is a linked-list of all the parsed schema nodes */ /* 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) { while (*pnodes_p) {
pnodes_p = &(*pnodes_p)->next; 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_TYPEDEF:
case LY_STMT_UNIQUE: case LY_STMT_UNIQUE:
/* parse, sized array */ /* 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; break;
case LY_STMT_ARGUMENT: 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_YANG_VERSION:
case LY_STMT_YIN_ELEMENT: case LY_STMT_YIN_ELEMENT:
/* single item */ /* single item */
if (*VOIDPTR2_C(substmt->storage)) { if (*substmt->storage_p) {
LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt); LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
rc = LY_EVALID; rc = LY_EVALID;
goto cleanup; goto cleanup;
} }
/* parse */ /* 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; break;
case LY_STMT_CONFIG: case LY_STMT_CONFIG:
/* single item */ /* 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); LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
rc = LY_EVALID; rc = LY_EVALID;
goto cleanup; goto cleanup;
} }
/* parse */ /* 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; break;
case LY_STMT_ORDERED_BY: case LY_STMT_ORDERED_BY:
/* single item */ /* 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); LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
rc = LY_EVALID; rc = LY_EVALID;
goto cleanup; goto cleanup;
} }
/* parse */ /* 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; break;
case LY_STMT_STATUS: case LY_STMT_STATUS:
/* single item */ /* 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); LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
rc = LY_EVALID; rc = LY_EVALID;
goto cleanup; goto cleanup;
} }
/* parse */ /* 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; break;
default: default:

View file

@ -53,6 +53,30 @@ lyd_xml_ctx_free(struct lyd_ctx *lydctx)
free(ctx); 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. * @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) { if (lydctx->parse_opts & LYD_PARSE_STRICT) {
LOGVAL(xmlctx->ctx, LYVE_REFERENCE, "Missing mandatory prefix for XML metadata \"%.*s\".", LOGVAL(xmlctx->ctx, LYVE_REFERENCE, "Missing mandatory prefix for XML metadata \"%.*s\".",
(int)xmlctx->name_len, xmlctx->name); (int)xmlctx->name_len, xmlctx->name);
ret = LY_EVALID; /* If LYD_VALIDATE_MULTI_ERROR is set, then continue parsing, because otherwise the parser context
goto cleanup; * 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 */ /* 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 */ /* get namespace of the attribute to find its annotation definition */
ns = lyxml_ns_get(&xmlctx->ns, xmlctx->prefix, xmlctx->prefix_len); ns = lyxml_ns_get(&xmlctx->ns, xmlctx->prefix, xmlctx->prefix_len);
if (!ns) { if (!ns) {
/* unknown namespace, XML error */ lydxml_log_namespace_err(xmlctx, xmlctx->prefix, xmlctx->prefix_len, xmlctx->name, xmlctx->name_len);
LOGVAL(xmlctx->ctx, LYVE_REFERENCE, "Unknown XML prefix \"%.*s\".", (int)xmlctx->prefix_len, xmlctx->prefix);
ret = LY_ENOTFOUND; ret = LY_ENOTFOUND;
goto cleanup; goto cleanup;
} }
@ -215,7 +240,7 @@ lydxml_attrs(struct lyxml_ctx *xmlctx, struct lyd_attr **attr)
if (prefix_len) { if (prefix_len) {
ns = lyxml_ns_get(&xmlctx->ns, prefix, prefix_len); ns = lyxml_ns_get(&xmlctx->ns, prefix, prefix_len);
if (!ns) { 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; ret = LY_EVALID;
goto cleanup; 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; struct lyd_node_opaq *opaq;
char *ptr; 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; *hints = 0;
*anchor = NULL; *anchor = NULL;
@ -453,11 +480,11 @@ lydxml_get_hints_opaq(const char *name, size_t name_len, const char *value, size
/* boolean value */ /* boolean value */
*hints |= LYD_VALHINT_BOOLEAN; *hints |= LYD_VALHINT_BOOLEAN;
} else { } else {
num = strtol(value, &ptr, 10); num = strtoll(value, &ptr, 10);
if ((unsigned)(ptr - value) == value_len) { if ((unsigned)(ptr - value) == value_len) {
/* number value */ /* number value */
*hints |= LYD_VALHINT_DECNUM; *hints |= LYD_VALHINT_DECNUM;
if ((num < INT32_MIN) || (num > (long)UINT32_MAX)) { if ((num < INT32_MIN) || (num > UINT32_MAX)) {
/* large number */ /* large number */
*hints |= LYD_VALHINT_NUM64; *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) { if (lydctx->int_opts & LYD_INTOPT_ANY) {
goto unknown_module; goto unknown_module;
} }
lydxml_log_namespace_err(xmlctx, prefix, prefix_len, NULL, 0);
if (prefix_len) {
LOGVAL(ctx, LYVE_REFERENCE, "Unknown XML prefix \"%.*s\".", (int)prefix_len, prefix);
} else {
LOGVAL(ctx, LYVE_REFERENCE, "Missing XML namespace.");
}
return LY_EVALID; return LY_EVALID;
} }
@ -1056,14 +1078,13 @@ lydxml_subtree_r(struct lyd_xml_ctx *lydctx, struct lyd_node *parent, struct lyd
/* create metadata/attributes */ /* create metadata/attributes */
if (xmlctx->status == LYXML_ATTRIBUTE) { if (xmlctx->status == LYXML_ATTRIBUTE) {
if (snode) { if (snode) {
rc = lydxml_metadata(lydctx, snode, &meta); r = lydxml_metadata(lydctx, snode, &meta);
LY_CHECK_GOTO(rc, cleanup);
} else { } else {
assert(lydctx->parse_opts & LYD_PARSE_OPAQ); assert(lydctx->parse_opts & LYD_PARSE_OPAQ);
rc = lydxml_attrs(xmlctx, &attr); r = lydxml_attrs(xmlctx, &attr);
LY_CHECK_GOTO(rc, cleanup);
} }
} }
LY_DPARSER_ERR_GOTO(r, rc = r, lydctx, cleanup);
assert(xmlctx->status == LYXML_ELEM_CONTENT); assert(xmlctx->status == LYXML_ELEM_CONTENT);
if (!snode) { if (!snode) {
@ -1175,7 +1196,7 @@ lydxml_envelope(struct lyxml_ctx *xmlctx, const char *name, const char *uri, ly_
prefix_len = xmlctx->prefix_len; prefix_len = xmlctx->prefix_len;
ns = lyxml_ns_get(&xmlctx->ns, prefix, prefix_len); ns = lyxml_ns_get(&xmlctx->ns, prefix, prefix_len);
if (!ns) { 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; return LY_EVALID;
} else if (strcmp(ns->uri, uri)) { } else if (strcmp(ns->uri, uri)) {
/* different namespace */ /* different namespace */
@ -1399,7 +1420,7 @@ lydxml_opaq_r(struct lyxml_ctx *xmlctx, struct lyd_node *parent)
prefix_len = xmlctx->prefix_len; prefix_len = xmlctx->prefix_len;
ns = lyxml_ns_get(&xmlctx->ns, prefix, prefix_len); ns = lyxml_ns_get(&xmlctx->ns, prefix, prefix_len);
if (!ns) { 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; 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; size_t buf_len = 0;
uint8_t prefix = 0; uint8_t prefix = 0;
ly_bool str_end = 0; ly_bool str_end = 0;
int comment;
/* word buffer - dynamically allocated */ /* word buffer - dynamically allocated */
*word_b = NULL; *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; str_end = 1;
break; break;
case '/': case '/':
comment = 0;
if (ctx->in->current[1] == '/') { if (ctx->in->current[1] == '/') {
/* one-line comment */ /* one-line comment */
MOVE_INPUT(ctx, 2); comment = 1;
LY_CHECK_GOTO(ret = skip_comment(ctx, 1), error);
} else if (ctx->in->current[1] == '*') { } else if (ctx->in->current[1] == '*') {
/* block comment */ /* block comment */
MOVE_INPUT(ctx, 2); comment = 2;
LY_CHECK_GOTO(ret = skip_comment(ctx, 2), error);
} else { } else {
/* not a comment after all */ /* 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); 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; break;
case ' ': case ' ':
if (*word_len) { if (*word_len) {
@ -838,6 +851,8 @@ keyword_start:
/* fall through */ /* fall through */
default: default:
MOVE_INPUT(ctx, 1); MOVE_INPUT(ctx, 1);
/* fall through */
case '\0':
LOGVAL_PARSER(ctx, LY_VCODE_INSTREXP, (int)(ctx->in->current - word_start), word_start, LOGVAL_PARSER(ctx, LY_VCODE_INSTREXP, (int)(ctx->in->current - word_start), word_start,
"a keyword followed by a separator"); "a keyword followed by a separator");
return LY_EVALID; 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; e->parent_stmt_index = parent_stmt_index;
YANG_READ_SUBSTMT_FOR_GOTO(ctx, kw, word, word_len, ret, cleanup) { 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) 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: cleanup:

View file

@ -4,7 +4,7 @@
* @author Michal Vasko <mvasko@cesnet.cz> * @author Michal Vasko <mvasko@cesnet.cz>
* @brief YIN parser. * @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"). * 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 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) { if (ctx->xmlctx->ws_only) {
LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx)); LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
while (ctx->xmlctx->status == LYXML_ELEMENT) { 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)); LY_CHECK_RET(yin_parse_element_generic(ctx, LY_STMT_EXTENSION_INSTANCE, &new_subelem));
if (!e->child) { if (!e->child) {
e->child = new_subelem; 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); assert(ctx->xmlctx->status == LYXML_ELEM_CLOSE);
LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx)); 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) { } else if (ctx->xmlctx->value_len) {
/* invalid text content */ /* invalid text content */
LOGVAL_PARSER(ctx, LYVE_SYNTAX, "Extension instance \"%s\" with unexpected text content \"%.*s\".", ext_name, 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 */ /* store the value */
LOG_LOCSET(key, NULL); 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); NULL, format, prefix_data, LYD_HINT_DATA, key, NULL);
LOG_LOCBACK(1, 0); LOG_LOCBACK(1, 0);
LY_CHECK_ERR_GOTO(ret, p->value.realtype = NULL, cleanup); 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 */ /* names (keys) are unique - it was checked when parsing */
LOGVAL(ctx, LYVE_XPATH, "Predicate missing for a key of %s \"%s\" in path.", LOGVAL(ctx, LYVE_XPATH, "Predicate missing for a key of %s \"%s\" in path.",
lys_nodetype2str(ctx_node->nodetype), ctx_node->name); 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; *predicates = NULL;
ret = LY_EVALID; ret = LY_EVALID;
goto cleanup; goto cleanup;
@ -771,12 +771,10 @@ ly_path_compile_predicate(const struct ly_ctx *ctx, const struct lysc_node *cur_
} }
/* store the value */ /* store the value */
if (ctx_node) {
LOG_LOCSET(ctx_node, NULL); LOG_LOCSET(ctx_node, NULL);
} ret = lyd_value_store(ctx_node->module->ctx, &p->value, ((struct lysc_node_leaflist *)ctx_node)->type, val, val_len, 0, 0,
ret = lyd_value_store(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); 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); LY_CHECK_ERR_GOTO(ret, p->value.realtype = NULL, cleanup);
++(*tok_idx); ++(*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; lref = (const struct lysc_type_leafref *)deref_leaf_node->type;
LY_CHECK_GOTO(ret = ly_path_append(ctx, path2, path), cleanup); LY_CHECK_GOTO(ret = ly_path_append(ctx, path2, path), cleanup);
ly_path_free(ctx, path2); ly_path_free(path2);
path2 = NULL; path2 = NULL;
/* compile dereferenced leafref expression and append it to the path */ /* 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); &path2), cleanup);
node2 = path2[LY_ARRAY_COUNT(path2) - 1].node; node2 = path2[LY_ARRAY_COUNT(path2) - 1].node;
LY_CHECK_GOTO(ret = ly_path_append(ctx, path2, path), cleanup); LY_CHECK_GOTO(ret = ly_path_append(ctx, path2, path), cleanup);
ly_path_free(ctx, path2); ly_path_free(path2);
path2 = NULL; path2 = NULL;
/* properly parsed path must always continue with ')' and '/' */ /* 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); LY_CHECK_GOTO(ret = ly_path_append(ctx, path2, path), cleanup);
cleanup: cleanup:
ly_path_free(ctx, path2); ly_path_free(path2);
if (ret) { if (ret) {
ly_path_free(ctx, *path); ly_path_free(*path);
*path = NULL; *path = NULL;
} }
return ret; return ret;
@ -1283,7 +1281,7 @@ _ly_path_compile(const struct ly_ctx *ctx, const struct lys_module *cur_mod, con
cleanup: cleanup:
if (ret) { if (ret) {
ly_path_free(ctx, *path); ly_path_free(*path);
*path = NULL; *path = NULL;
} }
LOG_LOCBACK(cur_node ? 1 : 0, 0); 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 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; 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_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); 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. * @brief Free ly_path structure.
* *
* @param[in] ctx libyang context.
* @param[in] path The structure ([sized array](@ref sizedarrays)) to free. * @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_ */ #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[]; extern const struct lyplg_type_record plugins_node_instanceid[];
/*
* libnetconf2-netconf-server
*/
extern const struct lyplg_type_record plugins_time_period[];
/* /*
* lyds_tree * 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_hex_string), error);
LY_CHECK_GOTO(ret = plugins_insert(NULL, LYPLG_TYPE, plugins_xpath10), 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 */ /* ietf-netconf-acm */
LY_CHECK_GOTO(ret = plugins_insert(NULL, LYPLG_TYPE, plugins_node_instanceid), error); 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 * 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 * 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. * 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 * The external plugins are in the same phase loaded as dynamic shared objects (shared libraries) from the default directories
* variables `PLUGINS_DIR` (where the `extensions` and `types` subdirectories are added for each plugin type) or separately * specified at compile time via cmake variables `PLUGINS_DIR` (where the `extensions` and `types` subdirectories are added
* via `PLUGINS_DIR_EXTENSIONS` and `PLUGINS_DIR_TYPES` for each plugin type. The default directories can be replaced runtime * for each plugin type) or separately via `PLUGINS_DIR_EXTENSIONS` and `PLUGINS_DIR_TYPES` for each plugin type. The default
* using environment variables `LIBYANG_TYPES_PLUGINS_DIR` and `LIBYANG_EXTENSIONS_PLUGINS_DIR`. * 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 * 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 * 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. * 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 * Note, that manually added plugin via lyplg_add*() function is added with the lowest priority among other already loaded plugins.
* after it is added with the lowest priority among other already loaded plugins. Also note that since all the plugins are * Also note that since all the plugins are unloaded with the destruction of the last context, creating a new context after that
* unloaded with the destruction of the last context, creating a new context after that starts the standard plugins * starts the standard plugins initiation and the manually added plugins are not loaded automatically.
* initiation and the manually added plugins are not loaded automatically.
* *
* The following pages contain description of the API for creating user plugins. * The following pages contain description of the API for creating user plugins.
* *

View file

@ -4,7 +4,7 @@
* @author Michal Vasko <mvasko@cesnet.cz> * @author Michal Vasko <mvasko@cesnet.cz>
* @brief helper functions for extension plugins * @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"). * 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 not use this file except in compliance with the License.
@ -81,34 +81,34 @@ cleanup:
* @brief Compile an instance extension statement. * @brief Compile an instance extension statement.
* *
* @param[in] ctx Compile context. * @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] ext Compiled ext instance.
* @param[in] substmt Compled ext instance substatement info. * @param[in] substmt Compled ext instance substatement info.
* @return LY_ERR value. * @return LY_ERR value.
*/ */
static LY_ERR 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) struct lysc_ext_substmt *substmt)
{ {
LY_ERR rc = LY_SUCCESS; LY_ERR rc = LY_SUCCESS;
ly_bool length_restr = 0; ly_bool length_restr = 0;
LY_DATA_TYPE basetype; LY_DATA_TYPE basetype;
assert(parsed); assert(*parsed_p);
/* compilation wthout any storage */ /* compilation wthout any storage */
if (substmt->stmt == LY_STMT_IF_FEATURE) { if (substmt->stmt == LY_STMT_IF_FEATURE) {
ly_bool enabled; ly_bool enabled;
/* evaluate */ /* 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) { if (!enabled) {
/* it is disabled, remove the whole extension instance */ /* it is disabled, remove the whole extension instance */
rc = LY_ENOT; rc = LY_ENOT;
} }
} }
if (!substmt->storage) { if (!substmt->storage_p) {
/* nothing to store */ /* nothing to store */
goto cleanup; goto cleanup;
} }
@ -133,7 +133,7 @@ lys_compile_ext_instance_stmt(struct lysc_ctx *ctx, uint64_t parsed, struct lysc
struct lysc_node *node; struct lysc_node *node;
lyplg_ext_get_storage(ext, LY_STMT_STATUS, sizeof flags, (const void **)&flags); lyplg_ext_get_storage(ext, LY_STMT_STATUS, sizeof flags, (const void **)&flags);
pnodes = VOIDPTR_C(parsed); pnodes = *parsed_p;
/* compile nodes */ /* compile nodes */
LY_LIST_FOR(pnodes, pnode) { 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_REFERENCE:
case LY_STMT_UNITS: case LY_STMT_UNITS:
/* just make a copy */ /* 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; break;
case LY_STMT_BIT: case LY_STMT_BIT:
@ -175,7 +175,7 @@ lys_compile_ext_instance_stmt(struct lysc_ctx *ctx, uint64_t parsed, struct lysc
} }
/* compile */ /* 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); LY_CHECK_GOTO(rc, cleanup);
break; break;
@ -183,7 +183,7 @@ lys_compile_ext_instance_stmt(struct lysc_ctx *ctx, uint64_t parsed, struct lysc
uint16_t flags; uint16_t flags;
if (!(ctx->compile_opts & LYS_COMPILE_NO_CONFIG)) { if (!(ctx->compile_opts & LYS_COMPILE_NO_CONFIG)) {
memcpy(&flags, &parsed, 2); memcpy(&flags, parsed_p, 2);
if (flags & LYS_CONFIG_MASK) { if (flags & LYS_CONFIG_MASK) {
/* explicitly set */ /* explicitly set */
flags |= LYS_SET_CONFIG; flags |= LYS_SET_CONFIG;
@ -194,56 +194,56 @@ lys_compile_ext_instance_stmt(struct lysc_ctx *ctx, uint64_t parsed, struct lysc
/* default config */ /* default config */
flags = LYS_CONFIG_W; flags = LYS_CONFIG_W;
} }
memcpy(VOIDPTR_C(substmt->storage), &flags, 2); memcpy(substmt->storage_p, &flags, 2);
} /* else leave zero */ } /* else leave zero */
break; break;
} }
case LY_STMT_MUST: { case LY_STMT_MUST: {
const struct lysp_restr *restrs = VOIDPTR_C(parsed); const struct lysp_restr *restrs = *parsed_p;
/* sized array */ /* 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; break;
} }
case LY_STMT_WHEN: { case LY_STMT_WHEN: {
const uint16_t flags; const uint16_t flags;
const struct lysp_when *when = VOIDPTR_C(parsed); const struct lysp_when *when = *parsed_p;
/* read compiled status */ /* read compiled status */
lyplg_ext_get_storage(ext, LY_STMT_STATUS, sizeof flags, (const void **)&flags); lyplg_ext_get_storage(ext, LY_STMT_STATUS, sizeof flags, (const void **)&flags);
/* compile */ /* 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; break;
} }
case LY_STMT_FRACTION_DIGITS: case LY_STMT_FRACTION_DIGITS:
case LY_STMT_REQUIRE_INSTANCE: case LY_STMT_REQUIRE_INSTANCE:
/* just make a copy */ /* just make a copy */
memcpy(VOIDPTR_C(substmt->storage), &parsed, 1); memcpy(substmt->storage_p, parsed_p, 1);
break; break;
case LY_STMT_MANDATORY: case LY_STMT_MANDATORY:
case LY_STMT_ORDERED_BY: case LY_STMT_ORDERED_BY:
case LY_STMT_STATUS: case LY_STMT_STATUS:
/* just make a copy */ /* just make a copy */
memcpy(VOIDPTR_C(substmt->storage), &parsed, 2); memcpy(substmt->storage_p, parsed_p, 2);
break; break;
case LY_STMT_MAX_ELEMENTS: case LY_STMT_MAX_ELEMENTS:
case LY_STMT_MIN_ELEMENTS: case LY_STMT_MIN_ELEMENTS:
/* just make a copy */ /* just make a copy */
memcpy(VOIDPTR_C(substmt->storage), &parsed, 4); memcpy(substmt->storage_p, parsed_p, 4);
break; break;
case LY_STMT_POSITION: case LY_STMT_POSITION:
case LY_STMT_VALUE: case LY_STMT_VALUE:
/* just make a copy */ /* just make a copy */
memcpy(VOIDPTR_C(substmt->storage), &parsed, 8); memcpy(substmt->storage_p, parsed_p, 8);
break; break;
case LY_STMT_IDENTITY: case LY_STMT_IDENTITY:
/* compile */ /* 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); LY_CHECK_GOTO(rc, cleanup);
break; break;
@ -252,36 +252,36 @@ lys_compile_ext_instance_stmt(struct lysc_ctx *ctx, uint64_t parsed, struct lysc
/* fallthrough */ /* fallthrough */
case LY_STMT_RANGE: case LY_STMT_RANGE:
/* compile, use uint64 default 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); LY_CHECK_GOTO(rc, cleanup);
break; break;
case LY_STMT_PATTERN: case LY_STMT_PATTERN:
/* compile */ /* 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); LY_CHECK_GOTO(rc, cleanup);
break; break;
case LY_STMT_TYPE: { case LY_STMT_TYPE: {
const uint16_t flags; const uint16_t flags;
const char *units; const char *units;
const struct lysp_type *ptype = VOIDPTR_C(parsed); const struct lysp_type *ptype = *parsed_p;
/* read compiled info */ /* read compiled info */
lyplg_ext_get_storage(ext, LY_STMT_STATUS, sizeof flags, (const void **)&flags); 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); lyplg_ext_get_storage(ext, LY_STMT_UNITS, sizeof units, (const void **)&units);
/* compile */ /* 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_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; break;
} }
case LY_STMT_EXTENSION_INSTANCE: { case LY_STMT_EXTENSION_INSTANCE: {
struct lysp_ext_instance *extps = VOIDPTR_C(parsed); struct lysp_ext_instance *extps = *parsed_p;
/* compile sized array */ /* 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; break;
} }
case LY_STMT_AUGMENT: 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_ERR rc = LY_SUCCESS;
LY_ARRAY_COUNT_TYPE u, v; LY_ARRAY_COUNT_TYPE u, v;
enum ly_stmt stmtp; enum ly_stmt stmtp;
uint64_t storagep; void **storagep;
struct ly_set storagep_compiled = {0}; struct ly_set storagep_compiled = {0};
LY_CHECK_ARG_RET(ctx ? ctx->ctx : NULL, ctx, extp, ext, LY_EINVAL); 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) { LY_ARRAY_FOR(extp->substmts, u) {
stmtp = extp->substmts[u].stmt; 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) */ /* nothing parsed or already compiled (for example, if it is a linked list of parsed nodes) */
continue; continue;
} }
@ -361,7 +361,7 @@ lyplg_ext_compile_extension_instance(struct lysc_ctx *ctx, const struct lysp_ext
} }
/* compiled */ /* compiled */
ly_set_add(&storagep_compiled, VOIDPTR_C(storagep), 1, NULL); ly_set_add(&storagep_compiled, storagep, 1, NULL);
} }
cleanup: cleanup:
@ -420,7 +420,7 @@ lyplg_ext_sprinter_ctree_add_ext_nodes(const struct lyspr_tree_ctx *ctx, struct
uint32_t i; uint32_t i;
struct lysc_node *schema; 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) { LY_ARRAY_FOR(ext->substmts, i) {
switch (ext->substmts[i].stmt) { 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:
case LY_STMT_LEAF_LIST: case LY_STMT_LEAF_LIST:
case LY_STMT_LIST: case LY_STMT_LIST:
schema = *VOIDPTR2_C(ext->substmts[i].storage); schema = *ext->substmts[i].storage_p;
if (schema) { if (schema) {
rc = lyplg_ext_sprinter_ctree_add_nodes(ctx, schema, clb); rc = lyplg_ext_sprinter_ctree_add_nodes(ctx, schema, clb);
return rc; return rc;
@ -458,7 +458,7 @@ lyplg_ext_sprinter_ptree_add_ext_nodes(const struct lyspr_tree_ctx *ctx, struct
uint32_t i; uint32_t i;
struct lysp_node *schema; 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) { LY_ARRAY_FOR(ext->substmts, i) {
switch (ext->substmts[i].stmt) { 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:
case LY_STMT_LEAF_LIST: case LY_STMT_LEAF_LIST:
case LY_STMT_LIST: case LY_STMT_LIST:
schema = *VOIDPTR2_C(ext->substmts[i].storage); schema = *ext->substmts[i].storage_p;
if (schema) { if (schema) {
rc = lyplg_ext_sprinter_ptree_add_nodes(ctx, schema, clb); rc = lyplg_ext_sprinter_ptree_add_nodes(ctx, schema, clb);
return rc; 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; struct lyspr_tree_schema *new;
LY_CHECK_ARG_RET1(NULL, ctx, LY_EINVAL); LY_CHECK_ARG_RET(NULL, ctx, LY_EINVAL);
if (!nodes) { if (!nodes) {
return LY_SUCCESS; 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; struct lyspr_tree_schema *new;
LY_CHECK_ARG_RET1(NULL, ctx, LY_EINVAL); LY_CHECK_ARG_RET(NULL, ctx, LY_EINVAL);
if (!nodes) { if (!nodes) {
return LY_SUCCESS; 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 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)) 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)->plugin_priv = plugin_priv;
((struct lyspr_tree_ctx *)ctx)->free_plugin_priv = free_clb; ((struct lyspr_tree_ctx *)ctx)->free_plugin_priv = free_clb;
@ -587,12 +587,12 @@ lyplg_ext_nodetype2stmt(uint16_t nodetype)
} }
LY_ERR 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; LY_ARRAY_COUNT_TYPE u;
enum ly_stmt match = 0; enum ly_stmt match = 0;
*storage_p = 0; *storage_pp = NULL;
if (!(stmt & LY_STMT_NODE_MASK)) { if (!(stmt & LY_STMT_NODE_MASK)) {
/* matching a non-node statement */ /* 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) { LY_ARRAY_FOR(ext->substmts, u) {
if ((match && (ext->substmts[u].stmt == match)) || (!match && (ext->substmts[u].stmt & stmt))) { 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; 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) lyplg_ext_get_storage(const struct lysc_ext_instance *ext, int stmt, uint32_t storage_size, const void **storage)
{ {
LY_ERR rc = LY_SUCCESS; LY_ERR rc = LY_SUCCESS;
uint64_t s; void **s_p;
/* get pointer to the storage, is set even on error */ /* 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 */ /* assign */
if (s) { if (s_p) {
memcpy(storage, VOIDPTR_C(s), storage_size); memcpy(storage, s_p, storage_size);
} else { } else {
memset(storage, 0, storage_size); 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; LY_ARRAY_COUNT_TYPE u;
const struct lysp_ext_instance *extp = NULL; const struct lysp_ext_instance *extp = NULL;
enum ly_stmt match = 0; 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 */ /* find the parsed ext instance */
LY_ARRAY_FOR(ext->module->parsed->exts, u) { 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 */ /* get the substatement */
LY_ARRAY_FOR(extp->substmts, u) { LY_ARRAY_FOR(extp->substmts, u) {
if ((match && (extp->substmts[u].stmt == match)) || (!match && (extp->substmts[u].stmt & stmt))) { 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; break;
} }
} }
/* assign */ /* assign */
if (s) { if (s_p) {
memcpy(storage, VOIDPTR_C(s), storage_size); memcpy(storage, s_p, storage_size);
} else { } else {
memset(storage, 0, storage_size); memset(storage, 0, storage_size);
} }

View file

@ -109,7 +109,7 @@ extern "C" {
/** /**
* @brief Extensions API version * @brief Extensions API version
*/ */
#define LYPLG_EXT_API_VERSION 6 #define LYPLG_EXT_API_VERSION 8
/** /**
* @brief Mask for an operation statement. * @brief Mask for an operation statement.
@ -393,7 +393,7 @@ struct lysp_stmt {
*/ */
struct lysp_ext_substmt { struct lysp_ext_substmt {
enum ly_stmt stmt; /**< parsed substatement */ 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 */ lys_ext_substmt::stmt */
}; };
@ -419,6 +419,7 @@ struct lysp_ext_instance {
parsed data ([sized array](@ref sizedarrays)) */ parsed data ([sized array](@ref sizedarrays)) */
void *parsed; /**< private plugin parsed data */ void *parsed; /**< private plugin parsed data */
struct lysp_stmt *child; /**< list of generic (unknown) YANG statements */ 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 { struct lysc_ext_substmt {
enum ly_stmt stmt; /**< compiled substatement */ 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 */ 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); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[0].stmt = LY_STMT_IF_FEATURE; 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); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[1].stmt = LY_STMT_UNITS; 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); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[2].stmt = LY_STMT_STATUS; 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); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[3].stmt = LY_STMT_TYPE; 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); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[4].stmt = LY_STMT_DESCRIPTION; 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); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[5].stmt = LY_STMT_REFERENCE; 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))) { if ((r = lyplg_ext_parse_extension_instance(pctx, ext))) {
return r; return r;
@ -139,27 +139,27 @@ annotation_compile(struct lysc_ctx *cctx, const struct lysp_ext_instance *extp,
LY_ARRAY_INCREMENT(ext->substmts); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[0].stmt = LY_STMT_IF_FEATURE; ext->substmts[0].stmt = LY_STMT_IF_FEATURE;
ext->substmts[0].storage = 0; ext->substmts[0].storage_p = NULL;
LY_ARRAY_INCREMENT(ext->substmts); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[1].stmt = LY_STMT_UNITS; 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); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[2].stmt = LY_STMT_STATUS; 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); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[3].stmt = LY_STMT_TYPE; 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); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[4].stmt = LY_STMT_DESCRIPTION; 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); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[5].stmt = LY_STMT_REFERENCE; 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); ret = lyplg_ext_compile_extension_instance(cctx, extp, ext);
return ret; return ret;

View file

@ -90,60 +90,60 @@ structure_parse(struct lysp_ctx *pctx, struct lysp_ext_instance *ext)
/* parse substatements */ /* parse substatements */
LY_ARRAY_INCREMENT(ext->substmts); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[0].stmt = LY_STMT_MUST; 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); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[1].stmt = LY_STMT_STATUS; 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); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[2].stmt = LY_STMT_DESCRIPTION; 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); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[3].stmt = LY_STMT_REFERENCE; 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); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[4].stmt = LY_STMT_TYPEDEF; 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); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[5].stmt = LY_STMT_GROUPING; 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 */ /* data-def-stmt */
LY_ARRAY_INCREMENT(ext->substmts); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[6].stmt = LY_STMT_CONTAINER; 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); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[7].stmt = LY_STMT_LEAF; 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); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[8].stmt = LY_STMT_LEAF_LIST; 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); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[9].stmt = LY_STMT_LIST; 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); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[10].stmt = LY_STMT_CHOICE; 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); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[11].stmt = LY_STMT_ANYDATA; 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); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[12].stmt = LY_STMT_ANYXML; 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); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[13].stmt = LY_STMT_USES; 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); rc = lyplg_ext_parse_extension_instance(pctx, ext);
return rc; 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_CREATE_GOTO(cctx->ctx, ext->substmts, 14, rc, emem);
LY_ARRAY_INCREMENT(ext->substmts); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[0].stmt = LY_STMT_MUST; 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); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[1].stmt = LY_STMT_STATUS; 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); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[2].stmt = LY_STMT_DESCRIPTION; 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); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[3].stmt = LY_STMT_REFERENCE; 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); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[4].stmt = LY_STMT_TYPEDEF; ext->substmts[4].stmt = LY_STMT_TYPEDEF;
ext->substmts[4].storage = 0; ext->substmts[4].storage_p = 0;
LY_ARRAY_INCREMENT(ext->substmts); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[5].stmt = LY_STMT_GROUPING; ext->substmts[5].stmt = LY_STMT_GROUPING;
ext->substmts[5].storage = 0; ext->substmts[5].storage_p = 0;
/* data-def-stmt */ /* data-def-stmt */
LY_ARRAY_INCREMENT(ext->substmts); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[6].stmt = LY_STMT_CONTAINER; 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); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[7].stmt = LY_STMT_LEAF; 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); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[8].stmt = LY_STMT_LEAF_LIST; 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); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[9].stmt = LY_STMT_LIST; 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); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[10].stmt = LY_STMT_CHOICE; 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); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[11].stmt = LY_STMT_ANYDATA; 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); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[12].stmt = LY_STMT_ANYXML; 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); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[13].stmt = LY_STMT_USES; 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; *lyplg_ext_compile_get_options(cctx) |= LYS_COMPILE_NO_CONFIG | LYS_COMPILE_NO_DISABLED;
rc = lyplg_ext_compile_extension_instance(cctx, extp, ext); 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 */ /* parse substatements */
LY_ARRAY_INCREMENT(ext->substmts); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[0].stmt = LY_STMT_STATUS; 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); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[1].stmt = LY_STMT_DESCRIPTION; 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); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[2].stmt = LY_STMT_REFERENCE; 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 */ /* data-def-stmt */
LY_ARRAY_INCREMENT(ext->substmts); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[3].stmt = LY_STMT_CONTAINER; 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); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[4].stmt = LY_STMT_LEAF; 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); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[5].stmt = LY_STMT_LEAF_LIST; 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); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[6].stmt = LY_STMT_LIST; 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); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[7].stmt = LY_STMT_CHOICE; 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); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[8].stmt = LY_STMT_ANYDATA; 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); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[9].stmt = LY_STMT_ANYXML; 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); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[10].stmt = LY_STMT_USES; 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 */ /* case */
LY_ARRAY_INCREMENT(ext->substmts); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[11].stmt = LY_STMT_CASE; 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))) { if ((rc = lyplg_ext_parse_extension_instance(pctx, ext))) {
return rc; return rc;
@ -394,7 +394,7 @@ structure_aug_parse(struct lysp_ctx *pctx, struct lysp_ext_instance *ext)
/* add fake parsed augment node */ /* add fake parsed augment node */
LY_ARRAY_INCREMENT(ext->substmts); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[12].stmt = LY_STMT_AUGMENT; 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); aug_pdata->aug = calloc(1, sizeof *aug_pdata->aug);
if (!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); 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); rc = lyplg_ext_sprinter_ptree_add_nodes(ctx, (*aug)->child, structure_sprinter_pnode);
return rc; 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_CREATE_GOTO(lyplg_ext_parse_get_cur_pmod(pctx)->mod->ctx, ext->substmts, 3, ret, emem);
LY_ARRAY_INCREMENT(ext->substmts); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[0].stmt = LY_STMT_CONTAINER; 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); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[1].stmt = LY_STMT_CHOICE; 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); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[2].stmt = LY_STMT_USES; 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))) { if ((ret = lyplg_ext_parse_extension_instance(pctx, ext))) {
return ret; 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_CREATE_GOTO(cctx->ctx, ext->substmts, 3, ret, emem);
LY_ARRAY_INCREMENT(ext->substmts); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[0].stmt = LY_STMT_CONTAINER; 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); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[1].stmt = LY_STMT_CHOICE; 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); LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[2].stmt = LY_STMT_USES; 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; *lyplg_ext_compile_get_options(cctx) |= LYS_COMPILE_NO_CONFIG | LYS_COMPILE_NO_DISABLED;
ret = lyplg_ext_compile_extension_instance(cctx, extp, ext); 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 LIBYANG_API_DEF LY_ERR
lyplg_type_dup_simple(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup) 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); 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); memcpy(dup->fixed_mem, original->fixed_mem, sizeof dup->fixed_mem);
dup->realtype = original->realtype; dup->realtype = original->realtype;
return LY_SUCCESS; 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; uint32_t prefix_opt = 0;
struct ly_err_item *e; struct ly_err_item *e;
const char *err_fmt = NULL; 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; *path = NULL;
*err = 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 */ /* resolve it on schema tree */
ret = ly_path_compile(ctx, NULL, ctx_node, NULL, exp, (ctx_node->flags & LYS_IS_OUTPUT) ? oper = (ctx_node && (ctx_node->flags & LYS_IS_OUTPUT)) ? LY_PATH_OPER_OUTPUT : LY_PATH_OPER_INPUT;
LY_PATH_OPER_OUTPUT : LY_PATH_OPER_INPUT, LY_PATH_TARGET_SINGLE, 1, format, prefix_data, path); ret = ly_path_compile(ctx, NULL, ctx_node, NULL, exp, oper, LY_PATH_TARGET_SINGLE, 1, format, prefix_data, path);
if (ret) { if (ret) {
err_fmt = "Invalid instance-identifier \"%.*s\" value - semantic error%s%s"; err_fmt = "Invalid instance-identifier \"%.*s\" value - semantic error%s%s";
goto cleanup; goto cleanup;
@ -888,7 +895,7 @@ cleanup:
ly_err_clean((struct ly_ctx *)ctx, e); ly_err_clean((struct ly_ctx *)ctx, e);
} }
ly_path_free(ctx, *path); ly_path_free(*path);
*path = NULL; *path = NULL;
} }
@ -896,9 +903,9 @@ cleanup:
} }
LIBYANG_API_DEF void 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 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); LY_CHECK_GOTO(lyxp_expr_parse(ctx_node->module->ctx, str_path, 0, 1, target_path), cleanup);
cleanup: cleanup:
ly_path_free(ctx_node->module->ctx, p); ly_path_free(p);
free(str_path); free(str_path);
return rc; 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 #define LYPLG_TYPE_STORE_IMPLEMENT 0x02 /**< If a foreign module is needed to be implemented to successfully instantiate
the value, make the module implemented. */ 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_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) */ #define LYPLG_TYPE_STORE_ONLY 0x08 /**< The value is stored only, type-specific validation is skipped (performed before) */
/** @} plugintypestoreopts */ /**
* @} plugintypestoreopts
*/
/** /**
* @brief Callback to store the given @p value according to the given @p type. * @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 * @p value_len is always correct. All store functions have to free a dynamically allocated @p value in all
* cases (even on error). * 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] type Type of the value being stored.
* @param[in] value Value to be stored. * @param[in] value Value to be stored.
* @param[in] value_len Length (number of bytes) of the given @p value. * @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); 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 * This callback is optional and may not be defined for types that do not require the accessible data tree for
* in case the ::lyplg_type_store_clb callback returned ::LY_EINCOMPLETE for the value to be valid. However, this * validation (::lyplg_type_store_cb fully stores and validates the value).
* callback can be called even in other cases (such as separate/repeated validation).
* *
* @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] 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] 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[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 * @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 const char *id; /**< Plugin identification (mainly for distinguish incompatible versions when
used by external tools) */ used by external tools) */
lyplg_type_store_clb store; /**< store and canonize the value in the type-specific way */ 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_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_sort_clb sort; /**< comparison callback for sorting values */
lyplg_type_print_clb print; /**< printer callback to get string representing the value */ 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, 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); 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. * @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 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. * @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) struct ly_err_item **err)
{ {
LY_ERR ret = LY_SUCCESS; LY_ERR ret = LY_SUCCESS;
struct lysc_type_bin *type_bin = (struct lysc_type_bin *)type;
struct lyd_value_binary *val; struct lyd_value_binary *val;
/* init storage */ /* 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); ret = lydict_insert_zc(ctx, (char *)value, &storage->_canonical);
options &= ~LYPLG_TYPE_STORE_DYNAMIC; options &= ~LYPLG_TYPE_STORE_DYNAMIC;
LY_CHECK_GOTO(ret, cleanup); LY_CHECK_GOTO(ret, cleanup);
/* value may have been freed */
value = storage->_canonical;
} else { } else {
ret = lydict_insert(ctx, value_len ? value : "", value_len, &storage->_canonical); ret = lydict_insert(ctx, value_len ? value : "", value_len, &storage->_canonical);
LY_CHECK_GOTO(ret, cleanup); LY_CHECK_GOTO(ret, cleanup);
} }
if (!(options & LYPLG_TYPE_STORE_ONLY)) { if (!(options & LYPLG_TYPE_STORE_ONLY)) {
/* validate value */ /* validate length restriction of the binary value */
ret = lyplg_type_validate_binary(ctx, type, NULL, NULL, storage, err); 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); LY_CHECK_GOTO(ret, cleanup);
} }
}
cleanup: cleanup:
if (options & LYPLG_TYPE_STORE_DYNAMIC) { if (options & LYPLG_TYPE_STORE_DYNAMIC) {
@ -334,33 +338,6 @@ cleanup:
return ret; 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 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) 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.id = "libyang 2 - binary, version 1",
.plugin.store = lyplg_type_store_binary, .plugin.store = lyplg_type_store_binary,
.plugin.validate = lyplg_type_validate_binary, .plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_binary, .plugin.compare = lyplg_type_compare_binary,
.plugin.sort = lyplg_type_sort_binary, .plugin.sort = lyplg_type_sort_binary,
.plugin.print = lyplg_type_print_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) struct ly_err_item **err)
{ {
LY_ERR ret = LY_SUCCESS; LY_ERR ret = LY_SUCCESS;
struct lysc_type_str *type_dat = (struct lysc_type_str *)type;
struct lyd_value_date_and_time *val; struct lyd_value_date_and_time *val;
uint32_t i; uint32_t i;
char c; 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); ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
LY_CHECK_GOTO(ret, cleanup); LY_CHECK_GOTO(ret, cleanup);
/* length restriction, there can be only ASCII chars */ /* convert to UNIX time and fractions of second, function must check for all the possible errors */
if (type_dat->length) { if (ly_time_str2time(value, &val->time, &val->fractions_s)) {
ret = lyplg_type_validate_range(LY_TYPE_STRING, type_dat->length, value_len, value, value_len, err); ret = ly_err_new(err, LY_EVALID, 0, NULL, NULL, "%s", ly_last_logmsg());
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());
goto cleanup; goto cleanup;
} }

View file

@ -33,8 +33,6 @@
* | 8 | yes | `int64_t *` | little-endian value represented without floating point | * | 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. * @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; struct lysc_type_dec *type_dec = (struct lysc_type_dec *)type;
LY_ERR ret = LY_SUCCESS; LY_ERR ret = LY_SUCCESS;
int64_t num; int64_t num = 0;
char *canon; char *canon;
/* init storage */ /* 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)) { if (!(options & LYPLG_TYPE_STORE_ONLY)) {
/* validate value */ /* 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); LY_CHECK_GOTO(ret, cleanup);
} }
}
cleanup: cleanup:
if (options & LYPLG_TYPE_STORE_DYNAMIC) { if (options & LYPLG_TYPE_STORE_DYNAMIC) {
@ -159,31 +161,6 @@ cleanup:
return ret; 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 LIBYANG_API_DEF LY_ERR
lyplg_type_compare_decimal64(const struct ly_ctx *UNUSED(ctx), const struct lyd_value *val1, lyplg_type_compare_decimal64(const struct ly_ctx *UNUSED(ctx), const struct lyd_value *val1,
const struct lyd_value *val2) const struct lyd_value *val2)
@ -262,7 +239,7 @@ const struct lyplg_type_record plugins_decimal64[] = {
.plugin.id = "libyang 2 - decimal64, version 1", .plugin.id = "libyang 2 - decimal64, version 1",
.plugin.store = lyplg_type_store_decimal64, .plugin.store = lyplg_type_store_decimal64,
.plugin.validate = lyplg_type_validate_decimal64, .plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_decimal64, .plugin.compare = lyplg_type_compare_decimal64,
.plugin.sort = lyplg_type_sort_decimal64, .plugin.sort = lyplg_type_sort_decimal64,
.plugin.print = lyplg_type_print_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); ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
LY_CHECK_GOTO(ret, cleanup); 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 */ /* make a copy, it is needed for canonization */
if ((format != LY_VALUE_CANON) && !(options & LYPLG_TYPE_STORE_DYNAMIC)) { if ((format != LY_VALUE_CANON) && !(options & LYPLG_TYPE_STORE_DYNAMIC)) {
value = strndup(value, value_len); 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); ret = lydict_insert_zc(ctx, (char *)value, &storage->_canonical);
options &= ~LYPLG_TYPE_STORE_DYNAMIC; options &= ~LYPLG_TYPE_STORE_DYNAMIC;
LY_CHECK_GOTO(ret, cleanup); LY_CHECK_GOTO(ret, cleanup);
/* value may have been freed */
value = storage->_canonical;
} else { } else {
/* store directly */ /* store directly */
ret = lydict_insert(ctx, value_len ? value : "", value_len, &storage->_canonical); ret = lydict_insert(ctx, value_len ? value : "", value_len, &storage->_canonical);
LY_CHECK_GOTO(ret, cleanup); 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: cleanup:
if (options & LYPLG_TYPE_STORE_DYNAMIC) { if (options & LYPLG_TYPE_STORE_DYNAMIC) {
free((void *)value); 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; 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 * 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) 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 ((format == LY_VALUE_CANON) || (format == LY_VALUE_JSON) || (format == LY_VALUE_LYB)) {
if (dynamic) { if (dynamic) {
@ -280,14 +271,34 @@ lyplg_type_print_instanceid(const struct ly_ctx *UNUSED(ctx), const struct lyd_v
return value->_canonical; return value->_canonical;
} }
/* print the value in the specific format */ if (!value->target) {
if (instanceid_path2str(value->target, format, prefix_data, &ret)) { /* schema default value, compile it first */
return NULL; 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; *dynamic = 1;
if (value_len) { if (value_len) {
*value_len = strlen(ret); *value_len = strlen(ret);
} }
cleanup:
ly_path_free(p);
return ret; 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) lyplg_type_dup_instanceid(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup)
{ {
LY_ERR ret; LY_ERR ret;
struct ly_err_item *err;
memset(dup, 0, sizeof *dup); 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); ret = lydict_insert(ctx, original->_canonical, 0, &dup->_canonical);
LY_CHECK_GOTO(ret, error); 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 */ /* copy path */
ret = ly_path_dup(ctx, original->target, &dup->target); ret = ly_path_dup(ctx, original->target, &dup->target);
LY_CHECK_GOTO(ret, error); LY_CHECK_GOTO(ret, error);
}
dup->realtype = original->realtype; dup->realtype = original->realtype;
return LY_SUCCESS; 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); lydict_remove(ctx, value->_canonical);
value->_canonical = NULL; 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.id = "libyang 2 - instance-identifier, version 1",
.plugin.store = lyplg_type_store_instanceid, .plugin.store = lyplg_type_store_instanceid,
.plugin.validate = lyplg_type_validate_instanceid, .plugin.validate = lyplg_type_validate_instanceid,
.plugin.compare = lyplg_type_compare_instanceid, .plugin.compare = lyplg_type_compare_simple,
.plugin.sort = lyplg_type_sort_instanceid, .plugin.sort = lyplg_type_sort_simple,
.plugin.print = lyplg_type_print_instanceid, .plugin.print = lyplg_type_print_instanceid,
.plugin.duplicate = lyplg_type_dup_instanceid, .plugin.duplicate = lyplg_type_dup_instanceid,
.plugin.free = lyplg_type_free_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 | * | 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. * @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), const struct lysc_node *UNUSED(ctx_node), struct lyd_value *storage, struct lys_glob_unres *UNUSED(unres),
struct ly_err_item **err) struct ly_err_item **err)
{ {
struct lysc_type_num *type_num = (struct lysc_type_num *)type;
LY_ERR ret = LY_SUCCESS; LY_ERR ret = LY_SUCCESS;
int64_t num = 0; int64_t num = 0;
int base = 1; 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)) { if (!(options & LYPLG_TYPE_STORE_ONLY)) {
/* validate value */ /* validate range of the number */
ret = lyplg_type_validate_int(ctx, type, NULL, NULL, storage, err); 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); LY_CHECK_GOTO(ret, cleanup);
} }
}
cleanup: cleanup:
if (options & LYPLG_TYPE_STORE_DYNAMIC) { if (options & LYPLG_TYPE_STORE_DYNAMIC) {
@ -173,48 +174,6 @@ cleanup:
return ret; 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 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) 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), const struct lysc_node *UNUSED(ctx_node), struct lyd_value *storage, struct lys_glob_unres *UNUSED(unres),
struct ly_err_item **err) struct ly_err_item **err)
{ {
struct lysc_type_num *type_num = (struct lysc_type_num *)type;
LY_ERR ret = LY_SUCCESS; LY_ERR ret = LY_SUCCESS;
uint64_t num = 0; uint64_t num = 0;
int base = 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)) { if (!(options & LYPLG_TYPE_STORE_ONLY)) {
/* validate value */ /* validate range of the number */
ret = lyplg_type_validate_uint(ctx, type, NULL, NULL, storage, err); 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); LY_CHECK_GOTO(ret, cleanup);
} }
}
cleanup: cleanup:
if (options & LYPLG_TYPE_STORE_DYNAMIC) { if (options & LYPLG_TYPE_STORE_DYNAMIC) {
@ -457,48 +420,6 @@ cleanup:
return ret; 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 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) 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.id = "libyang 2 - integers, version 1",
.plugin.store = lyplg_type_store_uint, .plugin.store = lyplg_type_store_uint,
.plugin.validate = lyplg_type_validate_uint, .plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_uint, .plugin.compare = lyplg_type_compare_uint,
.plugin.sort = lyplg_type_sort_uint, .plugin.sort = lyplg_type_sort_uint,
.plugin.print = lyplg_type_print_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.id = "libyang 2 - integers, version 1",
.plugin.store = lyplg_type_store_uint, .plugin.store = lyplg_type_store_uint,
.plugin.validate = lyplg_type_validate_uint, .plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_uint, .plugin.compare = lyplg_type_compare_uint,
.plugin.sort = lyplg_type_sort_uint, .plugin.sort = lyplg_type_sort_uint,
.plugin.print = lyplg_type_print_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.id = "libyang 2 - integers, version 1",
.plugin.store = lyplg_type_store_uint, .plugin.store = lyplg_type_store_uint,
.plugin.validate = lyplg_type_validate_uint, .plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_uint, .plugin.compare = lyplg_type_compare_uint,
.plugin.sort = lyplg_type_sort_uint, .plugin.sort = lyplg_type_sort_uint,
.plugin.print = lyplg_type_print_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.id = "libyang 2 - integers, version 1",
.plugin.store = lyplg_type_store_uint, .plugin.store = lyplg_type_store_uint,
.plugin.validate = lyplg_type_validate_uint, .plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_uint, .plugin.compare = lyplg_type_compare_uint,
.plugin.sort = lyplg_type_sort_uint, .plugin.sort = lyplg_type_sort_uint,
.plugin.print = lyplg_type_print_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.id = "libyang 2 - integers, version 1",
.plugin.store = lyplg_type_store_int, .plugin.store = lyplg_type_store_int,
.plugin.validate = lyplg_type_validate_int, .plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_int, .plugin.compare = lyplg_type_compare_int,
.plugin.sort = lyplg_type_sort_int, .plugin.sort = lyplg_type_sort_int,
.plugin.print = lyplg_type_print_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.id = "libyang 2 - integers, version 1",
.plugin.store = lyplg_type_store_int, .plugin.store = lyplg_type_store_int,
.plugin.validate = lyplg_type_validate_int, .plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_int, .plugin.compare = lyplg_type_compare_int,
.plugin.sort = lyplg_type_sort_int, .plugin.sort = lyplg_type_sort_int,
.plugin.print = lyplg_type_print_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.id = "libyang 2 - integers, version 1",
.plugin.store = lyplg_type_store_int, .plugin.store = lyplg_type_store_int,
.plugin.validate = lyplg_type_validate_int, .plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_int, .plugin.compare = lyplg_type_compare_int,
.plugin.sort = lyplg_type_sort_int, .plugin.sort = lyplg_type_sort_int,
.plugin.print = lyplg_type_print_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.id = "libyang 2 - integers, version 1",
.plugin.store = lyplg_type_store_int, .plugin.store = lyplg_type_store_int,
.plugin.validate = lyplg_type_validate_int, .plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_int, .plugin.compare = lyplg_type_compare_int,
.plugin.sort = lyplg_type_sort_int, .plugin.sort = lyplg_type_sort_int,
.plugin.print = lyplg_type_print_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); ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
LY_CHECK_GOTO(ret, cleanup); LY_CHECK_GOTO(ret, cleanup);
if (!(options & LYPLG_TYPE_STORE_ONLY)) {
/* length restriction of the string */ /* length restriction of the string */
if (type_str->length) { if (type_str->length) {
/* value_len is in bytes, but we need number of characters here */ /* 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 */ /* pattern restrictions */
ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err); ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err);
LY_CHECK_GOTO(ret, cleanup); LY_CHECK_GOTO(ret, cleanup);
}
/* get the network-byte order address */ /* get the network-byte order address */
ret = ipv4address_str2ip(value, value_len, options, ctx, &val->addr, &val->zone, err); 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) struct ly_err_item **err)
{ {
LY_ERR ret = LY_SUCCESS; LY_ERR ret = LY_SUCCESS;
struct lysc_type_str *type_str = (struct lysc_type_str *)type;
struct lyd_value_ipv4_address_no_zone *val; struct lyd_value_ipv4_address_no_zone *val;
/* init storage */ /* 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); ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
LY_CHECK_GOTO(ret, cleanup); 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 */ /* we always need a dynamic value */
if (!(options & LYPLG_TYPE_STORE_DYNAMIC)) { if (!(options & LYPLG_TYPE_STORE_DYNAMIC)) {
value = strndup(value, value_len); 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; 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)) { 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); ret = ly_err_new(err, LY_EVALID, LYVE_DATA, NULL, NULL, "Failed to convert IPv4 address \"%s\".", (char *)value);
goto cleanup; 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); ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
LY_CHECK_GOTO(ret, cleanup); LY_CHECK_GOTO(ret, cleanup);
if (!(options & LYPLG_TYPE_STORE_ONLY)) {
/* length restriction of the string */ /* length restriction of the string */
if (type_str->length) { if (type_str->length) {
/* value_len is in bytes, but we need number of characters here */ /* 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 */ /* pattern restrictions */
ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err); ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err);
LY_CHECK_GOTO(ret, cleanup); LY_CHECK_GOTO(ret, cleanup);
}
/* get the mask in network-byte order */ /* get the mask in network-byte order */
ret = ipv4prefix_str2ip(value, value_len, &val->addr, &val->prefix, err); 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); ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
LY_CHECK_GOTO(ret, cleanup); LY_CHECK_GOTO(ret, cleanup);
if (!(options & LYPLG_TYPE_STORE_ONLY)) {
/* length restriction of the string */ /* length restriction of the string */
if (type_str->length) { if (type_str->length) {
/* value_len is in bytes, but we need number of characters here */ /* 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 */ /* pattern restrictions */
ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err); ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err);
LY_CHECK_GOTO(ret, cleanup); LY_CHECK_GOTO(ret, cleanup);
}
/* get the network-byte order address */ /* get the network-byte order address */
ret = ipv6address_str2ip(value, value_len, options, ctx, &val->addr, &val->zone, err); 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) struct ly_err_item **err)
{ {
LY_ERR ret = LY_SUCCESS; LY_ERR ret = LY_SUCCESS;
struct lysc_type_str *type_str = (struct lysc_type_str *)type;
struct lyd_value_ipv6_address_no_zone *val; struct lyd_value_ipv6_address_no_zone *val;
/* init storage */ /* 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); ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
LY_CHECK_GOTO(ret, cleanup); LY_CHECK_GOTO(ret, cleanup);
/* length restriction of the string */ /* get the network-byte order address, validates the value */
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 */
ret = ipv6addressnozone_str2ip(value, value_len, options, &val->addr, err); ret = ipv6addressnozone_str2ip(value, value_len, options, &val->addr, err);
LY_CHECK_GOTO(ret, cleanup); 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); ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
LY_CHECK_GOTO(ret, cleanup); LY_CHECK_GOTO(ret, cleanup);
if (!(options & LYPLG_TYPE_STORE_ONLY)) {
/* length restriction of the string */ /* length restriction of the string */
if (type_str->length) { if (type_str->length) {
/* value_len is in bytes, but we need number of characters here */ /* 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 */ /* pattern restrictions */
ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err); ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err);
LY_CHECK_GOTO(ret, cleanup); LY_CHECK_GOTO(ret, cleanup);
}
/* get the mask in network-byte order */ /* get the mask in network-byte order */
ret = ipv6prefix_str2ip(value, value_len, &val->addr, &val->prefix, err); 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, 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) 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; struct lysc_type_leafref *type_lr = (struct lysc_type_leafref *)type;
assert(type_lr->realtype); assert(type_lr->realtype);
/* store the value as the real type of the leafref target */ /* 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); hints, ctx_node, storage, unres, err);
if (ret == LY_EINCOMPLETE) { if (rc == LY_EINCOMPLETE) {
/* it is irrelevant whether the target type needs some resolving */ /* 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) { if (type_lr->require_instance) {
/* needs to be resolved */ /* 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, 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) 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; struct lysc_type_leafref *type_lr = (struct lysc_type_leafref *)type;
char *errmsg = NULL, *path; char *errmsg = NULL, *path;
struct ly_set *targets = NULL; 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; 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); rc = lyplg_type_resolve_leafref(type_lr, ctx_node, storage, tree,
if (ret != LY_SUCCESS) { (ly_ctx_get_options(ctx) & LY_CTX_LEAFREF_LINKING) ? &targets : NULL, &errmsg);
if (rc) {
path = lyd_path(ctx_node, LYD_PATH_STD, NULL, 0); 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); free(errmsg);
goto cleanup; goto cleanup;
} }
if (ly_ctx_get_options(ctx) & LY_CTX_LEAFREF_LINKING) { if (ly_ctx_get_options(ctx) & LY_CTX_LEAFREF_LINKING) {
for (i = 0; i < targets->count; ++i) { 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); rc = lyd_link_leafref_node((struct lyd_node_term *)targets->dnodes[i], (struct lyd_node_term *)ctx_node);
LY_CHECK_GOTO(ret, cleanup); LY_CHECK_GOTO(rc, cleanup);
} }
} }
cleanup: cleanup:
ly_set_free(targets, NULL); ly_set_free(targets, NULL);
return ret; return rc;
} }
LIBYANG_API_DEF LY_ERR 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.id = "libyang 2 - node-instance-identifier, version 1",
.plugin.store = lyplg_type_store_node_instanceid, .plugin.store = lyplg_type_store_node_instanceid,
.plugin.validate = NULL, .plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_instanceid, .plugin.compare = lyplg_type_compare_simple,
.plugin.sort = lyplg_type_sort_instanceid, .plugin.sort = lyplg_type_sort_simple,
.plugin.print = lyplg_type_print_node_instanceid, .plugin.print = lyplg_type_print_node_instanceid,
.plugin.duplicate = lyplg_type_dup_instanceid, .plugin.duplicate = lyplg_type_dup_instanceid,
.plugin.free = lyplg_type_free_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.id = "libyang 2 - node-instance-identifier, version 1",
.plugin.store = lyplg_type_store_node_instanceid, .plugin.store = lyplg_type_store_node_instanceid,
.plugin.validate = NULL, .plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_instanceid, .plugin.compare = lyplg_type_compare_simple,
.plugin.sort = lyplg_type_sort_instanceid, .plugin.sort = lyplg_type_sort_simple,
.plugin.print = lyplg_type_print_node_instanceid, .plugin.print = lyplg_type_print_node_instanceid,
.plugin.duplicate = lyplg_type_dup_instanceid, .plugin.duplicate = lyplg_type_dup_instanceid,
.plugin.free = lyplg_type_free_instanceid, .plugin.free = lyplg_type_free_instanceid,

View file

@ -34,8 +34,6 @@
* | string length | yes | `char *` | string itself | * | 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. * @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), const struct lysc_node *UNUSED(ctx_node), struct lyd_value *storage, struct lys_glob_unres *UNUSED(unres),
struct ly_err_item **err) struct ly_err_item **err)
{ {
struct lysc_type_str *type_str = (struct lysc_type_str *)type;
LY_ERR ret = LY_SUCCESS; LY_ERR ret = LY_SUCCESS;
/* init storage */ /* 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); ret = lydict_insert_zc(ctx, (char *)value, &storage->_canonical);
options &= ~LYPLG_TYPE_STORE_DYNAMIC; options &= ~LYPLG_TYPE_STORE_DYNAMIC;
LY_CHECK_GOTO(ret, cleanup); LY_CHECK_GOTO(ret, cleanup);
/* value may have been freed */
value = storage->_canonical;
} else { } else {
ret = lydict_insert(ctx, value_len ? value : "", value_len, &storage->_canonical); ret = lydict_insert(ctx, value_len ? value : "", value_len, &storage->_canonical);
LY_CHECK_GOTO(ret, cleanup); LY_CHECK_GOTO(ret, cleanup);
} }
if (!(options & LYPLG_TYPE_STORE_ONLY)) { if (!(options & LYPLG_TYPE_STORE_ONLY)) {
/* validate value */ /* length restriction of the string */
ret = lyplg_type_validate_string(ctx, type, NULL, NULL, storage, err); 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); LY_CHECK_GOTO(ret, cleanup);
} }
@ -108,37 +117,6 @@ cleanup:
return ret; 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. * @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.id = "libyang 2 - string, version 1",
.plugin.store = lyplg_type_store_string, .plugin.store = lyplg_type_store_string,
.plugin.validate = lyplg_type_validate_string, .plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_simple, .plugin.compare = lyplg_type_compare_simple,
.plugin.sort = lyplg_type_sort_simple, .plugin.sort = lyplg_type_sort_simple,
.plugin.print = lyplg_type_print_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 LIBYANG_API_DEF int
lyplg_type_sort_union(const struct ly_ctx *ctx, const struct lyd_value *val1, const struct lyd_value *val2) 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; LY_ARRAY_COUNT_TYPE u;
struct lysc_type **types; 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 */ /* compare according to the order of types */
ret = 0;
types = ((struct lysc_type_union *)val1->realtype)->types; types = ((struct lysc_type_union *)val1->realtype)->types;
LY_ARRAY_FOR(types, u) { LY_ARRAY_FOR(types, u) {
if (types[u] == val1->subvalue->value.realtype) { if (types[u] == val1->subvalue->value.realtype) {
ret = 1; rc = 1;
break; break;
} else if (types[u] == val2->subvalue->value.realtype) { } else if (types[u] == val2->subvalue->value.realtype) {
ret = -1; rc = -1;
break; 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) struct lyd_value *storage, struct lys_glob_unres *UNUSED(unres), struct ly_err_item **err)
{ {
LY_ERR ret = LY_SUCCESS; LY_ERR ret = LY_SUCCESS;
struct lysc_type_str *type_str = (struct lysc_type_str *)type;
struct lyd_value_xpath10 *val; struct lyd_value_xpath10 *val;
char *canon; 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); ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
LY_CHECK_GOTO(ret, cleanup); 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 */ /* parse */
ret = lyxp_expr_parse(ctx, value_len ? value : "", value_len, 1, &val->exp); ret = lyxp_expr_parse(ctx, value_len ? value : "", value_len, 1, &val->exp);
LY_CHECK_GOTO(ret, cleanup); 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); ly_print_(pctx->out, "%*s%s {\n", INDENT, inout->name);
LEVEL++; 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) { LY_ARRAY_FOR(inout->musts, u) {
yprp_restr(pctx, &inout->musts[u], LY_STMT_MUST, NULL); 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; 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); ypr_open(pctx->out, flag);
if (ext->substmts[u].stmt == LY_STMT_NOTIFICATION) { if (ext->substmts[u].stmt == LY_STMT_NOTIFICATION) {
yprc_notification(pctx, (struct lysc_node_notif *)node); 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_PRESENCE:
case LY_STMT_REFERENCE: case LY_STMT_REFERENCE:
case LY_STMT_UNITS: case LY_STMT_UNITS:
if (*VOIDPTR2_C(ext->substmts[u].storage)) { if (*ext->substmts[u].storage_p) {
ypr_open(pctx->out, flag); 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; break;
case LY_STMT_BIT: case LY_STMT_BIT:
case LY_STMT_ENUM: { 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); yprc_bits_enum(pctx, items, ext->substmts[u].stmt == LY_STMT_BIT ? LY_TYPE_BITS : LY_TYPE_ENUM, flag);
break; break;
} }
case LY_STMT_CONFIG: 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; break;
case LY_STMT_EXTENSION_INSTANCE: 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; break;
case LY_STMT_FRACTION_DIGITS: 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, 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; break;
case LY_STMT_IDENTITY: { 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) { LY_ARRAY_FOR(idents, v) {
yprc_identity(pctx, &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; break;
} }
case LY_STMT_LENGTH: case LY_STMT_LENGTH:
if (*VOIDPTR2_C(ext->substmts[u].storage)) { if (*ext->substmts[u].storage_p) {
yprc_range(pctx, *VOIDPTR2_C(ext->substmts[u].storage), LY_TYPE_STRING, flag); yprc_range(pctx, *ext->substmts[u].storage_p, LY_TYPE_STRING, flag);
} }
break; break;
case LY_STMT_MANDATORY: 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; break;
case LY_STMT_MAX_ELEMENTS: { 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) { if (max) {
ypr_unsigned(pctx, LY_STMT_MAX_ELEMENTS, 0, ext->exts, max, flag); 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; break;
} }
case LY_STMT_MIN_ELEMENTS: 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; break;
case LY_STMT_ORDERED_BY: case LY_STMT_ORDERED_BY:
ypr_open(pctx->out, flag); ypr_open(pctx->out, flag);
ypr_substmt(pctx, LY_STMT_ORDERED_BY, 0, 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; break;
case LY_STMT_MUST: { 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) { LY_ARRAY_FOR(musts, v) {
yprc_must(pctx, &musts[v], flag); yprc_must(pctx, &musts[v], flag);
@ -2660,7 +2660,7 @@ lyplg_ext_print_info_extension_instance(struct lyspr_ctx *ctx, const struct lysc
break; break;
} }
case LY_STMT_PATTERN: { 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) { LY_ARRAY_FOR(patterns, v) {
yprc_pattern(pctx, &patterns[v], flag); yprc_pattern(pctx, &patterns[v], flag);
@ -2668,36 +2668,36 @@ lyplg_ext_print_info_extension_instance(struct lyspr_ctx *ctx, const struct lysc
break; break;
} }
case LY_STMT_POSITION: case LY_STMT_POSITION:
if (*VOIDPTR2_C(ext->substmts[u].storage)) { if (*ext->substmts[u].storage_p) {
ypr_unsigned(pctx, ext->substmts[u].stmt, 0, ext->exts, *(int64_t *)VOIDPTR_C(ext->substmts[u].storage), flag); ypr_unsigned(pctx, ext->substmts[u].stmt, 0, ext->exts, *(int64_t *)ext->substmts[u].storage_p, flag);
} }
break; break;
case LY_STMT_VALUE: case LY_STMT_VALUE:
if (*VOIDPTR2_C(ext->substmts[u].storage)) { if (*ext->substmts[u].storage_p) {
ypr_signed(pctx, ext->substmts[u].stmt, 0, ext->exts, *(int64_t *)VOIDPTR_C(ext->substmts[u].storage), flag); ypr_signed(pctx, ext->substmts[u].stmt, 0, ext->exts, *(int64_t *)ext->substmts[u].storage_p, flag);
} }
break; break;
case LY_STMT_RANGE: case LY_STMT_RANGE:
if (*VOIDPTR2_C(ext->substmts[u].storage)) { if (*ext->substmts[u].storage_p) {
yprc_range(pctx, *VOIDPTR2_C(ext->substmts[u].storage), LY_TYPE_UINT64, flag); yprc_range(pctx, *ext->substmts[u].storage_p, LY_TYPE_UINT64, flag);
} }
break; break;
case LY_STMT_REQUIRE_INSTANCE: case LY_STMT_REQUIRE_INSTANCE:
ypr_open(pctx->out, flag); 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); 0, ext->exts);
break; break;
case LY_STMT_STATUS: 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; break;
case LY_STMT_TYPE: case LY_STMT_TYPE:
if (*VOIDPTR2_C(ext->substmts[u].storage)) { if (*ext->substmts[u].storage_p) {
ypr_open(pctx->out, flag); ypr_open(pctx->out, flag);
yprc_type(pctx, *VOIDPTR2_C(ext->substmts[u].storage)); yprc_type(pctx, *ext->substmts[u].storage_p);
} }
break; break;
case LY_STMT_WHEN: case LY_STMT_WHEN:
yprc_when(pctx, *VOIDPTR2_C(ext->substmts[u].storage), flag); yprc_when(pctx, *ext->substmts[u].storage_p, flag);
break; break;
case LY_STMT_AUGMENT: case LY_STMT_AUGMENT:
case LY_STMT_BASE: case LY_STMT_BASE:

View file

@ -4,7 +4,7 @@
* @author Michal Vasko <mvasko@cesnet.cz> * @author Michal Vasko <mvasko@cesnet.cz>
* @brief Schema compilation. * @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"). * 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 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 */ /* compile extension if not already */
LY_CHECK_GOTO(ret = lys_compile_extension(ctx, extp, &ext->def), cleanup); 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->def->plugin && ext->def->plugin->compile) {
if (ext->argument) { if (ext->argument) {
lysc_update_path(ctx, ext->module, 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) const struct lysp_ident *identities_p, struct lysc_ident **identities)
{ {
LY_ARRAY_COUNT_TYPE u; LY_ARRAY_COUNT_TYPE u;
struct lysc_ctx cctx; struct lysc_ctx cctx = {0};
struct lysc_ident *ident; struct lysc_ident *ident;
LY_ERR ret = LY_SUCCESS; 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 */ /* get the target node */
target = p[LY_ARRAY_COUNT(p) - 1].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))) { 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.", 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); 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; return LY_SUCCESS;
} }
@ -1453,7 +1462,7 @@ resolve_all:
ret = ly_path_compile_leafref(cctx.ctx, l->node, cctx.ext, lref->path, 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, (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_VALUE_SCHEMA_RESOLVED, lref->prefixes, &path);
ly_path_free(l->node->module->ctx, path); ly_path_free(path);
assert(ret != LY_ERECOMPILE); assert(ret != LY_ERECOMPILE);
if (ret) { if (ret) {
@ -1468,7 +1477,7 @@ resolve_all:
} }
cleanup: cleanup:
lysf_ctx_erase(&cctx.free_ctx); assert(!cctx.free_ctx.ext_set.count);
return ret; return ret;
} }
@ -1548,8 +1557,8 @@ lys_compile_depset_r(struct ly_ctx *ctx, struct ly_set *dep_set, struct lys_glob
} }
cleanup: cleanup:
assert(!fctx.ext_set.count);
lys_compile_unres_depset_erase(ctx, unres); lys_compile_unres_depset_erase(ctx, unres);
lysf_ctx_erase(&fctx);
return ret; return ret;
} }
@ -1693,7 +1702,7 @@ lys_compile_unres_mod_erase(struct lysc_ctx *ctx, ly_bool error)
LY_ERR LY_ERR
lys_compile(struct lys_module *mod, struct lys_depset_unres *unres) 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 lysc_module *mod_c = NULL;
struct lysp_module *sp; struct lysp_module *sp;
struct lysp_submodule *submod; struct lysp_submodule *submod;
@ -1814,7 +1823,7 @@ LY_ERR
lys_compile_identities(struct lys_module *mod) lys_compile_identities(struct lys_module *mod)
{ {
LY_ERR rc = LY_SUCCESS; LY_ERR rc = LY_SUCCESS;
struct lysc_ctx ctx; struct lysc_ctx ctx = {0};
struct lysp_submodule *submod; struct lysp_submodule *submod;
LY_ARRAY_COUNT_TYPE u; LY_ARRAY_COUNT_TYPE u;

View file

@ -67,7 +67,6 @@ struct lysc_ctx {
* @param[in] CTX libyang context. * @param[in] CTX libyang context.
*/ */
#define LYSC_CTX_INIT_CTX(CCTX, CTX) \ #define LYSC_CTX_INIT_CTX(CCTX, CTX) \
memset(&(CCTX), 0, sizeof (CCTX)); \
(CCTX).ctx = (CTX); \ (CCTX).ctx = (CTX); \
(CCTX).path_len = 1; \ (CCTX).path_len = 1; \
(CCTX).path[0] = '/'; \ (CCTX).path[0] = '/'; \
@ -81,7 +80,6 @@ struct lysc_ctx {
* @param[in] EXT Ancestor extension instance. * @param[in] EXT Ancestor extension instance.
*/ */
#define LYSC_CTX_INIT_PMOD(CCTX, PMOD, EXT) \ #define LYSC_CTX_INIT_PMOD(CCTX, PMOD, EXT) \
memset(&(CCTX), 0, sizeof (CCTX)); \
(CCTX).ctx = (PMOD)->mod->ctx; \ (CCTX).ctx = (PMOD)->mod->ctx; \
(CCTX).cur_mod = (PMOD)->mod; \ (CCTX).cur_mod = (PMOD)->mod; \
(CCTX).pmod = (PMOD); \ (CCTX).pmod = (PMOD); \
@ -164,9 +162,9 @@ struct lysc_unres_dflt {
* @param[out] DUP Where to store the result. * @param[out] DUP Where to store the result.
* @param[out] RET Where to store the return code. * @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(CTX, ORIG, DUP, RET) RET = lydict_dup(CTX, ORIG, &(DUP))
#define DUP_STRING_RET(CTX, ORIG, DUP) LY_CHECK_RET(lydict_insert(CTX, ORIG, 0, &(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_insert(CTX, ORIG, 0, &(DUP)), GOTO) #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) \ #define DUP_ARRAY(CTX, ORIG_ARRAY, NEW_ARRAY, DUP_FUNC) \
if (ORIG_ARRAY) { \ 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; aug_p = NULL;
LY_ARRAY_FOR(pmod->exts[u].substmts, v) { LY_ARRAY_FOR(pmod->exts[u].substmts, v) {
if (pmod->exts[u].substmts[v].stmt == LY_STMT_AUGMENT) { 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; break;
} }
} }
@ -2443,7 +2443,7 @@ lys_precompile_mod_augments_deviations(struct lysp_module *pmod, struct ly_set *
{ {
LY_ERR ret = LY_SUCCESS; LY_ERR ret = LY_SUCCESS;
LY_ARRAY_COUNT_TYPE u, v; LY_ARRAY_COUNT_TYPE u, v;
struct lysc_ctx ctx; struct lysc_ctx ctx = {0};
struct lys_module *m; struct lys_module *m;
struct lysp_node_augment *aug; struct lysp_node_augment *aug;
struct ly_set set = {0}; struct ly_set set = {0};
@ -2488,7 +2488,7 @@ lys_precompile_mod_augments_deviations(struct lysp_module *pmod, struct ly_set *
aug = NULL; aug = NULL;
LY_ARRAY_FOR(pmod->exts[u].substmts, v) { LY_ARRAY_FOR(pmod->exts[u].substmts, v) {
if (pmod->exts[u].substmts[v].stmt == LY_STMT_AUGMENT) { 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; 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) { if (patterns_p[u].arg.str[0] == LYSP_RESTR_PATTERN_NACK) {
(*pattern)->inverted = 1; (*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].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].emsg, (*pattern)->emsg, ret, done);
DUP_STRING_GOTO(ctx->ctx, patterns_p[u].dsc, (*pattern)->dsc, 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 { } else {
/* top-level element */ /* top-level element */
struct lysc_node **list; struct lysc_node **list = NULL;
if (ctx->ext) { 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) { } else if (node->nodetype == LYS_RPC) {
list = (struct lysc_node **)&ctx->cur_mod->compiled->rpcs; list = (struct lysc_node **)&ctx->cur_mod->compiled->rpcs;
} else if (node->nodetype == LYS_NOTIF) { } 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; 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_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; ctx->compile_opts |= (inout_p->nodetype == LYS_INPUT) ? LYS_COMPILE_RPC_INPUT : LYS_COMPILE_RPC_OUTPUT;
LY_LIST_FOR(inout_p->child, child_p) { 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; const struct lysp_ident *idents_p, *found_ident = NULL;
struct lysp_include *includes; struct lysp_include *includes;
assert(ident); LY_CHECK_ARG_RET(NULL, ident, ident->module->parsed, LY_EINVAL);
/* Search parsed identity in the module. */ /* Search parsed identity in the module. */
idents_p = ident->module->parsed->identities; 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; struct lysp_feature *features;
LY_CHECK_ARG_RET(NULL, pmod, NULL);
if (!*idx) { if (!*idx) {
/* module features */ /* module features */
features = pmod->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; 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) { if (sibling) {
LY_CHECK_RET(lyd_insert_check_schema(NULL, sibling->schema, node->schema)); 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; struct lyd_node *child;
if (options & LYD_DUP_RECURSIVE) { 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 */ /* duplicate all the children */
LY_LIST_FOR(orig->child, child) { 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); 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; 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. * @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 *local_parent = NULL; /* the direct parent node for the duplicated node(s) */
struct lyd_node *dup = NULL; /* duplicate node */ struct lyd_node *dup = NULL; /* duplicate node */
struct lyd_node *first_sibling = NULL; /* first sibling 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); 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); rc = lyd_dup_r(orig, trg_ctx, NULL, LYD_INSERT_NODE_DEFAULT, &first_sibling, options, &dup);
LY_CHECK_GOTO(rc, error); 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 { } else {
rc = lyd_dup_r(orig, trg_ctx, local_parent, /* decide insert order */
options & LYD_DUP_NO_LYDS ? LYD_INSERT_NODE_LAST_BY_SCHEMA : LYD_INSERT_NODE_DEFAULT, insert_order = (options & LYD_DUP_NO_LYDS) ? LYD_INSERT_NODE_LAST_BY_SCHEMA : LYD_INSERT_NODE_DEFAULT;
&first_sibling, options, &dup); 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); 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; first_dup = first_dup ? first_dup : dup;
if (nosiblings || !orig) { if (nosiblings) {
break; break;
} }
} }
@ -3624,7 +3595,7 @@ lyd_find_path(const struct lyd_node *ctx_node, const char *path, ly_bool output,
cleanup: cleanup:
lyxp_expr_free(LYD_CTX(ctx_node), expr); lyxp_expr_free(LYD_CTX(ctx_node), expr);
ly_path_free(LYD_CTX(ctx_node), lypath); ly_path_free(lypath);
return ret; return ret;
} }

View file

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

View file

@ -84,7 +84,7 @@ lyd_hash(struct lyd_node *node)
* *
* Implementation of ::lyht_value_equal_cb. * 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)) lyd_hash_table_val_equal(void *val1_p, void *val2_p, ly_bool mod, void *UNUSED(cb_data))
{ {
struct lyd_node *val1, *val2; struct lyd_node *val1, *val2;

View file

@ -16,6 +16,7 @@
#ifndef LY_TREE_DATA_INTERNAL_H_ #ifndef LY_TREE_DATA_INTERNAL_H_
#define LY_TREE_DATA_INTERNAL_H_ #define LY_TREE_DATA_INTERNAL_H_
#include "compat.h"
#include "log.h" #include "log.h"
#include "plugins_types.h" #include "plugins_types.h"
#include "tree_data.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); 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. * @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); 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, 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) 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) const char *prefix, const char *module_name, struct lyd_node **node)
{ {
struct lyd_node *ret = NULL; 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_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); 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) { if (!value) {
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, 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) { if (parent) {
lyd_insert_node(parent, NULL, ret, LYD_INSERT_NODE_LAST); 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_bool store_only = (options & LYD_NEW_VAL_STORE_ONLY) ? 1 : 0;
LY_ARRAY_COUNT_TYPE path_idx = 0, orig_count = 0; LY_ARRAY_COUNT_TYPE path_idx = 0, orig_count = 0;
LY_VALUE_FORMAT format; LY_VALUE_FORMAT format;
uint32_t hints;
assert(parent || ctx); assert(parent || ctx);
assert(path && ((path[0] == '/') || parent)); 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)) { if (r && (r != LY_EINCOMPLETE)) {
/* creating opaque leaf-list */ /* 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, 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, schema->module->name, strlen(schema->module->name), value, value_len, NULL, format, NULL,
LYD_NODEHINT_LEAFLIST, &node), cleanup); hints, &node), cleanup);
break; 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)) { if (r && (r != LY_EINCOMPLETE)) {
/* creating opaque leaf */ /* 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, 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); cleanup);
break; break;
} }
@ -1811,7 +1823,7 @@ cleanup:
LY_ARRAY_INCREMENT(p); LY_ARRAY_INCREMENT(p);
} }
} }
ly_path_free(ctx, p); ly_path_free(p);
if (!ret) { if (!ret) {
/* set out params only on success */ /* set out params only on success */
if (new_parent) { 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); ret = lys_find_lypath_atoms(p, set);
cleanup: cleanup:
ly_path_free(ctx, p); ly_path_free(p);
lyxp_expr_free(ctx, expr); lyxp_expr_free(ctx, expr);
return ret; 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; snode = p[LY_ARRAY_COUNT(p) - 1].node;
cleanup: cleanup:
ly_path_free(ctx, p); ly_path_free(p);
lyxp_expr_free(ctx, expr); lyxp_expr_free(ctx, expr);
return snode; return snode;
} }
@ -1179,7 +1179,7 @@ lys_set_implemented(struct lys_module *mod, const char **features)
LY_ERR ret = LY_SUCCESS; LY_ERR ret = LY_SUCCESS;
struct lys_glob_unres *unres = &mod->ctx->unres; 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 */ /* implement */
ret = _lys_set_implemented(mod, features, unres); 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; struct ly_in *in;
char *filepath = NULL; char *filepath = NULL;
LYS_INFORMAT format; LYS_INFORMAT format = 0;
void *mod = NULL; void *mod = NULL;
LY_ERR ret = LY_SUCCESS; LY_ERR ret = LY_SUCCESS;
struct lysp_load_module_check_data check_data = {0}; 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 */ /* get the target node */
target = p[LY_ARRAY_COUNT(p) - 1].node; target = p[LY_ARRAY_COUNT(p) - 1].node;
ly_path_free(node->module->ctx, p); ly_path_free(p);
return target; 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) { LY_LIST_FOR_SAFE(ext->child, next, stmt) {
lysp_stmt_free(ctx->ctx, 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_bool node_free;
LY_ARRAY_FOR(substmts, u) { LY_ARRAY_FOR(substmts, u) {
if (!substmts[u].storage) { if (!substmts[u].storage_p) {
continue; continue;
} }
@ -1383,75 +1385,75 @@ lyplg_ext_pfree_instance_substatements(const struct ly_ctx *ctx, struct lysp_ext
case LY_STMT_USES: { case LY_STMT_USES: {
struct lysp_node *child, *child_next; 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; node_free = (child->nodetype & (LYS_INPUT | LYS_OUTPUT)) ? 1 : 0;
lysp_node_free(&fctx, child); lysp_node_free(&fctx, child);
if (node_free) { if (node_free) {
free(child); free(child);
} }
} }
*VOIDPTR2_C(substmts[u].storage) = NULL; *substmts[u].storage_p = NULL;
break; break;
} }
case LY_STMT_BASE: case LY_STMT_BASE:
/* multiple strings */ /* 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; break;
case LY_STMT_BIT: case LY_STMT_BIT:
case LY_STMT_ENUM: case LY_STMT_ENUM:
/* single enum */ /* single enum */
lysp_type_enum_free(&fctx, *VOIDPTR2_C(substmts[u].storage)); lysp_type_enum_free(&fctx, *substmts[u].storage_p);
break; break;
case LY_STMT_DEVIATE: case LY_STMT_DEVIATE:
/* single deviate */ /* single deviate */
lysp_deviate_free(&fctx, *VOIDPTR2_C(substmts[u].storage)); lysp_deviate_free(&fctx, *substmts[u].storage_p);
break; break;
case LY_STMT_DEVIATION: case LY_STMT_DEVIATION:
/* single deviation */ /* single deviation */
lysp_deviation_free(&fctx, *VOIDPTR2_C(substmts[u].storage)); lysp_deviation_free(&fctx, *substmts[u].storage_p);
break; break;
case LY_STMT_EXTENSION: case LY_STMT_EXTENSION:
/* single extension */ /* single extension */
lysp_ext_free(&fctx, *VOIDPTR2_C(substmts[u].storage)); lysp_ext_free(&fctx, *substmts[u].storage_p);
break; break;
case LY_STMT_EXTENSION_INSTANCE: case LY_STMT_EXTENSION_INSTANCE:
/* multiple extension instances */ /* 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; break;
case LY_STMT_FEATURE: case LY_STMT_FEATURE:
/* multiple features */ /* 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; break;
case LY_STMT_IDENTITY: case LY_STMT_IDENTITY:
/* multiple identities */ /* 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; break;
case LY_STMT_IMPORT: case LY_STMT_IMPORT:
/* multiple imports */ /* 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; break;
case LY_STMT_INCLUDE: case LY_STMT_INCLUDE:
/* multiple includes */ /* 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; break;
case LY_STMT_REFINE: case LY_STMT_REFINE:
/* multiple refines */ /* 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; break;
case LY_STMT_REVISION: case LY_STMT_REVISION:
/* multiple revisions */ /* 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; break;
case LY_STMT_CONFIG: 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_REVISION_DATE:
case LY_STMT_UNITS: case LY_STMT_UNITS:
/* single string */ /* single string */
lydict_remove(ctx, *VOIDPTR2_C(substmts[u].storage)); lydict_remove(ctx, *substmts[u].storage_p);
break; break;
case LY_STMT_LENGTH: 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_PATTERN:
case LY_STMT_RANGE: case LY_STMT_RANGE:
/* multiple restrictions */ /* 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; break;
case LY_STMT_WHEN: case LY_STMT_WHEN:
/* multiple whens */ /* 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; break;
case LY_STMT_PATH: case LY_STMT_PATH:
/* single expression */ /* single expression */
lyxp_expr_free(ctx, *VOIDPTR2_C(substmts[u].storage)); lyxp_expr_free(ctx, *substmts[u].storage_p);
break; break;
case LY_STMT_DEFAULT: case LY_STMT_DEFAULT:
case LY_STMT_IF_FEATURE: case LY_STMT_IF_FEATURE:
case LY_STMT_UNIQUE: case LY_STMT_UNIQUE:
/* multiple qnames */ /* 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; break;
case LY_STMT_TYPEDEF: case LY_STMT_TYPEDEF:
/* multiple typedefs */ /* 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; break;
case LY_STMT_TYPE: { case LY_STMT_TYPE: {
/* single 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); lysp_type_free(&fctx, *type_p);
free(*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_MODULE:
case LY_STMT_SUBMODULE: case LY_STMT_SUBMODULE:
/* single (sub)module */ /* single (sub)module */
lysp_module_free(&fctx, *VOIDPTR2_C(substmts[u].storage)); lysp_module_free(&fctx, *substmts[u].storage_p);
break; break;
default: default:
@ -1548,7 +1550,7 @@ lyplg_ext_cfree_instance_substatements(const struct ly_ctx *ctx, struct lysc_ext
ly_bool node_free; ly_bool node_free;
LY_ARRAY_FOR(substmts, u) { LY_ARRAY_FOR(substmts, u) {
if (!substmts[u].storage) { if (!substmts[u].storage_p) {
continue; continue;
} }
@ -1568,14 +1570,14 @@ lyplg_ext_cfree_instance_substatements(const struct ly_ctx *ctx, struct lysc_ext
case LY_STMT_LIST: { case LY_STMT_LIST: {
struct lysc_node *child, *child_next; 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; node_free = (child->nodetype & (LYS_INPUT | LYS_OUTPUT)) ? 1 : 0;
lysc_node_free_(&fctx, child); lysc_node_free_(&fctx, child);
if (node_free) { if (node_free) {
free(child); free(child);
} }
} }
*VOIDPTR2_C(substmts[u].storage) = NULL; *substmts[u].storage_p = NULL;
break; break;
} }
case LY_STMT_USES: 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_REFERENCE:
case LY_STMT_UNITS: { case LY_STMT_UNITS: {
/* single item */ /* single item */
const char *str = *VOIDPTR2_C(substmts[u].storage); const char *str = *substmts[u].storage_p;
lydict_remove(ctx, str); lydict_remove(ctx, str);
break; 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_BIT:
case LY_STMT_ENUM: { case LY_STMT_ENUM: {
/* sized array */ /* 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); FREE_ARRAY(&fctx, items, lysc_enum_item_free);
break; 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_LENGTH:
case LY_STMT_RANGE: { case LY_STMT_RANGE: {
/* single item */ /* single item */
struct lysc_range *range = *VOIDPTR2_C(substmts[u].storage); struct lysc_range *range = *substmts[u].storage_p;
lysc_range_free(&fctx, range); lysc_range_free(&fctx, range);
break; break;
} }
case LY_STMT_MUST: { case LY_STMT_MUST: {
/* sized array */ /* 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); FREE_ARRAY(&fctx, musts, lysc_must_free);
break; break;
} }
case LY_STMT_WHEN: case LY_STMT_WHEN:
/* single item, expects a pointer */ /* 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; break;
case LY_STMT_PATTERN: { case LY_STMT_PATTERN: {
/* sized array of pointers */ /* 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); FREE_ARRAY(&fctx, patterns, lysc_pattern_free);
break; break;
} }
case LY_STMT_TYPE: { case LY_STMT_TYPE: {
/* single item */ /* single item */
struct lysc_type *type = *VOIDPTR2_C(substmts[u].storage); struct lysc_type *type = *substmts[u].storage_p;
lysc_type_free(&fctx, type); lysc_type_free(&fctx, type);
break; break;
} }
case LY_STMT_IDENTITY: { case LY_STMT_IDENTITY: {
/* sized array */ /* 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); FREE_ARRAY(&fctx, idents, lysc_ident_free);
break; break;
} }
case LY_STMT_EXTENSION_INSTANCE: { case LY_STMT_EXTENSION_INSTANCE: {
/* sized array */ /* 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); FREE_ARRAY(&fctx, exts, lysc_ext_instance_free);
break; break;

View file

@ -726,11 +726,11 @@ uint8_t lys_stmt_flags(enum ly_stmt stmt);
* @param[in] ext Compiled ext instance. * @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 * @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. * 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_SUCCESS on success.
* @return LY_ENOT if the substatement is not supported. * @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 * @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] 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 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_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. * @param[in,out] diff Validation diff.
* @return 1 if @p node auto-deleted and updated to its next sibling. * @return 1 if @p node auto-deleted and updated to its next sibling.
* @return 0 if @p node was not auto-deleted. * @return 0 if @p node was not auto-deleted.
*/ */
static ly_bool static ly_bool
lyd_validate_autodel_node_del(struct lyd_node **first, struct lyd_node *del, const struct lys_module *mod, 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; struct lyd_node *iter;
ly_bool node_autodel = 0; 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) { if (node_types && node_types->count) {
/* remove from node_types set */ /* remove from node_types set */
LYD_TREE_DFS_BEGIN(del, iter) { 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) uint32_t xpath_options, struct ly_set *node_types, struct lyd_node **diff)
{ {
LY_ERR rc = LY_SUCCESS, r; LY_ERR rc = LY_SUCCESS, r;
uint32_t i; uint32_t i, count;
const struct lysc_when *disabled; const struct lysc_when *disabled;
struct lyd_node *node = NULL; 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 */ /* when false */
if (node->flags & LYD_WHEN_TRUE) { if (node->flags & LYD_WHEN_TRUE) {
/* autodelete */ /* 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) { } else if (val_opts & LYD_VALIDATE_OPERATIONAL) {
/* only a warning */ /* only a warning */
LOGWRN(LYD_CTX(node), "When condition \"%s\" not satisfied.", disabled->cond->expr); 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) { LYD_LIST_FOR_INST_SAFE(*first, schema, next, iter) {
if (iter->flags & LYD_DEFAULT) { if (iter->flags & LYD_DEFAULT) {
/* default instance found, remove it */ /* 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; 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) { LYD_LIST_FOR_INST_SAFE(*first, schema, next, iter) {
if (iter->flags & LYD_DEFAULT) { if (iter->flags & LYD_DEFAULT) {
/* default instance, remove it */ /* 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; 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) { LYD_LIST_FOR_INST(*first, schema, iter) {
if ((iter->flags & LYD_DEFAULT) && !(iter->flags & LYD_NEW)) { if ((iter->flags & LYD_DEFAULT) && !(iter->flags & LYD_NEW)) {
/* old default instance, remove it */ /* 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; node_autodel = 1;
} }
break; break;
@ -753,7 +769,7 @@ lyd_validate_autodel_case_dflt(struct lyd_node **first, struct lyd_node **node,
if (!iter) { if (!iter) {
/* there are only default nodes of the case meaning it does not exist and neither should any default nodes /* 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 */ * 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; node_autodel = 1;
} }
} }

View file

@ -16,6 +16,8 @@
#ifndef LY_VERSION_H_ #ifndef LY_VERSION_H_
#define LY_VERSION_H_ #define LY_VERSION_H_
#include "ly_config.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -30,22 +32,61 @@ extern "C" {
#define LY_PROJ_VERSION_MICRO @LIBYANG_MICRO_VERSION@ /**< project micro version number */ #define LY_PROJ_VERSION_MICRO @LIBYANG_MICRO_VERSION@ /**< project micro version number */
#define LY_PROJ_VERSION "@LIBYANG_VERSION@" /**< project version string */ #define LY_PROJ_VERSION "@LIBYANG_VERSION@" /**< project version string */
struct ly_version { /**
uint32_t major; /**< Major version number */ * @brief Get libyang major SO version.
uint32_t minor; /**< Minor version number */ *
uint32_t micro; /**< Micro version number */ * @return LY version.
const char *str; /**< Version string */ */
}; 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 #ifdef __cplusplus
} }

View file

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

View file

@ -80,7 +80,7 @@ module notifications {
} }
} }
/*container notification { container notification {
description "internal struct to start a notification"; description "internal struct to start a notification";
config false; config false;
@ -90,6 +90,6 @@ module notifications {
} }
// eventType and any data content goes here // 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); 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; 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) { LY_ARRAY_FOR(ext, u) {
substmts = ext[u].substmts; substmts = ext[u].substmts;
LY_ARRAY_FOR(substmts, v) { LY_ARRAY_FOR(substmts, v) {
if (substmts && substmts[v].storage && (substmts[v].stmt & LY_STMT_DATA_NODE_MASK)) { if (substmts && substmts[v].storage_p && (substmts[v].stmt & LY_STMT_DATA_NODE_MASK)) {
cnode = *(struct lysc_node **)substmts[v].storage; cnode = *(struct lysc_node **)substmts[v].storage_p;
iter = check; iter = check;
assert_int_equal(LY_SUCCESS, lysc_tree_dfs_full(cnode, check_node_priv_parsed_is_set, &iter)); 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) { LY_ARRAY_FOR(ext, u) {
substmts = ext[u].substmts; substmts = ext[u].substmts;
LY_ARRAY_FOR(substmts, v) { LY_ARRAY_FOR(substmts, v) {
if (substmts && substmts[v].storage && (substmts[v].stmt & LY_STMT_DATA_NODE_MASK)) { if (substmts && substmts[v].storage_p && (substmts[v].stmt & LY_STMT_DATA_NODE_MASK)) {
cnode = *(struct lysc_node **)substmts[v].storage; cnode = *(struct lysc_node **)substmts[v].storage_p;
if (cnode) { if (cnode) {
CHECK_POINTER((struct lysp_node *)cnode->priv, 0); CHECK_POINTER((struct lysp_node *)cnode->priv, 0);
} }

View file

@ -193,6 +193,18 @@ test_anyxml(void **state)
free(str); free(str);
CHECK_LYD_STRING(tree, LYD_PRINT_WITHSIBLINGS, data_expected); CHECK_LYD_STRING(tree, LYD_PRINT_WITHSIBLINGS, data_expected);
lyd_free_all(tree); 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 static void
@ -349,7 +361,7 @@ test_opaq(void **state)
" <c xmld:id=\"D\">1</c>\n" " <c xmld:id=\"D\">1</c>\n"
"</a>\n", "</a>\n",
LYD_XML, LYD_PARSE_OPAQ, LYD_VALIDATE_PRESENT, &tree)); 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 static void

View file

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

View file

@ -130,6 +130,57 @@ test_insert_cont_leaflist(void **state)
lyd_free_all(cont); 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 static void
test_try_user_order_func(void **state) test_try_user_order_func(void **state)
{ {
@ -1599,6 +1650,7 @@ main(void)
UTEST(test_insert_top_level_leaflist), UTEST(test_insert_top_level_leaflist),
UTEST(test_insert_cont_list), UTEST(test_insert_cont_list),
UTEST(test_insert_cont_leaflist), UTEST(test_insert_cont_leaflist),
UTEST(test_dup_sort),
UTEST(test_try_user_order_func), UTEST(test_try_user_order_func),
UTEST(test_ordered_by_user), UTEST(test_ordered_by_user),
UTEST(test_remove), 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); LY_ARRAY_NEW_GOTO(UTEST_LYCTX, ext_p.substmts, substmtp, rc, cleanup);
substmtp->stmt = LY_STMT_ERROR_MESSAGE; substmtp->stmt = LY_STMT_ERROR_MESSAGE;
substmtp->storage = (uintptr_t)(void *)&ext_p.parsed; substmtp->storage_p = &ext_p.parsed;
/* fake parse */ /* fake parse */
lydict_insert(UTEST_LYCTX, "my error", 0, (const char **)&ext_p.parsed); 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); LY_ARRAY_NEW_GOTO(UTEST_LYCTX, ext_c.substmts, substmt, rc, cleanup);
substmt->stmt = LY_STMT_ERROR_MESSAGE; substmt->stmt = LY_STMT_ERROR_MESSAGE;
substmt->storage = (uintptr_t)(void *)&ext_c.compiled; substmt->storage_p = &ext_c.compiled;
/* /*
* error-message * error-message

View file

@ -1233,6 +1233,7 @@ test_type_instanceid(void **state)
{ {
struct lys_module *mod; struct lys_module *mod;
struct lysc_type *type; 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;}}" 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;}}" "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(LY_TYPE_INST, type->basetype);
assert_int_equal(1, ((struct lysc_type_instanceid *)type)->require_instance); 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 */ /* 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("Parsing module \"aa\" failed.", NULL, 0);
CHECK_LOG_CTX("Invalid value \"yes\" of \"require-instance\".", NULL, 1); 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); 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 ", 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); TEST_GET_ARGUMENT_SUCCESS("\"hello\\n\\t\\\"\\\\\";", YCTX, Y_STR_ARG, "hello\n\t\"\\", 9, ";", 1);
free(buf); 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_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); 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 " CHECK_LOG_CTX("Missing date-and-time fractions after '.'.",
"\"\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d+)?(Z|[\\+\\-]\\d{2}:\\d{2})\".",
"/a:l", 1); "/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); 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); CHECK_LOG_CTX("Invalid date-and-time timezone hour \"95\".", "/a:l", 1);
/* hex-string */ /* 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" send "exit\r"
expect eof 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; uint32_t idx;
const char *start; const char *start;
char *end, *module_name = NULL, *path = NULL; 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; int rc = 0;
size_t len; size_t len;