summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--.github/workflows/ci.yml6
-rw-r--r--CMakeLists.txt13
-rw-r--r--README.md2
-rw-r--r--src/context.c2
-rw-r--r--src/context.h6
-rw-r--r--src/dict.c55
-rw-r--r--src/dict.h12
-rw-r--r--src/hash_table.c26
-rw-r--r--src/log.c11
-rw-r--r--src/ly_common.c58
-rw-r--r--src/ly_common.h3
-rw-r--r--src/parser_common.c74
-rw-r--r--src/parser_xml.c61
-rw-r--r--src/parser_yang.c35
-rw-r--r--src/parser_yin.c13
-rw-r--r--src/path.c26
-rw-r--r--src/path.h3
-rw-r--r--src/plugins.c8
-rw-r--r--src/plugins.h19
-rw-r--r--src/plugins_exts.c100
-rw-r--r--src/plugins_exts.h7
-rw-r--r--src/plugins_exts/metadata.c24
-rw-r--r--src/plugins_exts/structure.c84
-rw-r--r--src/plugins_exts/yangdata.c12
-rw-r--r--src/plugins_types.c25
-rw-r--r--src/plugins_types.h35
-rw-r--r--src/plugins_types/binary.c43
-rw-r--r--src/plugins_types/date_and_time.c18
-rw-r--r--src/plugins_types/decimal64.c39
-rw-r--r--src/plugins_types/hex_string.c27
-rw-r--r--src/plugins_types/instanceid.c68
-rw-r--r--src/plugins_types/integer.c123
-rw-r--r--src/plugins_types/ipv4_address.c18
-rw-r--r--src/plugins_types/ipv4_address_no_zone.c14
-rw-r--r--src/plugins_types/ipv4_prefix.c18
-rw-r--r--src/plugins_types/ipv6_address.c18
-rw-r--r--src/plugins_types/ipv6_address_no_zone.c14
-rw-r--r--src/plugins_types/ipv6_prefix.c18
-rw-r--r--src/plugins_types/leafref.c25
-rw-r--r--src/plugins_types/node_instanceid.c8
-rw-r--r--src/plugins_types/string.c50
-rw-r--r--src/plugins_types/time_period.c100
-rw-r--r--src/plugins_types/union.c11
-rw-r--r--src/plugins_types/xpath1.0.c12
-rw-r--r--src/printer_yang.c58
-rw-r--r--src/schema_compile.c27
-rw-r--r--src/schema_compile.h8
-rw-r--r--src/schema_compile_amend.c6
-rw-r--r--src/schema_compile_node.c7
-rw-r--r--src/schema_features.c4
-rw-r--r--src/tree_data.c107
-rw-r--r--src/tree_data_common.c18
-rw-r--r--src/tree_data_hash.c2
-rw-r--r--src/tree_data_internal.h8
-rw-r--r--src/tree_data_new.c22
-rw-r--r--src/tree_schema.c6
-rw-r--r--src/tree_schema_common.c4
-rw-r--r--src/tree_schema_free.c72
-rw-r--r--src/tree_schema_internal.h4
-rw-r--r--src/validation.c30
-rw-r--r--src/version.h.in61
-rw-r--r--src/xpath.c8
-rw-r--r--tests/modules/yang/notifications@2008-07-14.yang4
-rw-r--r--tests/perf/perf.c3
-rw-r--r--tests/utests/basic/test_context.c8
-rw-r--r--tests/utests/data/test_parser_xml.c14
-rw-r--r--tests/utests/data/test_tree_data.c2
-rw-r--r--tests/utests/data/test_tree_data_sorted.c52
-rw-r--r--tests/utests/schema/test_schema.c4
-rw-r--r--tests/utests/schema/test_tree_schema_compile.c15
-rw-r--r--tests/utests/schema/test_yang.c2
-rw-r--r--tests/utests/types/yang_types.c7
-rw-r--r--tests/yanglint/interactive/debug.test33
-rw-r--r--tests/yanglint/interactive/ly.tcl14
-rw-r--r--tools/lint/completion.c2
75 files changed, 1080 insertions, 876 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index ef3bfe6..6ab2938 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -64,13 +64,13 @@ jobs:
build-cmd: "make"
}
- {
- name: "Release, macOS 11, clang",
- os: "macos-11",
+ name: "Release, macOS 14, clang",
+ os: "macos-14",
build-type: "Release",
cc: "clang",
options: "-DENABLE_TESTS=ON -DPATH_EXPECT=",
packager: "brew",
- packages: "cmocka shunit2",
+ packages: "cmocka shunit2 tcl-tk",
snaps: "",
build-cmd: "make"
}
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 75740a9..8d0bb28 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -59,14 +59,14 @@ set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
# set version of the project
set(LIBYANG_MAJOR_VERSION 3)
-set(LIBYANG_MINOR_VERSION 1)
-set(LIBYANG_MICRO_VERSION 0)
+set(LIBYANG_MINOR_VERSION 4)
+set(LIBYANG_MICRO_VERSION 2)
set(LIBYANG_VERSION ${LIBYANG_MAJOR_VERSION}.${LIBYANG_MINOR_VERSION}.${LIBYANG_MICRO_VERSION})
# set version of the library
set(LIBYANG_MAJOR_SOVERSION 3)
-set(LIBYANG_MINOR_SOVERSION 2)
-set(LIBYANG_MICRO_SOVERSION 0)
+set(LIBYANG_MINOR_SOVERSION 4)
+set(LIBYANG_MICRO_SOVERSION 2)
set(LIBYANG_SOVERSION_FULL ${LIBYANG_MAJOR_SOVERSION}.${LIBYANG_MINOR_SOVERSION}.${LIBYANG_MICRO_SOVERSION})
set(LIBYANG_SOVERSION ${LIBYANG_MAJOR_SOVERSION})
@@ -106,7 +106,8 @@ set(type_plugins
src/plugins_types/date_and_time.c
src/plugins_types/hex_string.c
src/plugins_types/xpath1.0.c
- src/plugins_types/node_instanceid.c)
+ src/plugins_types/node_instanceid.c
+ src/plugins_types/time_period.c)
set(libsrc
src/ly_common.c
@@ -471,7 +472,7 @@ endif()
# generate API/ABI report
if("${BUILD_TYPE_UPPER}" STREQUAL "ABICHECK")
- lib_abi_check(yang "${headers}" ${LIBYANG_SOVERSION_FULL} 708a8bfad983a4095c8d4dc537a9d2a1d5ca65c5)
+ lib_abi_check(yang "${headers}" ${LIBYANG_SOVERSION_FULL} 670385f9595014dc9307615fa6e929b46dba026b)
endif()
# source code format target for Makefile
diff --git a/README.md b/README.md
index bcb94be..cdfc1e0 100644
--- a/README.md
+++ b/README.md
@@ -58,8 +58,6 @@ the `distro` directory.
* C compiler
* cmake >= 2.8.12
* libpcre2 >= 10.21 (including devel package)
- * note, that PCRE is supposed to be compiled with unicode support (configure's options
- `--enable-utf` and `--enable-unicode-properties`)
#### Optional
diff --git a/src/context.c b/src/context.c
index 912f56d..2345cf2 100644
--- a/src/context.c
+++ b/src/context.c
@@ -721,7 +721,7 @@ ly_ctx_unset_options(struct ly_ctx *ctx, uint16_t option)
ext = &mod->compiled->exts[u];
LY_ARRAY_FOR(ext->substmts, v) {
if (ext->substmts[v].stmt & LY_STMT_DATA_NODE_MASK) {
- LY_LIST_FOR(*VOIDPTR2_C(ext->substmts[v].storage), root) {
+ LY_LIST_FOR(*ext->substmts[v].storage_p, root) {
lysc_tree_dfs_full(root, lysc_node_clear_priv_dfs_cb, NULL);
}
}
diff --git a/src/context.h b/src/context.h
index 31f41b9..a9ad91f 100644
--- a/src/context.h
+++ b/src/context.h
@@ -602,10 +602,10 @@ LIBYANG_API_DECL const struct lysp_submodule *ly_ctx_get_submodule2_latest(const
LIBYANG_API_DECL uint32_t ly_ctx_internal_modules_count(const struct ly_ctx *ctx);
/**
- * @brief Try to find the model in the searchpaths of \p ctx and load it into it. If custom missing
+ * @brief Try to find the model in the searchpaths of @p ctx and load it into it. If custom missing
* module callback is set, it is used instead.
*
- * The context itself is searched for the requested module first. If \p revision is not specified
+ * The context itself is searched for the requested module first. If @p revision is not specified
* (the module of the latest revision is requested) and there is implemented revision of the requested
* module in the context, this implemented revision is returned despite there might be a newer revision.
* This behavior is cause by the fact that it is not possible to have multiple implemented revisions of
@@ -660,7 +660,7 @@ LIBYANG_API_DECL LY_ERR ly_ctx_get_yanglib_data(const struct ly_ctx *ctx, struct
* Note that the data stored by user into the ::lysc_node.priv pointer are kept
* untouched and the caller is responsible for freeing this private data.
*
- * @param[in] ctx libyang context to destroy
+ * @param[in] ctx Context to destroy.
*/
LIBYANG_API_DECL void ly_ctx_destroy(struct ly_ctx *ctx);
diff --git a/src/dict.c b/src/dict.c
index 9f741a2..ba574c8 100644
--- a/src/dict.c
+++ b/src/dict.c
@@ -104,9 +104,6 @@ lydict_resize_val_eq(void *val1_p, void *val2_p, ly_bool mod, void *UNUSED(cb_da
str1 = ((struct ly_dict_rec *)val1_p)->value;
str2 = ((struct ly_dict_rec *)val2_p)->value;
- LY_CHECK_ERR_RET(!str1, LOGARG(NULL, val1_p), 0);
- LY_CHECK_ERR_RET(!str2, LOGARG(NULL, val2_p), 0);
-
if (mod) {
/* used when inserting new values */
if (strcmp(str1, str2) == 0) {
@@ -177,7 +174,7 @@ finish:
return ret;
}
-LY_ERR
+static LY_ERR
dict_insert(const struct ly_ctx *ctx, char *value, size_t len, ly_bool zerocopy, const char **str_p)
{
LY_ERR ret = LY_SUCCESS;
@@ -221,9 +218,7 @@ dict_insert(const struct ly_ctx *ctx, char *value, size_t len, ly_bool zerocopy,
return ret;
}
- if (str_p) {
- *str_p = match->value;
- }
+ *str_p = match->value;
return ret;
}
@@ -269,3 +264,49 @@ lydict_insert_zc(const struct ly_ctx *ctx, char *value, const char **str_p)
return result;
}
+
+static LY_ERR
+dict_dup(const struct ly_ctx *ctx, char *value, const char **str_p)
+{
+ LY_ERR ret = LY_SUCCESS;
+ struct ly_dict_rec *match = NULL, rec;
+ uint32_t hash;
+
+ /* set new callback to only compare memory addresses */
+ lyht_value_equal_cb prev = lyht_set_cb(ctx->dict.hash_tab, lydict_resize_val_eq);
+
+ LOGDBG(LY_LDGDICT, "duplicating %s", value);
+ hash = lyht_hash(value, strlen(value));
+ rec.value = value;
+
+ ret = lyht_find(ctx->dict.hash_tab, (void *)&rec, hash, (void **)&match);
+ if (ret == LY_SUCCESS) {
+ /* record found, increase refcount */
+ match->refcount++;
+ *str_p = match->value;
+ }
+
+ /* restore callback */
+ lyht_set_cb(ctx->dict.hash_tab, prev);
+
+ return ret;
+}
+
+LIBYANG_API_DEF LY_ERR
+lydict_dup(const struct ly_ctx *ctx, const char *value, const char **str_p)
+{
+ LY_ERR result;
+
+ LY_CHECK_ARG_RET(ctx, ctx, str_p, LY_EINVAL);
+
+ if (!value) {
+ *str_p = NULL;
+ return LY_SUCCESS;
+ }
+
+ pthread_mutex_lock((pthread_mutex_t *)&ctx->dict.lock);
+ result = dict_dup(ctx, (char *)value, str_p);
+ pthread_mutex_unlock((pthread_mutex_t *)&ctx->dict.lock);
+
+ return result;
+}
diff --git a/src/dict.h b/src/dict.h
index cf897e7..bc8cac1 100644
--- a/src/dict.h
+++ b/src/dict.h
@@ -113,6 +113,18 @@ LIBYANG_API_DECL LY_ERR lydict_insert_zc(const struct ly_ctx *ctx, char *value,
*/
LIBYANG_API_DECL LY_ERR lydict_remove(const struct ly_ctx *ctx, const char *value);
+/**
+ * @brief Duplicate string in dictionary. Only a reference counter is incremented.
+ *
+ * @param[in] ctx libyang context handler
+ * @param[in] value NULL-terminated string to be duplicated in the dictionary (reference counter is incremented).
+ * @param[out] str_p Optional parameter to get pointer to the string corresponding to the @p value and stored in dictionary.
+ * @return LY_SUCCESS in case the string already exists in the dictionary.
+ * @return LY_ENOTFOUND in case the string was not found.
+ * @return LY_ERR on other errors
+ */
+LIBYANG_API_DECL LY_ERR lydict_dup(const struct ly_ctx *ctx, const char *value, const char **str_p);
+
/** @} dict */
#ifdef __cplusplus
diff --git a/src/hash_table.c b/src/hash_table.c
index f951e6a..4dbfdd1 100644
--- a/src/hash_table.c
+++ b/src/hash_table.c
@@ -179,6 +179,7 @@ lyht_free(struct ly_ht *ht, void (*val_free)(void *val_p))
*
* @param[in] ht Hash table to resize.
* @param[in] operation Operation to perform. 1 to enlarge, -1 to shrink, 0 to only rehash all records.
+ * @param[in] check Whether to check if the value has already been inserted or not.
* @return LY_ERR value.
*/
static LY_ERR
@@ -247,7 +248,6 @@ lyht_resize(struct ly_ht *ht, int operation, int check)
* @param[in] hash Hash to find.
* @param[in] mod Whether the operation modifies the hash table (insert or remove) or not (find).
* @param[in] val_equal Callback for checking value equivalence.
- * @param[out] crec_p Optional found first record.
* @param[out] col Optional collision number of @p rec_p, 0 for no collision.
* @param[out] rec_p Found exact matching record, may be a collision of @p crec_p.
* @return LY_ENOTFOUND if no record found,
@@ -255,15 +255,12 @@ lyht_resize(struct ly_ht *ht, int operation, int check)
*/
static LY_ERR
lyht_find_rec(const struct ly_ht *ht, void *val_p, uint32_t hash, ly_bool mod, lyht_value_equal_cb val_equal,
- struct ly_ht_rec **crec_p, uint32_t *col, struct ly_ht_rec **rec_p)
+ uint32_t *col, struct ly_ht_rec **rec_p)
{
uint32_t hlist_idx = hash & (ht->size - 1);
struct ly_ht_rec *rec;
uint32_t rec_idx;
- if (crec_p) {
- *crec_p = NULL;
- }
if (col) {
*col = 0;
}
@@ -271,9 +268,6 @@ lyht_find_rec(const struct ly_ht *ht, void *val_p, uint32_t hash, ly_bool mod, l
LYHT_ITER_HLIST_RECS(ht, hlist_idx, rec_idx, rec) {
if ((rec->hash == hash) && val_equal(val_p, &rec->val, mod, ht->cb_data)) {
- if (crec_p) {
- *crec_p = rec;
- }
*rec_p = rec;
return LY_SUCCESS;
}
@@ -292,7 +286,11 @@ lyht_find(const struct ly_ht *ht, void *val_p, uint32_t hash, void **match_p)
{
struct ly_ht_rec *rec;
- lyht_find_rec(ht, val_p, hash, 0, ht->val_equal, NULL, NULL, &rec);
+ if (match_p) {
+ *match_p = NULL;
+ }
+
+ lyht_find_rec(ht, val_p, hash, 0, ht->val_equal, NULL, &rec);
if (rec && match_p) {
*match_p = rec->val;
@@ -305,7 +303,7 @@ lyht_find_with_val_cb(const struct ly_ht *ht, void *val_p, uint32_t hash, lyht_v
{
struct ly_ht_rec *rec;
- lyht_find_rec(ht, val_p, hash, 0, val_equal ? val_equal : ht->val_equal, NULL, NULL, &rec);
+ lyht_find_rec(ht, val_p, hash, 0, val_equal ? val_equal : ht->val_equal, NULL, &rec);
if (rec && match_p) {
*match_p = rec->val;
@@ -317,12 +315,12 @@ LIBYANG_API_DEF LY_ERR
lyht_find_next_with_collision_cb(const struct ly_ht *ht, void *val_p, uint32_t hash,
lyht_value_equal_cb collision_val_equal, void **match_p)
{
- struct ly_ht_rec *rec, *crec;
+ struct ly_ht_rec *rec;
uint32_t rec_idx;
uint32_t i;
/* find the record of the previously found value */
- if (lyht_find_rec(ht, val_p, hash, 1, ht->val_equal, &crec, &i, &rec)) {
+ if (lyht_find_rec(ht, val_p, hash, 1, ht->val_equal, &i, &rec)) {
/* not found, cannot happen */
LOGINT_RET(NULL);
}
@@ -373,7 +371,7 @@ _lyht_insert_with_resize_cb(struct ly_ht *ht, void *val_p, uint32_t hash, lyht_v
uint32_t rec_idx;
if (check) {
- if (lyht_find_rec(ht, val_p, hash, 1, ht->val_equal, NULL, NULL, &rec) == LY_SUCCESS) {
+ if (lyht_find_rec(ht, val_p, hash, 1, ht->val_equal, NULL, &rec) == LY_SUCCESS) {
if (rec && match_p) {
*match_p = rec->val;
}
@@ -459,7 +457,7 @@ lyht_remove_with_resize_cb(struct ly_ht *ht, void *val_p, uint32_t hash, lyht_va
uint32_t prev_rec_idx;
uint32_t rec_idx;
- if (lyht_find_rec(ht, val_p, hash, 1, ht->val_equal, NULL, NULL, &found_rec)) {
+ if (lyht_find_rec(ht, val_p, hash, 1, ht->val_equal, NULL, &found_rec)) {
LOGARG(NULL, hash);
return LY_ENOTFOUND;
}
diff --git a/src/log.c b/src/log.c
index 9bb4b19..9cb60b3 100644
--- a/src/log.c
+++ b/src/log.c
@@ -189,10 +189,15 @@ ly_err_get_rec(const struct ly_ctx *ctx)
/* prepare record */
rec.tid = pthread_self();
+ /* reuse lock */
+ /* LOCK */
+ pthread_mutex_lock((pthread_mutex_t *)&ctx->lyb_hash_lock);
+
/* get the pointer to the matching record */
- if (lyht_find(ctx->err_ht, &rec, lyht_hash((void *)&rec.tid, sizeof rec.tid), (void **)&match)) {
- return NULL;
- }
+ lyht_find(ctx->err_ht, &rec, lyht_hash((void *)&rec.tid, sizeof rec.tid), (void **)&match);
+
+ /* UNLOCK */
+ pthread_mutex_unlock((pthread_mutex_t *)&ctx->lyb_hash_lock);
return match;
}
diff --git a/src/ly_common.c b/src/ly_common.c
index 28d7514..449c862 100644
--- a/src/ly_common.c
+++ b/src/ly_common.c
@@ -40,19 +40,53 @@
#include "version.h"
#include "xml.h"
-LIBYANG_API_DEF struct ly_version ly_version_so = {
- .major = LY_VERSION_MAJOR,
- .minor = LY_VERSION_MINOR,
- .micro = LY_VERSION_MICRO,
- .str = LY_VERSION
-};
+LIBYANG_API_DEF uint32_t
+ly_version_so_major(void)
+{
+ return LY_VERSION_MAJOR;
+}
-LIBYANG_API_DEF struct ly_version ly_version_proj = {
- .major = LY_PROJ_VERSION_MAJOR,
- .minor = LY_PROJ_VERSION_MINOR,
- .micro = LY_PROJ_VERSION_MICRO,
- .str = LY_PROJ_VERSION
-};
+LIBYANG_API_DEF uint32_t
+ly_version_so_minor(void)
+{
+ return LY_VERSION_MINOR;
+}
+
+LIBYANG_API_DEF uint32_t
+ly_version_so_micro(void)
+{
+ return LY_VERSION_MICRO;
+}
+
+LIBYANG_API_DEF const char *
+ly_version_so_str(void)
+{
+ return LY_VERSION;
+}
+
+LIBYANG_API_DEF uint32_t
+ly_version_proj_major(void)
+{
+ return LY_PROJ_VERSION_MAJOR;
+}
+
+LIBYANG_API_DEF uint32_t
+ly_version_proj_minor(void)
+{
+ return LY_PROJ_VERSION_MINOR;
+}
+
+LIBYANG_API_DEF uint32_t
+ly_version_proj_micro(void)
+{
+ return LY_PROJ_VERSION_MICRO;
+}
+
+LIBYANG_API_DEF const char *
+ly_version_proj_str(void)
+{
+ return LY_PROJ_VERSION;
+}
void *
ly_realloc(void *ptr, size_t size)
diff --git a/src/ly_common.h b/src/ly_common.h
index 8dc32d7..ec0d3ea 100644
--- a/src/ly_common.h
+++ b/src/ly_common.h
@@ -61,9 +61,6 @@ struct lysc_node;
#define GETMACRO6(_1, _2, _3, _4, _5, _6, NAME, ...) NAME
#define GETMACRO7(_1, _2, _3, _4, _5, _6, _7, NAME, ...) NAME
-#define VOIDPTR_C(var) ((void *)(uintptr_t)(var))
-#define VOIDPTR2_C(var) ((void **)(uintptr_t)(var))
-
/******************************************************************************
* Logger
*****************************************************************************/
diff --git a/src/parser_common.c b/src/parser_common.c
index 290e3a5..5dadecf 100644
--- a/src/parser_common.c
+++ b/src/parser_common.c
@@ -3,7 +3,7 @@
* @author Michal Vasko <mvasko@cesnet.cz>
* @brief libyang common parser functions.
*
- * Copyright (c) 2015 - 2022 CESNET, z.s.p.o.
+ * Copyright (c) 2015 - 2024 CESNET, z.s.p.o.
*
* This source code is licensed under BSD 3-Clause License (the "License").
* You may not use this file except in compliance with the License.
@@ -70,34 +70,48 @@ lyd_parser_notif_eventtime_validate(const struct lyd_node *node)
{
LY_ERR rc = LY_SUCCESS;
struct ly_ctx *ctx = (struct ly_ctx *)LYD_CTX(node);
- struct lysc_ctx cctx;
- const struct lys_module *mod;
+ struct lysc_ctx cctx = {0};
+ const struct lys_module *mod1, *mod2;
+ const struct lysc_node *schema;
LY_ARRAY_COUNT_TYPE u;
struct ly_err_item *err = NULL;
struct lysp_type *type_p = NULL;
struct lysc_pattern **patterns = NULL;
const char *value;
- LYSC_CTX_INIT_CTX(cctx, ctx);
+ /* 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);
- /* get date-and-time parsed type */
- mod = ly_ctx_get_module_latest(ctx, "ietf-yang-types");
- assert(mod);
- LY_ARRAY_FOR(mod->parsed->typedefs, u) {
- if (!strcmp(mod->parsed->typedefs[u].name, "date-and-time")) {
- type_p = &mod->parsed->typedefs[u].type;
- break;
+ if (mod1 || !mod2->parsed) {
+ /* get date-and-time leaf */
+ schema = lys_find_path(LYD_CTX(node), NULL, "/notifications:notification/eventTime", 0);
+ LY_CHECK_RET(!schema, LY_ENOTFOUND);
+
+ /* validate the value */
+ value = lyd_get_value(node);
+ LY_CHECK_RET(lyd_value_validate(LYD_CTX(node), schema, value, strlen(value), NULL, NULL, NULL));
+ } else {
+ LYSC_CTX_INIT_CTX(cctx, ctx);
+
+ /* get date-and-time parsed type */
+ LY_ARRAY_FOR(mod2->parsed->typedefs, u) {
+ if (!strcmp(mod2->parsed->typedefs[u].name, "date-and-time")) {
+ type_p = &mod2->parsed->typedefs[u].type;
+ break;
+ }
}
- }
- assert(type_p);
+ assert(type_p);
- /* compile patterns */
- assert(type_p->patterns);
- LY_CHECK_GOTO(rc = lys_compile_type_patterns(&cctx, type_p->patterns, NULL, &patterns), cleanup);
+ /* compile patterns */
+ assert(type_p->patterns);
+ LY_CHECK_GOTO(rc = lys_compile_type_patterns(&cctx, type_p->patterns, NULL, &patterns), cleanup);
- /* validate */
- value = lyd_get_value(node);
- rc = lyplg_type_validate_patterns(patterns, value, strlen(value), &err);
+ /* validate */
+ value = lyd_get_value(node);
+ rc = lyplg_type_validate_patterns(patterns, value, strlen(value), &err);
+ }
cleanup:
FREE_ARRAY(&cctx.free_ctx, patterns, lysc_pattern_free);
@@ -3559,7 +3573,7 @@ lys_parse_ext_instance_stmt(struct lysp_ctx *pctx, struct lysp_ext_substmt *subs
{
LY_ERR rc = LY_SUCCESS;
- if (!substmt->storage) {
+ if (!substmt->storage_p) {
/* nothing to parse, ignored */
goto cleanup;
}
@@ -3587,7 +3601,7 @@ lys_parse_ext_instance_stmt(struct lysp_ctx *pctx, struct lysp_ext_substmt *subs
LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, (void **)&pnode, NULL), cleanup);
/* usually is a linked-list of all the parsed schema nodes */
- pnodes_p = VOIDPTR_C(substmt->storage);
+ pnodes_p = (struct lysp_node **)substmt->storage_p;
while (*pnodes_p) {
pnodes_p = &(*pnodes_p)->next;
}
@@ -3615,7 +3629,7 @@ lys_parse_ext_instance_stmt(struct lysp_ctx *pctx, struct lysp_ext_substmt *subs
case LY_STMT_TYPEDEF:
case LY_STMT_UNIQUE:
/* parse, sized array */
- LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, VOIDPTR_C(substmt->storage), NULL), cleanup);
+ LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage_p, NULL), cleanup);
break;
case LY_STMT_ARGUMENT:
@@ -3650,50 +3664,50 @@ lys_parse_ext_instance_stmt(struct lysp_ctx *pctx, struct lysp_ext_substmt *subs
case LY_STMT_YANG_VERSION:
case LY_STMT_YIN_ELEMENT:
/* single item */
- if (*VOIDPTR2_C(substmt->storage)) {
+ if (*substmt->storage_p) {
LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
rc = LY_EVALID;
goto cleanup;
}
/* parse */
- LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, VOIDPTR_C(substmt->storage), NULL), cleanup);
+ LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage_p, NULL), cleanup);
break;
case LY_STMT_CONFIG:
/* single item */
- if ((*(uint16_t *)VOIDPTR2_C(substmt->storage)) & LYS_CONFIG_MASK) {
+ if ((*(uint16_t *)substmt->storage_p) & LYS_CONFIG_MASK) {
LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
rc = LY_EVALID;
goto cleanup;
}
/* parse */
- LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, VOIDPTR_C(substmt->storage), NULL), cleanup);
+ LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage_p, NULL), cleanup);
break;
case LY_STMT_ORDERED_BY:
/* single item */
- if ((*(uint16_t *)VOIDPTR2_C(substmt->storage)) & LYS_ORDBY_MASK) {
+ if ((*(uint16_t *)substmt->storage_p) & LYS_ORDBY_MASK) {
LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
rc = LY_EVALID;
goto cleanup;
}
/* parse */
- LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, VOIDPTR_C(substmt->storage), NULL), cleanup);
+ LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage_p, NULL), cleanup);
break;
case LY_STMT_STATUS:
/* single item */
- if ((*(uint16_t *)VOIDPTR2_C(substmt->storage)) & LYS_STATUS_MASK) {
+ if ((*(uint16_t *)substmt->storage_p) & LYS_STATUS_MASK) {
LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
rc = LY_EVALID;
goto cleanup;
}
/* parse */
- LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, VOIDPTR_C(substmt->storage), NULL), cleanup);
+ LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage_p, NULL), cleanup);
break;
default:
diff --git a/src/parser_xml.c b/src/parser_xml.c
index 0db10ca..34d6fdc 100644
--- a/src/parser_xml.c
+++ b/src/parser_xml.c
@@ -54,6 +54,30 @@ lyd_xml_ctx_free(struct lyd_ctx *lydctx)
}
/**
+ * @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.
*
* @param[in] lydctx XML data parser context.
@@ -109,8 +133,10 @@ lydxml_metadata(struct lyd_xml_ctx *lydctx, const struct lysc_node *sparent, str
if (lydctx->parse_opts & LYD_PARSE_STRICT) {
LOGVAL(xmlctx->ctx, LYVE_REFERENCE, "Missing mandatory prefix for XML metadata \"%.*s\".",
(int)xmlctx->name_len, xmlctx->name);
- ret = LY_EVALID;
- goto cleanup;
+ /* If LYD_VALIDATE_MULTI_ERROR is set, then continue parsing, because otherwise the parser context
+ * will remain in a bad state, which will cause termination on some assert or undefined behavior.
+ */
+ LY_DPARSER_ERR_GOTO(LY_EVALID, ret = LY_EVALID, lydctx, cleanup);
}
/* skip attr */
@@ -123,8 +149,7 @@ lydxml_metadata(struct lyd_xml_ctx *lydctx, const struct lysc_node *sparent, str
/* get namespace of the attribute to find its annotation definition */
ns = lyxml_ns_get(&xmlctx->ns, xmlctx->prefix, xmlctx->prefix_len);
if (!ns) {
- /* unknown namespace, XML error */
- LOGVAL(xmlctx->ctx, LYVE_REFERENCE, "Unknown XML prefix \"%.*s\".", (int)xmlctx->prefix_len, xmlctx->prefix);
+ lydxml_log_namespace_err(xmlctx, xmlctx->prefix, xmlctx->prefix_len, xmlctx->name, xmlctx->name_len);
ret = LY_ENOTFOUND;
goto cleanup;
}
@@ -215,7 +240,7 @@ lydxml_attrs(struct lyxml_ctx *xmlctx, struct lyd_attr **attr)
if (prefix_len) {
ns = lyxml_ns_get(&xmlctx->ns, prefix, prefix_len);
if (!ns) {
- LOGVAL(xmlctx->ctx, LYVE_REFERENCE, "Unknown XML prefix \"%.*s\".", (int)prefix_len, prefix);
+ lydxml_log_namespace_err(xmlctx, prefix, prefix_len, name, name_len);
ret = LY_EVALID;
goto cleanup;
}
@@ -441,7 +466,9 @@ lydxml_get_hints_opaq(const char *name, size_t name_len, const char *value, size
{
struct lyd_node_opaq *opaq;
char *ptr;
- long num;
+ /* this needs to be at least 64bit, and it "should not" be an explicit int64_t
+ * because the code calls strtoll later on, which "might" return a bigger type */
+ long long num;
*hints = 0;
*anchor = NULL;
@@ -453,11 +480,11 @@ lydxml_get_hints_opaq(const char *name, size_t name_len, const char *value, size
/* boolean value */
*hints |= LYD_VALHINT_BOOLEAN;
} else {
- num = strtol(value, &ptr, 10);
+ num = strtoll(value, &ptr, 10);
if ((unsigned)(ptr - value) == value_len) {
/* number value */
*hints |= LYD_VALHINT_DECNUM;
- if ((num < INT32_MIN) || (num > (long)UINT32_MAX)) {
+ if ((num < INT32_MIN) || (num > UINT32_MAX)) {
/* large number */
*hints |= LYD_VALHINT_NUM64;
}
@@ -535,12 +562,7 @@ lydxml_subtree_get_snode(struct lyd_xml_ctx *lydctx, const struct lyd_node *pare
if (lydctx->int_opts & LYD_INTOPT_ANY) {
goto unknown_module;
}
-
- if (prefix_len) {
- LOGVAL(ctx, LYVE_REFERENCE, "Unknown XML prefix \"%.*s\".", (int)prefix_len, prefix);
- } else {
- LOGVAL(ctx, LYVE_REFERENCE, "Missing XML namespace.");
- }
+ lydxml_log_namespace_err(xmlctx, prefix, prefix_len, NULL, 0);
return LY_EVALID;
}
@@ -1056,14 +1078,13 @@ lydxml_subtree_r(struct lyd_xml_ctx *lydctx, struct lyd_node *parent, struct lyd
/* create metadata/attributes */
if (xmlctx->status == LYXML_ATTRIBUTE) {
if (snode) {
- rc = lydxml_metadata(lydctx, snode, &meta);
- LY_CHECK_GOTO(rc, cleanup);
+ r = lydxml_metadata(lydctx, snode, &meta);
} else {
assert(lydctx->parse_opts & LYD_PARSE_OPAQ);
- rc = lydxml_attrs(xmlctx, &attr);
- LY_CHECK_GOTO(rc, cleanup);
+ r = lydxml_attrs(xmlctx, &attr);
}
}
+ LY_DPARSER_ERR_GOTO(r, rc = r, lydctx, cleanup);
assert(xmlctx->status == LYXML_ELEM_CONTENT);
if (!snode) {
@@ -1175,7 +1196,7 @@ lydxml_envelope(struct lyxml_ctx *xmlctx, const char *name, const char *uri, ly_
prefix_len = xmlctx->prefix_len;
ns = lyxml_ns_get(&xmlctx->ns, prefix, prefix_len);
if (!ns) {
- LOGVAL(xmlctx->ctx, LYVE_REFERENCE, "Unknown XML prefix \"%.*s\".", (int)prefix_len, prefix);
+ lydxml_log_namespace_err(xmlctx, prefix, prefix_len, NULL, 0);
return LY_EVALID;
} else if (strcmp(ns->uri, uri)) {
/* different namespace */
@@ -1399,7 +1420,7 @@ lydxml_opaq_r(struct lyxml_ctx *xmlctx, struct lyd_node *parent)
prefix_len = xmlctx->prefix_len;
ns = lyxml_ns_get(&xmlctx->ns, prefix, prefix_len);
if (!ns) {
- LOGVAL(xmlctx->ctx, LYVE_REFERENCE, "Unknown XML prefix \"%.*s\".", (int)prefix_len, prefix);
+ lydxml_log_namespace_err(xmlctx, prefix, prefix_len, NULL, 0);
return LY_EVALID;
}
diff --git a/src/parser_yang.c b/src/parser_yang.c
index 8511d26..57b5f9b 100644
--- a/src/parser_yang.c
+++ b/src/parser_yang.c
@@ -596,6 +596,7 @@ get_argument(struct lysp_yang_ctx *ctx, enum yang_arg arg, uint16_t *flags, char
size_t buf_len = 0;
uint8_t prefix = 0;
ly_bool str_end = 0;
+ int comment;
/* word buffer - dynamically allocated */
*word_b = NULL;
@@ -627,18 +628,30 @@ get_argument(struct lysp_yang_ctx *ctx, enum yang_arg arg, uint16_t *flags, char
str_end = 1;
break;
case '/':
+ comment = 0;
if (ctx->in->current[1] == '/') {
/* one-line comment */
- MOVE_INPUT(ctx, 2);
- LY_CHECK_GOTO(ret = skip_comment(ctx, 1), error);
+ comment = 1;
} else if (ctx->in->current[1] == '*') {
/* block comment */
- MOVE_INPUT(ctx, 2);
- LY_CHECK_GOTO(ret = skip_comment(ctx, 2), error);
+ comment = 2;
} else {
/* not a comment after all */
LY_CHECK_GOTO(ret = buf_store_char(ctx, arg, word_p, word_len, word_b, &buf_len, 0, &prefix), error);
}
+
+ if (comment) {
+ if (*word_len) {
+ /* invalid comment sequence (RFC 7950 sec. 6.1.3.) */
+ LOGVAL_PARSER(ctx, LYVE_SYNTAX, "Invalid comment sequence \"%.2s\" in an unquoted string.", ctx->in->current);
+ ret = LY_EVALID;
+ goto error;
+ }
+
+ /* skip the comment */
+ MOVE_INPUT(ctx, 2);
+ LY_CHECK_GOTO(ret = skip_comment(ctx, comment), error);
+ }
break;
case ' ':
if (*word_len) {
@@ -838,6 +851,8 @@ keyword_start:
/* fall through */
default:
MOVE_INPUT(ctx, 1);
+ /* fall through */
+ case '\0':
LOGVAL_PARSER(ctx, LY_VCODE_INSTREXP, (int)(ctx->in->current - word_start), word_start,
"a keyword followed by a separator");
return LY_EVALID;
@@ -982,8 +997,16 @@ parse_ext(struct lysp_yang_ctx *ctx, const char *ext_name, size_t ext_name_len,
e->parent_stmt_index = parent_stmt_index;
YANG_READ_SUBSTMT_FOR_GOTO(ctx, kw, word, word_len, ret, cleanup) {
- 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);
+ 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)
+ break;
+ }
+ YANG_READ_SUBSTMT_NEXT_ITER(ctx, kw, word, word_len, e->exts, ret, cleanup);
}
cleanup:
diff --git a/src/parser_yin.c b/src/parser_yin.c
index 3924d0e..eab9c37 100644
--- a/src/parser_yin.c
+++ b/src/parser_yin.c
@@ -4,7 +4,7 @@
* @author Michal Vasko <mvasko@cesnet.cz>
* @brief YIN parser.
*
- * Copyright (c) 2015 - 2022 CESNET, z.s.p.o.
+ * Copyright (c) 2015 - 2024 CESNET, z.s.p.o.
*
* This source code is licensed under BSD 3-Clause License (the "License").
* You may not use this file except in compliance with the License.
@@ -3409,6 +3409,14 @@ yin_parse_extension_instance(struct lysp_yin_ctx *ctx, const void *parent, enum
if (ctx->xmlctx->ws_only) {
LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
while (ctx->xmlctx->status == LYXML_ELEMENT) {
+ /* BUG nested extensions will not be parsed because we are not able to dinsguish between them
+ * and the argument of this extension, in case there is one and its 'yin-element' is 'true'
+ stmt = yin_match_keyword(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix,
+ ctx->xmlctx->prefix_len, LY_STMT_EXTENSION_INSTANCE);
+ if (stmt == LY_STMT_EXTENSION_INSTANCE) {
+ LY_CHECK_RET(yin_parse_extension_instance(ctx, e, LY_STMT_EXTENSION_INSTANCE, 0, &e->exts));
+ } else { */
+
LY_CHECK_RET(yin_parse_element_generic(ctx, LY_STMT_EXTENSION_INSTANCE, &new_subelem));
if (!e->child) {
e->child = new_subelem;
@@ -3420,6 +3428,9 @@ yin_parse_extension_instance(struct lysp_yin_ctx *ctx, const void *parent, enum
assert(ctx->xmlctx->status == LYXML_ELEM_CLOSE);
LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
}
+
+ /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
+ LY_CHECK_RET(yin_unres_exts_add(ctx, e->exts));
} else if (ctx->xmlctx->value_len) {
/* invalid text content */
LOGVAL_PARSER(ctx, LYVE_SYNTAX, "Extension instance \"%s\" with unexpected text content \"%.*s\".", ext_name,
diff --git a/src/path.c b/src/path.c
index 9a77414..3876762 100644
--- a/src/path.c
+++ b/src/path.c
@@ -708,7 +708,7 @@ ly_path_compile_predicate(const struct ly_ctx *ctx, const struct lysc_node *cur_
/* store the value */
LOG_LOCSET(key, NULL);
- ret = lyd_value_store(ctx, &p->value, ((struct lysc_node_leaf *)key)->type, val, val_len, 0, 0,
+ ret = lyd_value_store(ctx_node->module->ctx, &p->value, ((struct lysc_node_leaf *)key)->type, val, val_len, 0, 0,
NULL, format, prefix_data, LYD_HINT_DATA, key, NULL);
LOG_LOCBACK(1, 0);
LY_CHECK_ERR_GOTO(ret, p->value.realtype = NULL, cleanup);
@@ -736,7 +736,7 @@ ly_path_compile_predicate(const struct ly_ctx *ctx, const struct lysc_node *cur_
/* names (keys) are unique - it was checked when parsing */
LOGVAL(ctx, LYVE_XPATH, "Predicate missing for a key of %s \"%s\" in path.",
lys_nodetype2str(ctx_node->nodetype), ctx_node->name);
- ly_path_predicates_free(ctx, *predicates);
+ ly_path_predicates_free(ctx_node->module->ctx, *predicates);
*predicates = NULL;
ret = LY_EVALID;
goto cleanup;
@@ -771,12 +771,10 @@ ly_path_compile_predicate(const struct ly_ctx *ctx, const struct lysc_node *cur_
}
/* store the value */
- if (ctx_node) {
- LOG_LOCSET(ctx_node, NULL);
- }
- ret = lyd_value_store(ctx, &p->value, ((struct lysc_node_leaflist *)ctx_node)->type, val, val_len, 0, 0,
+ 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,
NULL, format, prefix_data, LYD_HINT_DATA, ctx_node, NULL);
- LOG_LOCBACK(ctx_node ? 1 : 0, 0);
+ LOG_LOCBACK(1, 0);
LY_CHECK_ERR_GOTO(ret, p->value.realtype = NULL, cleanup);
++(*tok_idx);
@@ -1093,7 +1091,7 @@ ly_path_compile_deref(const struct ly_ctx *ctx, const struct lysc_node *ctx_node
}
lref = (const struct lysc_type_leafref *)deref_leaf_node->type;
LY_CHECK_GOTO(ret = ly_path_append(ctx, path2, path), cleanup);
- ly_path_free(ctx, path2);
+ ly_path_free(path2);
path2 = NULL;
/* compile dereferenced leafref expression and append it to the path */
@@ -1101,7 +1099,7 @@ ly_path_compile_deref(const struct ly_ctx *ctx, const struct lysc_node *ctx_node
&path2), cleanup);
node2 = path2[LY_ARRAY_COUNT(path2) - 1].node;
LY_CHECK_GOTO(ret = ly_path_append(ctx, path2, path), cleanup);
- ly_path_free(ctx, path2);
+ ly_path_free(path2);
path2 = NULL;
/* properly parsed path must always continue with ')' and '/' */
@@ -1125,9 +1123,9 @@ ly_path_compile_deref(const struct ly_ctx *ctx, const struct lysc_node *ctx_node
LY_CHECK_GOTO(ret = ly_path_append(ctx, path2, path), cleanup);
cleanup:
- ly_path_free(ctx, path2);
+ ly_path_free(path2);
if (ret) {
- ly_path_free(ctx, *path);
+ ly_path_free(*path);
*path = NULL;
}
return ret;
@@ -1283,7 +1281,7 @@ _ly_path_compile(const struct ly_ctx *ctx, const struct lys_module *cur_mod, con
cleanup:
if (ret) {
- ly_path_free(ctx, *path);
+ ly_path_free(*path);
*path = NULL;
}
LOG_LOCBACK(cur_node ? 1 : 0, 0);
@@ -1488,7 +1486,7 @@ ly_path_predicates_free(const struct ly_ctx *ctx, struct ly_path_predicate *pred
}
void
-ly_path_free(const struct ly_ctx *ctx, struct ly_path *path)
+ly_path_free(struct ly_path *path)
{
LY_ARRAY_COUNT_TYPE u;
@@ -1497,7 +1495,7 @@ ly_path_free(const struct ly_ctx *ctx, struct ly_path *path)
}
LY_ARRAY_FOR(path, u) {
- ly_path_predicates_free(ctx, path[u].predicates);
+ ly_path_predicates_free(path[u].node->module->ctx, path[u].predicates);
}
LY_ARRAY_FREE(path);
}
diff --git a/src/path.h b/src/path.h
index 9a9e342..68cf76e 100644
--- a/src/path.h
+++ b/src/path.h
@@ -257,9 +257,8 @@ void ly_path_predicates_free(const struct ly_ctx *ctx, struct ly_path_predicate
/**
* @brief Free ly_path structure.
*
- * @param[in] ctx libyang context.
* @param[in] path The structure ([sized array](@ref sizedarrays)) to free.
*/
-void ly_path_free(const struct ly_ctx *ctx, struct ly_path *path);
+void ly_path_free(struct ly_path *path);
#endif /* LY_PATH_H_ */
diff --git a/src/plugins.c b/src/plugins.c
index 5ff6616..22c4947 100644
--- a/src/plugins.c
+++ b/src/plugins.c
@@ -81,6 +81,11 @@ extern const struct lyplg_type_record plugins_xpath10[];
extern const struct lyplg_type_record plugins_node_instanceid[];
/*
+ * libnetconf2-netconf-server
+ */
+extern const struct lyplg_type_record plugins_time_period[];
+
+/*
* lyds_tree
*/
extern const struct lyplg_type_record plugins_lyds_tree[];
@@ -522,6 +527,9 @@ lyplg_init(ly_bool builtin_type_plugins_only)
LY_CHECK_GOTO(ret = plugins_insert(NULL, LYPLG_TYPE, plugins_hex_string), error);
LY_CHECK_GOTO(ret = plugins_insert(NULL, LYPLG_TYPE, plugins_xpath10), error);
+ /* libnetconf2-netconf-server */
+ LY_CHECK_GOTO(ret = plugins_insert(NULL, LYPLG_TYPE, plugins_time_period), error);
+
/* ietf-netconf-acm */
LY_CHECK_GOTO(ret = plugins_insert(NULL, LYPLG_TYPE, plugins_node_instanceid), error);
diff --git a/src/plugins.h b/src/plugins.h
index 3ffc7cf..b635878 100644
--- a/src/plugins.h
+++ b/src/plugins.h
@@ -38,19 +38,22 @@ extern "C" {
* Furthermore, there are several internal plugins, implementing built-in data types and selected derived types and YANG
* extensions. These internal plugins uses the same API and can be taken as examples for implementing user plugins. Internal
* plugins are always loaded with the first created [context](@ref howtoContext) and unloaded with destroying the last one.
- * The external plugins are in the same phase loaded from the default directories specified at compile time via cmake
- * variables `PLUGINS_DIR` (where the `extensions` and `types` subdirectories are added for each plugin type) or separately
- * via `PLUGINS_DIR_EXTENSIONS` and `PLUGINS_DIR_TYPES` for each plugin type. The default directories can be replaced runtime
- * using environment variables `LIBYANG_TYPES_PLUGINS_DIR` and `LIBYANG_EXTENSIONS_PLUGINS_DIR`.
+ * The external plugins are in the same phase loaded as dynamic shared objects (shared libraries) from the default directories
+ * specified at compile time via cmake variables `PLUGINS_DIR` (where the `extensions` and `types` subdirectories are added
+ * for each plugin type) or separately via `PLUGINS_DIR_EXTENSIONS` and `PLUGINS_DIR_TYPES` for each plugin type. The default
+ * directories can be replaced runtime using environment variables `LIBYANG_TYPES_PLUGINS_DIR` and `LIBYANG_EXTENSIONS_PLUGINS_DIR`.
+ * There is also a separate function ::lyplg_add() to manually add a plugin (dynamic shared object) anytime later.
+ * Another option to manually add an external plugin is using the ::lyplg_add_extension_plugin() or ::lyplg_add_type_plugin()
+ * which is useful when loading a dynamic shared object is problematic. These functions allow for setting the necessary callbacks
+ * for the plugin at runtime.
*
* Order of the plugins determines their priority. libyang searches for the first match with the extension and type, so the
* firstly loaded plugin for the specific item is used. Since the internal plugins are loaded always before the external
* plugins, the internal plugins cannot be replaced.
*
- * There is also a separate function ::lyplg_add() to add a plugin anytime later. Note, that such a plugin is being used
- * after it is added with the lowest priority among other already loaded plugins. Also note that since all the plugins are
- * unloaded with the destruction of the last context, creating a new context after that starts the standard plugins
- * initiation and the manually added plugins are not loaded automatically.
+ * Note, that manually added plugin via lyplg_add*() function is added with the lowest priority among other already loaded plugins.
+ * Also note that since all the plugins are unloaded with the destruction of the last context, creating a new context after that
+ * starts the standard plugins initiation and the manually added plugins are not loaded automatically.
*
* The following pages contain description of the API for creating user plugins.
*
diff --git a/src/plugins_exts.c b/src/plugins_exts.c
index cffbe53..71449ba 100644
--- a/src/plugins_exts.c
+++ b/src/plugins_exts.c
@@ -4,7 +4,7 @@
* @author Michal Vasko <mvasko@cesnet.cz>
* @brief helper functions for extension plugins
*
- * Copyright (c) 2019 - 2022 CESNET, z.s.p.o.
+ * Copyright (c) 2019 - 2024 CESNET, z.s.p.o.
*
* This source code is licensed under BSD 3-Clause License (the "License").
* You may not use this file except in compliance with the License.
@@ -81,34 +81,34 @@ cleanup:
* @brief Compile an instance extension statement.
*
* @param[in] ctx Compile context.
- * @param[in] parsed Parsed ext instance substatement structure.
+ * @param[in] parsed_p Parsed ext instance substatement structure.
* @param[in] ext Compiled ext instance.
* @param[in] substmt Compled ext instance substatement info.
* @return LY_ERR value.
*/
static LY_ERR
-lys_compile_ext_instance_stmt(struct lysc_ctx *ctx, uint64_t parsed, struct lysc_ext_instance *ext,
+lys_compile_ext_instance_stmt(struct lysc_ctx *ctx, void **parsed_p, struct lysc_ext_instance *ext,
struct lysc_ext_substmt *substmt)
{
LY_ERR rc = LY_SUCCESS;
ly_bool length_restr = 0;
LY_DATA_TYPE basetype;
- assert(parsed);
+ assert(*parsed_p);
/* compilation wthout any storage */
if (substmt->stmt == LY_STMT_IF_FEATURE) {
ly_bool enabled;
/* evaluate */
- LY_CHECK_GOTO(rc = lys_eval_iffeatures(ctx->ctx, VOIDPTR_C(parsed), &enabled), cleanup);
+ LY_CHECK_GOTO(rc = lys_eval_iffeatures(ctx->ctx, *parsed_p, &enabled), cleanup);
if (!enabled) {
/* it is disabled, remove the whole extension instance */
rc = LY_ENOT;
}
}
- if (!substmt->storage) {
+ if (!substmt->storage_p) {
/* nothing to store */
goto cleanup;
}
@@ -133,7 +133,7 @@ lys_compile_ext_instance_stmt(struct lysc_ctx *ctx, uint64_t parsed, struct lysc
struct lysc_node *node;
lyplg_ext_get_storage(ext, LY_STMT_STATUS, sizeof flags, (const void **)&flags);
- pnodes = VOIDPTR_C(parsed);
+ pnodes = *parsed_p;
/* compile nodes */
LY_LIST_FOR(pnodes, pnode) {
@@ -163,7 +163,7 @@ lys_compile_ext_instance_stmt(struct lysc_ctx *ctx, uint64_t parsed, struct lysc
case LY_STMT_REFERENCE:
case LY_STMT_UNITS:
/* just make a copy */
- LY_CHECK_GOTO(rc = lydict_insert(ctx->ctx, VOIDPTR_C(parsed), 0, VOIDPTR_C(substmt->storage)), cleanup);
+ LY_CHECK_GOTO(rc = lydict_insert(ctx->ctx, *parsed_p, 0, (const char **)substmt->storage_p), cleanup);
break;
case LY_STMT_BIT:
@@ -175,7 +175,7 @@ lys_compile_ext_instance_stmt(struct lysc_ctx *ctx, uint64_t parsed, struct lysc
}
/* compile */
- rc = lys_compile_type_enums(ctx, VOIDPTR_C(parsed), basetype, NULL, VOIDPTR_C(substmt->storage));
+ rc = lys_compile_type_enums(ctx, *parsed_p, basetype, NULL, (struct lysc_type_bitenum_item **)substmt->storage_p);
LY_CHECK_GOTO(rc, cleanup);
break;
@@ -183,7 +183,7 @@ lys_compile_ext_instance_stmt(struct lysc_ctx *ctx, uint64_t parsed, struct lysc
uint16_t flags;
if (!(ctx->compile_opts & LYS_COMPILE_NO_CONFIG)) {
- memcpy(&flags, &parsed, 2);
+ memcpy(&flags, parsed_p, 2);
if (flags & LYS_CONFIG_MASK) {
/* explicitly set */
flags |= LYS_SET_CONFIG;
@@ -194,56 +194,56 @@ lys_compile_ext_instance_stmt(struct lysc_ctx *ctx, uint64_t parsed, struct lysc
/* default config */
flags = LYS_CONFIG_W;
}
- memcpy(VOIDPTR_C(substmt->storage), &flags, 2);
+ memcpy(substmt->storage_p, &flags, 2);
} /* else leave zero */
break;
}
case LY_STMT_MUST: {
- const struct lysp_restr *restrs = VOIDPTR_C(parsed);
+ const struct lysp_restr *restrs = *parsed_p;
/* sized array */
- COMPILE_ARRAY_GOTO(ctx, restrs, *(struct lysc_must **)VOIDPTR_C(substmt->storage), lys_compile_must, rc, cleanup);
+ COMPILE_ARRAY_GOTO(ctx, restrs, *(struct lysc_must **)substmt->storage_p, lys_compile_must, rc, cleanup);
break;
}
case LY_STMT_WHEN: {
const uint16_t flags;
- const struct lysp_when *when = VOIDPTR_C(parsed);
+ const struct lysp_when *when = *parsed_p;
/* read compiled status */
lyplg_ext_get_storage(ext, LY_STMT_STATUS, sizeof flags, (const void **)&flags);
/* compile */
- LY_CHECK_GOTO(rc = lys_compile_when(ctx, when, flags, NULL, NULL, NULL, VOIDPTR_C(substmt->storage)), cleanup);
+ LY_CHECK_GOTO(rc = lys_compile_when(ctx, when, flags, NULL, NULL, NULL, (struct lysc_when **)substmt->storage_p), cleanup);
break;
}
case LY_STMT_FRACTION_DIGITS:
case LY_STMT_REQUIRE_INSTANCE:
/* just make a copy */
- memcpy(VOIDPTR_C(substmt->storage), &parsed, 1);
+ memcpy(substmt->storage_p, parsed_p, 1);
break;
case LY_STMT_MANDATORY:
case LY_STMT_ORDERED_BY:
case LY_STMT_STATUS:
/* just make a copy */
- memcpy(VOIDPTR_C(substmt->storage), &parsed, 2);
+ memcpy(substmt->storage_p, parsed_p, 2);
break;
case LY_STMT_MAX_ELEMENTS:
case LY_STMT_MIN_ELEMENTS:
/* just make a copy */
- memcpy(VOIDPTR_C(substmt->storage), &parsed, 4);
+ memcpy(substmt->storage_p, parsed_p, 4);
break;
case LY_STMT_POSITION:
case LY_STMT_VALUE:
/* just make a copy */
- memcpy(VOIDPTR_C(substmt->storage), &parsed, 8);
+ memcpy(substmt->storage_p, parsed_p, 8);
break;
case LY_STMT_IDENTITY:
/* compile */
- rc = lys_identity_precompile(ctx, NULL, NULL, VOIDPTR_C(parsed), VOIDPTR_C(substmt->storage));
+ rc = lys_identity_precompile(ctx, NULL, NULL, *parsed_p, (struct lysc_ident **)substmt->storage_p);
LY_CHECK_GOTO(rc, cleanup);
break;
@@ -252,36 +252,36 @@ lys_compile_ext_instance_stmt(struct lysc_ctx *ctx, uint64_t parsed, struct lysc
/* fallthrough */
case LY_STMT_RANGE:
/* compile, use uint64 default range */
- rc = lys_compile_type_range(ctx, VOIDPTR_C(parsed), LY_TYPE_UINT64, length_restr, 0, NULL, VOIDPTR_C(substmt->storage));
+ rc = lys_compile_type_range(ctx, *parsed_p, LY_TYPE_UINT64, length_restr, 0, NULL, (struct lysc_range **)substmt->storage_p);
LY_CHECK_GOTO(rc, cleanup);
break;
case LY_STMT_PATTERN:
/* compile */
- rc = lys_compile_type_patterns(ctx, VOIDPTR_C(parsed), NULL, VOIDPTR_C(substmt->storage));
+ rc = lys_compile_type_patterns(ctx, *parsed_p, NULL, (struct lysc_pattern ***)substmt->storage_p);
LY_CHECK_GOTO(rc, cleanup);
break;
case LY_STMT_TYPE: {
const uint16_t flags;
const char *units;
- const struct lysp_type *ptype = VOIDPTR_C(parsed);
+ const struct lysp_type *ptype = *parsed_p;
/* read compiled info */
lyplg_ext_get_storage(ext, LY_STMT_STATUS, sizeof flags, (const void **)&flags);
lyplg_ext_get_storage(ext, LY_STMT_UNITS, sizeof units, (const void **)&units);
/* compile */
- rc = lys_compile_type(ctx, NULL, flags, ext->def->name, ptype, VOIDPTR_C(substmt->storage), &units, NULL);
+ rc = lys_compile_type(ctx, NULL, flags, ext->def->name, ptype, (struct lysc_type **)substmt->storage_p, &units, NULL);
LY_CHECK_GOTO(rc, cleanup);
- LY_ATOMIC_INC_BARRIER((*(struct lysc_type **)VOIDPTR_C(substmt->storage))->refcount);
+ LY_ATOMIC_INC_BARRIER((*(struct lysc_type **)substmt->storage_p)->refcount);
break;
}
case LY_STMT_EXTENSION_INSTANCE: {
- struct lysp_ext_instance *extps = VOIDPTR_C(parsed);
+ struct lysp_ext_instance *extps = *parsed_p;
/* compile sized array */
- COMPILE_EXTS_GOTO(ctx, extps, *(struct lysc_ext_instance **)VOIDPTR_C(substmt->storage), ext, rc, cleanup);
+ COMPILE_EXTS_GOTO(ctx, extps, *(struct lysc_ext_instance **)substmt->storage_p, ext, rc, cleanup);
break;
}
case LY_STMT_AUGMENT:
@@ -330,7 +330,7 @@ lyplg_ext_compile_extension_instance(struct lysc_ctx *ctx, const struct lysp_ext
LY_ERR rc = LY_SUCCESS;
LY_ARRAY_COUNT_TYPE u, v;
enum ly_stmt stmtp;
- uint64_t storagep;
+ void **storagep;
struct ly_set storagep_compiled = {0};
LY_CHECK_ARG_RET(ctx ? ctx->ctx : NULL, ctx, extp, ext, LY_EINVAL);
@@ -340,9 +340,9 @@ lyplg_ext_compile_extension_instance(struct lysc_ctx *ctx, const struct lysp_ext
LY_ARRAY_FOR(extp->substmts, u) {
stmtp = extp->substmts[u].stmt;
- storagep = *(uint64_t *)VOIDPTR_C(extp->substmts[u].storage);
+ storagep = extp->substmts[u].storage_p;
- if (!storagep || ly_set_contains(&storagep_compiled, VOIDPTR_C(storagep), NULL)) {
+ if (!*storagep || ly_set_contains(&storagep_compiled, storagep, NULL)) {
/* nothing parsed or already compiled (for example, if it is a linked list of parsed nodes) */
continue;
}
@@ -361,7 +361,7 @@ lyplg_ext_compile_extension_instance(struct lysc_ctx *ctx, const struct lysp_ext
}
/* compiled */
- ly_set_add(&storagep_compiled, VOIDPTR_C(storagep), 1, NULL);
+ ly_set_add(&storagep_compiled, storagep, 1, NULL);
}
cleanup:
@@ -420,7 +420,7 @@ lyplg_ext_sprinter_ctree_add_ext_nodes(const struct lyspr_tree_ctx *ctx, struct
uint32_t i;
struct lysc_node *schema;
- LY_CHECK_ARG_RET2(NULL, ctx, ext, LY_EINVAL);
+ LY_CHECK_ARG_RET(NULL, ctx, ext, LY_EINVAL);
LY_ARRAY_FOR(ext->substmts, i) {
switch (ext->substmts[i].stmt) {
@@ -437,7 +437,7 @@ lyplg_ext_sprinter_ctree_add_ext_nodes(const struct lyspr_tree_ctx *ctx, struct
case LY_STMT_LEAF:
case LY_STMT_LEAF_LIST:
case LY_STMT_LIST:
- schema = *VOIDPTR2_C(ext->substmts[i].storage);
+ schema = *ext->substmts[i].storage_p;
if (schema) {
rc = lyplg_ext_sprinter_ctree_add_nodes(ctx, schema, clb);
return rc;
@@ -458,7 +458,7 @@ lyplg_ext_sprinter_ptree_add_ext_nodes(const struct lyspr_tree_ctx *ctx, struct
uint32_t i;
struct lysp_node *schema;
- LY_CHECK_ARG_RET2(NULL, ctx, ext, LY_EINVAL);
+ LY_CHECK_ARG_RET(NULL, ctx, ext, LY_EINVAL);
LY_ARRAY_FOR(ext->substmts, i) {
switch (ext->substmts[i].stmt) {
@@ -475,7 +475,7 @@ lyplg_ext_sprinter_ptree_add_ext_nodes(const struct lyspr_tree_ctx *ctx, struct
case LY_STMT_LEAF:
case LY_STMT_LEAF_LIST:
case LY_STMT_LIST:
- schema = *VOIDPTR2_C(ext->substmts[i].storage);
+ schema = *ext->substmts[i].storage_p;
if (schema) {
rc = lyplg_ext_sprinter_ptree_add_nodes(ctx, schema, clb);
return rc;
@@ -494,7 +494,7 @@ lyplg_ext_sprinter_ctree_add_nodes(const struct lyspr_tree_ctx *ctx, struct lysc
{
struct lyspr_tree_schema *new;
- LY_CHECK_ARG_RET1(NULL, ctx, LY_EINVAL);
+ LY_CHECK_ARG_RET(NULL, ctx, LY_EINVAL);
if (!nodes) {
return LY_SUCCESS;
@@ -514,7 +514,7 @@ lyplg_ext_sprinter_ptree_add_nodes(const struct lyspr_tree_ctx *ctx, struct lysp
{
struct lyspr_tree_schema *new;
- LY_CHECK_ARG_RET1(NULL, ctx, LY_EINVAL);
+ LY_CHECK_ARG_RET(NULL, ctx, LY_EINVAL);
if (!nodes) {
return LY_SUCCESS;
@@ -531,7 +531,7 @@ lyplg_ext_sprinter_ptree_add_nodes(const struct lyspr_tree_ctx *ctx, struct lysp
LIBYANG_API_DECL LY_ERR
lyplg_ext_sprinter_tree_set_priv(const struct lyspr_tree_ctx *ctx, void *plugin_priv, void (*free_clb)(void *plugin_priv))
{
- LY_CHECK_ARG_RET1(NULL, ctx, LY_EINVAL);
+ LY_CHECK_ARG_RET(NULL, ctx, LY_EINVAL);
((struct lyspr_tree_ctx *)ctx)->plugin_priv = plugin_priv;
((struct lyspr_tree_ctx *)ctx)->free_plugin_priv = free_clb;
@@ -587,12 +587,12 @@ lyplg_ext_nodetype2stmt(uint16_t nodetype)
}
LY_ERR
-lyplg_ext_get_storage_p(const struct lysc_ext_instance *ext, int stmt, uint64_t *storage_p)
+lyplg_ext_get_storage_p(const struct lysc_ext_instance *ext, int stmt, void ***storage_pp)
{
LY_ARRAY_COUNT_TYPE u;
enum ly_stmt match = 0;
- *storage_p = 0;
+ *storage_pp = NULL;
if (!(stmt & LY_STMT_NODE_MASK)) {
/* matching a non-node statement */
@@ -601,7 +601,7 @@ lyplg_ext_get_storage_p(const struct lysc_ext_instance *ext, int stmt, uint64_t
LY_ARRAY_FOR(ext->substmts, u) {
if ((match && (ext->substmts[u].stmt == match)) || (!match && (ext->substmts[u].stmt & stmt))) {
- *storage_p = ext->substmts[u].storage;
+ *storage_pp = ext->substmts[u].storage_p;
return LY_SUCCESS;
}
}
@@ -613,14 +613,14 @@ LIBYANG_API_DEF LY_ERR
lyplg_ext_get_storage(const struct lysc_ext_instance *ext, int stmt, uint32_t storage_size, const void **storage)
{
LY_ERR rc = LY_SUCCESS;
- uint64_t s;
+ void **s_p;
/* get pointer to the storage, is set even on error */
- rc = lyplg_ext_get_storage_p(ext, stmt, &s);
+ rc = lyplg_ext_get_storage_p(ext, stmt, &s_p);
/* assign */
- if (s) {
- memcpy(storage, VOIDPTR_C(s), storage_size);
+ if (s_p) {
+ memcpy(storage, s_p, storage_size);
} else {
memset(storage, 0, storage_size);
}
@@ -634,7 +634,9 @@ lyplg_ext_parsed_get_storage(const struct lysc_ext_instance *ext, int stmt, uint
LY_ARRAY_COUNT_TYPE u;
const struct lysp_ext_instance *extp = NULL;
enum ly_stmt match = 0;
- uint64_t s = 0;
+ void **s_p = NULL;
+
+ LY_CHECK_ARG_RET(NULL, ext, ext->module->parsed, LY_EINVAL);
/* find the parsed ext instance */
LY_ARRAY_FOR(ext->module->parsed->exts, u) {
@@ -655,14 +657,14 @@ lyplg_ext_parsed_get_storage(const struct lysc_ext_instance *ext, int stmt, uint
/* get the substatement */
LY_ARRAY_FOR(extp->substmts, u) {
if ((match && (extp->substmts[u].stmt == match)) || (!match && (extp->substmts[u].stmt & stmt))) {
- s = extp->substmts[u].storage;
+ s_p = extp->substmts[u].storage_p;
break;
}
}
/* assign */
- if (s) {
- memcpy(storage, VOIDPTR_C(s), storage_size);
+ if (s_p) {
+ memcpy(storage, s_p, storage_size);
} else {
memset(storage, 0, storage_size);
}
diff --git a/src/plugins_exts.h b/src/plugins_exts.h
index 74ce215..4cf80b2 100644
--- a/src/plugins_exts.h
+++ b/src/plugins_exts.h
@@ -109,7 +109,7 @@ extern "C" {
/**
* @brief Extensions API version
*/
-#define LYPLG_EXT_API_VERSION 6
+#define LYPLG_EXT_API_VERSION 8
/**
* @brief Mask for an operation statement.
@@ -393,7 +393,7 @@ struct lysp_stmt {
*/
struct lysp_ext_substmt {
enum ly_stmt stmt; /**< parsed substatement */
- uint64_t storage; /**< (pointer to) the parsed storage of the statement according to the specific
+ void **storage_p; /**< pointer to the parsed storage of the statement according to the specific
lys_ext_substmt::stmt */
};
@@ -419,6 +419,7 @@ struct lysp_ext_instance {
parsed data ([sized array](@ref sizedarrays)) */
void *parsed; /**< private plugin parsed data */
struct lysp_stmt *child; /**< list of generic (unknown) YANG statements */
+ struct lysp_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
};
/**
@@ -426,7 +427,7 @@ struct lysp_ext_instance {
*/
struct lysc_ext_substmt {
enum ly_stmt stmt; /**< compiled substatement */
- uint64_t storage; /**< (pointer to) the compiled storage of the statement according to the specific
+ void **storage_p; /**< pointer to the compiled storage of the statement according to the specific
lys_ext_substmt::stmt */
};
diff --git a/src/plugins_exts/metadata.c b/src/plugins_exts/metadata.c
index aa6cb43..baec86f 100644
--- a/src/plugins_exts/metadata.c
+++ b/src/plugins_exts/metadata.c
@@ -79,27 +79,27 @@ annotation_parse(struct lysp_ctx *pctx, struct lysp_ext_instance *ext)
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[0].stmt = LY_STMT_IF_FEATURE;
- ext->substmts[0].storage = (uint64_t)(uintptr_t)&ann_pdata->iffeatures;
+ ext->substmts[0].storage_p = (void **)&ann_pdata->iffeatures;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[1].stmt = LY_STMT_UNITS;
- ext->substmts[1].storage = (uint64_t)(uintptr_t)&ann_pdata->units;
+ ext->substmts[1].storage_p = (void **)&ann_pdata->units;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[2].stmt = LY_STMT_STATUS;
- ext->substmts[2].storage = (uint64_t)(uintptr_t)&ann_pdata->flags;
+ ext->substmts[2].storage_p = (void **)&ann_pdata->flags;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[3].stmt = LY_STMT_TYPE;
- ext->substmts[3].storage = (uint64_t)(uintptr_t)&ann_pdata->type;
+ ext->substmts[3].storage_p = (void **)&ann_pdata->type;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[4].stmt = LY_STMT_DESCRIPTION;
- ext->substmts[4].storage = (uint64_t)(uintptr_t)&ann_pdata->dsc;
+ ext->substmts[4].storage_p = (void **)&ann_pdata->dsc;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[5].stmt = LY_STMT_REFERENCE;
- ext->substmts[5].storage = (uint64_t)(uintptr_t)&ann_pdata->ref;
+ ext->substmts[5].storage_p = (void **)&ann_pdata->ref;
if ((r = lyplg_ext_parse_extension_instance(pctx, ext))) {
return r;
@@ -139,27 +139,27 @@ annotation_compile(struct lysc_ctx *cctx, const struct lysp_ext_instance *extp,
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[0].stmt = LY_STMT_IF_FEATURE;
- ext->substmts[0].storage = 0;
+ ext->substmts[0].storage_p = NULL;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[1].stmt = LY_STMT_UNITS;
- ext->substmts[1].storage = (uint64_t)(uintptr_t)&ann_cdata->units;
+ ext->substmts[1].storage_p = (void **)&ann_cdata->units;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[2].stmt = LY_STMT_STATUS;
- ext->substmts[2].storage = (uint64_t)(uintptr_t)&ann_cdata->flags;
+ ext->substmts[2].storage_p = (void **)&ann_cdata->flags;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[3].stmt = LY_STMT_TYPE;
- ext->substmts[3].storage = (uint64_t)(uintptr_t)&ann_cdata->type;
+ ext->substmts[3].storage_p = (void **)&ann_cdata->type;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[4].stmt = LY_STMT_DESCRIPTION;
- ext->substmts[4].storage = (uint64_t)(uintptr_t)&ann_cdata->dsc;
+ ext->substmts[4].storage_p = (void **)&ann_cdata->dsc;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[5].stmt = LY_STMT_REFERENCE;
- ext->substmts[5].storage = (uint64_t)(uintptr_t)&ann_cdata->ref;
+ ext->substmts[5].storage_p = (void **)&ann_cdata->ref;
ret = lyplg_ext_compile_extension_instance(cctx, extp, ext);
return ret;
diff --git a/src/plugins_exts/structure.c b/src/plugins_exts/structure.c
index bc2ea0e..6aa902e 100644
--- a/src/plugins_exts/structure.c
+++ b/src/plugins_exts/structure.c
@@ -90,60 +90,60 @@ structure_parse(struct lysp_ctx *pctx, struct lysp_ext_instance *ext)
/* parse substatements */
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[0].stmt = LY_STMT_MUST;
- ext->substmts[0].storage = (uint64_t)(uintptr_t)&struct_pdata->musts;
+ ext->substmts[0].storage_p = (void **)&struct_pdata->musts;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[1].stmt = LY_STMT_STATUS;
- ext->substmts[1].storage = (uint64_t)(uintptr_t)&struct_pdata->flags;
+ ext->substmts[1].storage_p = (void **)&struct_pdata->flags;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[2].stmt = LY_STMT_DESCRIPTION;
- ext->substmts[2].storage = (uint64_t)(uintptr_t)&struct_pdata->dsc;
+ ext->substmts[2].storage_p = (void **)&struct_pdata->dsc;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[3].stmt = LY_STMT_REFERENCE;
- ext->substmts[3].storage = (uint64_t)(uintptr_t)&struct_pdata->ref;
+ ext->substmts[3].storage_p = (void **)&struct_pdata->ref;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[4].stmt = LY_STMT_TYPEDEF;
- ext->substmts[4].storage = (uint64_t)(uintptr_t)&struct_pdata->typedefs;
+ ext->substmts[4].storage_p = (void **)&struct_pdata->typedefs;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[5].stmt = LY_STMT_GROUPING;
- ext->substmts[5].storage = (uint64_t)(uintptr_t)&struct_pdata->groupings;
+ ext->substmts[5].storage_p = (void **)&struct_pdata->groupings;
/* data-def-stmt */
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[6].stmt = LY_STMT_CONTAINER;
- ext->substmts[6].storage = (uint64_t)(uintptr_t)&struct_pdata->child;
+ ext->substmts[6].storage_p = (void **)&struct_pdata->child;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[7].stmt = LY_STMT_LEAF;
- ext->substmts[7].storage = (uint64_t)(uintptr_t)&struct_pdata->child;
+ ext->substmts[7].storage_p = (void **)&struct_pdata->child;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[8].stmt = LY_STMT_LEAF_LIST;
- ext->substmts[8].storage = (uint64_t)(uintptr_t)&struct_pdata->child;
+ ext->substmts[8].storage_p = (void **)&struct_pdata->child;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[9].stmt = LY_STMT_LIST;
- ext->substmts[9].storage = (uint64_t)(uintptr_t)&struct_pdata->child;
+ ext->substmts[9].storage_p = (void **)&struct_pdata->child;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[10].stmt = LY_STMT_CHOICE;
- ext->substmts[10].storage = (uint64_t)(uintptr_t)&struct_pdata->child;
+ ext->substmts[10].storage_p = (void **)&struct_pdata->child;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[11].stmt = LY_STMT_ANYDATA;
- ext->substmts[11].storage = (uint64_t)(uintptr_t)&struct_pdata->child;
+ ext->substmts[11].storage_p = (void **)&struct_pdata->child;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[12].stmt = LY_STMT_ANYXML;
- ext->substmts[12].storage = (uint64_t)(uintptr_t)&struct_pdata->child;
+ ext->substmts[12].storage_p = (void **)&struct_pdata->child;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[13].stmt = LY_STMT_USES;
- ext->substmts[13].storage = (uint64_t)(uintptr_t)&struct_pdata->child;
+ ext->substmts[13].storage_p = (void **)&struct_pdata->child;
rc = lyplg_ext_parse_extension_instance(pctx, ext);
return rc;
@@ -190,60 +190,60 @@ structure_compile(struct lysc_ctx *cctx, const struct lysp_ext_instance *extp, s
LY_ARRAY_CREATE_GOTO(cctx->ctx, ext->substmts, 14, rc, emem);
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[0].stmt = LY_STMT_MUST;
- ext->substmts[0].storage = (uint64_t)(uintptr_t)&struct_cdata->musts;
+ ext->substmts[0].storage_p = (void **)&struct_cdata->musts;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[1].stmt = LY_STMT_STATUS;
- ext->substmts[1].storage = (uint64_t)(uintptr_t)&struct_cdata->flags;
+ ext->substmts[1].storage_p = (void **)&struct_cdata->flags;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[2].stmt = LY_STMT_DESCRIPTION;
- ext->substmts[2].storage = (uint64_t)(uintptr_t)&struct_cdata->dsc;
+ ext->substmts[2].storage_p = (void **)&struct_cdata->dsc;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[3].stmt = LY_STMT_REFERENCE;
- ext->substmts[3].storage = (uint64_t)(uintptr_t)&struct_cdata->ref;
+ ext->substmts[3].storage_p = (void **)&struct_cdata->ref;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[4].stmt = LY_STMT_TYPEDEF;
- ext->substmts[4].storage = 0;
+ ext->substmts[4].storage_p = 0;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[5].stmt = LY_STMT_GROUPING;
- ext->substmts[5].storage = 0;
+ ext->substmts[5].storage_p = 0;
/* data-def-stmt */
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[6].stmt = LY_STMT_CONTAINER;
- ext->substmts[6].storage = (uint64_t)(uintptr_t)&struct_cdata->child;
+ ext->substmts[6].storage_p = (void **)&struct_cdata->child;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[7].stmt = LY_STMT_LEAF;
- ext->substmts[7].storage = (uint64_t)(uintptr_t)&struct_cdata->child;
+ ext->substmts[7].storage_p = (void **)&struct_cdata->child;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[8].stmt = LY_STMT_LEAF_LIST;
- ext->substmts[8].storage = (uint64_t)(uintptr_t)&struct_cdata->child;
+ ext->substmts[8].storage_p = (void **)&struct_cdata->child;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[9].stmt = LY_STMT_LIST;
- ext->substmts[9].storage = (uint64_t)(uintptr_t)&struct_cdata->child;
+ ext->substmts[9].storage_p = (void **)&struct_cdata->child;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[10].stmt = LY_STMT_CHOICE;
- ext->substmts[10].storage = (uint64_t)(uintptr_t)&struct_cdata->child;
+ ext->substmts[10].storage_p = (void **)&struct_cdata->child;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[11].stmt = LY_STMT_ANYDATA;
- ext->substmts[11].storage = (uint64_t)(uintptr_t)&struct_cdata->child;
+ ext->substmts[11].storage_p = (void **)&struct_cdata->child;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[12].stmt = LY_STMT_ANYXML;
- ext->substmts[12].storage = (uint64_t)(uintptr_t)&struct_cdata->child;
+ ext->substmts[12].storage_p = (void **)&struct_cdata->child;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[13].stmt = LY_STMT_USES;
- ext->substmts[13].storage = (uint64_t)(uintptr_t)&struct_cdata->child;
+ ext->substmts[13].storage_p = (void **)&struct_cdata->child;
*lyplg_ext_compile_get_options(cctx) |= LYS_COMPILE_NO_CONFIG | LYS_COMPILE_NO_DISABLED;
rc = lyplg_ext_compile_extension_instance(cctx, extp, ext);
@@ -339,53 +339,53 @@ structure_aug_parse(struct lysp_ctx *pctx, struct lysp_ext_instance *ext)
/* parse substatements */
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[0].stmt = LY_STMT_STATUS;
- ext->substmts[0].storage = (uint64_t)(uintptr_t)&aug_pdata->flags;
+ ext->substmts[0].storage_p = (void **)&aug_pdata->flags;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[1].stmt = LY_STMT_DESCRIPTION;
- ext->substmts[1].storage = (uint64_t)(uintptr_t)&aug_pdata->dsc;
+ ext->substmts[1].storage_p = (void **)&aug_pdata->dsc;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[2].stmt = LY_STMT_REFERENCE;
- ext->substmts[2].storage = (uint64_t)(uintptr_t)&aug_pdata->ref;
+ ext->substmts[2].storage_p = (void **)&aug_pdata->ref;
/* data-def-stmt */
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[3].stmt = LY_STMT_CONTAINER;
- ext->substmts[3].storage = (uint64_t)(uintptr_t)&aug_pdata->child;
+ ext->substmts[3].storage_p = (void **)&aug_pdata->child;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[4].stmt = LY_STMT_LEAF;
- ext->substmts[4].storage = (uint64_t)(uintptr_t)&aug_pdata->child;
+ ext->substmts[4].storage_p = (void **)&aug_pdata->child;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[5].stmt = LY_STMT_LEAF_LIST;
- ext->substmts[5].storage = (uint64_t)(uintptr_t)&aug_pdata->child;
+ ext->substmts[5].storage_p = (void **)&aug_pdata->child;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[6].stmt = LY_STMT_LIST;
- ext->substmts[6].storage = (uint64_t)(uintptr_t)&aug_pdata->child;
+ ext->substmts[6].storage_p = (void **)&aug_pdata->child;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[7].stmt = LY_STMT_CHOICE;
- ext->substmts[7].storage = (uint64_t)(uintptr_t)&aug_pdata->child;
+ ext->substmts[7].storage_p = (void **)&aug_pdata->child;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[8].stmt = LY_STMT_ANYDATA;
- ext->substmts[8].storage = (uint64_t)(uintptr_t)&aug_pdata->child;
+ ext->substmts[8].storage_p = (void **)&aug_pdata->child;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[9].stmt = LY_STMT_ANYXML;
- ext->substmts[9].storage = (uint64_t)(uintptr_t)&aug_pdata->child;
+ ext->substmts[9].storage_p = (void **)&aug_pdata->child;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[10].stmt = LY_STMT_USES;
- ext->substmts[10].storage = (uint64_t)(uintptr_t)&aug_pdata->child;
+ ext->substmts[10].storage_p = (void **)&aug_pdata->child;
/* case */
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[11].stmt = LY_STMT_CASE;
- ext->substmts[11].storage = (uint64_t)(uintptr_t)&aug_pdata->child;
+ ext->substmts[11].storage_p = (void **)&aug_pdata->child;
if ((rc = lyplg_ext_parse_extension_instance(pctx, ext))) {
return rc;
@@ -394,7 +394,7 @@ structure_aug_parse(struct lysp_ctx *pctx, struct lysp_ext_instance *ext)
/* add fake parsed augment node */
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[12].stmt = LY_STMT_AUGMENT;
- ext->substmts[12].storage = (uint64_t)(uintptr_t)&aug_pdata->aug;
+ ext->substmts[12].storage_p = (void **)&aug_pdata->aug;
aug_pdata->aug = calloc(1, sizeof *aug_pdata->aug);
if (!aug_pdata->aug) {
@@ -476,7 +476,7 @@ structure_aug_sprinter_ptree(struct lysp_ext_instance *ext, const struct lyspr_t
assert(ctx);
- aug = (struct lysp_node_augment **)(uintptr_t)ext->substmts[12].storage;
+ aug = (struct lysp_node_augment **)ext->substmts[12].storage_p;
rc = lyplg_ext_sprinter_ptree_add_nodes(ctx, (*aug)->child, structure_sprinter_pnode);
return rc;
diff --git a/src/plugins_exts/yangdata.c b/src/plugins_exts/yangdata.c
index c9c5dd8..1736abc 100644
--- a/src/plugins_exts/yangdata.c
+++ b/src/plugins_exts/yangdata.c
@@ -58,15 +58,15 @@ yangdata_parse(struct lysp_ctx *pctx, struct lysp_ext_instance *ext)
LY_ARRAY_CREATE_GOTO(lyplg_ext_parse_get_cur_pmod(pctx)->mod->ctx, ext->substmts, 3, ret, emem);
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[0].stmt = LY_STMT_CONTAINER;
- ext->substmts[0].storage = (uint64_t)(uintptr_t)&ext->parsed;
+ ext->substmts[0].storage_p = (void **)&ext->parsed;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[1].stmt = LY_STMT_CHOICE;
- ext->substmts[1].storage = (uint64_t)(uintptr_t)&ext->parsed;
+ ext->substmts[1].storage_p = (void **)&ext->parsed;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[2].stmt = LY_STMT_USES;
- ext->substmts[2].storage = (uint64_t)(uintptr_t)&ext->parsed;
+ ext->substmts[2].storage_p = (void **)&ext->parsed;
if ((ret = lyplg_ext_parse_extension_instance(pctx, ext))) {
return ret;
@@ -96,15 +96,15 @@ yangdata_compile(struct lysc_ctx *cctx, const struct lysp_ext_instance *extp, st
LY_ARRAY_CREATE_GOTO(cctx->ctx, ext->substmts, 3, ret, emem);
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[0].stmt = LY_STMT_CONTAINER;
- ext->substmts[0].storage = (uint64_t)(uintptr_t)&ext->compiled;
+ ext->substmts[0].storage_p = (void **)&ext->compiled;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[1].stmt = LY_STMT_CHOICE;
- ext->substmts[1].storage = (uint64_t)(uintptr_t)&ext->compiled;
+ ext->substmts[1].storage_p = (void **)&ext->compiled;
LY_ARRAY_INCREMENT(ext->substmts);
ext->substmts[2].stmt = LY_STMT_USES;
- ext->substmts[2].storage = (uint64_t)(uintptr_t)&ext->compiled;
+ ext->substmts[2].storage_p = (void **)&ext->compiled;
*lyplg_ext_compile_get_options(cctx) |= LYS_COMPILE_NO_CONFIG | LYS_COMPILE_NO_DISABLED;
ret = lyplg_ext_compile_extension_instance(cctx, extp, ext);
diff --git a/src/plugins_types.c b/src/plugins_types.c
index 8305691..3373b0b 100644
--- a/src/plugins_types.c
+++ b/src/plugins_types.c
@@ -352,10 +352,16 @@ lyplg_type_print_simple(const struct ly_ctx *UNUSED(ctx), const struct lyd_value
LIBYANG_API_DEF LY_ERR
lyplg_type_dup_simple(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup)
{
- memset(dup, 0, sizeof *dup);
- LY_CHECK_RET(lydict_insert(ctx, original->_canonical, 0, &dup->_canonical));
+ 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);
+ return r;
+ }
memcpy(dup->fixed_mem, original->fixed_mem, sizeof dup->fixed_mem);
dup->realtype = original->realtype;
+
return LY_SUCCESS;
}
@@ -831,8 +837,9 @@ lyplg_type_lypath_new(const struct ly_ctx *ctx, const char *value, size_t value_
uint32_t prefix_opt = 0;
struct ly_err_item *e;
const char *err_fmt = NULL;
+ uint16_t oper;
- LY_CHECK_ARG_RET(ctx, ctx, value, ctx_node, path, err, LY_EINVAL);
+ LY_CHECK_ARG_RET(ctx, ctx, value, path, err, LY_EINVAL);
*path = NULL;
*err = NULL;
@@ -871,8 +878,8 @@ lyplg_type_lypath_new(const struct ly_ctx *ctx, const char *value, size_t value_
}
/* resolve it on schema tree */
- ret = ly_path_compile(ctx, NULL, ctx_node, NULL, exp, (ctx_node->flags & LYS_IS_OUTPUT) ?
- LY_PATH_OPER_OUTPUT : LY_PATH_OPER_INPUT, LY_PATH_TARGET_SINGLE, 1, format, prefix_data, path);
+ oper = (ctx_node && (ctx_node->flags & LYS_IS_OUTPUT)) ? LY_PATH_OPER_OUTPUT : LY_PATH_OPER_INPUT;
+ ret = ly_path_compile(ctx, NULL, ctx_node, NULL, exp, oper, LY_PATH_TARGET_SINGLE, 1, format, prefix_data, path);
if (ret) {
err_fmt = "Invalid instance-identifier \"%.*s\" value - semantic error%s%s";
goto cleanup;
@@ -888,7 +895,7 @@ cleanup:
ly_err_clean((struct ly_ctx *)ctx, e);
}
- ly_path_free(ctx, *path);
+ ly_path_free(*path);
*path = NULL;
}
@@ -896,9 +903,9 @@ cleanup:
}
LIBYANG_API_DEF void
-lyplg_type_lypath_free(const struct ly_ctx *ctx, struct ly_path *path)
+lyplg_type_lypath_free(const struct ly_ctx *UNUSED(ctx), struct ly_path *path)
{
- ly_path_free(ctx, path);
+ ly_path_free(path);
}
LIBYANG_API_DEF LY_ERR
@@ -1007,7 +1014,7 @@ lyplg_type_resolve_leafref_get_target_path(const struct lyxp_expr *path, const s
LY_CHECK_GOTO(lyxp_expr_parse(ctx_node->module->ctx, str_path, 0, 1, target_path), cleanup);
cleanup:
- ly_path_free(ctx_node->module->ctx, p);
+ ly_path_free(p);
free(str_path);
return rc;
}
diff --git a/src/plugins_types.h b/src/plugins_types.h
index 8598c5d..06acc38 100644
--- a/src/plugins_types.h
+++ b/src/plugins_types.h
@@ -475,8 +475,10 @@ LIBYANG_API_DECL LY_ERR lyplg_type_print_xpath10_value(const struct lyd_value_xp
#define LYPLG_TYPE_STORE_IMPLEMENT 0x02 /**< If a foreign module is needed to be implemented to successfully instantiate
the value, make the module implemented. */
#define LYPLG_TYPE_STORE_IS_UTF8 0x04 /**< The value is guaranteed to be a valid UTF-8 string, if applicable for the type. */
-#define LYPLG_TYPE_STORE_ONLY 0x08 /**< The value is stored only. The validation must be done using [validate](@ref lyplg_type_validate_clb) */
-/** @} plugintypestoreopts */
+#define LYPLG_TYPE_STORE_ONLY 0x08 /**< The value is stored only, type-specific validation is skipped (performed before) */
+/**
+ * @} plugintypestoreopts
+ */
/**
* @brief Callback to store the given @p value according to the given @p type.
@@ -490,7 +492,9 @@ LIBYANG_API_DECL LY_ERR lyplg_type_print_xpath10_value(const struct lyd_value_xp
* @p value_len is always correct. All store functions have to free a dynamically allocated @p value in all
* cases (even on error).
*
- * @param[in] ctx libyang context
+ * No unnecessary validation tasks should be performed by this callback and left for ::lyplg_type_validate_clb instead.
+ *
+ * @param[in] ctx libyang context.
* @param[in] type Type of the value being stored.
* @param[in] value Value to be stored.
* @param[in] value_len Length (number of bytes) of the given @p value.
@@ -513,15 +517,14 @@ LIBYANG_API_DECL typedef LY_ERR (*lyplg_type_store_clb)(const struct ly_ctx *ctx
const struct lysc_node *ctx_node, struct lyd_value *storage, struct lys_glob_unres *unres, struct ly_err_item **err);
/**
- * @brief Callback to validate the stored value in data.
+ * @brief Callback to validate the stored value in the accessible data tree.
*
- * This callback is optional for types that can only be validated in a data tree. It must be called and succeed
- * in case the ::lyplg_type_store_clb callback returned ::LY_EINCOMPLETE for the value to be valid. However, this
- * callback can be called even in other cases (such as separate/repeated validation).
+ * This callback is optional and may not be defined for types that do not require the accessible data tree for
+ * validation (::lyplg_type_store_cb fully stores and validates the value).
*
- * @param[in] ctx libyang context
+ * @param[in] ctx libyang context.
* @param[in] type Original type of the value (not necessarily the stored one) being validated.
- * @param[in] ctx_node The value data context node for validation.
+ * @param[in] ctx_node Value data context node for validation.
* @param[in] tree External data tree (e.g. when validating RPC/Notification) with possibly referenced data.
* @param[in,out] storage Storage of the value successfully filled by ::lyplg_type_store_clb. May be modified.
* @param[out] err Optionally provided error information in case of failure. If not provided to the caller, a generic
@@ -619,7 +622,7 @@ struct lyplg_type {
const char *id; /**< Plugin identification (mainly for distinguish incompatible versions when
used by external tools) */
lyplg_type_store_clb store; /**< store and canonize the value in the type-specific way */
- lyplg_type_validate_clb validate; /**< optional, validate the value in the type-specific way in data */
+ lyplg_type_validate_clb validate; /**< optional, validate the value in the accessible data tree */
lyplg_type_compare_clb compare; /**< comparison callback to compare 2 values of the same type */
lyplg_type_sort_clb sort; /**< comparison callback for sorting values */
lyplg_type_print_clb print; /**< printer callback to get string representing the value */
@@ -948,18 +951,6 @@ LIBYANG_API_DECL LY_ERR lyplg_type_validate_instanceid(const struct ly_ctx *ctx,
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.
*/
LIBYANG_API_DECL const void *lyplg_type_print_instanceid(const struct ly_ctx *ctx, const struct lyd_value *value,
diff --git a/src/plugins_types/binary.c b/src/plugins_types/binary.c
index c70b4a0..a020438 100644
--- a/src/plugins_types/binary.c
+++ b/src/plugins_types/binary.c
@@ -42,8 +42,6 @@
*/
static const char b64_etable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-static LY_ERR lyplg_type_validate_binary(const struct ly_ctx *UNUSED(ctx), const struct lysc_type *type, const struct lyd_node *UNUSED(ctx_node), const struct lyd_node *UNUSED(tree), struct lyd_value *storage, struct ly_err_item **err);
-
/**
* @brief Encode binary value into a base64 string value.
*
@@ -260,6 +258,7 @@ lyplg_type_store_binary(const struct ly_ctx *ctx, const struct lysc_type *type,
struct ly_err_item **err)
{
LY_ERR ret = LY_SUCCESS;
+ struct lysc_type_bin *type_bin = (struct lysc_type_bin *)type;
struct lyd_value_binary *val;
/* init storage */
@@ -312,15 +311,20 @@ lyplg_type_store_binary(const struct ly_ctx *ctx, const struct lysc_type *type,
ret = lydict_insert_zc(ctx, (char *)value, &storage->_canonical);
options &= ~LYPLG_TYPE_STORE_DYNAMIC;
LY_CHECK_GOTO(ret, cleanup);
+
+ /* value may have been freed */
+ value = storage->_canonical;
} else {
ret = lydict_insert(ctx, value_len ? value : "", value_len, &storage->_canonical);
LY_CHECK_GOTO(ret, cleanup);
}
if (!(options & LYPLG_TYPE_STORE_ONLY)) {
- /* validate value */
- ret = lyplg_type_validate_binary(ctx, type, NULL, NULL, storage, err);
- LY_CHECK_GOTO(ret, cleanup);
+ /* validate length restriction of the binary value */
+ if (type_bin->length) {
+ ret = lyplg_type_validate_range(LY_TYPE_BINARY, type_bin->length, val->size, value, value_len, err);
+ LY_CHECK_GOTO(ret, cleanup);
+ }
}
cleanup:
@@ -334,33 +338,6 @@ cleanup:
return ret;
}
-/**
- * @brief Implementation of ::lyplg_type_validate_clb for the binary type.
- */
-static LY_ERR
-lyplg_type_validate_binary(const struct ly_ctx *ctx, const struct lysc_type *type, const struct lyd_node *UNUSED(ctx_node),
- const struct lyd_node *UNUSED(tree), struct lyd_value *storage, struct ly_err_item **err)
-{
- struct lysc_type_bin *type_bin = (struct lysc_type_bin *)type;
- struct lyd_value_binary *val;
- const void *value;
- size_t value_len;
-
- LY_CHECK_ARG_RET(NULL, type, storage, err, LY_EINVAL);
-
- val = LYPLG_TYPE_VAL_IS_DYN(val) ? (struct lyd_value_binary *)(storage->dyn_mem) : (struct lyd_value_binary *)(storage->fixed_mem);
- value = lyd_value_get_canonical(ctx, storage);
- value_len = strlen(value);
- *err = NULL;
-
- /* length restriction of the binary value */
- if (type_bin->length) {
- LY_CHECK_RET(lyplg_type_validate_range(LY_TYPE_BINARY, type_bin->length, val->size, value, value_len, err));
- }
-
- return LY_SUCCESS;
-}
-
LIBYANG_API_DEF LY_ERR
lyplg_type_compare_binary(const struct ly_ctx *UNUSED(ctx), const struct lyd_value *val1, const struct lyd_value *val2)
{
@@ -496,7 +473,7 @@ const struct lyplg_type_record plugins_binary[] = {
.plugin.id = "libyang 2 - binary, version 1",
.plugin.store = lyplg_type_store_binary,
- .plugin.validate = lyplg_type_validate_binary,
+ .plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_binary,
.plugin.sort = lyplg_type_sort_binary,
.plugin.print = lyplg_type_print_binary,
diff --git a/src/plugins_types/date_and_time.c b/src/plugins_types/date_and_time.c
index 1cc0ec4..1d013c1 100644
--- a/src/plugins_types/date_and_time.c
+++ b/src/plugins_types/date_and_time.c
@@ -53,7 +53,6 @@ lyplg_type_store_date_and_time(const struct ly_ctx *ctx, const struct lysc_type
struct ly_err_item **err)
{
LY_ERR ret = LY_SUCCESS;
- struct lysc_type_str *type_dat = (struct lysc_type_str *)type;
struct lyd_value_date_and_time *val;
uint32_t i;
char c;
@@ -102,20 +101,9 @@ lyplg_type_store_date_and_time(const struct ly_ctx *ctx, const struct lysc_type
ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
LY_CHECK_GOTO(ret, cleanup);
- /* length restriction, there can be only ASCII chars */
- if (type_dat->length) {
- ret = lyplg_type_validate_range(LY_TYPE_STRING, type_dat->length, value_len, value, value_len, err);
- LY_CHECK_GOTO(ret, cleanup);
- }
-
- /* date-and-time pattern */
- ret = lyplg_type_validate_patterns(type_dat->patterns, value, value_len, err);
- LY_CHECK_GOTO(ret, cleanup);
-
- /* convert to UNIX time and fractions of second */
- ret = ly_time_str2time(value, &val->time, &val->fractions_s);
- if (ret) {
- ret = ly_err_new(err, ret, 0, NULL, NULL, "%s", ly_last_logmsg());
+ /* convert to UNIX time and fractions of second, function must check for all the possible errors */
+ if (ly_time_str2time(value, &val->time, &val->fractions_s)) {
+ ret = ly_err_new(err, LY_EVALID, 0, NULL, NULL, "%s", ly_last_logmsg());
goto cleanup;
}
diff --git a/src/plugins_types/decimal64.c b/src/plugins_types/decimal64.c
index 0eb01a0..a6ac54b 100644
--- a/src/plugins_types/decimal64.c
+++ b/src/plugins_types/decimal64.c
@@ -33,8 +33,6 @@
* | 8 | yes | `int64_t *` | little-endian value represented without floating point |
*/
-static LY_ERR lyplg_type_validate_decimal64(const struct ly_ctx *UNUSED(ctx), const struct lysc_type *type, const struct lyd_node *UNUSED(ctx_node), const struct lyd_node *UNUSED(tree), struct lyd_value *storage, struct ly_err_item **err);
-
/**
* @brief Convert decimal64 number to canonical string.
*
@@ -90,7 +88,7 @@ lyplg_type_store_decimal64(const struct ly_ctx *ctx, const struct lysc_type *typ
{
struct lysc_type_dec *type_dec = (struct lysc_type_dec *)type;
LY_ERR ret = LY_SUCCESS;
- int64_t num;
+ int64_t num = 0;
char *canon;
/* init storage */
@@ -144,8 +142,12 @@ lyplg_type_store_decimal64(const struct ly_ctx *ctx, const struct lysc_type *typ
if (!(options & LYPLG_TYPE_STORE_ONLY)) {
/* validate value */
- ret = lyplg_type_validate_decimal64(ctx, type, NULL, NULL, storage, err);
- LY_CHECK_GOTO(ret, cleanup);
+ if (type_dec->range) {
+ /* check range of the number */
+ ret = lyplg_type_validate_range(type->basetype, type_dec->range, num, storage->_canonical,
+ strlen(storage->_canonical), err);
+ LY_CHECK_GOTO(ret, cleanup);
+ }
}
cleanup:
@@ -159,31 +161,6 @@ cleanup:
return ret;
}
-/**
- * @brief Implementation of ::lyplg_type_validate_clb for the built-in decimal64 type.
- */
-static LY_ERR
-lyplg_type_validate_decimal64(const struct ly_ctx *UNUSED(ctx), const struct lysc_type *type, const struct lyd_node *UNUSED(ctx_node),
- const struct lyd_node *UNUSED(tree), struct lyd_value *storage, struct ly_err_item **err)
-{
- LY_ERR ret;
- struct lysc_type_dec *type_dec = (struct lysc_type_dec *)type;
- int64_t num;
-
- LY_CHECK_ARG_RET(NULL, type, storage, err, LY_EINVAL);
- *err = NULL;
- num = storage->dec64;
-
- if (type_dec->range) {
- /* check range of the number */
- ret = lyplg_type_validate_range(type->basetype, type_dec->range, num, storage->_canonical,
- strlen(storage->_canonical), err);
- LY_CHECK_RET(ret);
- }
-
- return LY_SUCCESS;
-}
-
LIBYANG_API_DEF LY_ERR
lyplg_type_compare_decimal64(const struct ly_ctx *UNUSED(ctx), const struct lyd_value *val1,
const struct lyd_value *val2)
@@ -262,7 +239,7 @@ const struct lyplg_type_record plugins_decimal64[] = {
.plugin.id = "libyang 2 - decimal64, version 1",
.plugin.store = lyplg_type_store_decimal64,
- .plugin.validate = lyplg_type_validate_decimal64,
+ .plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_decimal64,
.plugin.sort = lyplg_type_sort_decimal64,
.plugin.print = lyplg_type_print_decimal64,
diff --git a/src/plugins_types/hex_string.c b/src/plugins_types/hex_string.c
index 9f8d80a..b013cf4 100644
--- a/src/plugins_types/hex_string.c
+++ b/src/plugins_types/hex_string.c
@@ -55,17 +55,6 @@ lyplg_type_store_hex_string(const struct ly_ctx *ctx, const struct lysc_type *ty
ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
LY_CHECK_GOTO(ret, cleanup);
- /* length restriction of the string */
- if (type_str->length) {
- /* value_len is in bytes, but we need number of characters here */
- ret = lyplg_type_validate_range(LY_TYPE_STRING, type_str->length, ly_utf8len(value, value_len), value, value_len, err);
- LY_CHECK_GOTO(ret, cleanup);
- }
-
- /* pattern restrictions */
- ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err);
- LY_CHECK_GOTO(ret, cleanup);
-
/* make a copy, it is needed for canonization */
if ((format != LY_VALUE_CANON) && !(options & LYPLG_TYPE_STORE_DYNAMIC)) {
value = strndup(value, value_len);
@@ -83,12 +72,28 @@ lyplg_type_store_hex_string(const struct ly_ctx *ctx, const struct lysc_type *ty
ret = lydict_insert_zc(ctx, (char *)value, &storage->_canonical);
options &= ~LYPLG_TYPE_STORE_DYNAMIC;
LY_CHECK_GOTO(ret, cleanup);
+
+ /* value may have been freed */
+ value = storage->_canonical;
} else {
/* store directly */
ret = lydict_insert(ctx, value_len ? value : "", value_len, &storage->_canonical);
LY_CHECK_GOTO(ret, cleanup);
}
+ if (!(options & LYPLG_TYPE_STORE_ONLY)) {
+ /* validate length restriction of the string */
+ if (type_str->length) {
+ /* value_len is in bytes, but we need number of characters here */
+ ret = lyplg_type_validate_range(LY_TYPE_STRING, type_str->length, ly_utf8len(value, value_len), value, value_len, err);
+ LY_CHECK_GOTO(ret, cleanup);
+ }
+
+ /* validate pattern restrictions */
+ ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err);
+ LY_CHECK_GOTO(ret, cleanup);
+ }
+
cleanup:
if (options & LYPLG_TYPE_STORE_DYNAMIC) {
free((void *)value);
diff --git a/src/plugins_types/instanceid.c b/src/plugins_types/instanceid.c
index 00ad45a..46bb4ba 100644
--- a/src/plugins_types/instanceid.c
+++ b/src/plugins_types/instanceid.c
@@ -252,23 +252,14 @@ lyplg_type_validate_instanceid(const struct ly_ctx *ctx, const struct lysc_type
return LY_SUCCESS;
}
-LIBYANG_API_DEF LY_ERR
-lyplg_type_compare_instanceid(const struct ly_ctx *ctx, const struct lyd_value *val1, const struct lyd_value *val2)
-{
- return lyplg_type_compare_simple(ctx, val1, val2);
-}
-
-LIBYANG_API_DEF int
-lyplg_type_sort_instanceid(const struct ly_ctx *ctx, const struct lyd_value *val1, const struct lyd_value *val2)
-{
- return lyplg_type_sort_simple(ctx, val1, val2);
-}
-
LIBYANG_API_DEF const void *
-lyplg_type_print_instanceid(const struct ly_ctx *UNUSED(ctx), const struct lyd_value *value, LY_VALUE_FORMAT format,
+lyplg_type_print_instanceid(const struct ly_ctx *ctx, const struct lyd_value *value, LY_VALUE_FORMAT format,
void *prefix_data, ly_bool *dynamic, size_t *value_len)
{
- char *ret;
+ char *ret = NULL;
+ struct ly_path *p = NULL;
+ const struct ly_path *target;
+ struct ly_err_item *err;
if ((format == LY_VALUE_CANON) || (format == LY_VALUE_JSON) || (format == LY_VALUE_LYB)) {
if (dynamic) {
@@ -280,14 +271,34 @@ lyplg_type_print_instanceid(const struct ly_ctx *UNUSED(ctx), const struct lyd_v
return value->_canonical;
}
+ if (!value->target) {
+ /* schema default value, compile it first */
+ if (lyplg_type_lypath_new(ctx, value->_canonical, strlen(value->_canonical), 0, LY_VALUE_JSON, NULL, NULL,
+ NULL, &p, &err)) {
+ if (err) {
+ ly_err_print(ctx, err);
+ ly_err_free(err);
+ }
+ goto cleanup;
+ }
+
+ target = p;
+ } else {
+ target = value->target;
+ }
+
/* print the value in the specific format */
- if (instanceid_path2str(value->target, format, prefix_data, &ret)) {
- return NULL;
+ if (instanceid_path2str(target, format, prefix_data, &ret)) {
+ goto cleanup;
}
+
*dynamic = 1;
if (value_len) {
*value_len = strlen(ret);
}
+
+cleanup:
+ ly_path_free(p);
return ret;
}
@@ -295,6 +306,7 @@ LIBYANG_API_DEF LY_ERR
lyplg_type_dup_instanceid(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup)
{
LY_ERR ret;
+ struct ly_err_item *err;
memset(dup, 0, sizeof *dup);
@@ -302,9 +314,21 @@ lyplg_type_dup_instanceid(const struct ly_ctx *ctx, const struct lyd_value *orig
ret = lydict_insert(ctx, original->_canonical, 0, &dup->_canonical);
LY_CHECK_GOTO(ret, error);
- /* copy path */
- ret = ly_path_dup(ctx, original->target, &dup->target);
- LY_CHECK_GOTO(ret, error);
+ if (!original->target) {
+ /* schema default value, needs to be compiled */
+ if (lyplg_type_lypath_new(ctx, original->_canonical, strlen(original->_canonical), 0, LY_VALUE_JSON, NULL, NULL,
+ NULL, &dup->target, &err)) {
+ if (err) {
+ ly_err_print(ctx, err);
+ ly_err_free(err);
+ }
+ goto error;
+ }
+ } else {
+ /* copy path */
+ ret = ly_path_dup(ctx, original->target, &dup->target);
+ LY_CHECK_GOTO(ret, error);
+ }
dup->realtype = original->realtype;
return LY_SUCCESS;
@@ -319,7 +343,7 @@ lyplg_type_free_instanceid(const struct ly_ctx *ctx, struct lyd_value *value)
{
lydict_remove(ctx, value->_canonical);
value->_canonical = NULL;
- ly_path_free(ctx, value->target);
+ ly_path_free(value->target);
}
/**
@@ -338,8 +362,8 @@ const struct lyplg_type_record plugins_instanceid[] = {
.plugin.id = "libyang 2 - instance-identifier, version 1",
.plugin.store = lyplg_type_store_instanceid,
.plugin.validate = lyplg_type_validate_instanceid,
- .plugin.compare = lyplg_type_compare_instanceid,
- .plugin.sort = lyplg_type_sort_instanceid,
+ .plugin.compare = lyplg_type_compare_simple,
+ .plugin.sort = lyplg_type_sort_simple,
.plugin.print = lyplg_type_print_instanceid,
.plugin.duplicate = lyplg_type_dup_instanceid,
.plugin.free = lyplg_type_free_instanceid,
diff --git a/src/plugins_types/integer.c b/src/plugins_types/integer.c
index eb66499..ac165ac 100644
--- a/src/plugins_types/integer.c
+++ b/src/plugins_types/integer.c
@@ -36,9 +36,6 @@
* | 1/2/4/8 | yes | pointer to the specific integer type | little-endian integer value |
*/
-static LY_ERR lyplg_type_validate_int(const struct ly_ctx *UNUSED(ctx), const struct lysc_type *type, const struct lyd_node *UNUSED(ctx_node), const struct lyd_node *UNUSED(tree), struct lyd_value *storage, struct ly_err_item **err);
-static LY_ERR lyplg_type_validate_uint(const struct ly_ctx *UNUSED(ctx), const struct lysc_type *type, const struct lyd_node *UNUSED(ctx_node), const struct lyd_node *UNUSED(tree), struct lyd_value *storage, struct ly_err_item **err);
-
/**
* @brief LYB value size of each integer type.
*/
@@ -53,6 +50,7 @@ lyplg_type_store_int(const struct ly_ctx *ctx, const struct lysc_type *type, con
const struct lysc_node *UNUSED(ctx_node), struct lyd_value *storage, struct lys_glob_unres *UNUSED(unres),
struct ly_err_item **err)
{
+ struct lysc_type_num *type_num = (struct lysc_type_num *)type;
LY_ERR ret = LY_SUCCESS;
int64_t num = 0;
int base = 1;
@@ -157,9 +155,12 @@ lyplg_type_store_int(const struct ly_ctx *ctx, const struct lysc_type *type, con
}
if (!(options & LYPLG_TYPE_STORE_ONLY)) {
- /* validate value */
- ret = lyplg_type_validate_int(ctx, type, NULL, NULL, storage, err);
- LY_CHECK_GOTO(ret, cleanup);
+ /* validate range of the number */
+ if (type_num->range) {
+ ret = lyplg_type_validate_range(type->basetype, type_num->range, num, storage->_canonical,
+ strlen(storage->_canonical), err);
+ LY_CHECK_GOTO(ret, cleanup);
+ }
}
cleanup:
@@ -173,48 +174,6 @@ cleanup:
return ret;
}
-/**
- * @brief Implementation of ::lyplg_type_validate_clb for the signed interger types.
- */
-static LY_ERR
-lyplg_type_validate_int(const struct ly_ctx *UNUSED(ctx), const struct lysc_type *type, const struct lyd_node *UNUSED(ctx_node),
- const struct lyd_node *UNUSED(tree), struct lyd_value *storage, struct ly_err_item **err)
-{
- LY_ERR ret;
- struct lysc_type_num *type_num = (struct lysc_type_num *)type;
- int64_t num;
-
- LY_CHECK_ARG_RET(NULL, type, storage, err, LY_EINVAL);
- *err = NULL;
-
- /* set the value (matters for big-endian) and get the correct int64 number */
- switch (type->basetype) {
- case LY_TYPE_INT8:
- num = storage->int8;
- break;
- case LY_TYPE_INT16:
- num = storage->int16;
- break;
- case LY_TYPE_INT32:
- num = storage->int32;
- break;
- case LY_TYPE_INT64:
- num = storage->int64;
- break;
- default:
- return LY_EINVAL;
- }
-
- /* validate range of the number */
- if (type_num->range) {
- ret = lyplg_type_validate_range(type->basetype, type_num->range, num, storage->_canonical,
- strlen(storage->_canonical), err);
- LY_CHECK_RET(ret);
- }
-
- return LY_SUCCESS;
-}
-
LIBYANG_API_DEF LY_ERR
lyplg_type_compare_int(const struct ly_ctx *UNUSED(ctx), const struct lyd_value *val1, const struct lyd_value *val2)
{
@@ -357,6 +316,7 @@ lyplg_type_store_uint(const struct ly_ctx *ctx, const struct lysc_type *type, co
const struct lysc_node *UNUSED(ctx_node), struct lyd_value *storage, struct lys_glob_unres *UNUSED(unres),
struct ly_err_item **err)
{
+ struct lysc_type_num *type_num = (struct lysc_type_num *)type;
LY_ERR ret = LY_SUCCESS;
uint64_t num = 0;
int base = 0;
@@ -441,9 +401,12 @@ lyplg_type_store_uint(const struct ly_ctx *ctx, const struct lysc_type *type, co
}
if (!(options & LYPLG_TYPE_STORE_ONLY)) {
- /* validate value */
- ret = lyplg_type_validate_uint(ctx, type, NULL, NULL, storage, err);
- LY_CHECK_GOTO(ret, cleanup);
+ /* validate range of the number */
+ if (type_num->range) {
+ ret = lyplg_type_validate_range(type->basetype, type_num->range, num, storage->_canonical,
+ strlen(storage->_canonical), err);
+ LY_CHECK_GOTO(ret, cleanup);
+ }
}
cleanup:
@@ -457,48 +420,6 @@ cleanup:
return ret;
}
-/**
- * @brief Implementation of ::lyplg_type_validate_clb for the unsigned interger types.
- */
-static LY_ERR
-lyplg_type_validate_uint(const struct ly_ctx *UNUSED(ctx), const struct lysc_type *type, const struct lyd_node *UNUSED(ctx_node),
- const struct lyd_node *UNUSED(tree), struct lyd_value *storage, struct ly_err_item **err)
-{
- LY_ERR ret;
- struct lysc_type_num *type_num = (struct lysc_type_num *)type;
- uint64_t num;
-
- LY_CHECK_ARG_RET(NULL, type, storage, err, LY_EINVAL);
- *err = NULL;
-
- /* set the value (matters for big-endian) and get the correct int64 number */
- switch (type->basetype) {
- case LY_TYPE_UINT8:
- num = storage->uint8;
- break;
- case LY_TYPE_UINT16:
- num = storage->uint16;
- break;
- case LY_TYPE_UINT32:
- num = storage->uint32;
- break;
- case LY_TYPE_UINT64:
- num = storage->uint64;
- break;
- default:
- return LY_EINVAL;
- }
-
- /* validate range of the number */
- if (type_num->range) {
- ret = lyplg_type_validate_range(type->basetype, type_num->range, num, storage->_canonical,
- strlen(storage->_canonical), err);
- LY_CHECK_RET(ret);
- }
-
- return LY_SUCCESS;
-}
-
LIBYANG_API_DEF LY_ERR
lyplg_type_compare_uint(const struct ly_ctx *UNUSED(ctx), const struct lyd_value *val1, const struct lyd_value *val2)
{
@@ -646,7 +567,7 @@ const struct lyplg_type_record plugins_integer[] = {
.plugin.id = "libyang 2 - integers, version 1",
.plugin.store = lyplg_type_store_uint,
- .plugin.validate = lyplg_type_validate_uint,
+ .plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_uint,
.plugin.sort = lyplg_type_sort_uint,
.plugin.print = lyplg_type_print_uint,
@@ -660,7 +581,7 @@ const struct lyplg_type_record plugins_integer[] = {
.plugin.id = "libyang 2 - integers, version 1",
.plugin.store = lyplg_type_store_uint,
- .plugin.validate = lyplg_type_validate_uint,
+ .plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_uint,
.plugin.sort = lyplg_type_sort_uint,
.plugin.print = lyplg_type_print_uint,
@@ -674,7 +595,7 @@ const struct lyplg_type_record plugins_integer[] = {
.plugin.id = "libyang 2 - integers, version 1",
.plugin.store = lyplg_type_store_uint,
- .plugin.validate = lyplg_type_validate_uint,
+ .plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_uint,
.plugin.sort = lyplg_type_sort_uint,
.plugin.print = lyplg_type_print_uint,
@@ -688,7 +609,7 @@ const struct lyplg_type_record plugins_integer[] = {
.plugin.id = "libyang 2 - integers, version 1",
.plugin.store = lyplg_type_store_uint,
- .plugin.validate = lyplg_type_validate_uint,
+ .plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_uint,
.plugin.sort = lyplg_type_sort_uint,
.plugin.print = lyplg_type_print_uint,
@@ -702,7 +623,7 @@ const struct lyplg_type_record plugins_integer[] = {
.plugin.id = "libyang 2 - integers, version 1",
.plugin.store = lyplg_type_store_int,
- .plugin.validate = lyplg_type_validate_int,
+ .plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_int,
.plugin.sort = lyplg_type_sort_int,
.plugin.print = lyplg_type_print_int,
@@ -716,7 +637,7 @@ const struct lyplg_type_record plugins_integer[] = {
.plugin.id = "libyang 2 - integers, version 1",
.plugin.store = lyplg_type_store_int,
- .plugin.validate = lyplg_type_validate_int,
+ .plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_int,
.plugin.sort = lyplg_type_sort_int,
.plugin.print = lyplg_type_print_int,
@@ -730,7 +651,7 @@ const struct lyplg_type_record plugins_integer[] = {
.plugin.id = "libyang 2 - integers, version 1",
.plugin.store = lyplg_type_store_int,
- .plugin.validate = lyplg_type_validate_int,
+ .plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_int,
.plugin.sort = lyplg_type_sort_int,
.plugin.print = lyplg_type_print_int,
@@ -744,7 +665,7 @@ const struct lyplg_type_record plugins_integer[] = {
.plugin.id = "libyang 2 - integers, version 1",
.plugin.store = lyplg_type_store_int,
- .plugin.validate = lyplg_type_validate_int,
+ .plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_int,
.plugin.sort = lyplg_type_sort_int,
.plugin.print = lyplg_type_print_int,
diff --git a/src/plugins_types/ipv4_address.c b/src/plugins_types/ipv4_address.c
index 022689b..0ed6d36 100644
--- a/src/plugins_types/ipv4_address.c
+++ b/src/plugins_types/ipv4_address.c
@@ -171,17 +171,19 @@ lyplg_type_store_ipv4_address(const struct ly_ctx *ctx, const struct lysc_type *
ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
LY_CHECK_GOTO(ret, cleanup);
- /* 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);
+ if (!(options & LYPLG_TYPE_STORE_ONLY)) {
+ /* length restriction of the string */
+ if (type_str->length) {
+ /* value_len is in bytes, but we need number of characters here */
+ 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);
}
- /* pattern restrictions */
- ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err);
- LY_CHECK_GOTO(ret, cleanup);
-
/* get the network-byte order address */
ret = ipv4address_str2ip(value, value_len, options, ctx, &val->addr, &val->zone, err);
LY_CHECK_GOTO(ret, cleanup);
diff --git a/src/plugins_types/ipv4_address_no_zone.c b/src/plugins_types/ipv4_address_no_zone.c
index 4438306..5a0f009 100644
--- a/src/plugins_types/ipv4_address_no_zone.c
+++ b/src/plugins_types/ipv4_address_no_zone.c
@@ -57,7 +57,6 @@ lyplg_type_store_ipv4_address_no_zone(const struct ly_ctx *ctx, const struct lys
struct ly_err_item **err)
{
LY_ERR ret = LY_SUCCESS;
- struct lysc_type_str *type_str = (struct lysc_type_str *)type;
struct lyd_value_ipv4_address_no_zone *val;
/* init storage */
@@ -85,17 +84,6 @@ lyplg_type_store_ipv4_address_no_zone(const struct ly_ctx *ctx, const struct lys
ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
LY_CHECK_GOTO(ret, cleanup);
- /* length restriction of the string */
- if (type_str->length) {
- /* value_len is in bytes, but we need number of characters here */
- ret = lyplg_type_validate_range(LY_TYPE_STRING, type_str->length, ly_utf8len(value, value_len), value, value_len, err);
- LY_CHECK_GOTO(ret, cleanup);
- }
-
- /* pattern restrictions */
- ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err);
- LY_CHECK_GOTO(ret, cleanup);
-
/* we always need a dynamic value */
if (!(options & LYPLG_TYPE_STORE_DYNAMIC)) {
value = strndup(value, value_len);
@@ -104,7 +92,7 @@ lyplg_type_store_ipv4_address_no_zone(const struct ly_ctx *ctx, const struct lys
options |= LYPLG_TYPE_STORE_DYNAMIC;
}
- /* get the network-byte order address */
+ /* get the network-byte order address, validates the value */
if (!inet_pton(AF_INET, value, &val->addr)) {
ret = ly_err_new(err, LY_EVALID, LYVE_DATA, NULL, NULL, "Failed to convert IPv4 address \"%s\".", (char *)value);
goto cleanup;
diff --git a/src/plugins_types/ipv4_prefix.c b/src/plugins_types/ipv4_prefix.c
index 2a86f36..4d1916e 100644
--- a/src/plugins_types/ipv4_prefix.c
+++ b/src/plugins_types/ipv4_prefix.c
@@ -156,17 +156,19 @@ lyplg_type_store_ipv4_prefix(const struct ly_ctx *ctx, const struct lysc_type *t
ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
LY_CHECK_GOTO(ret, cleanup);
- /* 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);
+ if (!(options & LYPLG_TYPE_STORE_ONLY)) {
+ /* length restriction of the string */
+ if (type_str->length) {
+ /* value_len is in bytes, but we need number of characters here */
+ 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);
}
- /* pattern restrictions */
- ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err);
- LY_CHECK_GOTO(ret, cleanup);
-
/* get the mask in network-byte order */
ret = ipv4prefix_str2ip(value, value_len, &val->addr, &val->prefix, err);
LY_CHECK_GOTO(ret, cleanup);
diff --git a/src/plugins_types/ipv6_address.c b/src/plugins_types/ipv6_address.c
index 8ddcd18..147df3e 100644
--- a/src/plugins_types/ipv6_address.c
+++ b/src/plugins_types/ipv6_address.c
@@ -172,17 +172,19 @@ lyplg_type_store_ipv6_address(const struct ly_ctx *ctx, const struct lysc_type *
ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
LY_CHECK_GOTO(ret, cleanup);
- /* 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);
+ if (!(options & LYPLG_TYPE_STORE_ONLY)) {
+ /* length restriction of the string */
+ if (type_str->length) {
+ /* value_len is in bytes, but we need number of characters here */
+ 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);
}
- /* pattern restrictions */
- ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err);
- LY_CHECK_GOTO(ret, cleanup);
-
/* get the network-byte order address */
ret = ipv6address_str2ip(value, value_len, options, ctx, &val->addr, &val->zone, err);
LY_CHECK_GOTO(ret, cleanup);
diff --git a/src/plugins_types/ipv6_address_no_zone.c b/src/plugins_types/ipv6_address_no_zone.c
index caa2c8f..76d47ae 100644
--- a/src/plugins_types/ipv6_address_no_zone.c
+++ b/src/plugins_types/ipv6_address_no_zone.c
@@ -96,7 +96,6 @@ lyplg_type_store_ipv6_address_no_zone(const struct ly_ctx *ctx, const struct lys
struct ly_err_item **err)
{
LY_ERR ret = LY_SUCCESS;
- struct lysc_type_str *type_str = (struct lysc_type_str *)type;
struct lyd_value_ipv6_address_no_zone *val;
/* init storage */
@@ -136,18 +135,7 @@ lyplg_type_store_ipv6_address_no_zone(const struct ly_ctx *ctx, const struct lys
ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
LY_CHECK_GOTO(ret, cleanup);
- /* length restriction of the string */
- if (type_str->length) {
- /* value_len is in bytes, but we need number of characters here */
- ret = lyplg_type_validate_range(LY_TYPE_STRING, type_str->length, ly_utf8len(value, value_len), value, value_len, err);
- LY_CHECK_GOTO(ret, cleanup);
- }
-
- /* pattern restrictions */
- ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err);
- LY_CHECK_GOTO(ret, cleanup);
-
- /* get the network-byte order address */
+ /* get the network-byte order address, validates the value */
ret = ipv6addressnozone_str2ip(value, value_len, options, &val->addr, err);
LY_CHECK_GOTO(ret, cleanup);
diff --git a/src/plugins_types/ipv6_prefix.c b/src/plugins_types/ipv6_prefix.c
index 05b1be7..4643e85 100644
--- a/src/plugins_types/ipv6_prefix.c
+++ b/src/plugins_types/ipv6_prefix.c
@@ -170,17 +170,19 @@ lyplg_type_store_ipv6_prefix(const struct ly_ctx *ctx, const struct lysc_type *t
ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
LY_CHECK_GOTO(ret, cleanup);
- /* 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);
+ if (!(options & LYPLG_TYPE_STORE_ONLY)) {
+ /* length restriction of the string */
+ if (type_str->length) {
+ /* value_len is in bytes, but we need number of characters here */
+ 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);
}
- /* pattern restrictions */
- ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err);
- LY_CHECK_GOTO(ret, cleanup);
-
/* get the mask in network-byte order */
ret = ipv6prefix_str2ip(value, value_len, &val->addr, &val->prefix, err);
LY_CHECK_GOTO(ret, cleanup);
diff --git a/src/plugins_types/leafref.c b/src/plugins_types/leafref.c
index fee2ef9..5863895 100644
--- a/src/plugins_types/leafref.c
+++ b/src/plugins_types/leafref.c
@@ -41,19 +41,19 @@ lyplg_type_store_leafref(const struct ly_ctx *ctx, const struct lysc_type *type,
uint32_t options, LY_VALUE_FORMAT format, void *prefix_data, uint32_t hints, const struct lysc_node *ctx_node,
struct lyd_value *storage, struct lys_glob_unres *unres, struct ly_err_item **err)
{
- LY_ERR ret = LY_SUCCESS;
+ LY_ERR rc = LY_SUCCESS;
struct lysc_type_leafref *type_lr = (struct lysc_type_leafref *)type;
assert(type_lr->realtype);
/* store the value as the real type of the leafref target */
- ret = type_lr->realtype->plugin->store(ctx, type_lr->realtype, value, value_len, options, format, prefix_data,
+ rc = type_lr->realtype->plugin->store(ctx, type_lr->realtype, value, value_len, options, format, prefix_data,
hints, ctx_node, storage, unres, err);
- if (ret == LY_EINCOMPLETE) {
+ if (rc == LY_EINCOMPLETE) {
/* it is irrelevant whether the target type needs some resolving */
- ret = LY_SUCCESS;
+ rc = LY_SUCCESS;
}
- LY_CHECK_RET(ret);
+ LY_CHECK_RET(rc);
if (type_lr->require_instance) {
/* needs to be resolved */
@@ -67,7 +67,7 @@ LIBYANG_API_DEF LY_ERR
lyplg_type_validate_leafref(const struct ly_ctx *ctx, const struct lysc_type *type, const struct lyd_node *ctx_node,
const struct lyd_node *tree, struct lyd_value *storage, struct ly_err_item **err)
{
- LY_ERR ret;
+ LY_ERR rc = LY_SUCCESS;
struct lysc_type_leafref *type_lr = (struct lysc_type_leafref *)type;
char *errmsg = NULL, *path;
struct ly_set *targets = NULL;
@@ -80,24 +80,25 @@ lyplg_type_validate_leafref(const struct ly_ctx *ctx, const struct lysc_type *ty
return LY_SUCCESS;
}
- ret = lyplg_type_resolve_leafref(type_lr, ctx_node, storage, tree, (ly_ctx_get_options(ctx) & LY_CTX_LEAFREF_LINKING) ? &targets : NULL, &errmsg);
- if (ret != LY_SUCCESS) {
+ rc = lyplg_type_resolve_leafref(type_lr, ctx_node, storage, tree,
+ (ly_ctx_get_options(ctx) & LY_CTX_LEAFREF_LINKING) ? &targets : NULL, &errmsg);
+ if (rc) {
path = lyd_path(ctx_node, LYD_PATH_STD, NULL, 0);
- ret = ly_err_new(err, LY_EVALID, LYVE_DATA, path, strdup("instance-required"), "%s", errmsg);
+ rc = ly_err_new(err, LY_EVALID, LYVE_DATA, path, strdup("instance-required"), "%s", errmsg);
free(errmsg);
goto cleanup;
}
if (ly_ctx_get_options(ctx) & LY_CTX_LEAFREF_LINKING) {
for (i = 0; i < targets->count; ++i) {
- ret = lyd_link_leafref_node((struct lyd_node_term *)targets->dnodes[i], (struct lyd_node_term *)ctx_node);
- LY_CHECK_GOTO(ret, cleanup);
+ rc = lyd_link_leafref_node((struct lyd_node_term *)targets->dnodes[i], (struct lyd_node_term *)ctx_node);
+ LY_CHECK_GOTO(rc, cleanup);
}
}
cleanup:
ly_set_free(targets, NULL);
- return ret;
+ return rc;
}
LIBYANG_API_DEF LY_ERR
diff --git a/src/plugins_types/node_instanceid.c b/src/plugins_types/node_instanceid.c
index 21448e3..7c80e30 100644
--- a/src/plugins_types/node_instanceid.c
+++ b/src/plugins_types/node_instanceid.c
@@ -312,8 +312,8 @@ const struct lyplg_type_record plugins_node_instanceid[] = {
.plugin.id = "libyang 2 - node-instance-identifier, version 1",
.plugin.store = lyplg_type_store_node_instanceid,
.plugin.validate = NULL,
- .plugin.compare = lyplg_type_compare_instanceid,
- .plugin.sort = lyplg_type_sort_instanceid,
+ .plugin.compare = lyplg_type_compare_simple,
+ .plugin.sort = lyplg_type_sort_simple,
.plugin.print = lyplg_type_print_node_instanceid,
.plugin.duplicate = lyplg_type_dup_instanceid,
.plugin.free = lyplg_type_free_instanceid,
@@ -327,8 +327,8 @@ const struct lyplg_type_record plugins_node_instanceid[] = {
.plugin.id = "libyang 2 - node-instance-identifier, version 1",
.plugin.store = lyplg_type_store_node_instanceid,
.plugin.validate = NULL,
- .plugin.compare = lyplg_type_compare_instanceid,
- .plugin.sort = lyplg_type_sort_instanceid,
+ .plugin.compare = lyplg_type_compare_simple,
+ .plugin.sort = lyplg_type_sort_simple,
.plugin.print = lyplg_type_print_node_instanceid,
.plugin.duplicate = lyplg_type_dup_instanceid,
.plugin.free = lyplg_type_free_instanceid,
diff --git a/src/plugins_types/string.c b/src/plugins_types/string.c
index 2ad0035..d1888f3 100644
--- a/src/plugins_types/string.c
+++ b/src/plugins_types/string.c
@@ -34,8 +34,6 @@
* | string length | yes | `char *` | string itself |
*/
-static LY_ERR lyplg_type_validate_string(const struct ly_ctx *UNUSED(ctx), const struct lysc_type *type, const struct lyd_node *UNUSED(ctx_node), const struct lyd_node *UNUSED(tree), struct lyd_value *storage, struct ly_err_item **err);
-
/**
* @brief Check string value for invalid characters.
*
@@ -65,6 +63,7 @@ lyplg_type_store_string(const struct ly_ctx *ctx, const struct lysc_type *type,
const struct lysc_node *UNUSED(ctx_node), struct lyd_value *storage, struct lys_glob_unres *UNUSED(unres),
struct ly_err_item **err)
{
+ struct lysc_type_str *type_str = (struct lysc_type_str *)type;
LY_ERR ret = LY_SUCCESS;
/* init storage */
@@ -86,14 +85,24 @@ lyplg_type_store_string(const struct ly_ctx *ctx, const struct lysc_type *type,
ret = lydict_insert_zc(ctx, (char *)value, &storage->_canonical);
options &= ~LYPLG_TYPE_STORE_DYNAMIC;
LY_CHECK_GOTO(ret, cleanup);
+
+ /* value may have been freed */
+ value = storage->_canonical;
} else {
ret = lydict_insert(ctx, value_len ? value : "", value_len, &storage->_canonical);
LY_CHECK_GOTO(ret, cleanup);
}
if (!(options & LYPLG_TYPE_STORE_ONLY)) {
- /* validate value */
- ret = lyplg_type_validate_string(ctx, type, NULL, NULL, storage, err);
+ /* length restriction of the string */
+ if (type_str->length) {
+ /* value_len is in bytes, but we need number of characters here */
+ ret = lyplg_type_validate_range(LY_TYPE_STRING, type_str->length, ly_utf8len(value, value_len), value, value_len, err);
+ LY_CHECK_GOTO(ret, cleanup);
+ }
+
+ /* pattern restrictions */
+ ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err);
LY_CHECK_GOTO(ret, cleanup);
}
@@ -109,37 +118,6 @@ cleanup:
}
/**
- * @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.
*
* Note that external plugins are supposed to use:
@@ -154,7 +132,7 @@ const struct lyplg_type_record plugins_string[] = {
.plugin.id = "libyang 2 - string, version 1",
.plugin.store = lyplg_type_store_string,
- .plugin.validate = lyplg_type_validate_string,
+ .plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_simple,
.plugin.sort = lyplg_type_sort_simple,
.plugin.print = lyplg_type_print_simple,
diff --git a/src/plugins_types/time_period.c b/src/plugins_types/time_period.c
new file mode 100644
index 0000000..e2fbcd6
--- /dev/null
+++ b/src/plugins_types/time_period.c
@@ -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}
+};
diff --git a/src/plugins_types/union.c b/src/plugins_types/union.c
index b494c95..51cca6c 100644
--- a/src/plugins_types/union.c
+++ b/src/plugins_types/union.c
@@ -493,7 +493,7 @@ lyplg_type_compare_union(const struct ly_ctx *ctx, const struct lyd_value *val1,
LIBYANG_API_DEF int
lyplg_type_sort_union(const struct ly_ctx *ctx, const struct lyd_value *val1, const struct lyd_value *val2)
{
- int ret;
+ int rc = LY_SUCCESS;
LY_ARRAY_COUNT_TYPE u;
struct lysc_type **types;
@@ -502,20 +502,19 @@ lyplg_type_sort_union(const struct ly_ctx *ctx, const struct lyd_value *val1, co
}
/* compare according to the order of types */
- ret = 0;
types = ((struct lysc_type_union *)val1->realtype)->types;
LY_ARRAY_FOR(types, u) {
if (types[u] == val1->subvalue->value.realtype) {
- ret = 1;
+ rc = 1;
break;
} else if (types[u] == val2->subvalue->value.realtype) {
- ret = -1;
+ rc = -1;
break;
}
}
- assert(ret != 0);
+ assert(rc != 0);
- return ret;
+ return rc;
}
/**
diff --git a/src/plugins_types/xpath1.0.c b/src/plugins_types/xpath1.0.c
index 9376351..0c5dfce 100644
--- a/src/plugins_types/xpath1.0.c
+++ b/src/plugins_types/xpath1.0.c
@@ -248,7 +248,6 @@ lyplg_type_store_xpath10(const struct ly_ctx *ctx, const struct lysc_type *type,
struct lyd_value *storage, struct lys_glob_unres *UNUSED(unres), struct ly_err_item **err)
{
LY_ERR ret = LY_SUCCESS;
- struct lysc_type_str *type_str = (struct lysc_type_str *)type;
struct lyd_value_xpath10 *val;
char *canon;
@@ -262,17 +261,6 @@ lyplg_type_store_xpath10(const struct ly_ctx *ctx, const struct lysc_type *type,
ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
LY_CHECK_GOTO(ret, cleanup);
- /* length restriction of the string */
- if (type_str->length) {
- /* value_len is in bytes, but we need number of characters here */
- ret = lyplg_type_validate_range(LY_TYPE_STRING, type_str->length, ly_utf8len(value, value_len), value, value_len, err);
- LY_CHECK_GOTO(ret, cleanup);
- }
-
- /* pattern restrictions */
- ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err);
- LY_CHECK_GOTO(ret, cleanup);
-
/* parse */
ret = lyxp_expr_parse(ctx, value_len ? value : "", value_len, 1, &val->exp);
LY_CHECK_GOTO(ret, cleanup);
diff --git a/src/printer_yang.c b/src/printer_yang.c
index 6dc06a8..3adcc2a 100644
--- a/src/printer_yang.c
+++ b/src/printer_yang.c
@@ -1162,7 +1162,7 @@ yprp_inout(struct lys_ypr_ctx *pctx, const struct lysp_node_action_inout *inout,
ly_print_(pctx->out, "%*s%s {\n", INDENT, inout->name);
LEVEL++;
- yprp_extension_instances(pctx, LY_STMT_MUST, 0, inout->exts, NULL);
+ yprp_extension_instances(pctx, lyplg_ext_nodetype2stmt(inout->nodetype), 0, inout->exts, NULL);
LY_ARRAY_FOR(inout->musts, u) {
yprp_restr(pctx, &inout->musts[u], LY_STMT_MUST, NULL);
}
@@ -2563,7 +2563,7 @@ lyplg_ext_print_info_extension_instance(struct lyspr_ctx *ctx, const struct lysc
break;
}
- LY_LIST_FOR(*VOIDPTR2_C(ext->substmts[u].storage), node) {
+ LY_LIST_FOR(*ext->substmts[u].storage_p, node) {
ypr_open(pctx->out, flag);
if (ext->substmts[u].stmt == LY_STMT_NOTIFICATION) {
yprc_notification(pctx, (struct lysc_node_notif *)node);
@@ -2592,32 +2592,32 @@ lyplg_ext_print_info_extension_instance(struct lyspr_ctx *ctx, const struct lysc
case LY_STMT_PRESENCE:
case LY_STMT_REFERENCE:
case LY_STMT_UNITS:
- if (*VOIDPTR2_C(ext->substmts[u].storage)) {
+ if (*ext->substmts[u].storage_p) {
ypr_open(pctx->out, flag);
- ypr_substmt(pctx, ext->substmts[u].stmt, 0, *VOIDPTR2_C(ext->substmts[u].storage), 0, ext->exts);
+ ypr_substmt(pctx, ext->substmts[u].stmt, 0, *ext->substmts[u].storage_p, 0, ext->exts);
}
break;
case LY_STMT_BIT:
case LY_STMT_ENUM: {
- const struct lysc_type_bitenum_item *items = *VOIDPTR2_C(ext->substmts[u].storage);
+ const struct lysc_type_bitenum_item *items = *ext->substmts[u].storage_p;
yprc_bits_enum(pctx, items, ext->substmts[u].stmt == LY_STMT_BIT ? LY_TYPE_BITS : LY_TYPE_ENUM, flag);
break;
}
case LY_STMT_CONFIG:
- ypr_config(pctx, *(uint16_t *)VOIDPTR2_C(ext->substmts[u].storage), ext->exts, flag);
+ ypr_config(pctx, *(uint16_t *)ext->substmts[u].storage_p, ext->exts, flag);
break;
case LY_STMT_EXTENSION_INSTANCE:
- yprc_extension_instances(pctx, LY_STMT_EXTENSION_INSTANCE, 0, *VOIDPTR2_C(ext->substmts[u].storage), flag);
+ yprc_extension_instances(pctx, LY_STMT_EXTENSION_INSTANCE, 0, *ext->substmts[u].storage_p, flag);
break;
case LY_STMT_FRACTION_DIGITS:
- if (*VOIDPTR2_C(ext->substmts[u].storage)) {
+ if (*ext->substmts[u].storage_p) {
ypr_unsigned(pctx, LY_STMT_FRACTION_DIGITS, 0, ext->exts,
- (long unsigned int)*VOIDPTR2_C(ext->substmts[u].storage), flag);
+ (long unsigned int)*ext->substmts[u].storage_p, flag);
}
break;
case LY_STMT_IDENTITY: {
- const struct lysc_ident *idents = *VOIDPTR2_C(ext->substmts[u].storage);
+ const struct lysc_ident *idents = *ext->substmts[u].storage_p;
LY_ARRAY_FOR(idents, v) {
yprc_identity(pctx, &idents[v]);
@@ -2625,15 +2625,15 @@ lyplg_ext_print_info_extension_instance(struct lyspr_ctx *ctx, const struct lysc
break;
}
case LY_STMT_LENGTH:
- if (*VOIDPTR2_C(ext->substmts[u].storage)) {
- yprc_range(pctx, *VOIDPTR2_C(ext->substmts[u].storage), LY_TYPE_STRING, flag);
+ if (*ext->substmts[u].storage_p) {
+ yprc_range(pctx, *ext->substmts[u].storage_p, LY_TYPE_STRING, flag);
}
break;
case LY_STMT_MANDATORY:
- ypr_mandatory(pctx, *(uint16_t *)VOIDPTR_C(ext->substmts[u].storage), ext->exts, flag);
+ ypr_mandatory(pctx, *(uint16_t *)ext->substmts[u].storage_p, ext->exts, flag);
break;
case LY_STMT_MAX_ELEMENTS: {
- uint32_t max = *(uint32_t *)VOIDPTR_C(ext->substmts[u].storage);
+ uint32_t max = *(uint32_t *)ext->substmts[u].storage_p;
if (max) {
ypr_unsigned(pctx, LY_STMT_MAX_ELEMENTS, 0, ext->exts, max, flag);
@@ -2644,15 +2644,15 @@ lyplg_ext_print_info_extension_instance(struct lyspr_ctx *ctx, const struct lysc
break;
}
case LY_STMT_MIN_ELEMENTS:
- ypr_unsigned(pctx, LY_STMT_MIN_ELEMENTS, 0, ext->exts, *(uint32_t *)VOIDPTR_C(ext->substmts[u].storage), flag);
+ ypr_unsigned(pctx, LY_STMT_MIN_ELEMENTS, 0, ext->exts, *(uint32_t *)ext->substmts[u].storage_p, flag);
break;
case LY_STMT_ORDERED_BY:
ypr_open(pctx->out, flag);
ypr_substmt(pctx, LY_STMT_ORDERED_BY, 0,
- ((*(uint16_t *)VOIDPTR_C(ext->substmts[u].storage)) & LYS_ORDBY_USER) ? "user" : "system", 0, ext->exts);
+ ((*(uint16_t *)ext->substmts[u].storage_p) & LYS_ORDBY_USER) ? "user" : "system", 0, ext->exts);
break;
case LY_STMT_MUST: {
- const struct lysc_must *musts = *VOIDPTR2_C(ext->substmts[u].storage);
+ const struct lysc_must *musts = *ext->substmts[u].storage_p;
LY_ARRAY_FOR(musts, v) {
yprc_must(pctx, &musts[v], flag);
@@ -2660,7 +2660,7 @@ lyplg_ext_print_info_extension_instance(struct lyspr_ctx *ctx, const struct lysc
break;
}
case LY_STMT_PATTERN: {
- const struct lysc_pattern *patterns = *VOIDPTR2_C(ext->substmts[u].storage);
+ const struct lysc_pattern *patterns = *ext->substmts[u].storage_p;
LY_ARRAY_FOR(patterns, v) {
yprc_pattern(pctx, &patterns[v], flag);
@@ -2668,36 +2668,36 @@ lyplg_ext_print_info_extension_instance(struct lyspr_ctx *ctx, const struct lysc
break;
}
case LY_STMT_POSITION:
- if (*VOIDPTR2_C(ext->substmts[u].storage)) {
- ypr_unsigned(pctx, ext->substmts[u].stmt, 0, ext->exts, *(int64_t *)VOIDPTR_C(ext->substmts[u].storage), flag);
+ if (*ext->substmts[u].storage_p) {
+ ypr_unsigned(pctx, ext->substmts[u].stmt, 0, ext->exts, *(int64_t *)ext->substmts[u].storage_p, flag);
}
break;
case LY_STMT_VALUE:
- if (*VOIDPTR2_C(ext->substmts[u].storage)) {
- ypr_signed(pctx, ext->substmts[u].stmt, 0, ext->exts, *(int64_t *)VOIDPTR_C(ext->substmts[u].storage), flag);
+ if (*ext->substmts[u].storage_p) {
+ ypr_signed(pctx, ext->substmts[u].stmt, 0, ext->exts, *(int64_t *)ext->substmts[u].storage_p, flag);
}
break;
case LY_STMT_RANGE:
- if (*VOIDPTR2_C(ext->substmts[u].storage)) {
- yprc_range(pctx, *VOIDPTR2_C(ext->substmts[u].storage), LY_TYPE_UINT64, flag);
+ if (*ext->substmts[u].storage_p) {
+ yprc_range(pctx, *ext->substmts[u].storage_p, LY_TYPE_UINT64, flag);
}
break;
case LY_STMT_REQUIRE_INSTANCE:
ypr_open(pctx->out, flag);
- ypr_substmt(pctx, LY_STMT_REQUIRE_INSTANCE, 0, *(uint8_t *)VOIDPTR_C(ext->substmts[u].storage) ? "true" : "false",
+ ypr_substmt(pctx, LY_STMT_REQUIRE_INSTANCE, 0, *(uint8_t *)ext->substmts[u].storage_p ? "true" : "false",
0, ext->exts);
break;
case LY_STMT_STATUS:
- ypr_status(pctx, *(uint16_t *)VOIDPTR_C(ext->substmts[u].storage), ext->exts, flag);
+ ypr_status(pctx, *(uint16_t *)ext->substmts[u].storage_p, ext->exts, flag);
break;
case LY_STMT_TYPE:
- if (*VOIDPTR2_C(ext->substmts[u].storage)) {
+ if (*ext->substmts[u].storage_p) {
ypr_open(pctx->out, flag);
- yprc_type(pctx, *VOIDPTR2_C(ext->substmts[u].storage));
+ yprc_type(pctx, *ext->substmts[u].storage_p);
}
break;
case LY_STMT_WHEN:
- yprc_when(pctx, *VOIDPTR2_C(ext->substmts[u].storage), flag);
+ yprc_when(pctx, *ext->substmts[u].storage_p, flag);
break;
case LY_STMT_AUGMENT:
case LY_STMT_BASE:
diff --git a/src/schema_compile.c b/src/schema_compile.c
index aa9a3d0..d21f0dc 100644
--- a/src/schema_compile.c
+++ b/src/schema_compile.c
@@ -4,7 +4,7 @@
* @author Michal Vasko <mvasko@cesnet.cz>
* @brief Schema compilation.
*
- * Copyright (c) 2015 - 2022 CESNET, z.s.p.o.
+ * Copyright (c) 2015 - 2024 CESNET, z.s.p.o.
*
* This source code is licensed under BSD 3-Clause License (the "License").
* You may not use this file except in compliance with the License.
@@ -172,7 +172,10 @@ lys_compile_ext(struct lysc_ctx *ctx, struct lysp_ext_instance *extp, struct lys
/* compile extension if not already */
LY_CHECK_GOTO(ret = lys_compile_extension(ctx, extp, &ext->def), cleanup);
- /* compile */
+ /* compile nested extensions */
+ COMPILE_EXTS_GOTO(ctx, extp->exts, ext->exts, ext, ret, cleanup);
+
+ /* compile this extension */
if (ext->def->plugin && ext->def->plugin->compile) {
if (ext->argument) {
lysc_update_path(ctx, ext->module, ext->argument);
@@ -218,7 +221,7 @@ lys_identity_precompile(struct lysc_ctx *ctx_sc, struct ly_ctx *ctx, struct lysp
const struct lysp_ident *identities_p, struct lysc_ident **identities)
{
LY_ARRAY_COUNT_TYPE u;
- struct lysc_ctx cctx;
+ struct lysc_ctx cctx = {0};
struct lysc_ident *ident;
LY_ERR ret = LY_SUCCESS;
@@ -863,7 +866,7 @@ lys_compile_unres_leafref(struct lysc_ctx *ctx, const struct lysc_node *node, st
/* get the target node */
target = p[LY_ARRAY_COUNT(p) - 1].node;
- ly_path_free(node->module->ctx, p);
+ ly_path_free(p);
if (!(target->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
LOGVAL(ctx->ctx, LYVE_REFERENCE, "Invalid leafref path \"%s\" - target node is %s instead of leaf or leaf-list.",
@@ -960,6 +963,12 @@ lys_compile_unres_dflt(struct lysc_ctx *ctx, struct lysc_node *node, struct lysc
}
LY_ATOMIC_INC_BARRIER(((struct lysc_type *)storage->realtype)->refcount);
+ if (storage->realtype->basetype == LY_TYPE_INST) {
+ /* ly_path includes references to other nodes, in case they are in foreign modules, the context would
+ * need to be freed in specific order to avoid accessing freed memory, so just avoid storing it */
+ ly_path_free(storage->target);
+ storage->target = NULL;
+ }
return LY_SUCCESS;
}
@@ -1453,7 +1462,7 @@ resolve_all:
ret = ly_path_compile_leafref(cctx.ctx, l->node, cctx.ext, lref->path,
(l->node->flags & LYS_IS_OUTPUT) ? LY_PATH_OPER_OUTPUT : LY_PATH_OPER_INPUT, LY_PATH_TARGET_MANY,
LY_VALUE_SCHEMA_RESOLVED, lref->prefixes, &path);
- ly_path_free(l->node->module->ctx, path);
+ ly_path_free(path);
assert(ret != LY_ERECOMPILE);
if (ret) {
@@ -1468,7 +1477,7 @@ resolve_all:
}
cleanup:
- lysf_ctx_erase(&cctx.free_ctx);
+ assert(!cctx.free_ctx.ext_set.count);
return ret;
}
@@ -1548,8 +1557,8 @@ lys_compile_depset_r(struct ly_ctx *ctx, struct ly_set *dep_set, struct lys_glob
}
cleanup:
+ assert(!fctx.ext_set.count);
lys_compile_unres_depset_erase(ctx, unres);
- lysf_ctx_erase(&fctx);
return ret;
}
@@ -1693,7 +1702,7 @@ lys_compile_unres_mod_erase(struct lysc_ctx *ctx, ly_bool error)
LY_ERR
lys_compile(struct lys_module *mod, struct lys_depset_unres *unres)
{
- struct lysc_ctx ctx;
+ struct lysc_ctx ctx = {0};
struct lysc_module *mod_c = NULL;
struct lysp_module *sp;
struct lysp_submodule *submod;
@@ -1814,7 +1823,7 @@ LY_ERR
lys_compile_identities(struct lys_module *mod)
{
LY_ERR rc = LY_SUCCESS;
- struct lysc_ctx ctx;
+ struct lysc_ctx ctx = {0};
struct lysp_submodule *submod;
LY_ARRAY_COUNT_TYPE u;
diff --git a/src/schema_compile.h b/src/schema_compile.h
index d45156e..8f67ce3 100644
--- a/src/schema_compile.h
+++ b/src/schema_compile.h
@@ -67,7 +67,6 @@ struct lysc_ctx {
* @param[in] CTX libyang context.
*/
#define LYSC_CTX_INIT_CTX(CCTX, CTX) \
- memset(&(CCTX), 0, sizeof (CCTX)); \
(CCTX).ctx = (CTX); \
(CCTX).path_len = 1; \
(CCTX).path[0] = '/'; \
@@ -81,7 +80,6 @@ struct lysc_ctx {
* @param[in] EXT Ancestor extension instance.
*/
#define LYSC_CTX_INIT_PMOD(CCTX, PMOD, EXT) \
- memset(&(CCTX), 0, sizeof (CCTX)); \
(CCTX).ctx = (PMOD)->mod->ctx; \
(CCTX).cur_mod = (PMOD)->mod; \
(CCTX).pmod = (PMOD); \
@@ -164,9 +162,9 @@ struct lysc_unres_dflt {
* @param[out] DUP Where to store the result.
* @param[out] RET Where to store the return code.
*/
-#define DUP_STRING(CTX, ORIG, DUP, RET) RET = lydict_insert(CTX, ORIG, 0, &(DUP))
-#define DUP_STRING_RET(CTX, ORIG, DUP) LY_CHECK_RET(lydict_insert(CTX, ORIG, 0, &(DUP)))
-#define DUP_STRING_GOTO(CTX, ORIG, DUP, RET, GOTO) LY_CHECK_GOTO(RET = lydict_insert(CTX, ORIG, 0, &(DUP)), GOTO)
+#define DUP_STRING(CTX, ORIG, DUP, RET) RET = lydict_dup(CTX, ORIG, &(DUP))
+#define DUP_STRING_RET(CTX, ORIG, DUP) LY_CHECK_RET(lydict_dup(CTX, ORIG, &(DUP)))
+#define DUP_STRING_GOTO(CTX, ORIG, DUP, RET, GOTO) LY_CHECK_GOTO(RET = lydict_dup(CTX, ORIG, &(DUP)), GOTO)
#define DUP_ARRAY(CTX, ORIG_ARRAY, NEW_ARRAY, DUP_FUNC) \
if (ORIG_ARRAY) { \
diff --git a/src/schema_compile_amend.c b/src/schema_compile_amend.c
index 4eac4ec..6179220 100644
--- a/src/schema_compile_amend.c
+++ b/src/schema_compile_amend.c
@@ -2218,7 +2218,7 @@ lys_precompile_own_augments_mod(struct lysc_ctx *ctx, const struct lysp_module *
aug_p = NULL;
LY_ARRAY_FOR(pmod->exts[u].substmts, v) {
if (pmod->exts[u].substmts[v].stmt == LY_STMT_AUGMENT) {
- aug_p = *VOIDPTR2_C(pmod->exts[u].substmts[v].storage);
+ aug_p = *(pmod->exts[u].substmts[v].storage_p);
break;
}
}
@@ -2443,7 +2443,7 @@ lys_precompile_mod_augments_deviations(struct lysp_module *pmod, struct ly_set *
{
LY_ERR ret = LY_SUCCESS;
LY_ARRAY_COUNT_TYPE u, v;
- struct lysc_ctx ctx;
+ struct lysc_ctx ctx = {0};
struct lys_module *m;
struct lysp_node_augment *aug;
struct ly_set set = {0};
@@ -2488,7 +2488,7 @@ lys_precompile_mod_augments_deviations(struct lysp_module *pmod, struct ly_set *
aug = NULL;
LY_ARRAY_FOR(pmod->exts[u].substmts, v) {
if (pmod->exts[u].substmts[v].stmt == LY_STMT_AUGMENT) {
- aug = *VOIDPTR2_C(pmod->exts[u].substmts[v].storage);
+ aug = *(pmod->exts[u].substmts[v].storage_p);
break;
}
}
diff --git a/src/schema_compile_node.c b/src/schema_compile_node.c
index a627799..d57d8a7 100644
--- a/src/schema_compile_node.c
+++ b/src/schema_compile_node.c
@@ -1390,7 +1390,7 @@ lys_compile_type_patterns(struct lysc_ctx *ctx, const struct lysp_restr *pattern
if (patterns_p[u].arg.str[0] == LYSP_RESTR_PATTERN_NACK) {
(*pattern)->inverted = 1;
}
- DUP_STRING_GOTO(ctx->ctx, &patterns_p[u].arg.str[1], (*pattern)->expr, ret, done);
+ LY_CHECK_GOTO(ret = lydict_insert(ctx->ctx, &patterns_p[u].arg.str[1], 0, &(*pattern)->expr), done);
DUP_STRING_GOTO(ctx->ctx, patterns_p[u].eapptag, (*pattern)->eapptag, ret, done);
DUP_STRING_GOTO(ctx->ctx, patterns_p[u].emsg, (*pattern)->emsg, ret, done);
DUP_STRING_GOTO(ctx->ctx, patterns_p[u].dsc, (*pattern)->dsc, ret, done);
@@ -2582,10 +2582,10 @@ lys_compile_node_connect(struct lysc_ctx *ctx, struct lysc_node *parent, struct
}
} else {
/* top-level element */
- struct lysc_node **list;
+ struct lysc_node **list = NULL;
if (ctx->ext) {
- lyplg_ext_get_storage_p(ctx->ext, LY_STMT_DATA_NODE_MASK, (uint64_t *)&list);
+ lyplg_ext_get_storage_p(ctx->ext, LY_STMT_DATA_NODE_MASK, (void ***)&list);
} else if (node->nodetype == LYS_RPC) {
list = (struct lysc_node **)&ctx->cur_mod->compiled->rpcs;
} else if (node->nodetype == LYS_NOTIF) {
@@ -2794,7 +2794,6 @@ lys_compile_node_action_inout(struct lysc_ctx *ctx, struct lysp_node *pnode, str
struct lysc_node_action_inout *inout = (struct lysc_node_action_inout *)node;
COMPILE_ARRAY_GOTO(ctx, inout_p->musts, inout->musts, lys_compile_must, ret, done);
- COMPILE_EXTS_GOTO(ctx, inout_p->exts, inout->exts, inout, ret, done);
ctx->compile_opts |= (inout_p->nodetype == LYS_INPUT) ? LYS_COMPILE_RPC_INPUT : LYS_COMPILE_RPC_OUTPUT;
LY_LIST_FOR(inout_p->child, child_p) {
diff --git a/src/schema_features.c b/src/schema_features.c
index 9f6c368..5552267 100644
--- a/src/schema_features.c
+++ b/src/schema_features.c
@@ -105,7 +105,7 @@ lys_identity_iffeature_value(const struct lysc_ident *ident)
const struct lysp_ident *idents_p, *found_ident = NULL;
struct lysp_include *includes;
- assert(ident);
+ LY_CHECK_ARG_RET(NULL, ident, ident->module->parsed, LY_EINVAL);
/* Search parsed identity in the module. */
idents_p = ident->module->parsed->identities;
@@ -146,6 +146,8 @@ lysp_feature_next(const struct lysp_feature *last, const struct lysp_module *pmo
{
struct lysp_feature *features;
+ LY_CHECK_ARG_RET(NULL, pmod, NULL);
+
if (!*idx) {
/* module features */
features = pmod->features;
diff --git a/src/tree_data.c b/src/tree_data.c
index dede407..a8c42bf 100644
--- a/src/tree_data.c
+++ b/src/tree_data.c
@@ -1078,7 +1078,7 @@ lyd_insert_sibling(struct lyd_node *sibling, struct lyd_node *node, struct lyd_n
{
struct lyd_node *first_sibling;
- LY_CHECK_ARG_RET(NULL, node, LY_EINVAL);
+ LY_CHECK_ARG_RET(NULL, node, sibling != node, LY_EINVAL);
if (sibling) {
LY_CHECK_RET(lyd_insert_check_schema(NULL, sibling->schema, node->schema));
@@ -2148,6 +2148,11 @@ lyd_dup_r(const struct lyd_node *node, const struct ly_ctx *trg_ctx, struct lyd_
struct lyd_node *child;
if (options & LYD_DUP_RECURSIVE) {
+ /* create a hash table with the size of the previous hash table (duplicate) */
+ if (orig->children_ht) {
+ ((struct lyd_node_inner *)dup)->children_ht = lyht_new(orig->children_ht->size, sizeof(struct lyd_node *), lyd_hash_table_val_equal, NULL, 1);
+ }
+
/* duplicate all the children */
LY_LIST_FOR(orig->child, child) {
LY_CHECK_GOTO(ret = lyd_dup_r(child, trg_ctx, dup, LYD_INSERT_NODE_LAST, NULL, options, NULL), error);
@@ -2179,58 +2184,6 @@ error:
}
/**
- * @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.
*
* @param[in] node Node (subtree) to duplicate.
@@ -2311,12 +2264,14 @@ lyd_dup(const struct lyd_node *node, const struct ly_ctx *trg_ctx, struct lyd_no
ly_bool nosiblings, struct lyd_node **dup_p)
{
LY_ERR rc;
- const struct lyd_node *orig; /* original node to be duplicated */
- struct lyd_node *first_dup = NULL; /* the first duplicated node, this is returned */
- struct lyd_node *top = NULL; /* the most higher created node */
- struct lyd_node *local_parent = NULL; /* the direct parent node for the duplicated node(s) */
- struct lyd_node *dup = NULL; /* duplicate node */
- struct lyd_node *first_sibling = NULL; /* first sibling node */
+ const struct lyd_node *orig; /* original node to be duplicated */
+ struct lyd_node *first_dup = NULL; /* the first duplicated node, this is returned */
+ struct lyd_node *top = NULL; /* the most higher created node */
+ struct lyd_node *local_parent = NULL; /* the direct parent node for the duplicated node(s) */
+ struct lyd_node *dup = NULL; /* duplicate node */
+ struct lyd_node *first_sibling = NULL; /* first sibling node */
+ const struct lyd_node *first_llist = NULL; /* first duplicated (leaf-)list node, if any */
+ uint32_t insert_order;
assert(node && trg_ctx);
@@ -2339,19 +2294,35 @@ lyd_dup(const struct lyd_node *node, const struct ly_ctx *trg_ctx, struct lyd_no
rc = lyd_dup_r(orig, trg_ctx, NULL, LYD_INSERT_NODE_DEFAULT, &first_sibling, options, &dup);
LY_CHECK_GOTO(rc, error);
}
- } else if (!nosiblings && orig->schema && (orig->schema->nodetype & (LYS_LIST | LYS_LEAFLIST))) {
- /* duplicate the whole (leaf-)list */
- rc = lyd_dup_list(&orig, trg_ctx, local_parent, &first_sibling, options, &dup);
- LY_CHECK_GOTO(rc, error);
} else {
- rc = lyd_dup_r(orig, trg_ctx, local_parent,
- options & LYD_DUP_NO_LYDS ? LYD_INSERT_NODE_LAST_BY_SCHEMA : LYD_INSERT_NODE_DEFAULT,
- &first_sibling, options, &dup);
+ /* decide insert order */
+ insert_order = (options & LYD_DUP_NO_LYDS) ? LYD_INSERT_NODE_LAST_BY_SCHEMA : LYD_INSERT_NODE_DEFAULT;
+ if (first_llist) {
+ if (orig->schema != first_llist->schema) {
+ /* all the (leaf-)list instances duplicated */
+ first_llist = NULL;
+ } else {
+ /* duplicating all the instances of a (leaf-)list, no need to change their order */
+ insert_order = LYD_INSERT_NODE_LAST;
+ }
+ } else if (orig->schema && (orig->schema->nodetype & (LYS_LIST | LYS_LEAFLIST))) {
+ /* duplicating the first (leaf-)list instance, duplicate the rest more efficiently */
+ first_llist = orig;
+ }
+
+ /* duplicate the node */
+ rc = lyd_dup_r(orig, trg_ctx, local_parent, insert_order, &first_sibling, options, &dup);
LY_CHECK_GOTO(rc, error);
+
+ if (first_llist && dup->next) {
+ /* orig was not the last node (because we are inserting into a parent with some previous instances),
+ * we must check find the order */
+ first_llist = NULL;
+ }
}
first_dup = first_dup ? first_dup : dup;
- if (nosiblings || !orig) {
+ if (nosiblings) {
break;
}
}
@@ -3624,7 +3595,7 @@ lyd_find_path(const struct lyd_node *ctx_node, const char *path, ly_bool output,
cleanup:
lyxp_expr_free(LYD_CTX(ctx_node), expr);
- ly_path_free(LYD_CTX(ctx_node), lypath);
+ ly_path_free(lypath);
return ret;
}
diff --git a/src/tree_data_common.c b/src/tree_data_common.c
index 05cab2a..f480a5a 100644
--- a/src/tree_data_common.c
+++ b/src/tree_data_common.c
@@ -1656,10 +1656,11 @@ ly_time_str2time(const char *value, time_t *time, char **fractions_s)
struct tm tm = {0};
uint32_t i, frac_len;
const char *frac;
+ char *ptr;
int64_t shift, shift_m;
time_t t;
- LY_CHECK_ARG_RET(NULL, value, time, LY_EINVAL);
+ LY_CHECK_ARG_RET(NULL, value, strlen(value) > 17, time, LY_EINVAL);
tm.tm_year = atoi(&value[0]) - 1900;
tm.tm_mon = atoi(&value[5]) - 1;
@@ -1698,6 +1699,10 @@ ly_time_str2time(const char *value, time_t *time, char **fractions_s)
++i;
frac = &value[i];
for (frac_len = 0; isdigit(frac[frac_len]); ++frac_len) {}
+ if (!frac_len) {
+ LOGERR(NULL, LY_EINVAL, "Missing date-and-time fractions after '.'.");
+ return LY_EINVAL;
+ }
i += frac_len;
} else {
@@ -1709,15 +1714,20 @@ ly_time_str2time(const char *value, time_t *time, char **fractions_s)
/* zero shift */
shift = 0;
} else {
- shift = strtol(&value[i], NULL, 10);
+ value += i;
+ shift = strtol(value, &ptr, 10);
if (shift > 23) {
LOGERR(NULL, LY_EINVAL, "Invalid date-and-time timezone hour \"%" PRIi64 "\".", shift);
return LY_EINVAL;
+ } else if (ptr[0] != ':') {
+ LOGERR(NULL, LY_EINVAL, "Invalid date-and-time timezone hour \"%s\".", value);
+ return LY_EINVAL;
}
shift = shift * 60 * 60; /* convert from hours to seconds */
- shift_m = strtol(&value[i + 4], NULL, 10);
- if (shift_m > 59) {
+ value = ptr + 1;
+ shift_m = strtol(value, NULL, 10);
+ if ((shift_m < 0) || (shift_m > 59)) {
LOGERR(NULL, LY_EINVAL, "Invalid date-and-time timezone minutes \"%" PRIi64 "\".", shift_m);
return LY_EINVAL;
}
diff --git a/src/tree_data_hash.c b/src/tree_data_hash.c
index ce237b1..9be655c 100644
--- a/src/tree_data_hash.c
+++ b/src/tree_data_hash.c
@@ -84,7 +84,7 @@ lyd_hash(struct lyd_node *node)
*
* Implementation of ::lyht_value_equal_cb.
*/
-static ly_bool
+ly_bool
lyd_hash_table_val_equal(void *val1_p, void *val2_p, ly_bool mod, void *UNUSED(cb_data))
{
struct lyd_node *val1, *val2;
diff --git a/src/tree_data_internal.h b/src/tree_data_internal.h
index 2bfa66d..b3a027c 100644
--- a/src/tree_data_internal.h
+++ b/src/tree_data_internal.h
@@ -16,6 +16,7 @@
#ifndef LY_TREE_DATA_INTERNAL_H_
#define LY_TREE_DATA_INTERNAL_H_
+#include "compat.h"
#include "log.h"
#include "plugins_types.h"
#include "tree_data.h"
@@ -601,6 +602,13 @@ LY_ERR ly_value_validate(const struct ly_ctx *ctx, const struct lysc_node *node,
LY_ERR lyd_hash(struct lyd_node *node);
/**
+ * @brief Compare callback for values in hash table.
+ *
+ * Implementation of ::lyht_value_equal_cb.
+ */
+ly_bool lyd_hash_table_val_equal(void *val1_p, void *val2_p, ly_bool mod, void *cb_data);
+
+/**
* @brief Insert hash of the node into the hash table of its parent.
*
* @param[in] node Data node which hash will be inserted into the ::lyd_node_inner.children_ht hash table of its parent.
diff --git a/src/tree_data_new.c b/src/tree_data_new.c
index f3bd9e7..7b26508 100644
--- a/src/tree_data_new.c
+++ b/src/tree_data_new.c
@@ -885,7 +885,7 @@ lyd_new_term(struct lyd_node *parent, const struct lys_module *module, const cha
return _lyd_new_term(parent, module, name, value, value ? strlen(value) : 0, options, node);
}
-LIBYANG_API_DECL LY_ERR
+LIBYANG_API_DEF LY_ERR
lyd_new_term_bin(struct lyd_node *parent, const struct lys_module *module, const char *name,
const void *value, size_t value_len, uint32_t options, struct lyd_node **node)
{
@@ -1089,6 +1089,7 @@ lyd_new_opaq(struct lyd_node *parent, const struct ly_ctx *ctx, const char *name
const char *prefix, const char *module_name, struct lyd_node **node)
{
struct lyd_node *ret = NULL;
+ uint32_t hints = 0;
LY_CHECK_ARG_RET(ctx, parent || ctx, parent || node, name, module_name, !prefix || !strcmp(prefix, module_name), LY_EINVAL);
LY_CHECK_CTX_EQUAL_RET(ctx, parent ? LYD_CTX(parent) : NULL, LY_EINVAL);
@@ -1098,10 +1099,12 @@ lyd_new_opaq(struct lyd_node *parent, const struct ly_ctx *ctx, const char *name
}
if (!value) {
value = "";
+ } else if (!strcmp(value, "[null]")) {
+ hints |= LYD_VALHINT_EMPTY;
}
LY_CHECK_RET(lyd_create_opaq(ctx, name, strlen(name), prefix, prefix ? strlen(prefix) : 0, module_name,
- strlen(module_name), value, strlen(value), NULL, LY_VALUE_JSON, NULL, 0, &ret));
+ strlen(module_name), value, strlen(value), NULL, LY_VALUE_JSON, NULL, hints, &ret));
if (parent) {
lyd_insert_node(parent, NULL, ret, LYD_INSERT_NODE_LAST);
}
@@ -1626,6 +1629,7 @@ lyd_new_path_(struct lyd_node *parent, const struct ly_ctx *ctx, const struct ly
ly_bool store_only = (options & LYD_NEW_VAL_STORE_ONLY) ? 1 : 0;
LY_ARRAY_COUNT_TYPE path_idx = 0, orig_count = 0;
LY_VALUE_FORMAT format;
+ uint32_t hints;
assert(parent || ctx);
assert(path && ((path[0] == '/') || parent));
@@ -1728,9 +1732,13 @@ lyd_new_path_(struct lyd_node *parent, const struct ly_ctx *ctx, const struct ly
}
if (r && (r != LY_EINCOMPLETE)) {
/* creating opaque leaf-list */
+ hints = LYD_NODEHINT_LEAFLIST;
+ if (value && (format == LY_VALUE_JSON) && !ly_strncmp("[null]", value, value_len)) {
+ hints |= LYD_VALHINT_EMPTY;
+ }
LY_CHECK_GOTO(ret = lyd_create_opaq(ctx, schema->name, strlen(schema->name), NULL, 0,
schema->module->name, strlen(schema->module->name), value, value_len, NULL, format, NULL,
- LYD_NODEHINT_LEAFLIST, &node), cleanup);
+ hints, &node), cleanup);
break;
}
}
@@ -1765,8 +1773,12 @@ lyd_new_path_(struct lyd_node *parent, const struct ly_ctx *ctx, const struct ly
}
if (r && (r != LY_EINCOMPLETE)) {
/* creating opaque leaf */
+ hints = 0;
+ if (value && (format == LY_VALUE_JSON) && !ly_strncmp("[null]", value, value_len)) {
+ hints |= LYD_VALHINT_EMPTY;
+ }
LY_CHECK_GOTO(ret = lyd_create_opaq(ctx, schema->name, strlen(schema->name), NULL, 0,
- schema->module->name, strlen(schema->module->name), value, value_len, NULL, format, NULL, 0, &node),
+ schema->module->name, strlen(schema->module->name), value, value_len, NULL, format, NULL, hints, &node),
cleanup);
break;
}
@@ -1811,7 +1823,7 @@ cleanup:
LY_ARRAY_INCREMENT(p);
}
}
- ly_path_free(ctx, p);
+ ly_path_free(p);
if (!ret) {
/* set out params only on success */
if (new_parent) {
diff --git a/src/tree_schema.c b/src/tree_schema.c
index d7ac8d8..21e2413 100644
--- a/src/tree_schema.c
+++ b/src/tree_schema.c
@@ -644,7 +644,7 @@ lys_find_path_atoms(const struct ly_ctx *ctx, const struct lysc_node *ctx_node,
ret = lys_find_lypath_atoms(p, set);
cleanup:
- ly_path_free(ctx, p);
+ ly_path_free(p);
lyxp_expr_free(ctx, expr);
return ret;
}
@@ -679,7 +679,7 @@ lys_find_path(const struct ly_ctx *ctx, const struct lysc_node *ctx_node, const
snode = p[LY_ARRAY_COUNT(p) - 1].node;
cleanup:
- ly_path_free(ctx, p);
+ ly_path_free(p);
lyxp_expr_free(ctx, expr);
return snode;
}
@@ -1179,7 +1179,7 @@ lys_set_implemented(struct lys_module *mod, const char **features)
LY_ERR ret = LY_SUCCESS;
struct lys_glob_unres *unres = &mod->ctx->unres;
- LY_CHECK_ARG_RET(NULL, mod, LY_EINVAL);
+ LY_CHECK_ARG_RET(NULL, mod, mod->parsed, LY_EINVAL);
/* implement */
ret = _lys_set_implemented(mod, features, unres);
diff --git a/src/tree_schema_common.c b/src/tree_schema_common.c
index 803009a..0faaa3c 100644
--- a/src/tree_schema_common.c
+++ b/src/tree_schema_common.c
@@ -768,7 +768,7 @@ lys_parse_localfile(struct ly_ctx *ctx, const char *name, const char *revision,
{
struct ly_in *in;
char *filepath = NULL;
- LYS_INFORMAT format;
+ LYS_INFORMAT format = 0;
void *mod = NULL;
LY_ERR ret = LY_SUCCESS;
struct lysp_load_module_check_data check_data = {0};
@@ -1829,7 +1829,7 @@ lysc_node_lref_target(const struct lysc_node *node)
/* get the target node */
target = p[LY_ARRAY_COUNT(p) - 1].node;
- ly_path_free(node->module->ctx, p);
+ ly_path_free(p);
return target;
}
diff --git a/src/tree_schema_free.c b/src/tree_schema_free.c
index 91ba72b..040872b 100644
--- a/src/tree_schema_free.c
+++ b/src/tree_schema_free.c
@@ -80,6 +80,8 @@ lysp_ext_instance_free(struct lysf_ctx *ctx, struct lysp_ext_instance *ext)
LY_LIST_FOR_SAFE(ext->child, next, stmt) {
lysp_stmt_free(ctx->ctx, stmt);
}
+
+ FREE_ARRAY(ctx, ext->exts, lysp_ext_instance_free);
}
/**
@@ -1360,7 +1362,7 @@ lyplg_ext_pfree_instance_substatements(const struct ly_ctx *ctx, struct lysp_ext
ly_bool node_free;
LY_ARRAY_FOR(substmts, u) {
- if (!substmts[u].storage) {
+ if (!substmts[u].storage_p) {
continue;
}
@@ -1383,75 +1385,75 @@ lyplg_ext_pfree_instance_substatements(const struct ly_ctx *ctx, struct lysp_ext
case LY_STMT_USES: {
struct lysp_node *child, *child_next;
- LY_LIST_FOR_SAFE(*VOIDPTR2_C(substmts[u].storage), child_next, child) {
+ LY_LIST_FOR_SAFE(*substmts[u].storage_p, child_next, child) {
node_free = (child->nodetype & (LYS_INPUT | LYS_OUTPUT)) ? 1 : 0;
lysp_node_free(&fctx, child);
if (node_free) {
free(child);
}
}
- *VOIDPTR2_C(substmts[u].storage) = NULL;
+ *substmts[u].storage_p = NULL;
break;
}
case LY_STMT_BASE:
/* multiple strings */
- FREE_ARRAY(ctx, **(const char ***)VOIDPTR2_C(substmts[u].storage), lydict_remove);
+ FREE_ARRAY(ctx, **(const char ***)substmts[u].storage_p, lydict_remove);
break;
case LY_STMT_BIT:
case LY_STMT_ENUM:
/* single enum */
- lysp_type_enum_free(&fctx, *VOIDPTR2_C(substmts[u].storage));
+ lysp_type_enum_free(&fctx, *substmts[u].storage_p);
break;
case LY_STMT_DEVIATE:
/* single deviate */
- lysp_deviate_free(&fctx, *VOIDPTR2_C(substmts[u].storage));
+ lysp_deviate_free(&fctx, *substmts[u].storage_p);
break;
case LY_STMT_DEVIATION:
/* single deviation */
- lysp_deviation_free(&fctx, *VOIDPTR2_C(substmts[u].storage));
+ lysp_deviation_free(&fctx, *substmts[u].storage_p);
break;
case LY_STMT_EXTENSION:
/* single extension */
- lysp_ext_free(&fctx, *VOIDPTR2_C(substmts[u].storage));
+ lysp_ext_free(&fctx, *substmts[u].storage_p);
break;
case LY_STMT_EXTENSION_INSTANCE:
/* multiple extension instances */
- FREE_ARRAY(&fctx, *(struct lysp_ext_instance **)VOIDPTR2_C(substmts[u].storage), lysp_ext_instance_free);
+ FREE_ARRAY(&fctx, *(struct lysp_ext_instance **)substmts[u].storage_p, lysp_ext_instance_free);
break;
case LY_STMT_FEATURE:
/* multiple features */
- FREE_ARRAY(&fctx, *(struct lysp_feature **)VOIDPTR2_C(substmts[u].storage), lysp_feature_free);
+ FREE_ARRAY(&fctx, *(struct lysp_feature **)substmts[u].storage_p, lysp_feature_free);
break;
case LY_STMT_IDENTITY:
/* multiple identities */
- FREE_ARRAY(&fctx, *(struct lysp_ident **)VOIDPTR2_C(substmts[u].storage), lysp_ident_free);
+ FREE_ARRAY(&fctx, *(struct lysp_ident **)substmts[u].storage_p, lysp_ident_free);
break;
case LY_STMT_IMPORT:
/* multiple imports */
- FREE_ARRAY(&fctx, *(struct lysp_import **)VOIDPTR2_C(substmts[u].storage), lysp_import_free);
+ FREE_ARRAY(&fctx, *(struct lysp_import **)substmts[u].storage_p, lysp_import_free);
break;
case LY_STMT_INCLUDE:
/* multiple includes */
- FREE_ARRAY(&fctx, *(struct lysp_include **)VOIDPTR2_C(substmts[u].storage), lysp_include_free);
+ FREE_ARRAY(&fctx, *(struct lysp_include **)substmts[u].storage_p, lysp_include_free);
break;
case LY_STMT_REFINE:
/* multiple refines */
- FREE_ARRAY(&fctx, *(struct lysp_refine **)VOIDPTR2_C(substmts[u].storage), lysp_refine_free);
+ FREE_ARRAY(&fctx, *(struct lysp_refine **)substmts[u].storage_p, lysp_refine_free);
break;
case LY_STMT_REVISION:
/* multiple revisions */
- FREE_ARRAY(&fctx, *(struct lysp_revision **)VOIDPTR2_C(substmts[u].storage), lysp_revision_free);
+ FREE_ARRAY(&fctx, *(struct lysp_revision **)substmts[u].storage_p, lysp_revision_free);
break;
case LY_STMT_CONFIG:
@@ -1485,7 +1487,7 @@ lyplg_ext_pfree_instance_substatements(const struct ly_ctx *ctx, struct lysp_ext
case LY_STMT_REVISION_DATE:
case LY_STMT_UNITS:
/* single string */
- lydict_remove(ctx, *VOIDPTR2_C(substmts[u].storage));
+ lydict_remove(ctx, *substmts[u].storage_p);
break;
case LY_STMT_LENGTH:
@@ -1493,34 +1495,34 @@ lyplg_ext_pfree_instance_substatements(const struct ly_ctx *ctx, struct lysp_ext
case LY_STMT_PATTERN:
case LY_STMT_RANGE:
/* multiple restrictions */
- FREE_ARRAY(&fctx, *(struct lysp_restr **)VOIDPTR2_C(substmts[u].storage), lysp_restr_free);
+ FREE_ARRAY(&fctx, *(struct lysp_restr **)substmts[u].storage_p, lysp_restr_free);
break;
case LY_STMT_WHEN:
/* multiple whens */
- FREE_ARRAY(&fctx, *(struct lysp_when **)VOIDPTR2_C(substmts[u].storage), lysp_when_free);
+ FREE_ARRAY(&fctx, *(struct lysp_when **)substmts[u].storage_p, lysp_when_free);
break;
case LY_STMT_PATH:
/* single expression */
- lyxp_expr_free(ctx, *VOIDPTR2_C(substmts[u].storage));
+ lyxp_expr_free(ctx, *substmts[u].storage_p);
break;
case LY_STMT_DEFAULT:
case LY_STMT_IF_FEATURE:
case LY_STMT_UNIQUE:
/* multiple qnames */
- FREE_ARRAY(ctx, *(struct lysp_qname **)VOIDPTR2_C(substmts[u].storage), lysp_qname_free);
+ FREE_ARRAY(ctx, *(struct lysp_qname **)substmts[u].storage_p, lysp_qname_free);
break;
case LY_STMT_TYPEDEF:
/* multiple typedefs */
- FREE_ARRAY(&fctx, *(struct lysp_tpdf **)VOIDPTR2_C(substmts[u].storage), lysp_tpdf_free);
+ FREE_ARRAY(&fctx, *(struct lysp_tpdf **)substmts[u].storage_p, lysp_tpdf_free);
break;
case LY_STMT_TYPE: {
/* single type */
- struct lysp_type **type_p = VOIDPTR_C(substmts[u].storage);
+ struct lysp_type **type_p = (struct lysp_type **)substmts[u].storage_p;
lysp_type_free(&fctx, *type_p);
free(*type_p);
@@ -1529,7 +1531,7 @@ lyplg_ext_pfree_instance_substatements(const struct ly_ctx *ctx, struct lysp_ext
case LY_STMT_MODULE:
case LY_STMT_SUBMODULE:
/* single (sub)module */
- lysp_module_free(&fctx, *VOIDPTR2_C(substmts[u].storage));
+ lysp_module_free(&fctx, *substmts[u].storage_p);
break;
default:
@@ -1548,7 +1550,7 @@ lyplg_ext_cfree_instance_substatements(const struct ly_ctx *ctx, struct lysc_ext
ly_bool node_free;
LY_ARRAY_FOR(substmts, u) {
- if (!substmts[u].storage) {
+ if (!substmts[u].storage_p) {
continue;
}
@@ -1568,14 +1570,14 @@ lyplg_ext_cfree_instance_substatements(const struct ly_ctx *ctx, struct lysc_ext
case LY_STMT_LIST: {
struct lysc_node *child, *child_next;
- LY_LIST_FOR_SAFE(*VOIDPTR2_C(substmts[u].storage), child_next, child) {
+ LY_LIST_FOR_SAFE(*substmts[u].storage_p, child_next, child) {
node_free = (child->nodetype & (LYS_INPUT | LYS_OUTPUT)) ? 1 : 0;
lysc_node_free_(&fctx, child);
if (node_free) {
free(child);
}
}
- *VOIDPTR2_C(substmts[u].storage) = NULL;
+ *substmts[u].storage_p = NULL;
break;
}
case LY_STMT_USES:
@@ -1605,7 +1607,7 @@ lyplg_ext_cfree_instance_substatements(const struct ly_ctx *ctx, struct lysc_ext
case LY_STMT_REFERENCE:
case LY_STMT_UNITS: {
/* single item */
- const char *str = *VOIDPTR2_C(substmts[u].storage);
+ const char *str = *substmts[u].storage_p;
lydict_remove(ctx, str);
break;
@@ -1613,7 +1615,7 @@ lyplg_ext_cfree_instance_substatements(const struct ly_ctx *ctx, struct lysc_ext
case LY_STMT_BIT:
case LY_STMT_ENUM: {
/* sized array */
- struct lysc_type_bitenum_item *items = *VOIDPTR2_C(substmts[u].storage);
+ struct lysc_type_bitenum_item *items = *substmts[u].storage_p;
FREE_ARRAY(&fctx, items, lysc_enum_item_free);
break;
@@ -1621,47 +1623,47 @@ lyplg_ext_cfree_instance_substatements(const struct ly_ctx *ctx, struct lysc_ext
case LY_STMT_LENGTH:
case LY_STMT_RANGE: {
/* single item */
- struct lysc_range *range = *VOIDPTR2_C(substmts[u].storage);
+ struct lysc_range *range = *substmts[u].storage_p;
lysc_range_free(&fctx, range);
break;
}
case LY_STMT_MUST: {
/* sized array */
- struct lysc_must *musts = *VOIDPTR2_C(substmts[u].storage);
+ struct lysc_must *musts = *substmts[u].storage_p;
FREE_ARRAY(&fctx, musts, lysc_must_free);
break;
}
case LY_STMT_WHEN:
/* single item, expects a pointer */
- lysc_when_free(&fctx, VOIDPTR_C(substmts[u].storage));
+ lysc_when_free(&fctx, (struct lysc_when **)substmts[u].storage_p);
break;
case LY_STMT_PATTERN: {
/* sized array of pointers */
- struct lysc_pattern **patterns = *VOIDPTR2_C(substmts[u].storage);
+ struct lysc_pattern **patterns = *substmts[u].storage_p;
FREE_ARRAY(&fctx, patterns, lysc_pattern_free);
break;
}
case LY_STMT_TYPE: {
/* single item */
- struct lysc_type *type = *VOIDPTR2_C(substmts[u].storage);
+ struct lysc_type *type = *substmts[u].storage_p;
lysc_type_free(&fctx, type);
break;
}
case LY_STMT_IDENTITY: {
/* sized array */
- struct lysc_ident *idents = *VOIDPTR2_C(substmts[u].storage);
+ struct lysc_ident *idents = *substmts[u].storage_p;
FREE_ARRAY(&fctx, idents, lysc_ident_free);
break;
}
case LY_STMT_EXTENSION_INSTANCE: {
/* sized array */
- struct lysc_ext_instance *exts = *VOIDPTR2_C(substmts[u].storage);
+ struct lysc_ext_instance *exts = *substmts[u].storage_p;
FREE_ARRAY(&fctx, exts, lysc_ext_instance_free);
break;
diff --git a/src/tree_schema_internal.h b/src/tree_schema_internal.h
index d3e399c..ee40f58 100644
--- a/src/tree_schema_internal.h
+++ b/src/tree_schema_internal.h
@@ -726,11 +726,11 @@ uint8_t lys_stmt_flags(enum ly_stmt stmt);
* @param[in] ext Compiled ext instance.
* @param[in] stmt Compiled statement. Can be a mask when the first match is returned, it is expected the storage is
* the same for all the masked statements.
- * @param[out] storage_p Pointer to a compiled ext instance substatement storage, NULL if was not compiled.
+ * @param[out] storage_pp Pointer to a compiled ext instance substatement storage, NULL if was not compiled.
* @return LY_SUCCESS on success.
* @return LY_ENOT if the substatement is not supported.
*/
-LY_ERR lyplg_ext_get_storage_p(const struct lysc_ext_instance *ext, int stmt, uint64_t *storage_p);
+LY_ERR lyplg_ext_get_storage_p(const struct lysc_ext_instance *ext, int stmt, void ***storage_pp);
/**
* @brief Warning if the filename does not match the expected module name and version
diff --git a/src/validation.c b/src/validation.c
index 501dd69..a950c54 100644
--- a/src/validation.c
+++ b/src/validation.c
@@ -197,13 +197,14 @@ lyd_validate_node_when(const struct lyd_node *tree, const struct lyd_node *node,
* @param[in] np_cont_diff Whether to put NP container into diff or only its children.
* @param[in,out] node Optional current iteration node, update it if it is deleted.
* @param[in,out] node_when Optional set with nodes with "when" conditions, may be removed from.
+ * @param[in,out] node_types Optional set with unresolved type nodes, may be removed from.
* @param[in,out] diff Validation diff.
* @return 1 if @p node auto-deleted and updated to its next sibling.
* @return 0 if @p node was not auto-deleted.
*/
static ly_bool
lyd_validate_autodel_node_del(struct lyd_node **first, struct lyd_node *del, const struct lys_module *mod,
- int np_cont_diff, struct lyd_node **node, struct ly_set *node_types, struct lyd_node **diff)
+ int np_cont_diff, struct lyd_node **node, struct ly_set *node_when, struct ly_set *node_types, struct lyd_node **diff)
{
struct lyd_node *iter;
ly_bool node_autodel = 0;
@@ -228,6 +229,16 @@ lyd_validate_autodel_node_del(struct lyd_node **first, struct lyd_node *del, con
}
}
+ if (node_when && node_when->count) {
+ /* remove nested from node_when set */
+ LYD_TREE_DFS_BEGIN(del, iter) {
+ if ((del != iter) && ly_set_contains(node_when, iter, &idx)) {
+ ly_set_rm_index(node_when, idx, NULL);
+ }
+ LYD_TREE_DFS_END(del, iter);
+ }
+ }
+
if (node_types && node_types->count) {
/* remove from node_types set */
LYD_TREE_DFS_BEGIN(del, iter) {
@@ -264,7 +275,7 @@ lyd_validate_unres_when(struct lyd_node **tree, const struct lys_module *mod, st
uint32_t xpath_options, struct ly_set *node_types, struct lyd_node **diff)
{
LY_ERR rc = LY_SUCCESS, r;
- uint32_t i;
+ uint32_t i, count;
const struct lysc_when *disabled;
struct lyd_node *node = NULL;
@@ -285,7 +296,12 @@ lyd_validate_unres_when(struct lyd_node **tree, const struct lys_module *mod, st
/* when false */
if (node->flags & LYD_WHEN_TRUE) {
/* autodelete */
- lyd_validate_autodel_node_del(tree, node, mod, 1, NULL, node_types, diff);
+ count = node_when->count;
+ lyd_validate_autodel_node_del(tree, node, mod, 1, NULL, node_when, node_types, diff);
+ if (count > node_when->count) {
+ /* nested nodes removed, we lost the index */
+ ly_set_contains(node_when, node, &i);
+ }
} else if (val_opts & LYD_VALIDATE_OPERATIONAL) {
/* only a warning */
LOGWRN(LYD_CTX(node), "When condition \"%s\" not satisfied.", disabled->cond->expr);
@@ -640,7 +656,7 @@ lyd_validate_autodel_leaflist_dflt(struct lyd_node **first, struct lyd_node **no
LYD_LIST_FOR_INST_SAFE(*first, schema, next, iter) {
if (iter->flags & LYD_DEFAULT) {
/* default instance found, remove it */
- if (lyd_validate_autodel_node_del(first, iter, mod, 0, node, NULL, diff)) {
+ if (lyd_validate_autodel_node_del(first, iter, mod, 0, node, NULL, NULL, diff)) {
node_autodel = 1;
}
}
@@ -685,7 +701,7 @@ lyd_validate_autodel_cont_leaf_dflt(struct lyd_node **first, struct lyd_node **n
LYD_LIST_FOR_INST_SAFE(*first, schema, next, iter) {
if (iter->flags & LYD_DEFAULT) {
/* default instance, remove it */
- if (lyd_validate_autodel_node_del(first, iter, mod, 0, node, NULL, diff)) {
+ if (lyd_validate_autodel_node_del(first, iter, mod, 0, node, NULL, NULL, diff)) {
node_autodel = 1;
}
}
@@ -695,7 +711,7 @@ lyd_validate_autodel_cont_leaf_dflt(struct lyd_node **first, struct lyd_node **n
LYD_LIST_FOR_INST(*first, schema, iter) {
if ((iter->flags & LYD_DEFAULT) && !(iter->flags & LYD_NEW)) {
/* old default instance, remove it */
- if (lyd_validate_autodel_node_del(first, iter, mod, 0, node, NULL, diff)) {
+ if (lyd_validate_autodel_node_del(first, iter, mod, 0, node, NULL, NULL, diff)) {
node_autodel = 1;
}
break;
@@ -753,7 +769,7 @@ lyd_validate_autodel_case_dflt(struct lyd_node **first, struct lyd_node **node,
if (!iter) {
/* there are only default nodes of the case meaning it does not exist and neither should any default nodes
* of the case, remove this one default node */
- if (lyd_validate_autodel_node_del(first, *node, mod, 0, node, NULL, diff)) {
+ if (lyd_validate_autodel_node_del(first, *node, mod, 0, node, NULL, NULL, diff)) {
node_autodel = 1;
}
}
diff --git a/src/version.h.in b/src/version.h.in
index 1ed86c1..021cd05 100644
--- a/src/version.h.in
+++ b/src/version.h.in
@@ -16,6 +16,8 @@
#ifndef LY_VERSION_H_
#define LY_VERSION_H_
+#include "ly_config.h"
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -30,22 +32,61 @@ extern "C" {
#define LY_PROJ_VERSION_MICRO @LIBYANG_MICRO_VERSION@ /**< project micro version number */
#define LY_PROJ_VERSION "@LIBYANG_VERSION@" /**< project version string */
-struct ly_version {
- uint32_t major; /**< Major version number */
- uint32_t minor; /**< Minor version number */
- uint32_t micro; /**< Micro version number */
- const char *str; /**< Version string */
-};
+/**
+ * @brief Get libyang major SO version.
+ *
+ * @return LY version.
+ */
+LIBYANG_API_DECL uint32_t ly_version_so_major(void);
+
+/**
+ * @brief Get libyang minor SO version.
+ *
+ * @return LY version.
+ */
+LIBYANG_API_DECL uint32_t ly_version_so_minor(void);
+
+/**
+ * @brief Get libyang micro SO version.
+ *
+ * @return LY version.
+ */
+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 libyang SO version.
+ * @brief Get libyang major project version.
+ *
+ * @return LY version.
*/
-LIBYANG_API_DECL extern struct ly_version ly_version_so;
+LIBYANG_API_DECL uint32_t ly_version_proj_major(void);
/**
- * @brief libyang project version.
+ * @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 extern struct ly_version ly_version_proj;
+LIBYANG_API_DECL const char *ly_version_proj_str(void);
#ifdef __cplusplus
}
diff --git a/src/xpath.c b/src/xpath.c
index 8e9bf02..2251eab 100644
--- a/src/xpath.c
+++ b/src/xpath.c
@@ -330,7 +330,7 @@ print_set_debug(struct lyxp_set *set)
(lyd_child(item->node)->schema->nodetype == LYS_LEAF)) {
LOGDBG(LY_LDGXPATH, "\t%d (pos %u): ELEM %s (1st child val: %s)", i + 1, item->pos,
item->node->schema->name, lyd_get_value(lyd_child(item->node)));
- } else if ((!item->node->schema && !lyd_child(item->node)) || (item->node->schema->nodetype == LYS_LEAFLIST)) {
+ } else if (lyd_get_value(item->node)) {
LOGDBG(LY_LDGXPATH, "\t%d (pos %u): ELEM %s (val: %s)", i + 1, item->pos,
LYD_NAME(item->node), lyd_get_value(item->node));
} else {
@@ -4042,7 +4042,7 @@ xpath_deref(struct lyxp_set **args, uint32_t UNUSED(arg_count), struct lyxp_set
if (!r) {
/* get the target node */
target = p[LY_ARRAY_COUNT(p) - 1].node;
- ly_path_free(set->ctx, p);
+ ly_path_free(p);
LY_CHECK_RET(lyxp_set_scnode_insert_node(set, target, LYXP_NODE_ELEM, LYXP_AXIS_SELF, NULL));
} /* else the target was found before but is disabled so it was removed */
@@ -8272,7 +8272,9 @@ cleanup:
options &= ~LYXP_SKIP_EXPR;
}
lydict_remove(set->ctx, ncname_dict);
- ly_path_predicates_free(set->ctx, predicates);
+ if (predicates) {
+ ly_path_predicates_free(scnode->module->ctx, predicates);
+ }
return rc;
}
diff --git a/tests/modules/yang/notifications@2008-07-14.yang b/tests/modules/yang/notifications@2008-07-14.yang
index b696f39..8a723b2 100644
--- a/tests/modules/yang/notifications@2008-07-14.yang
+++ b/tests/modules/yang/notifications@2008-07-14.yang
@@ -80,7 +80,7 @@ module notifications {
}
}
- /*container notification {
+ container notification {
description "internal struct to start a notification";
config false;
@@ -90,6 +90,6 @@ module notifications {
}
// eventType and any data content goes here
- }*/
+ }
}
diff --git a/tests/perf/perf.c b/tests/perf/perf.c
index da1eb93..37591cb 100644
--- a/tests/perf/perf.c
+++ b/tests/perf/perf.c
@@ -580,6 +580,9 @@ test_dup_siblings_to_empty(struct test_state *state, struct timespec *ts_start,
TEST_END(ts_end);
+ /* need to remove the duplicated nodes if the test is repeated */
+ lyd_free_siblings(lyd_child(state->data1));
+
return LY_SUCCESS;
}
diff --git a/tests/utests/basic/test_context.c b/tests/utests/basic/test_context.c
index 7feb65f..476fd81 100644
--- a/tests/utests/basic/test_context.c
+++ b/tests/utests/basic/test_context.c
@@ -831,8 +831,8 @@ check_ext_instance_priv_parsed_is_set(struct lysc_ext_instance *ext)
LY_ARRAY_FOR(ext, u) {
substmts = ext[u].substmts;
LY_ARRAY_FOR(substmts, v) {
- if (substmts && substmts[v].storage && (substmts[v].stmt & LY_STMT_DATA_NODE_MASK)) {
- cnode = *(struct lysc_node **)substmts[v].storage;
+ if (substmts && substmts[v].storage_p && (substmts[v].stmt & LY_STMT_DATA_NODE_MASK)) {
+ cnode = *(struct lysc_node **)substmts[v].storage_p;
iter = check;
assert_int_equal(LY_SUCCESS, lysc_tree_dfs_full(cnode, check_node_priv_parsed_is_set, &iter));
}
@@ -850,8 +850,8 @@ check_ext_instance_priv_parsed_not_set(struct lysc_ext_instance *ext)
LY_ARRAY_FOR(ext, u) {
substmts = ext[u].substmts;
LY_ARRAY_FOR(substmts, v) {
- if (substmts && substmts[v].storage && (substmts[v].stmt & LY_STMT_DATA_NODE_MASK)) {
- cnode = *(struct lysc_node **)substmts[v].storage;
+ if (substmts && substmts[v].storage_p && (substmts[v].stmt & LY_STMT_DATA_NODE_MASK)) {
+ cnode = *(struct lysc_node **)substmts[v].storage_p;
if (cnode) {
CHECK_POINTER((struct lysp_node *)cnode->priv, 0);
}
diff --git a/tests/utests/data/test_parser_xml.c b/tests/utests/data/test_parser_xml.c
index d5336c0..d7203fa 100644
--- a/tests/utests/data/test_parser_xml.c
+++ b/tests/utests/data/test_parser_xml.c
@@ -193,6 +193,18 @@ test_anyxml(void **state)
free(str);
CHECK_LYD_STRING(tree, LYD_PRINT_WITHSIBLINGS, data_expected);
lyd_free_all(tree);
+
+ data = "<anyx xmlns=\"urn:tests:a\"><x>1</x><x>0</x><x>-1</x><x>4294967295</x><x>4294967296</x><x>-2147483648</x><x>-2147483649</x></anyx>";
+ CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
+ assert_non_null(tree);
+ tree = tree->next;
+ assert_int_equal(LY_SUCCESS, lyd_print_mem(&str, tree, LYD_XML, LYD_PRINT_SHRINK));
+ CHECK_STRING(str, data);
+ free(str);
+ assert_int_equal(LY_SUCCESS, lyd_print_mem(&str, tree, LYD_JSON, LYD_PRINT_SHRINK));
+ CHECK_STRING(str, "{\"a:anyx\":{\"x\":[1,0,-1,4294967295,\"4294967296\",-2147483648,\"-2147483649\"]}}");
+ free(str);
+ lyd_free_all(tree);
}
static void
@@ -349,7 +361,7 @@ test_opaq(void **state)
" <c xmld:id=\"D\">1</c>\n"
"</a>\n",
LYD_XML, LYD_PARSE_OPAQ, LYD_VALIDATE_PRESENT, &tree));
- CHECK_LOG_CTX("Unknown XML prefix \"xmld\".", "/a", 3);
+ CHECK_LOG_CTX("Unknown XML prefix \"xmld\" at attribute \"id\".", "/a", 3);
}
static void
diff --git a/tests/utests/data/test_tree_data.c b/tests/utests/data/test_tree_data.c
index fabd170..b3dde5a 100644
--- a/tests/utests/data/test_tree_data.c
+++ b/tests/utests/data/test_tree_data.c
@@ -409,7 +409,7 @@ test_target(void **state)
assert_string_equal(lyd_get_value(term->prev), "b");
lyd_free_all(tree);
- ly_path_free(UTEST_LYCTX, path);
+ ly_path_free(path);
lyxp_expr_free(UTEST_LYCTX, exp);
}
diff --git a/tests/utests/data/test_tree_data_sorted.c b/tests/utests/data/test_tree_data_sorted.c
index 0e812e7..bb6e4d6 100644
--- a/tests/utests/data/test_tree_data_sorted.c
+++ b/tests/utests/data/test_tree_data_sorted.c
@@ -131,6 +131,57 @@ test_insert_cont_leaflist(void **state)
}
static void
+test_dup_sort(void **state)
+{
+ const char *schema;
+ struct lys_module *mod;
+ struct lyd_node *cont, *cont2;
+ char *str;
+
+ schema = "module a {namespace urn:tests:a;prefix a;yang-version 1.1;revision 2014-05-08;"
+ "container cn { list lst {key \"k\"; leaf k {type uint32;}}}}";
+ UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod);
+
+ assert_int_equal(lyd_new_inner(NULL, mod, "cn", 0, &cont), LY_SUCCESS);
+ assert_int_equal(lyd_new_list(cont, NULL, "lst", 0, NULL, "2"), LY_SUCCESS);
+ assert_int_equal(lyd_new_list(cont, NULL, "lst", 0, NULL, "5"), LY_SUCCESS);
+ assert_int_equal(lyd_new_list(cont, NULL, "lst", 0, NULL, "9"), LY_SUCCESS);
+
+ assert_int_equal(lyd_new_inner(NULL, mod, "cn", 0, &cont2), LY_SUCCESS);
+ assert_int_equal(lyd_new_list(cont2, NULL, "lst", 0, NULL, "1"), LY_SUCCESS);
+ assert_int_equal(lyd_new_list(cont2, NULL, "lst", 0, NULL, "3"), LY_SUCCESS);
+ assert_int_equal(lyd_new_list(cont2, NULL, "lst", 0, NULL, "8"), LY_SUCCESS);
+
+ assert_int_equal(lyd_dup_siblings(lyd_child(cont2), (struct lyd_node_inner *)cont, 0, NULL), LY_SUCCESS);
+ lyd_print_mem(&str, cont, LYD_XML, 0);
+ assert_string_equal(str,
+ "<cn xmlns=\"urn:tests:a\">\n"
+ " <lst>\n"
+ " <k>1</k>\n"
+ " </lst>\n"
+ " <lst>\n"
+ " <k>2</k>\n"
+ " </lst>\n"
+ " <lst>\n"
+ " <k>3</k>\n"
+ " </lst>\n"
+ " <lst>\n"
+ " <k>5</k>\n"
+ " </lst>\n"
+ " <lst>\n"
+ " <k>8</k>\n"
+ " </lst>\n"
+ " <lst>\n"
+ " <k>9</k>\n"
+ " </lst>\n"
+ "</cn>\n");
+ free(str);
+
+ lyd_free_all(cont);
+ lyd_free_all(cont2);
+}
+
+static void
test_try_user_order_func(void **state)
{
const char *schema;
@@ -1599,6 +1650,7 @@ main(void)
UTEST(test_insert_top_level_leaflist),
UTEST(test_insert_cont_list),
UTEST(test_insert_cont_leaflist),
+ UTEST(test_dup_sort),
UTEST(test_try_user_order_func),
UTEST(test_ordered_by_user),
UTEST(test_remove),
diff --git a/tests/utests/schema/test_schema.c b/tests/utests/schema/test_schema.c
index 953aad8..cba2b2d 100644
--- a/tests/utests/schema/test_schema.c
+++ b/tests/utests/schema/test_schema.c
@@ -1712,7 +1712,7 @@ test_extension_compile(void **state)
LY_ARRAY_NEW_GOTO(UTEST_LYCTX, ext_p.substmts, substmtp, rc, cleanup);
substmtp->stmt = LY_STMT_ERROR_MESSAGE;
- substmtp->storage = (uintptr_t)(void *)&ext_p.parsed;
+ substmtp->storage_p = &ext_p.parsed;
/* fake parse */
lydict_insert(UTEST_LYCTX, "my error", 0, (const char **)&ext_p.parsed);
@@ -1721,7 +1721,7 @@ test_extension_compile(void **state)
LY_ARRAY_NEW_GOTO(UTEST_LYCTX, ext_c.substmts, substmt, rc, cleanup);
substmt->stmt = LY_STMT_ERROR_MESSAGE;
- substmt->storage = (uintptr_t)(void *)&ext_c.compiled;
+ substmt->storage_p = &ext_c.compiled;
/*
* error-message
diff --git a/tests/utests/schema/test_tree_schema_compile.c b/tests/utests/schema/test_tree_schema_compile.c
index 3d4fbf7..04c30db 100644
--- a/tests/utests/schema/test_tree_schema_compile.c
+++ b/tests/utests/schema/test_tree_schema_compile.c
@@ -1233,6 +1233,7 @@ test_type_instanceid(void **state)
{
struct lys_module *mod;
struct lysc_type *type;
+ char *str;
assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, "module a {namespace urn:a;prefix a;typedef mytype {type instance-identifier {require-instance false;}}"
"leaf l1 {type instance-identifier {require-instance true;}}"
@@ -1252,12 +1253,22 @@ test_type_instanceid(void **state)
assert_int_equal(LY_TYPE_INST, type->basetype);
assert_int_equal(1, ((struct lysc_type_instanceid *)type)->require_instance);
+ /* default value */
+ str = "module b1 {namespace urn:b1;prefix b1;"
+ "leaf l1 {type string;}}";
+ ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, str);
+ ly_ctx_set_options(UTEST_LYCTX, LY_CTX_REF_IMPLEMENTED);
+ assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, "module b2 {namespace urn:b2;prefix b2;"
+ "import b1 {prefix b1;}"
+ "leaf l1 {type instance-identifier; default \"/b1:l1\";}}", LYS_IN_YANG, NULL));
+ ly_ctx_set_options(UTEST_LYCTX, 0);
+
/* invalid cases */
- assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module aa {namespace urn:aa;prefix aa; leaf l {type instance-identifier {require-instance yes;}}}", LYS_IN_YANG, &mod));
+ assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module aa {namespace urn:aa;prefix aa; leaf l {type instance-identifier {require-instance yes;}}}", LYS_IN_YANG, NULL));
CHECK_LOG_CTX("Parsing module \"aa\" failed.", NULL, 0);
CHECK_LOG_CTX("Invalid value \"yes\" of \"require-instance\".", NULL, 1);
- assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module aa {namespace urn:aa;prefix aa; leaf l {type instance-identifier {fraction-digits 1;}}}", LYS_IN_YANG, &mod));
+ assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module aa {namespace urn:aa;prefix aa; leaf l {type instance-identifier {fraction-digits 1;}}}", LYS_IN_YANG, NULL));
CHECK_LOG_CTX("Invalid type restrictions for instance-identifier type.", "/aa:l", 0);
}
diff --git a/tests/utests/schema/test_yang.c b/tests/utests/schema/test_yang.c
index 67f9747..034f95d 100644
--- a/tests/utests/schema/test_yang.c
+++ b/tests/utests/schema/test_yang.c
@@ -284,8 +284,6 @@ test_arg(void **state)
TEST_GET_ARGUMENT_SUCCESS("hello ", YCTX, Y_STR_ARG, "hello ", 5, " ", 1);
- TEST_GET_ARGUMENT_SUCCESS("hello/*comment*/\n", YCTX, Y_STR_ARG, "hello/*comment*/\n", 5, "\n", 1);
-
TEST_GET_ARGUMENT_SUCCESS("\"hello\\n\\t\\\"\\\\\";", YCTX, Y_STR_ARG, "hello\n\t\"\\", 9, ";", 1);
free(buf);
diff --git a/tests/utests/types/yang_types.c b/tests/utests/types/yang_types.c
index f79238e..07c5e16 100644
--- a/tests/utests/types/yang_types.c
+++ b/tests/utests/types/yang_types.c
@@ -112,14 +112,13 @@ test_data_xml(void **state)
TEST_SUCCESS_XML("a", "l", "2021-02-29T00:00:00-00:00", STRING, "2021-03-01T00:00:00-00:00");
TEST_ERROR_XML("a", "l", "2005-05-31T23:15:15.-08:00", LY_EVALID);
- CHECK_LOG_CTX("Unsatisfied pattern - \"2005-05-31T23:15:15.-08:00\" does not conform to "
- "\"\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d+)?(Z|[\\+\\-]\\d{2}:\\d{2})\".",
+ CHECK_LOG_CTX("Missing date-and-time fractions after '.'.",
"/a:l", 1);
- TEST_ERROR_XML("a", "l", "2023-16-15T20:13:01+01:00", LY_EINVAL);
+ TEST_ERROR_XML("a", "l", "2023-16-15T20:13:01+01:00", LY_EVALID);
CHECK_LOG_CTX("Invalid date-and-time month \"15\".", "/a:l", 1);
- TEST_ERROR_XML("a", "l", "2023-10-15T20:13:01+95:00", LY_EINVAL);
+ TEST_ERROR_XML("a", "l", "2023-10-15T20:13:01+95:00", LY_EVALID);
CHECK_LOG_CTX("Invalid date-and-time timezone hour \"95\".", "/a:l", 1);
/* hex-string */
diff --git a/tests/yanglint/interactive/debug.test b/tests/yanglint/interactive/debug.test
deleted file mode 100644
index 8a64c92..0000000
--- a/tests/yanglint/interactive/debug.test
+++ /dev/null
@@ -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
diff --git a/tests/yanglint/interactive/ly.tcl b/tests/yanglint/interactive/ly.tcl
index 4c56be4..efa57f2 100644
--- a/tests/yanglint/interactive/ly.tcl
+++ b/tests/yanglint/interactive/ly.tcl
@@ -65,17 +65,3 @@ proc ly_exit {} {
send "exit\r"
expect eof
}
-
-# Check if yanglint is configured as DEBUG.
-# Return 1 on success.
-proc yanglint_debug {} {
- global TUT
- # Call non-interactive yanglint with --help.
- set output [exec -- $TUT "-h"]
- # Find option --debug.
- if { [regexp -- "--debug=GROUPS" $output] } {
- return 1
- } else {
- return 0
- }
-}
diff --git a/tools/lint/completion.c b/tools/lint/completion.c
index 59207ca..3c7503e 100644
--- a/tools/lint/completion.c
+++ b/tools/lint/completion.c
@@ -224,7 +224,7 @@ get_schema_completion(const char *hint, char ***matches, unsigned int *match_cou
uint32_t idx;
const char *start;
char *end, *module_name = NULL, *path = NULL;
- const struct lysc_node *parent, *last_node;
+ const struct lysc_node *parent, *last_node = NULL;
int rc = 0;
size_t len;