diff --git a/CMakeLists.txt b/CMakeLists.txt index e8f774d46..2d2d8bd66 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -60,7 +60,7 @@ set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) # set version of the project set(LIBYANG_MAJOR_VERSION 3) set(LIBYANG_MINOR_VERSION 13) -set(LIBYANG_MICRO_VERSION 2) +set(LIBYANG_MICRO_VERSION 3) set(LIBYANG_VERSION ${LIBYANG_MAJOR_VERSION}.${LIBYANG_MINOR_VERSION}.${LIBYANG_MICRO_VERSION}) # set version of the library @@ -75,7 +75,7 @@ if(WIN32) set(C_STANDARD_REQUIRED ON) set(CMAKE_C_FLAGS "/Zc:preprocessor /W3 /wd4711 /w14013 /utf-8 ${CMAKE_C_FLAGS}") else() - # global C flags + # global C flags (POSIX source because of pthread_rwlock_t) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wpedantic -std=c11") endif() @@ -149,6 +149,7 @@ set(libsrc src/printer_yang.c src/printer_yin.c src/printer_tree.c + src/printer_context.c src/plugins.c src/plugins_types.c src/plugins_exts.c diff --git a/CMakeModules/GenCoverage.cmake b/CMakeModules/GenCoverage.cmake index fe26d9e42..a57690950 100644 --- a/CMakeModules/GenCoverage.cmake +++ b/CMakeModules/GenCoverage.cmake @@ -41,14 +41,12 @@ macro(GEN_COVERAGE_ENABLE ENABLE_TESTS) endif() execute_process( - COMMAND bash "-c" "${CMAKE_C_COMPILER} --version | head -n1 | sed \"s/.* (.*) \\([0-9]\\+.[0-9]\\+.[0-9]\\+ .*\\)/\\1/\"" + COMMAND bash "-c" "${CMAKE_C_COMPILER} --version | head -n1 | cut -d' ' -f4" OUTPUT_VARIABLE GCC_VERSION_FULL - OUTPUT_STRIP_TRAILING_WHITESPACE ) execute_process( - COMMAND bash "-c" "${PATH_GCOV} --version | head -n1 | sed \"s/.* (.*) \\([0-9]\\+.[0-9]\\+.[0-9]\\+ .*\\)/\\1/\"" + COMMAND bash "-c" "${PATH_GCOV} --version | head -n1 | cut -d' ' -f4" OUTPUT_VARIABLE GCOV_VERSION_FULL - OUTPUT_STRIP_TRAILING_WHITESPACE ) if(NOT GCC_VERSION_FULL STREQUAL GCOV_VERSION_FULL) message(WARNING "gcc and gcov versions do not match! Generating coverage may fail with errors.") diff --git a/compat/compat.c b/compat/compat.c index ea8a61840..30343a535 100644 --- a/compat/compat.c +++ b/compat/compat.c @@ -11,7 +11,9 @@ * * https://opensource.org/licenses/BSD-3-Clause */ -#define _POSIX_C_SOURCE 200809L /* fdopen, _POSIX_PATH_MAX, strdup */ +#ifndef _POSIX_C_SOURCE +# define _POSIX_C_SOURCE 200809L /* fdopen, _POSIX_PATH_MAX, strdup */ +#endif #define _ISOC99_SOURCE /* vsnprintf */ #include "compat.h" diff --git a/src/context.c b/src/context.c index 68a8ff21e..d53f0eb93 100644 --- a/src/context.c +++ b/src/context.c @@ -36,6 +36,7 @@ #include "hash_table.h" #include "in.h" #include "ly_common.h" +#include "lyb.h" #include "parser_data.h" #include "plugins_internal.h" #include "plugins_types.h" @@ -88,7 +89,7 @@ ly_ctx_set_searchdir(struct ly_ctx *ctx, const char *search_dir) LY_ARRAY_COUNT_TYPE u; struct lys_module *mod; - LY_CHECK_ARG_RET(ctx, ctx, LY_EINVAL); + LY_CHECK_ARG_RET(ctx, ctx, !(ctx->opts & LY_CTX_INT_IMMUTABLE), LY_EINVAL); if (!search_dir) { /* fine, ignore */ @@ -134,8 +135,8 @@ ly_ctx_set_searchdir(struct ly_ctx *ctx, const char *search_dir) } /* new searchdir - reset latests flags (possibly new revisions available) */ - for (i = 0; i < ctx->list.count; ++i) { - mod = ctx->list.objs[i]; + for (i = 0; i < ctx->modules.count; ++i) { + mod = ctx->modules.objs[i]; mod->latest_revision &= ~LYS_MOD_LATEST_SEARCHDIRS; if (mod->parsed && mod->parsed->includes) { @@ -177,7 +178,7 @@ ly_ctx_get_searchdirs(const struct ly_ctx *ctx) LIBYANG_API_DEF LY_ERR ly_ctx_unset_searchdir(struct ly_ctx *ctx, const char *value) { - LY_CHECK_ARG_RET(ctx, ctx, LY_EINVAL); + LY_CHECK_ARG_RET(ctx, ctx, !(ctx->opts & LY_CTX_INT_IMMUTABLE), LY_EINVAL); if (!ctx->search_paths.count) { return LY_SUCCESS; @@ -210,7 +211,7 @@ ly_ctx_unset_searchdir(struct ly_ctx *ctx, const char *value) LIBYANG_API_DEF LY_ERR ly_ctx_unset_searchdir_last(struct ly_ctx *ctx, uint32_t count) { - LY_CHECK_ARG_RET(ctx, ctx, LY_EINVAL); + LY_CHECK_ARG_RET(ctx, ctx, !(ctx->opts & LY_CTX_INT_IMMUTABLE), LY_EINVAL); for ( ; count > 0 && ctx->search_paths.count; --count) { LY_CHECK_RET(ly_set_rm_index(&ctx->search_paths, ctx->search_paths.count - 1, free)) @@ -225,7 +226,7 @@ ly_ctx_load_module(struct ly_ctx *ctx, const char *name, const char *revision, c struct lys_module *mod = NULL; LY_ERR ret = LY_SUCCESS; - LY_CHECK_ARG_RET(ctx, ctx, name, NULL); + LY_CHECK_ARG_RET(ctx, ctx, !(ctx->opts & LY_CTX_INT_IMMUTABLE), name, NULL); /* load and parse */ ret = lys_parse_load(ctx, name, revision, &ctx->unres.creating, &mod); @@ -235,7 +236,7 @@ ly_ctx_load_module(struct ly_ctx *ctx, const char *name, const char *revision, c ret = _lys_set_implemented(mod, features, &ctx->unres); LY_CHECK_GOTO(ret, cleanup); - if (!(ctx->flags & LY_CTX_EXPLICIT_COMPILE)) { + if (!(ctx->opts & LY_CTX_EXPLICIT_COMPILE)) { /* create dep set for the module and mark all the modules that will be (re)compiled */ LY_CHECK_GOTO(ret = lys_unres_dep_sets_create(ctx, &ctx->unres.dep_sets, mod), cleanup); @@ -244,10 +245,10 @@ ly_ctx_load_module(struct ly_ctx *ctx, const char *name, const char *revision, c /* unres resolved */ lys_unres_glob_erase(&ctx->unres); - } - /* new context state */ - ly_ctx_new_change(ctx); + /* new context state */ + ly_ctx_new_change(ctx); + } cleanup: if (ret) { @@ -258,44 +259,8 @@ ly_ctx_load_module(struct ly_ctx *ctx, const char *name, const char *revision, c return mod; } -/** - * @brief Hash table value-equal callback for comparing context error hash table record. - */ -static ly_bool -ly_ctx_ht_err_equal_cb(void *val1_p, void *val2_p, ly_bool UNUSED(mod), void *UNUSED(cb_data)) -{ - struct ly_ctx_err_rec *err1 = val1_p, *err2 = val2_p; - - return !memcmp(&err1->tid, &err2->tid, sizeof err1->tid); -} - -/** - * @brief Hash table value-equal callback for comparing leafref links hash table record. - */ -static ly_bool -ly_ctx_ht_leafref_links_equal_cb(void *val1_p, void *val2_p, ly_bool UNUSED(mod), void *UNUSED(cb_data)) -{ - struct lyd_leafref_links_rec **rec1 = val1_p, **rec2 = val2_p; - - return (*rec1)->node == (*rec2)->node; -} - -/** - * @brief Callback for freeing leafref links recorcd internal resources. - * - * @param[in] val_p Pointer to leafref links record - */ -static void -ly_ctx_ht_leafref_links_rec_free(void *val_p) -{ - struct lyd_leafref_links_rec **rec = val_p; - - lyd_free_leafref_links_rec(*rec); - free(*rec); -} - LIBYANG_API_DEF LY_ERR -ly_ctx_new(const char *search_dir, uint16_t options, struct ly_ctx **new_ctx) +ly_ctx_new(const char *search_dir, uint32_t options, struct ly_ctx **new_ctx) { struct ly_ctx *ctx = NULL; struct lys_module *module; @@ -305,7 +270,7 @@ ly_ctx_new(const char *search_dir, uint16_t options, struct ly_ctx **new_ctx) struct ly_in *in = NULL; LY_ERR rc = LY_SUCCESS; struct lys_glob_unres unres = {0}; - ly_bool builtin_plugins_only; + ly_bool builtin_plugins_only, static_plugins_only; LY_CHECK_ARG_RET(NULL, new_ctx, LY_EINVAL); @@ -317,27 +282,17 @@ ly_ctx_new(const char *search_dir, uint16_t options, struct ly_ctx **new_ctx) /* plugins */ builtin_plugins_only = (options & LY_CTX_BUILTIN_PLUGINS_ONLY) ? 1 : 0; - LY_CHECK_ERR_GOTO(lyplg_init(builtin_plugins_only), LOGINT(NULL); rc = LY_EINT, cleanup); - - if (options & LY_CTX_LEAFREF_LINKING) { - /** - * storing the pointer instead of record itself is needed to avoid invalid memory reads. Hash table can reallocate - * its memory completely during various manipulation function (e.g. remove, insert). In case of using pointers, the - * pointer can be reallocated safely, while record itself remains untouched and can be accessed/modified freely - * */ - ctx->leafref_links_ht = lyht_new(1, sizeof(struct lyd_leafref_links_rec *), ly_ctx_ht_leafref_links_equal_cb, NULL, 1); - LY_CHECK_ERR_GOTO(!ctx->leafref_links_ht, rc = LY_EMEM, cleanup); - } + static_plugins_only = (options & LY_CTX_STATIC_PLUGINS_ONLY) ? 1 : 0; + LY_CHECK_ERR_GOTO(lyplg_init(builtin_plugins_only, static_plugins_only), LOGINT(NULL); rc = LY_EINT, cleanup); - /* initialize thread-specific error hash table */ - ctx->err_ht = lyht_new(1, sizeof(struct ly_ctx_err_rec), ly_ctx_ht_err_equal_cb, NULL, 1); - LY_CHECK_ERR_GOTO(!ctx->err_ht, rc = LY_EMEM, cleanup); + /* options */ + ctx->opts = options; - /* init LYB hash lock */ - pthread_mutex_init(&ctx->lyb_hash_lock, NULL); + /* ctx data */ + rc = ly_ctx_data_add(ctx); + LY_CHECK_GOTO(rc, cleanup); /* modules list */ - ctx->flags = options; if (search_dir) { search_dir_list = strdup(search_dir); LY_CHECK_ERR_GOTO(!search_dir_list, LOGMEM(NULL); rc = LY_EMEM, cleanup); @@ -366,7 +321,7 @@ ly_ctx_new(const char *search_dir, uint16_t options, struct ly_ctx **new_ctx) if (!(options & LY_CTX_EXPLICIT_COMPILE)) { /* use it for creating the initial context */ - ctx->flags |= LY_CTX_EXPLICIT_COMPILE; + ctx->opts |= LY_CTX_EXPLICIT_COMPILE; } /* create dummy in */ @@ -377,8 +332,8 @@ ly_ctx_new(const char *search_dir, uint16_t options, struct ly_ctx **new_ctx) for (i = 0; i < ((options & LY_CTX_NO_YANGLIBRARY) ? (LY_INTERNAL_MODS_COUNT - 2) : LY_INTERNAL_MODS_COUNT); i++) { ly_in_memory(in, internal_modules[i].data); LY_CHECK_GOTO(rc = lys_parse_in(ctx, in, internal_modules[i].format, NULL, &unres.creating, &module), cleanup); - if (internal_modules[i].implemented || (ctx->flags & LY_CTX_ALL_IMPLEMENTED)) { - imp_f = (ctx->flags & LY_CTX_ENABLE_IMP_FEATURES) ? all_f : NULL; + if (internal_modules[i].implemented || (ctx->opts & LY_CTX_ALL_IMPLEMENTED)) { + imp_f = (ctx->opts & LY_CTX_ENABLE_IMP_FEATURES) ? all_f : NULL; LY_CHECK_GOTO(rc = lys_implement(module, imp_f, &unres), cleanup); } } @@ -386,7 +341,7 @@ ly_ctx_new(const char *search_dir, uint16_t options, struct ly_ctx **new_ctx) if (!(options & LY_CTX_EXPLICIT_COMPILE)) { /* compile now */ LY_CHECK_GOTO(rc = ly_ctx_compile(ctx), cleanup); - ctx->flags &= ~LY_CTX_EXPLICIT_COMPILE; + ctx->opts &= ~LY_CTX_EXPLICIT_COMPILE; } cleanup: @@ -543,7 +498,7 @@ ly_ctx_new_yldata(const char *search_dir, const struct lyd_node *tree, int optio /* redundant to compile modules one-by-one */ if (!(options & LY_CTX_EXPLICIT_COMPILE)) { - ctx_new->flags |= LY_CTX_EXPLICIT_COMPILE; + ctx_new->opts |= LY_CTX_EXPLICIT_COMPILE; no_expl_compile = 1; } @@ -598,7 +553,7 @@ ly_ctx_new_yldata(const char *search_dir, const struct lyd_node *tree, int optio if (no_expl_compile) { /* unset flag */ - ctx_new->flags &= ~LY_CTX_EXPLICIT_COMPILE; + ctx_new->opts &= ~LY_CTX_EXPLICIT_COMPILE; } cleanup: @@ -619,7 +574,7 @@ ly_ctx_compile(struct ly_ctx *ctx) { LY_ERR ret = LY_SUCCESS; - LY_CHECK_ARG_RET(NULL, ctx, LY_EINVAL); + LY_CHECK_ARG_RET(NULL, ctx, !(ctx->opts & LY_CTX_INT_IMMUTABLE), LY_EINVAL); /* create dep sets and mark all the modules that will be (re)compiled */ LY_CHECK_GOTO(ret = lys_unres_dep_sets_create(ctx, &ctx->unres.dep_sets, NULL), cleanup); @@ -627,6 +582,9 @@ ly_ctx_compile(struct ly_ctx *ctx) /* (re)compile all the dep sets */ LY_CHECK_GOTO(ret = lys_compile_depset_all(ctx, &ctx->unres), cleanup); + /* new context state */ + ly_ctx_new_change(ctx); + cleanup: if (ret) { /* revert changes of modules */ @@ -636,42 +594,64 @@ ly_ctx_compile(struct ly_ctx *ctx) return ret; } -LIBYANG_API_DEF uint16_t +LIBYANG_API_DEF uint32_t ly_ctx_get_options(const struct ly_ctx *ctx) { LY_CHECK_ARG_RET(ctx, ctx, 0); - return ctx->flags; + return ctx->opts; } LIBYANG_API_DEF LY_ERR -ly_ctx_set_options(struct ly_ctx *ctx, uint16_t option) +ly_ctx_set_options(struct ly_ctx *ctx, uint32_t option) { LY_ERR lyrc = LY_SUCCESS; + struct ly_ctx_shared_data *ctx_data; struct lys_module *mod; uint32_t i; - LY_CHECK_ARG_RET(ctx, ctx, LY_EINVAL); - LY_CHECK_ERR_RET((option & LY_CTX_NO_YANGLIBRARY) && !(ctx->flags & LY_CTX_NO_YANGLIBRARY), + LY_CHECK_ARG_RET(ctx, ctx, !(ctx->opts & LY_CTX_INT_IMMUTABLE), LY_EINVAL); + LY_CHECK_ERR_RET((option & LY_CTX_NO_YANGLIBRARY) && !(ctx->opts & LY_CTX_NO_YANGLIBRARY), LOGARG(ctx, option), LY_EINVAL); - if (!(ctx->flags & LY_CTX_BUILTIN_PLUGINS_ONLY) && (option & LY_CTX_BUILTIN_PLUGINS_ONLY)) { + if (!(ctx->opts & LY_CTX_BUILTIN_PLUGINS_ONLY) && (option & LY_CTX_BUILTIN_PLUGINS_ONLY)) { LOGERR(ctx, LY_EINVAL, "Invalid argument %s (LY_CTX_BUILTIN_PLUGINS_ONLY can be set only when creating a new context) (%s()).", "option", __func__); return LY_EINVAL; } - if (!(ctx->flags & LY_CTX_LEAFREF_LINKING) && (option & LY_CTX_LEAFREF_LINKING)) { - ctx->leafref_links_ht = lyht_new(1, sizeof(struct lyd_leafref_links_rec *), ly_ctx_ht_leafref_links_equal_cb, NULL, 1); - LY_CHECK_ERR_RET(!ctx->leafref_links_ht, LOGARG(ctx, option), LY_EMEM); + if (!(ctx->opts & LY_CTX_STATIC_PLUGINS_ONLY) && (option & LY_CTX_STATIC_PLUGINS_ONLY)) { + LOGERR(ctx, LY_EINVAL, + "Invalid argument %s (LY_CTX_STATIC_PLUGINS_ONLY can be set only when creating a new context) (%s()).", + "option", __func__); + return LY_EINVAL; + } + + if (!(ctx->opts & LY_CTX_LEAFREF_LINKING) && (option & LY_CTX_LEAFREF_LINKING)) { + /* context is not printed (ctx data cant be shared with any other ctx), so no need to hold a lock */ + ctx_data = ly_ctx_shared_data_get(ctx); + ctx_data->leafref_links_ht = lyht_new(1, sizeof(struct lyd_leafref_links_rec *), ly_ctx_ht_leafref_links_equal_cb, NULL, 1); + LY_CHECK_ERR_RET(!ctx_data->leafref_links_ht, LOGARG(ctx, option), LY_EMEM); + } + + if (!(ctx->opts & LY_CTX_LYB_HASHES) && (option & LY_CTX_LYB_HASHES)) { + for (i = 0; i < ctx->modules.count; ++i) { + mod = ctx->modules.objs[i]; + if (!mod->implemented) { + continue; + } + + /* store all cached hashes for all the nodes */ + lysc_module_dfs_full(mod, lyb_cache_node_hash_cb, NULL); + } } - if (!(ctx->flags & LY_CTX_SET_PRIV_PARSED) && (option & LY_CTX_SET_PRIV_PARSED)) { - ctx->flags |= LY_CTX_SET_PRIV_PARSED; + if (!(ctx->opts & LY_CTX_SET_PRIV_PARSED) && (option & LY_CTX_SET_PRIV_PARSED)) { + ctx->opts |= LY_CTX_SET_PRIV_PARSED; /* recompile the whole context to set the priv pointers */ - for (i = 0; i < ctx->list.count; ++i) { - mod = ctx->list.objs[i]; + for (i = 0; i < ctx->modules.count; ++i) { + mod = ctx->modules.objs[i]; if (mod->implemented) { mod->to_compile = 1; } @@ -684,7 +664,7 @@ ly_ctx_set_options(struct ly_ctx *ctx, uint16_t option) /* set the option(s) */ if (!lyrc) { - ctx->flags |= option; + ctx->opts |= option; } return lyrc; @@ -698,21 +678,24 @@ lysc_node_clear_priv_dfs_cb(struct lysc_node *node, void *UNUSED(data), ly_bool } LIBYANG_API_DEF LY_ERR -ly_ctx_unset_options(struct ly_ctx *ctx, uint16_t option) +ly_ctx_unset_options(struct ly_ctx *ctx, uint32_t option) { LY_ARRAY_COUNT_TYPE u, v; const struct lysc_ext_instance *ext; struct lysc_node *root; + struct ly_ctx_shared_data *ctx_data; - LY_CHECK_ARG_RET(ctx, ctx, LY_EINVAL); + LY_CHECK_ARG_RET(ctx, ctx, !(ctx->opts & LY_CTX_INT_IMMUTABLE), LY_EINVAL); LY_CHECK_ERR_RET(option & LY_CTX_NO_YANGLIBRARY, LOGARG(ctx, option), LY_EINVAL); - if ((ctx->flags & LY_CTX_LEAFREF_LINKING) && (option & LY_CTX_LEAFREF_LINKING)) { - lyht_free(ctx->leafref_links_ht, ly_ctx_ht_leafref_links_rec_free); - ctx->leafref_links_ht = NULL; + if ((ctx->opts & LY_CTX_LEAFREF_LINKING) && (option & LY_CTX_LEAFREF_LINKING)) { + /* context is not printed (ctx data cant be shared with any other ctx), so no need to hold a lock */ + ctx_data = ly_ctx_shared_data_get(ctx); + lyht_free(ctx_data->leafref_links_ht, ly_ctx_ht_leafref_links_rec_free); + ctx_data->leafref_links_ht = NULL; } - if ((ctx->flags & LY_CTX_SET_PRIV_PARSED) && (option & LY_CTX_SET_PRIV_PARSED)) { + if ((ctx->opts & LY_CTX_SET_PRIV_PARSED) && (option & LY_CTX_SET_PRIV_PARSED)) { struct lys_module *mod; uint32_t index; @@ -740,7 +723,7 @@ ly_ctx_unset_options(struct ly_ctx *ctx, uint16_t option) } /* unset the option(s) */ - ctx->flags &= ~option; + ctx->opts &= ~option; return LY_SUCCESS; } @@ -765,8 +748,8 @@ void ly_ctx_new_change(struct ly_ctx *ctx) { const struct lys_module *mod; - uint32_t i = ly_ctx_internal_modules_count(ctx), hash = 0, fi = 0; - struct lysp_feature *f = NULL; + uint32_t i = ly_ctx_internal_modules_count(ctx), hash = 0; + LY_ARRAY_COUNT_TYPE u; /* change counter */ ctx->change_count++; @@ -782,9 +765,9 @@ ly_ctx_new_change(struct ly_ctx *ctx) } /* enabled features */ - while ((f = lysp_feature_next(f, mod->parsed, &fi))) { - if (f->flags & LYS_FENABLED) { - hash = lyht_hash_multi(hash, f->name, strlen(f->name)); + if (mod->implemented) { + LY_ARRAY_FOR(mod->compiled->features, u) { + hash = lyht_hash_multi(hash, mod->compiled->features[u], strlen(mod->compiled->features[u])); } } @@ -809,14 +792,14 @@ ly_ctx_get_module_imp_clb(const struct ly_ctx *ctx, void **user_data) LIBYANG_API_DEF void ly_ctx_set_module_imp_clb(struct ly_ctx *ctx, ly_module_imp_clb clb, void *user_data) { - LY_CHECK_ARG_RET(ctx, ctx, ); + LY_CHECK_ARG_RET(ctx, ctx, !(ctx->opts & LY_CTX_INT_IMMUTABLE), ); ctx->imp_clb = clb; ctx->imp_clb_data = user_data; /* new import callback - reset latests flags (possibly new revisions available) */ - for (uint32_t v = 0; v < ctx->list.count; ++v) { - struct lys_module *mod = ctx->list.objs[v]; + for (uint32_t v = 0; v < ctx->modules.count; ++v) { + struct lys_module *mod = ctx->modules.objs[v]; mod->latest_revision &= ~LYS_MOD_LATEST_IMPCLB; if (mod->parsed && mod->parsed->includes) { @@ -828,15 +811,24 @@ ly_ctx_set_module_imp_clb(struct ly_ctx *ctx, ly_module_imp_clb clb, void *user_ } LIBYANG_API_DEF ly_ext_data_clb -ly_ctx_set_ext_data_clb(struct ly_ctx *ctx, ly_ext_data_clb clb, void *user_data) +ly_ctx_set_ext_data_clb(const struct ly_ctx *ctx, ly_ext_data_clb clb, void *user_data) { + struct ly_ctx_shared_data *ctx_data; ly_ext_data_clb prev; LY_CHECK_ARG_RET(ctx, ctx, NULL); - prev = ctx->ext_clb; - ctx->ext_clb = clb; - ctx->ext_clb_data = user_data; + ctx_data = ly_ctx_shared_data_get(ctx); + + /* EXT CLB LOCK */ + pthread_mutex_lock(&ctx_data->ext_clb_lock); + + prev = ctx_data->ext_clb; + ctx_data->ext_clb = clb; + ctx_data->ext_clb_data = user_data; + + /* EXT CLB UNLOCK */ + pthread_mutex_unlock(&ctx_data->ext_clb_lock); return prev; } @@ -846,8 +838,8 @@ ly_ctx_get_module_iter(const struct ly_ctx *ctx, uint32_t *index) { LY_CHECK_ARG_RET(ctx, ctx, index, NULL); - if (*index < ctx->list.count) { - return ctx->list.objs[(*index)++]; + if (*index < ctx->modules.count) { + return ctx->modules.objs[(*index)++]; } else { return NULL; } @@ -872,8 +864,8 @@ ly_ctx_get_module_by_iter(const struct ly_ctx *ctx, const char *key, size_t key_ struct lys_module *mod; const char *value; - for ( ; *index < ctx->list.count; ++(*index)) { - mod = ctx->list.objs[*index]; + for ( ; *index < ctx->modules.count; ++(*index)) { + mod = ctx->modules.objs[*index]; value = *(const char **)(((int8_t *)(mod)) + key_offset); if ((!key_size && !strcmp(key, value)) || (key_size && !strncmp(key, value, key_size) && (value[key_size] == '\0'))) { /* increment index for the next run */ @@ -1066,8 +1058,8 @@ _ly_ctx_get_submodule(const struct ly_ctx *ctx, const char *submodule, const cha LY_CHECK_ARG_RET(ctx, ctx, submodule, NULL); - for (v = 0; v < ctx->list.count; ++v) { - mod = ctx->list.objs[v]; + for (v = 0; v < ctx->modules.count; ++v) { + mod = ctx->modules.objs[v]; if (!mod->parsed) { continue; } @@ -1112,7 +1104,7 @@ ly_ctx_internal_modules_count(const struct ly_ctx *ctx) return 0; } - if (ctx->flags & LY_CTX_NO_YANGLIBRARY) { + if (ctx->opts & LY_CTX_NO_YANGLIBRARY) { return LY_INTERNAL_MODS_COUNT - 2; } else { return LY_INTERNAL_MODS_COUNT; @@ -1120,32 +1112,17 @@ ly_ctx_internal_modules_count(const struct ly_ctx *ctx) } static LY_ERR -ylib_feature(struct lyd_node *parent, const struct lysp_module *pmod) +ylib_feature(struct lyd_node *parent, const struct lys_module *mod) { LY_ARRAY_COUNT_TYPE u; - struct lysp_feature *f; - if (!pmod->mod->implemented) { + if (!mod->implemented) { /* no features can be enabled */ return LY_SUCCESS; } - LY_ARRAY_FOR(pmod->features, struct lysp_feature, f) { - if (!(f->flags & LYS_FENABLED)) { - continue; - } - - LY_CHECK_RET(lyd_new_term(parent, NULL, "feature", f->name, 0, NULL)); - } - - LY_ARRAY_FOR(pmod->includes, u) { - LY_ARRAY_FOR(pmod->includes[u].submodule->features, struct lysp_feature, f) { - if (!(f->flags & LYS_FENABLED)) { - continue; - } - - LY_CHECK_RET(lyd_new_term(parent, NULL, "feature", f->name, 0, NULL)); - } + LY_ARRAY_FOR(mod->compiled->features, u) { + LY_CHECK_RET(lyd_new_term(parent, NULL, "feature", mod->compiled->features[u], 0, NULL)); } return LY_SUCCESS; @@ -1168,8 +1145,7 @@ ylib_deviation(struct lyd_node *parent, const struct lys_module *cur_mod, ly_boo if (bis) { LY_CHECK_RET(lyd_new_term(parent, NULL, "deviation", mod->name, 0, NULL)); } else { - LY_CHECK_RET(lyd_new_list(parent, NULL, "deviation", 0, NULL, mod->name, - (mod->parsed->revs ? mod->parsed->revs[0].date : ""))); + LY_CHECK_RET(lyd_new_list(parent, NULL, "deviation", 0, NULL, mod->name, mod->revision ? mod->revision : "")); } } @@ -1177,32 +1153,32 @@ ylib_deviation(struct lyd_node *parent, const struct lys_module *cur_mod, ly_boo } static LY_ERR -ylib_submodules(struct lyd_node *parent, const struct lysp_module *pmod, ly_bool bis) +ylib_submodules(struct lyd_node *parent, const struct lys_module *mod, ly_bool bis) { LY_ERR ret; - LY_ARRAY_COUNT_TYPE i; + LY_ARRAY_COUNT_TYPE u; struct lyd_node *cont; - struct lysp_submodule *submod; + struct lysc_submodule *submod; int r; char *str; - LY_ARRAY_FOR(pmod->includes, i) { - submod = pmod->includes[i].submodule; + LY_ARRAY_FOR(mod->submodules, u) { + submod = &mod->submodules[u]; if (bis) { LY_CHECK_RET(lyd_new_list(parent, NULL, "submodule", 0, &cont, submod->name)); - if (submod->revs) { - LY_CHECK_RET(lyd_new_term(cont, NULL, "revision", submod->revs[0].date, 0, NULL)); + if (submod->revision) { + LY_CHECK_RET(lyd_new_term(cont, NULL, "revision", submod->revision, 0, NULL)); } } else { LY_CHECK_RET(lyd_new_list(parent, NULL, "submodule", 0, &cont, submod->name, - (submod->revs ? submod->revs[0].date : ""))); + submod->revision ? submod->revision : "")); } if (submod->filepath) { r = asprintf(&str, "file://%s", submod->filepath); - LY_CHECK_ERR_RET(r == -1, LOGMEM(pmod->mod->ctx), LY_EMEM); + LY_CHECK_ERR_RET(r == -1, LOGMEM(mod->ctx), LY_EMEM); ret = lyd_new_term(cont, NULL, bis ? "location" : "schema", str, 0, NULL); free(str); @@ -1230,9 +1206,9 @@ ly_ctx_get_yanglib_data(const struct ly_ctx *ctx, struct lyd_node **root_p, cons mod = ly_ctx_get_module_implemented(ctx, "ietf-yang-library"); LY_CHECK_ERR_RET(!mod, LOGERR(ctx, LY_EINVAL, "Module \"ietf-yang-library\" is not implemented."), LY_EINVAL); - if (mod->parsed->revs && !strcmp(mod->parsed->revs[0].date, "2016-06-21")) { + if (mod->revision && !strcmp(mod->revision, "2016-06-21")) { bis = 0; - } else if (mod->parsed->revs && !strcmp(mod->parsed->revs[0].date, IETF_YANG_LIB_REV)) { + } else if (mod->revision && !strcmp(mod->revision, IETF_YANG_LIB_REV)) { bis = 1; } else { LOGERR(ctx, LY_EINVAL, "Incompatible ietf-yang-library version in context."); @@ -1246,18 +1222,14 @@ ly_ctx_get_yanglib_data(const struct ly_ctx *ctx, struct lyd_node **root_p, cons LY_CHECK_GOTO(ret = lyd_new_list(root_bis, NULL, "module-set", 0, &set_bis, "complete"), error); } - for (i = 0; i < ctx->list.count; ++i) { - mod = ctx->list.objs[i]; - if (!mod->parsed) { - LOGERR(ctx, LY_ENOTFOUND, "Parsed module \"%s\" missing in the context.", mod->name); - goto error; - } + for (i = 0; i < ctx->modules.count; ++i) { + mod = ctx->modules.objs[i]; /* * deprecated legacy */ - LY_CHECK_GOTO(ret = lyd_new_list(root, NULL, "module", 0, &cont, mod->name, - (mod->parsed->revs ? mod->parsed->revs[0].date : "")), error); + LY_CHECK_GOTO(ret = lyd_new_list(root, NULL, "module", 0, &cont, mod->name, mod->revision ? mod->revision : ""), + error); /* schema */ if (mod->filepath) { @@ -1273,7 +1245,7 @@ ly_ctx_get_yanglib_data(const struct ly_ctx *ctx, struct lyd_node **root_p, cons LY_CHECK_GOTO(ret = lyd_new_term(cont, NULL, "namespace", mod->ns, 0, NULL), error); /* feature leaf-list */ - LY_CHECK_GOTO(ret = ylib_feature(cont, mod->parsed), error); + LY_CHECK_GOTO(ret = ylib_feature(cont, mod), error); /* deviation list */ LY_CHECK_GOTO(ret = ylib_deviation(cont, mod, 0), error); @@ -1282,7 +1254,7 @@ ly_ctx_get_yanglib_data(const struct ly_ctx *ctx, struct lyd_node **root_p, cons LY_CHECK_GOTO(ret = lyd_new_term(cont, NULL, "conformance-type", mod->implemented ? "implement" : "import", 0, NULL), error); /* submodule list */ - LY_CHECK_GOTO(ret = ylib_submodules(cont, mod->parsed, 0), error); + LY_CHECK_GOTO(ret = ylib_submodules(cont, mod, 0), error); /* * current revision @@ -1292,12 +1264,12 @@ ly_ctx_get_yanglib_data(const struct ly_ctx *ctx, struct lyd_node **root_p, cons if (mod->implemented) { LY_CHECK_GOTO(ret = lyd_new_list(set_bis, NULL, "module", 0, &cont, mod->name), error); - if (mod->parsed->revs) { - LY_CHECK_GOTO(ret = lyd_new_term(cont, NULL, "revision", mod->parsed->revs[0].date, 0, NULL), error); + if (mod->revision) { + LY_CHECK_GOTO(ret = lyd_new_term(cont, NULL, "revision", mod->revision, 0, NULL), error); } } else { LY_CHECK_GOTO(ret = lyd_new_list(set_bis, NULL, "import-only-module", 0, &cont, mod->name, - (mod->parsed->revs ? mod->parsed->revs[0].date : "")), error); + mod->revision ? mod->revision : ""), error); } /* namespace */ @@ -1314,10 +1286,10 @@ ly_ctx_get_yanglib_data(const struct ly_ctx *ctx, struct lyd_node **root_p, cons } /* submodule list */ - LY_CHECK_GOTO(ret = ylib_submodules(cont, mod->parsed, 1), error); + LY_CHECK_GOTO(ret = ylib_submodules(cont, mod, 1), error); /* feature list */ - LY_CHECK_GOTO(ret = ylib_feature(cont, mod->parsed), error); + LY_CHECK_GOTO(ret = ylib_feature(cont, mod), error); /* deviation */ LY_CHECK_GOTO(ret = ylib_deviation(cont, mod, 1), error); @@ -1361,44 +1333,183 @@ ly_ctx_get_yanglib_data(const struct ly_ctx *ctx, struct lyd_node **root_p, cons return ret; } -/** - * @brief Callback for freeing context error hash table values. - * - * @param[in] val_p Pointer to a pointer to an error item to free with all the siblings. - */ -static void -ly_ctx_ht_err_rec_free(void *val_p) +LIBYANG_API_DEF void +ly_ctx_free_parsed(struct ly_ctx *ctx) { - struct ly_ctx_err_rec *err = val_p; + uint32_t i; + struct lys_module *mod; + + LY_CHECK_ARG_RET(ctx, ctx, !(ctx->opts & LY_CTX_INT_IMMUTABLE), ); + + for (i = 0; i < ctx->modules.count; ++i) { + mod = ctx->modules.objs[i]; - ly_err_free(err->err); + /* free the parsed modules */ + lysp_module_free(ctx, mod->parsed); + mod->parsed = NULL; + } +} + +static ly_bool +ctxs_ptr_val_equal(void *val1_p, void *val2_p, ly_bool UNUSED(mod), void *UNUSED(cb_data)) +{ + void *val1, *val2; + + val1 = *(void **)val1_p; + val2 = *(void **)val2_p; + + return val1 == val2; +} + +LIBYANG_API_DEF int +ly_ctx_compiled_size(const struct ly_ctx *ctx) +{ + int size = 0; + struct ly_ht *ht; + + LY_CHECK_ARG_RET(NULL, ctx, -1); + + /* create hash table for shared structures */ + ht = lyht_new(0, sizeof(void *), ctxs_ptr_val_equal, NULL, 1); + LY_CHECK_RET(!ht, -1); + + ly_ctx_compiled_size_context(ctx, ht, &size); + + /* cleanup */ + lyht_free(ht, NULL); + return size; +} + +static ly_bool +ctxp_ptr_val_equal(void *val1_p, void *val2_p, ly_bool UNUSED(mod), void *UNUSED(cb_data)) +{ + struct ctxp_ht_addr *val1, *val2; + + val1 = val1_p; + val2 = val2_p; + + return val1->orig_addr == val2->orig_addr; +} + +LIBYANG_API_DEF LY_ERR +ly_ctx_compiled_print(const struct ly_ctx *ctx, void *mem, void **mem_end) +{ + struct ly_ctx *pctx; + struct ly_ht *addr_ht = NULL; + struct ly_set ptr_set = {0}; + void **ptr_p; + uint32_t i; + + LY_CHECK_ARG_RET(ctx, ctx, mem, LY_EINVAL); + + if (ctx->plugins_types.count || ctx->plugins_extensions.count || !(ctx->opts & LY_CTX_STATIC_PLUGINS_ONLY)) { + LOGERR(ctx, LY_EINVAL, "Printing context with dynamic type or extension plugins is not supported."); + return LY_EINVAL; + } + + /* create hash table for shared structures */ + addr_ht = lyht_new(0, sizeof(struct ctxp_ht_addr), ctxp_ptr_val_equal, NULL, 1); + LY_CHECK_RET(!addr_ht, -1); + + /* context, referenced */ + pctx = mem; + mem = (char *)mem + sizeof *pctx; + ly_ctx_compiled_addr_ht_add(addr_ht, ctx, pctx); + ly_ctx_compiled_print_context(ctx, pctx, addr_ht, &ptr_set, &mem); + + /* immutable */ + pctx->opts |= LY_CTX_INT_IMMUTABLE; + + /* set all the pointers to the printed structures */ + for (i = 0; i < ptr_set.count; ++i) { + ptr_p = ptr_set.objs[i]; + *ptr_p = ly_ctx_compiled_addr_ht_get(addr_ht, *ptr_p, 0); + } + + /* cleanup */ + lyht_free(addr_ht, NULL); + ly_set_erase(&ptr_set, NULL); + if (mem_end) { + *mem_end = mem; + } + return LY_SUCCESS; +} + +LIBYANG_API_DEF LY_ERR +ly_ctx_new_printed(const void *mem, struct ly_ctx **ctx) +{ + LY_ERR rc = LY_SUCCESS; + ly_bool builtin_plugins_only, static_plugins_only; + + LY_CHECK_ARG_RET(NULL, mem, ctx, LY_EINVAL); + + *ctx = (void *)mem; + + /* ctx data */ + rc = ly_ctx_data_add(*ctx); + if (rc) { + goto cleanup; + } + + /* plugins */ + builtin_plugins_only = ((*ctx)->opts & LY_CTX_BUILTIN_PLUGINS_ONLY) ? 1 : 0; + static_plugins_only = 1; + LY_CHECK_ERR_GOTO(lyplg_init(builtin_plugins_only, static_plugins_only), LOGINT(NULL); rc = LY_EINT, cleanup); + +cleanup: + if (rc) { + if (rc != LY_EEXIST) { + /* do not free another context's data */ + ly_ctx_data_del(*ctx); + } + *ctx = NULL; + } + return rc; +} + +LIBYANG_API_DEF ly_bool +ly_ctx_is_printed(const struct ly_ctx *ctx) +{ + return (ctx->opts & LY_CTX_INT_IMMUTABLE) ? 1 : 0; } LIBYANG_API_DEF void ly_ctx_destroy(struct ly_ctx *ctx) { - struct lysf_ctx fctx = {.ctx = ctx}; + uint32_t i; + struct lys_module *mod; if (!ctx) { return; } - /* modules list */ - for ( ; ctx->list.count; ctx->list.count--) { - fctx.mod = ctx->list.objs[ctx->list.count - 1]; - - /* remove the module */ - if (fctx.mod->implemented) { - fctx.mod->implemented = 0; - lysc_module_free(&fctx, fctx.mod->compiled); - fctx.mod->compiled = NULL; + if (ctx->opts & LY_CTX_INT_IMMUTABLE) { + /* ctx data */ + ly_ctx_data_del(ctx); + lyplg_clean(); + return; + } + + /* free the parsed and compiled modules (both can reference ext instances, which need to be freed, so their + * definitions can be freed) */ + for (i = 0; i < ctx->modules.count; ++i) { + mod = ctx->modules.objs[i]; + + lysp_module_free(ctx, mod->parsed); + mod->parsed = NULL; + if (mod->implemented) { + mod->implemented = 0; + lysc_module_free(ctx, mod->compiled); + mod->compiled = NULL; } - lys_module_free(&fctx, fctx.mod, 0); } - free(ctx->list.objs); - /* free extensions */ - lysf_ctx_erase(&fctx); + /* free the modules (with compiled extension definitions) */ + for (i = 0; i < ctx->modules.count; ++i) { + mod = ctx->modules.objs[i]; + lys_module_free(ctx, mod, 0); + } + free(ctx->modules.objs); /* search paths list */ ly_set_erase(&ctx->search_paths, free); @@ -1406,20 +1517,12 @@ ly_ctx_destroy(struct ly_ctx *ctx) /* leftover unres */ lys_unres_glob_erase(&ctx->unres); - /* clean the leafref links hash table */ - if (ctx->leafref_links_ht) { - lyht_free(ctx->leafref_links_ht, ly_ctx_ht_leafref_links_rec_free); - } - - /* clean the error hash table */ - lyht_free(ctx->err_ht, ly_ctx_ht_err_rec_free); + /* ctx data */ + ly_ctx_data_del(ctx); /* dictionary */ lydict_clean(&ctx->dict); - /* LYB hash lock */ - pthread_mutex_destroy(&ctx->lyb_hash_lock); - /* context specific plugins */ ly_set_erase(&ctx->plugins_types, NULL); ly_set_erase(&ctx->plugins_extensions, NULL); diff --git a/src/context.h b/src/context.h index 1293dbcaa..79bf03a19 100644 --- a/src/context.h +++ b/src/context.h @@ -4,7 +4,7 @@ * @author Michal Vasko * @brief internal context structures and functions * - * Copyright (c) 2015 - 2023 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. @@ -202,11 +202,22 @@ struct ly_ctx; 'require-instance false;'. It also enables usage of [lyd_leafref_get_links](@ref lyd_leafref_get_links) and [lyd_leafref_link_node_tree](@ref lyd_leafref_link_node_tree) APIs. */ -#define LY_CTX_BUILTIN_PLUGINS_ONLY 0x0800 /**< By default, context uses all available plugins for types and extensions, - both included and external. This options prevents all included plugins to be - loaded except for built-in YANG types so all derived types will use these and - for all purposes behave as the base type. The option can be used for cases when - invalid data needs to be stored in YANG node values. */ +#define LY_CTX_BUILTIN_PLUGINS_ONLY 0x0800 /**< Limits the context to use only built-in YANG type plugins, + treating all derived types as their base type. + Useful for storing invalid data in YANG node values. + This option has a global effect: the global plugin array is initialized only when no contexts exist. + If any context was created without this flag and is still alive, + creating a new context with this flag will not have the intended effect. */ + +#define LY_CTX_LYB_HASHES 0x1000 /**< Generate hashes for all the schema nodes. Required when using LYB data parse + or print. */ +#define LY_CTX_STATIC_PLUGINS_ONLY 0x2000 /**< Restricts the context to load only static (built-in) plugins, + ignoring external plugins from directories specified by `LIBYANG_TYPES_PLUGINS_DIR` and + `LIBYANG_EXTENSIONS_PLUGINS_DIR`. This option has a global effect: the global plugin array + is initialized only when no contexts exist. If any context was created without this flag + and is still alive, creating a new context with this flag will not have the intended effect. */ + +/* 0x80000000 reserved for internal use */ /** @} contextoptions */ @@ -232,7 +243,7 @@ struct ly_ctx; * @param[out] new_ctx Pointer to the created libyang context if LY_SUCCESS returned. * @return LY_ERR return value. */ -LIBYANG_API_DECL LY_ERR ly_ctx_new(const char *search_dir, uint16_t options, struct ly_ctx **new_ctx); +LIBYANG_API_DECL LY_ERR ly_ctx_new(const char *search_dir, uint32_t options, struct ly_ctx **new_ctx); /** * @brief Create libyang context according to the provided yang-library data in a file. @@ -352,7 +363,7 @@ LIBYANG_API_DECL const char * const *ly_ctx_get_searchdirs(const struct ly_ctx * * @param[in] ctx Context to query. * @return Combination of all the currently set context's options, see @ref contextoptions. */ -LIBYANG_API_DECL uint16_t ly_ctx_get_options(const struct ly_ctx *ctx); +LIBYANG_API_DECL uint32_t ly_ctx_get_options(const struct ly_ctx *ctx); /** * @brief Set some of the context's options, see @ref contextoptions. @@ -362,7 +373,7 @@ LIBYANG_API_DECL uint16_t ly_ctx_get_options(const struct ly_ctx *ctx); * and all ::lysc_node.priv in the modules will be overwritten, see ::LY_CTX_SET_PRIV_PARSED. * @return LY_ERR value. */ -LIBYANG_API_DECL LY_ERR ly_ctx_set_options(struct ly_ctx *ctx, uint16_t option); +LIBYANG_API_DECL LY_ERR ly_ctx_set_options(struct ly_ctx *ctx, uint32_t option); /** * @brief Unset some of the context's options, see @ref contextoptions. @@ -370,7 +381,7 @@ LIBYANG_API_DECL LY_ERR ly_ctx_set_options(struct ly_ctx *ctx, uint16_t option); * @param[in] option Combination of the context's options to be unset, see @ref contextoptions. * @return LY_ERR value. */ -LIBYANG_API_DECL LY_ERR ly_ctx_unset_options(struct ly_ctx *ctx, uint16_t option); +LIBYANG_API_DECL LY_ERR ly_ctx_unset_options(struct ly_ctx *ctx, uint32_t option); /** * @brief Get the change count of the context (module set) during its life-time. @@ -449,13 +460,15 @@ LIBYANG_API_DECL void ly_ctx_set_module_imp_clb(struct ly_ctx *ctx, ly_module_im * @brief Callback for getting arbitrary run-time data required by an extension instance. * * @param[in] ext Compiled extension instance. + * @param[in] parent Data parent node instance of a schema node with @p ext instance. In special cases + * (when not working with data) it can be NULL! * @param[in] user_data User-supplied callback data. * @param[out] ext_data Provided extension instance data. * @param[out] ext_data_free Whether the extension instance should free @p ext_data or not. * @return LY_ERR value. */ -typedef LY_ERR (*ly_ext_data_clb)(const struct lysc_ext_instance *ext, void *user_data, void **ext_data, - ly_bool *ext_data_free); +typedef LY_ERR (*ly_ext_data_clb)(const struct lysc_ext_instance *ext, const struct lyd_node *parent, void *user_data, + void **ext_data, ly_bool *ext_data_free); /** * @brief Set callback providing run-time extension instance data. The expected data depend on the extension. @@ -470,7 +483,7 @@ typedef LY_ERR (*ly_ext_data_clb)(const struct lysc_ext_instance *ext, void *use * @param[in] clb Callback responsible for returning the extension instance data. * @param[in] user_data Arbitrary data that will always be passed to the callback @p clb. */ -LIBYANG_API_DECL ly_ext_data_clb ly_ctx_set_ext_data_clb(struct ly_ctx *ctx, ly_ext_data_clb clb, void *user_data); +LIBYANG_API_DECL ly_ext_data_clb ly_ctx_set_ext_data_clb(const struct ly_ctx *ctx, ly_ext_data_clb clb, void *user_data); /** * @brief Get YANG module of the given name and revision. @@ -647,6 +660,56 @@ LIBYANG_API_DECL struct lys_module *ly_ctx_load_module(struct ly_ctx *ctx, const LIBYANG_API_DECL LY_ERR ly_ctx_get_yanglib_data(const struct ly_ctx *ctx, struct lyd_node **root, const char *content_id_format, ...); +/** + * @brief Free all the parsed modules in a context. Any data manipulation will be possible but some schema functionality + * will no longer work. + * + * @param[in] ctx Context with parsed modules to free. + */ +LIBYANG_API_DECL void ly_ctx_free_parsed(struct ly_ctx *ctx); + +/** + * @brief Get the total size a compiled context requires for serialization. + * + * @param[in] ctx Context to use. + * @return Total required size; + * @return -1 on error. + */ +LIBYANG_API_DECL int ly_ctx_compiled_size(const struct ly_ctx *ctx); + +/** + * @brief Print (serialize) a compiled context (without any parsed modules) into a pre-allocated memory chunk. + * + * Context's dictionary contains strings from parsed modules. You should call ::ly_ctx_free_parsed() to free the parsed modules + * before printing the context, otherwise the printed context may contain many strings that will never be used. + * + * @param[in] ctx Compiled context to print. + * @param[in] mem Memory to print to, must be large enough. + * @param[out] mem_end Optional pointer after the printed context. + * @return LY_ERR value. + */ +LIBYANG_API_DECL LY_ERR ly_ctx_compiled_print(const struct ly_ctx *ctx, void *mem, void **mem_end); + +/** + * @brief Create a (immutable) context that was printed into a memory chunk. + * + * This function allows a given thread to create only one printed context at a particular memory address at any time. + * Another thread, however, may create a separate context at the same address. + * + * @param[in] mem Memory to use. + * @param[out] ctx Created immutable context. + * @return LY_ERR value. + */ +LIBYANG_API_DECL LY_ERR ly_ctx_new_printed(const void *mem, struct ly_ctx **ctx); + +/** + * @brief Check if the context was created from a printed (immutable) context. + * + * @param[in] ctx Context to check. + * @return 1 if the context was created from a printed context, 0 otherwise. + */ +LIBYANG_API_DECL ly_bool ly_ctx_is_printed(const struct ly_ctx *ctx); + /** * @brief Free all internal structures of the specified context. * diff --git a/src/dict.c b/src/dict.c index ba574c8ca..fb121c2d5 100644 --- a/src/dict.c +++ b/src/dict.c @@ -39,15 +39,10 @@ lydict_val_eq(void *val1_p, void *val2_p, ly_bool UNUSED(mod), void *cb_data) const char *str1, *str2; size_t *len1; - LY_CHECK_ARG_RET(NULL, val1_p, val2_p, cb_data, 0); - str1 = ((struct ly_dict_rec *)val1_p)->value; str2 = ((struct ly_dict_rec *)val2_p)->value; len1 = cb_data; - LY_CHECK_ERR_RET(!str1, LOGARG(NULL, val1_p), 0); - LY_CHECK_ERR_RET(!str2, LOGARG(NULL, val2_p), 0); - if (!strncmp(str1, str2, *len1) && !str2[*len1]) { return 1; } @@ -73,7 +68,9 @@ lydict_clean(struct ly_dict *dict) uint32_t hlist_idx; uint32_t rec_idx; - LY_CHECK_ARG_RET(NULL, dict, ); + if (!dict) { + return; + } LYHT_ITER_ALL_RECS(dict->hash_tab, hlist_idx, rec_idx, rec) { /* @@ -119,8 +116,16 @@ lydict_resize_val_eq(void *val1_p, void *val2_p, ly_bool mod, void *UNUSED(cb_da return 0; } -LIBYANG_API_DEF LY_ERR -lydict_remove(const struct ly_ctx *ctx, const char *value) +/** + * @brief Remove a string from the dictionary. + * + * @param[in] ctx Context to use. + * @param[in] dict Dictionary to remove from. + * @param[in] value Value to remove. + * @return LY_SUCCESS on success, LY_ERR value on error. + */ +static LY_ERR +_lydict_remove(const struct ly_ctx *ctx, struct ly_dict *dict, const char *value) { LY_ERR ret = LY_SUCCESS; size_t len; @@ -128,10 +133,6 @@ lydict_remove(const struct ly_ctx *ctx, const char *value) struct ly_dict_rec rec, *match = NULL; char *val_p; - if (!ctx || !value) { - return LY_SUCCESS; - } - LOGDBG(LY_LDGDICT, "removing \"%s\"", value); len = strlen(value); @@ -141,14 +142,13 @@ lydict_remove(const struct ly_ctx *ctx, const char *value) rec.value = (char *)value; rec.refcount = 0; - pthread_mutex_lock((pthread_mutex_t *)&ctx->dict.lock); /* set len as data for compare callback */ - lyht_set_cb_data(ctx->dict.hash_tab, (void *)&len); + lyht_set_cb_data(dict->hash_tab, (void *)&len); /* check if value is already inserted */ - ret = lyht_find(ctx->dict.hash_tab, &rec, hash, (void **)&match); + ret = lyht_find(dict->hash_tab, &rec, hash, (void **)&match); if (ret == LY_SUCCESS) { - LY_CHECK_ERR_GOTO(!match, LOGINT(ctx), finish); + LY_CHECK_ERR_GOTO(!match, LOGINT(ctx), cleanup); /* if value is already in dictionary, decrement reference counter */ match->refcount--; @@ -159,9 +159,9 @@ lydict_remove(const struct ly_ctx *ctx, const char *value) * free it after it is removed from hash table */ val_p = match->value; - ret = lyht_remove_with_resize_cb(ctx->dict.hash_tab, &rec, hash, lydict_resize_val_eq); + ret = lyht_remove_with_resize_cb(dict->hash_tab, &rec, hash, lydict_resize_val_eq); free(val_p); - LY_CHECK_ERR_GOTO(ret, LOGINT(ctx), finish); + LY_CHECK_ERR_GOTO(ret, LOGINT(ctx), cleanup); } } else if (ret == LY_ENOTFOUND) { LOGERR(ctx, LY_ENOTFOUND, "Value \"%s\" was not found in the dictionary.", value); @@ -169,13 +169,51 @@ lydict_remove(const struct ly_ctx *ctx, const char *value) LOGINT(ctx); } -finish: - pthread_mutex_unlock((pthread_mutex_t *)&ctx->dict.lock); +cleanup: + return ret; +} + +LY_ERR +lysdict_remove(const struct ly_ctx *ctx, const char *value) +{ + if (!ctx || !value) { + return LY_SUCCESS; + } + + return _lydict_remove(ctx, (struct ly_dict *)&ctx->dict, value); +} + +LIBYANG_API_DEF LY_ERR +lydict_remove(const struct ly_ctx *ctx, const char *value) +{ + LY_ERR ret; + struct ly_dict *dict; + + if (!ctx || !value) { + return LY_SUCCESS; + } + + dict = ly_ctx_data_dict_get(ctx); + + pthread_mutex_lock(&dict->lock); + ret = _lydict_remove(ctx, dict, value); + pthread_mutex_unlock(&dict->lock); + return ret; } +/** + * @brief Insert a new string into the dictionary. + * + * @param[in] dict Dictionary to insert into. + * @param[in] value Value to insert. + * @param[in] len Length of @p value. + * @param[in] zerocopy Whether to use the value directly or make a copy. + * @param[out] str_p Optional pointer to the inserted string. + * @return LY_SUCCESS on success, LY_ERR value on error. + */ static LY_ERR -dict_insert(const struct ly_ctx *ctx, char *value, size_t len, ly_bool zerocopy, const char **str_p) +dict_insert(struct ly_dict *dict, char *value, size_t len, ly_bool zerocopy, const char **str_p) { LY_ERR ret = LY_SUCCESS; struct ly_dict_rec *match = NULL, rec; @@ -185,12 +223,12 @@ dict_insert(const struct ly_ctx *ctx, char *value, size_t len, ly_bool zerocopy, hash = lyht_hash(value, len); /* set len as data for compare callback */ - lyht_set_cb_data(ctx->dict.hash_tab, (void *)&len); + lyht_set_cb_data(dict->hash_tab, (void *)&len); /* create record for lyht_insert */ rec.value = value; rec.refcount = 1; - ret = lyht_insert_with_resize_cb(ctx->dict.hash_tab, (void *)&rec, hash, lydict_resize_val_eq, (void **)&match); + ret = lyht_insert_with_resize_cb(dict->hash_tab, (void *)&rec, hash, lydict_resize_val_eq, (void **)&match); if (ret == LY_EEXIST) { match->refcount++; if (zerocopy) { @@ -204,7 +242,7 @@ dict_insert(const struct ly_ctx *ctx, char *value, size_t len, ly_bool zerocopy, * record is already inserted in hash table */ match->value = malloc(sizeof *match->value * (len + 1)); - LY_CHECK_ERR_RET(!match->value, LOGMEM(ctx), LY_EMEM); + LY_CHECK_ERR_RET(!match->value, LOGMEM(NULL), LY_EMEM); if (len) { memcpy(match->value, value, len); } @@ -223,10 +261,28 @@ dict_insert(const struct ly_ctx *ctx, char *value, size_t len, ly_bool zerocopy, return ret; } +LY_ERR +lysdict_insert(const struct ly_ctx *ctx, const char *value, size_t len, const char **str_p) +{ + if (!value) { + *str_p = NULL; + return LY_SUCCESS; + } + + if (!len) { + len = strlen(value); + } + + /* no need to lock dict lock, because we are inserting into a schema dict, + * which is thread safe unlike data parsing */ + return dict_insert((struct ly_dict *)&ctx->dict, (char *)value, len, 0, str_p); +} + LIBYANG_API_DEF LY_ERR lydict_insert(const struct ly_ctx *ctx, const char *value, size_t len, const char **str_p) { - LY_ERR result; + LY_ERR rc; + struct ly_dict *dict; LY_CHECK_ARG_RET(ctx, ctx, str_p, LY_EINVAL); @@ -239,17 +295,31 @@ lydict_insert(const struct ly_ctx *ctx, const char *value, size_t len, const cha len = strlen(value); } - pthread_mutex_lock((pthread_mutex_t *)&ctx->dict.lock); - result = dict_insert(ctx, (char *)value, len, 0, str_p); - pthread_mutex_unlock((pthread_mutex_t *)&ctx->dict.lock); + dict = ly_ctx_data_dict_get(ctx); + + pthread_mutex_lock(&dict->lock); + rc = dict_insert(dict, (char *)value, len, 0, str_p); + pthread_mutex_unlock(&dict->lock); + + return rc; +} - return result; +LY_ERR +lysdict_insert_zc(const struct ly_ctx *ctx, char *value, const char **str_p) +{ + if (!value) { + *str_p = NULL; + return LY_SUCCESS; + } + + return dict_insert((struct ly_dict *)&ctx->dict, value, strlen(value), 1, str_p); } LIBYANG_API_DEF LY_ERR lydict_insert_zc(const struct ly_ctx *ctx, char *value, const char **str_p) { - LY_ERR result; + LY_ERR rc; + struct ly_dict *dict; LY_CHECK_ARG_RET(ctx, ctx, str_p, LY_EINVAL); @@ -258,28 +328,30 @@ lydict_insert_zc(const struct ly_ctx *ctx, char *value, const char **str_p) return LY_SUCCESS; } - pthread_mutex_lock((pthread_mutex_t *)&ctx->dict.lock); - result = dict_insert(ctx, value, strlen(value), 1, str_p); - pthread_mutex_unlock((pthread_mutex_t *)&ctx->dict.lock); + dict = ly_ctx_data_dict_get(ctx); - return result; + pthread_mutex_lock(&dict->lock); + rc = dict_insert(dict, value, strlen(value), 1, str_p); + pthread_mutex_unlock(&dict->lock); + + return rc; } static LY_ERR -dict_dup(const struct ly_ctx *ctx, char *value, const char **str_p) +dict_dup(struct ly_dict *dict, 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); + lyht_value_equal_cb prev = lyht_set_cb(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); + ret = lyht_find(dict->hash_tab, (void *)&rec, hash, (void **)&match); if (ret == LY_SUCCESS) { /* record found, increase refcount */ match->refcount++; @@ -287,15 +359,27 @@ dict_dup(const struct ly_ctx *ctx, char *value, const char **str_p) } /* restore callback */ - lyht_set_cb(ctx->dict.hash_tab, prev); + lyht_set_cb(dict->hash_tab, prev); return ret; } +LY_ERR +lysdict_dup(const struct ly_ctx *ctx, const char *value, const char **str_p) +{ + if (!value) { + *str_p = NULL; + return LY_SUCCESS; + } + + return dict_dup((struct ly_dict *)&ctx->dict, (char *)value, str_p); +} + LIBYANG_API_DEF LY_ERR lydict_dup(const struct ly_ctx *ctx, const char *value, const char **str_p) { - LY_ERR result; + LY_ERR rc; + struct ly_dict *dict; LY_CHECK_ARG_RET(ctx, ctx, str_p, LY_EINVAL); @@ -304,9 +388,11 @@ lydict_dup(const struct ly_ctx *ctx, const char *value, const char **str_p) 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); + dict = ly_ctx_data_dict_get(ctx); + + pthread_mutex_lock(&dict->lock); + rc = dict_dup(dict, (char *)value, str_p); + pthread_mutex_unlock(&dict->lock); - return result; + return rc; } diff --git a/src/diff.c b/src/diff.c index 6ae5dc63d..b65c7df9e 100644 --- a/src/diff.c +++ b/src/diff.c @@ -29,6 +29,7 @@ #include "ly_common.h" #include "plugins_exts.h" #include "plugins_exts/metadata.h" +#include "plugins_internal.h" #include "plugins_types.h" #include "set.h" #include "tree.h" @@ -1071,7 +1072,8 @@ lyd_diff_node_metadata(const struct lyd_node *first, const struct lyd_node *seco } /* value match */ - if (m->value.realtype->plugin->compare(LYD_CTX(diff_node), &m->value, &meta_second[i]->value)) { + if (LYSC_GET_TYPE_PLG(m->value.realtype->plugin_ref)->compare(LYD_CTX(diff_node), + &m->value, &meta_second[i]->value)) { continue; } break; @@ -2210,8 +2212,7 @@ lyd_diff_merge_create(struct lyd_node **diff_match, struct lyd_node **diff, enum sleaf = (struct lysc_node_leaf *)src_diff->schema; } - if (sleaf && sleaf->dflt && !sleaf->dflt->realtype->plugin->compare(ctx, sleaf->dflt, - &((struct lyd_node_term *)src_diff)->value)) { + if (sleaf && sleaf->dflt.str && !lysc_value_cmp(src_diff->schema, NULL, &sleaf->dflt, lyd_get_value(src_diff))) { /* we deleted it, so a default value was in-use, and it matches the created value -> operation NONE */ LY_CHECK_RET(lyd_diff_change_op(*diff_match, LYD_DIFF_OP_NONE)); } else if (!lyd_compare_single(*diff_match, src_diff, 0)) { diff --git a/src/hash_table.c b/src/hash_table.c index b5f5f77a7..4011a73f5 100644 --- a/src/hash_table.c +++ b/src/hash_table.c @@ -105,9 +105,7 @@ lyht_new(uint32_t size, uint16_t val_size, lyht_value_equal_cb val_equal, void * struct ly_ht *ht; /* check that 2^x == size (power of 2) */ - assert(size && !(size & (size - 1))); - assert(val_equal && val_size); - assert(resize == 0 || resize == 1); + LY_CHECK_ARG_RET(NULL, !(size & (size - 1)), val_size, val_equal, (resize == 0) || (resize == 1), NULL); if (size < LYHT_MIN_SIZE) { size = LYHT_MIN_SIZE; diff --git a/src/in.c b/src/in.c index 38b42a8db..5d20a93c8 100644 --- a/src/in.c +++ b/src/in.c @@ -13,7 +13,6 @@ */ #define _GNU_SOURCE -#define _POSIX_C_SOURCE 200809L /* strdup, strndup */ #include "in.h" #include "in_internal.h" diff --git a/src/log.c b/src/log.c index 13da500ef..0cb76ae8f 100644 --- a/src/log.c +++ b/src/log.c @@ -30,6 +30,7 @@ #include "in_internal.h" #include "ly_common.h" #include "plugins_exts.h" +#include "plugins_internal.h" #include "set.h" #include "tree_data.h" #include "tree_data_internal.h" @@ -175,112 +176,48 @@ ly_err_new(struct ly_err_item **err, LY_ERR ecode, LY_VECODE vecode, char *data_ return e->err; } -/** - * @brief Get error record from error hash table of a context for the current thread. - * - * @param[in] ctx Context to use. - * @return Thread error record, if any. - */ -static struct ly_ctx_err_rec * -ly_err_get_rec(const struct ly_ctx *ctx) -{ - struct ly_ctx_err_rec rec, *match; - - /* 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 */ - 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; -} - -/** - * @brief Insert new error record to error hash table of a context for the current thread. - * - * @param[in] ctx Context to use. - * @return Thread error record. - */ -static struct ly_ctx_err_rec * -ly_err_new_rec(const struct ly_ctx *ctx) -{ - struct ly_ctx_err_rec new, *rec; - LY_ERR r; - - /* insert a new record */ - new.err = NULL; - new.tid = pthread_self(); - - /* reuse lock */ - /* LOCK */ - pthread_mutex_lock((pthread_mutex_t *)&ctx->lyb_hash_lock); - - r = lyht_insert(ctx->err_ht, &new, lyht_hash((void *)&new.tid, sizeof new.tid), (void **)&rec); - - /* UNLOCK */ - pthread_mutex_unlock((pthread_mutex_t *)&ctx->lyb_hash_lock); - - return r ? NULL : rec; -} - LIBYANG_API_DEF const struct ly_err_item * ly_err_first(const struct ly_ctx *ctx) { - struct ly_ctx_err_rec *rec; + struct ly_ctx_private_data *ctx_data; LY_CHECK_ARG_RET(NULL, ctx, NULL); - /* get the pointer to the matching record */ - rec = ly_err_get_rec(ctx); - - return rec ? rec->err : NULL; + ctx_data = ly_ctx_private_data_get_or_create(ctx); + LY_CHECK_RET(!ctx_data, NULL); + return ctx_data->errs; } LIBYANG_API_DEF const struct ly_err_item * ly_err_last(const struct ly_ctx *ctx) { - struct ly_ctx_err_rec *rec; + struct ly_ctx_private_data *ctx_data; LY_CHECK_ARG_RET(NULL, ctx, NULL); - /* get the pointer to the matching record */ - if (!(rec = ly_err_get_rec(ctx))) { - return NULL; - } - - return rec->err ? rec->err->prev : NULL; + ctx_data = ly_ctx_private_data_get_or_create(ctx); + LY_CHECK_RET(!ctx_data, NULL); + return ctx_data->errs ? ctx_data->errs->prev : NULL; } void ly_err_move(struct ly_ctx *src_ctx, struct ly_ctx *trg_ctx) { - struct ly_ctx_err_rec *rec; - struct ly_err_item *err = NULL; - - /* get and remove the errors from src */ - rec = ly_err_get_rec(src_ctx); - if (rec) { - err = rec->err; - rec->err = NULL; - } + struct ly_ctx_private_data *src_data, *trg_data; + struct ly_err_item *errs = NULL; + + /* get src context errs */ + src_data = ly_ctx_private_data_get_or_create(src_ctx); + errs = src_data->errs; + src_data->errs = NULL; + + /* get and free the trg context errs */ + trg_data = ly_ctx_private_data_get_or_create(trg_ctx); + ly_err_free(trg_data->errs); /* set them for trg */ - if (!(rec = ly_err_get_rec(trg_ctx))) { - if (!(rec = ly_err_new_rec(trg_ctx))) { - LOGINT(NULL); - ly_err_free(err); - return; - } - } - ly_err_free(rec->err); - rec->err = err; + ly_err_free(trg_data->errs); + trg_data->errs = errs; } LIBYANG_API_DEF void @@ -299,28 +236,31 @@ ly_err_free(void *ptr) } LIBYANG_API_DEF void -ly_err_clean(struct ly_ctx *ctx, struct ly_err_item *eitem) +ly_err_clean(const struct ly_ctx *ctx, struct ly_err_item *eitem) { - struct ly_ctx_err_rec *rec; + struct ly_ctx_private_data *ctx_data; struct ly_err_item *e; - if (!(rec = ly_err_get_rec(ctx))) { + if (!ctx) { return; } - if (rec->err == eitem) { + + ctx_data = ly_ctx_private_data_get_or_create(ctx); + if (ctx_data->errs == eitem) { eitem = NULL; } if (!eitem) { /* free all err */ - ly_err_free(rec->err); - rec->err = NULL; + ly_err_free(ctx_data->errs); + ctx_data->errs = NULL; } else { /* disconnect the error */ - for (e = rec->err; e && (e->next != eitem); e = e->next) {} + for (e = ctx_data->errs; e && (e->next != eitem); e = e->next) {} assert(e); e->next = NULL; - rec->err->prev = e; + ctx_data->errs->prev = e; + /* free this err and newer */ ly_err_free(eitem); } @@ -468,18 +408,16 @@ static LY_ERR log_store(const struct ly_ctx *ctx, LY_LOG_LEVEL level, LY_ERR err, LY_VECODE vecode, char *msg, char *data_path, char *schema_path, uint64_t line, char *apptag) { - struct ly_ctx_err_rec *rec; + struct ly_ctx_private_data *ctx_data; struct ly_err_item *e, *last; assert(ctx && (level < LY_LLVRB)); - if (!(rec = ly_err_get_rec(ctx))) { - if (!(rec = ly_err_new_rec(ctx))) { - goto mem_fail; - } - } + /* get context private data */ + ctx_data = ly_ctx_private_data_get_or_create(ctx); + LY_CHECK_GOTO(!ctx_data, mem_fail); - e = rec->err; + e = ctx_data->errs; if (!e) { /* if we are only to fill in path, there must have been an error stored */ assert(msg); @@ -488,7 +426,7 @@ log_store(const struct ly_ctx *ctx, LY_LOG_LEVEL level, LY_ERR err, LY_VECODE ve e->prev = e; e->next = NULL; - rec->err = e; + ctx_data->errs = e; } else if (!msg) { /* only filling the path */ assert(data_path || schema_path); @@ -939,7 +877,7 @@ lyplg_ext_parse_log(const struct lysp_ctx *pctx, const struct lysp_ext_instance ly_vlog_build_path_line(PARSER_CTX(pctx), &data_path, &schema_path, &line); va_start(ap, format); - ly_ext_log(PARSER_CTX(pctx), ext->record->plugin.id, level, err, data_path, schema_path, line, format, ap); + ly_ext_log(PARSER_CTX(pctx), LYSC_GET_EXT_PLG(ext->plugin_ref)->id, level, err, data_path, schema_path, line, format, ap); va_end(ap); } @@ -956,7 +894,7 @@ lyplg_ext_compile_log(const struct lysc_ctx *cctx, const struct lysc_ext_instanc } va_start(ap, format); - ly_ext_log(ext->module->ctx, ext->def->plugin->id, level, err, NULL, schema_path, 0, format, ap); + ly_ext_log(ext->module->ctx, LYSC_GET_EXT_PLG(ext->def->plugin_ref)->id, level, err, NULL, schema_path, 0, format, ap); va_end(ap); } @@ -973,7 +911,7 @@ lyplg_ext_compile_log_path(const char *path, const struct lysc_ext_instance *ext } va_start(ap, format); - ly_ext_log(ext->module->ctx, ext->def->plugin->id, level, err, NULL, schema_path, 0, format, ap); + ly_ext_log(ext->module->ctx, LYSC_GET_EXT_PLG(ext->def->plugin_ref)->id, level, err, NULL, schema_path, 0, format, ap); va_end(ap); } @@ -994,7 +932,8 @@ _lyplg_ext_compile_log_err(const struct ly_err_item *eitem, const struct lysc_ex } va_start(ap, ext); - ly_ext_log(ext->module->ctx, ext->def->plugin->id, eitem->level, eitem->err, data_path, schema_path, eitem->line, "%s", ap); + ly_ext_log(ext->module->ctx, LYSC_GET_EXT_PLG(ext->def->plugin_ref)->id, eitem->level, eitem->err, + data_path, schema_path, eitem->line, "%s", ap); va_end(ap); } diff --git a/src/log.h b/src/log.h index 85f2ac6d4..fc18b24ea 100644 --- a/src/log.h +++ b/src/log.h @@ -350,7 +350,7 @@ LIBYANG_API_DECL void ly_err_print(const struct ly_ctx *ctx, const struct ly_err * @param[in] ctx Relative context. * @param[in] eitem Oldest error structure to remove, optional. */ -LIBYANG_API_DECL void ly_err_clean(struct ly_ctx *ctx, struct ly_err_item *eitem); +LIBYANG_API_DECL void ly_err_clean(const struct ly_ctx *ctx, struct ly_err_item *eitem); /** @} errors */ diff --git a/src/ly_common.c b/src/ly_common.c index ac62677ef..3539ddbf4 100644 --- a/src/ly_common.c +++ b/src/ly_common.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -36,10 +37,25 @@ #include #include "compat.h" +#include "schema_compile_node.h" +#include "tree_data_internal.h" #include "tree_schema_internal.h" #include "version.h" #include "xml.h" +# define _POSIX_C_SOURCE 200809L /* pthread_rwlock_t */ + +/**< lock for creating and destroying both private & shared context data */ +static pthread_rwlock_t ly_ctx_data_rwlock = PTHREAD_RWLOCK_INITIALIZER; + +/**< sized array ([sized array](@ref sizedarrays)) of private context data. + * The context is identified by the thread ID of the thread that created it and its address. */ +static struct ly_ctx_private_data *ly_private_ctx_data; + +/**< sized array ([sized array](@ref sizedarrays)) of shared context data. + * The context is identified by the memory address of the context. */ +static struct ly_ctx_shared_data *ly_shared_ctx_data; + LIBYANG_API_DEF uint32_t ly_version_so_major(void) { @@ -88,6 +104,466 @@ ly_version_proj_str(void) return LY_PROJ_VERSION; } +/** + * @brief Callback for comparing two leafref links records. + */ +ly_bool +ly_ctx_ht_leafref_links_equal_cb(void *val1_p, void *val2_p, ly_bool UNUSED(mod), void *UNUSED(cb_data)) +{ + struct lyd_leafref_links_rec **rec1 = val1_p, **rec2 = val2_p; + + return (*rec1)->node == (*rec2)->node; +} + +/** + * @brief Callback for freeing two leafref links records. + */ +void +ly_ctx_ht_leafref_links_rec_free(void *val_p) +{ + struct lyd_leafref_links_rec **rec = val_p; + + lyd_free_leafref_links_rec(*rec); + free(*rec); +} + +/** + * @brief Callback for comparing two pattern records. + */ +static ly_bool +ly_ctx_ht_pattern_equal_cb(void *val1_p, void *val2_p, ly_bool UNUSED(mod), void *UNUSED(cb_data)) +{ + struct ly_pattern_ht_rec *val1 = val1_p; + struct ly_pattern_ht_rec *val2 = val2_p; + + /* compare the pattern strings, if they match we can use the stored + * serialized value to create the pcre2 code for the pattern */ + return !strcmp(val1->pattern, val2->pattern); +} + +/** + * @brief Callback for freeing a pattern record. + */ +static void +ly_ctx_ht_pattern_free_cb(void *val_p) +{ + struct ly_pattern_ht_rec *val = val_p; + + if (val->pcode) { + /* free the pcode */ + pcre2_code_free(val->pcode); + } +} + +/** + * @brief Remove private context data from the sized array and free its contents. + * + * @param[in] private_data Private context data to free. + */ +static void +ly_ctx_private_data_remove_and_free(struct ly_ctx_private_data *private_data) +{ + LY_ARRAY_COUNT_TYPE idx; + + if (!private_data) { + return; + } + + ly_err_free(private_data->errs); + + idx = private_data - ly_private_ctx_data; + if (idx < LY_ARRAY_COUNT(ly_private_ctx_data) - 1) { + /* replace the private data with the last one if it even was added */ + ly_private_ctx_data[idx] = ly_private_ctx_data[LY_ARRAY_COUNT(ly_private_ctx_data) - 1]; + } + LY_ARRAY_DECREMENT_FREE(ly_private_ctx_data); +} + +/** + * @brief Create the private context data for a specific context. + * + * @param[in] ctx Context to create the private data for. + * @param[out] private_data Optional created private context data. + * @return LY_SUCCESS on success, LY_EMEM on memory allocation failure. + */ +static LY_ERR +ly_ctx_private_data_create(const struct ly_ctx *ctx, struct ly_ctx_private_data **private_data) +{ + pthread_t tid = pthread_self(); + struct ly_ctx_private_data *priv_data = NULL; + LY_ERR rc = LY_SUCCESS; + + *private_data = NULL; + + /* create the private context data */ + LY_ARRAY_NEW_GOTO(ctx, ly_private_ctx_data, priv_data, rc, cleanup); + + /* fill */ + priv_data->tid = tid; + priv_data->ctx = ctx; + priv_data->errs = NULL; + + *private_data = priv_data; + +cleanup: + if (rc) { + ly_ctx_private_data_remove_and_free(priv_data); + } + return rc; +} + +/** + * @brief Get the private context data for a specific context. + * + * @param[in] ctx Context whose private data to get. + * @param[in] lock Whether to lock the data access. + * @param[in] own_data_only Whether to return only the private data of the current thread. + * @return Private context data of @p ctx, NULL if not found. + */ +static struct ly_ctx_private_data * +_ly_ctx_private_data_get(const struct ly_ctx *ctx, ly_bool lock, ly_bool own_data_only) +{ + struct ly_ctx_private_data *iter; + ly_bool found = 0; + pthread_t tid = pthread_self(); + + if (lock) { + /* RD LOCK */ + pthread_rwlock_rdlock(&ly_ctx_data_rwlock); + } + + LY_ARRAY_FOR(ly_private_ctx_data, struct ly_ctx_private_data, iter) { + /* either own - ctx and tid match, or "context's" - thread does not matter */ + if ((iter->ctx == ctx) && (!own_data_only || (iter->tid == tid))) { + found = 1; + break; + } + } + + if (lock) { + /* RD UNLOCK */ + pthread_rwlock_unlock(&ly_ctx_data_rwlock); + } + + /* pointer to the structure, cannot be changed so lock is not required */ + return found ? iter : NULL; +} + +struct ly_ctx_private_data * +ly_ctx_private_data_get_or_create(const struct ly_ctx *ctx) +{ + struct ly_ctx_private_data *private_data; + LY_ERR r; + + /* try to find existing data */ + private_data = _ly_ctx_private_data_get(ctx, 1, 1); + if (private_data) { + return private_data; + } + + /* WR LOCK */ + pthread_rwlock_wrlock(&ly_ctx_data_rwlock); + + /* create it */ + r = ly_ctx_private_data_create(ctx, &private_data); + if (r) { + /* NULL to avoid infinite loop in LOGERR */ + LOGERR(NULL, r, "Failed to create context private data."); + assert(0); + } + + /* WR UNLOCK */ + pthread_rwlock_unlock(&ly_ctx_data_rwlock); + + return private_data; +} + +/** + * @brief Remove shared context data from the sized array and free its contents. + * + * @param[in] shared_data Shared context data to free. + */ +static void +ly_ctx_shared_data_remove_and_free(struct ly_ctx_shared_data *shared_data) +{ + LY_ARRAY_COUNT_TYPE idx; + + if (!shared_data) { + return; + } + + lyht_free(shared_data->pattern_ht, ly_ctx_ht_pattern_free_cb); + lydict_clean(shared_data->data_dict); + free(shared_data->data_dict); + lyht_free(shared_data->leafref_links_ht, ly_ctx_ht_leafref_links_rec_free); + + idx = shared_data - ly_shared_ctx_data; + if (idx < LY_ARRAY_COUNT(ly_shared_ctx_data) - 1) { + /* replace the shared data with the last one */ + ly_shared_ctx_data[idx] = ly_shared_ctx_data[LY_ARRAY_COUNT(ly_shared_ctx_data) - 1]; + } + LY_ARRAY_DECREMENT_FREE(ly_shared_ctx_data); +} + +/** + * @brief Create the shared context data for a specific context. + * + * @param[in] ctx Context to create the shared data for. + * @param[out] shared_data Optional created shared context data. + * @return LY_SUCCESS on success, LY_EMEM on memory allocation failure. + */ +static LY_ERR +ly_ctx_shared_data_create(const struct ly_ctx *ctx, struct ly_ctx_shared_data **shared_data) +{ + LY_ERR rc = LY_SUCCESS; + struct ly_ctx_shared_data *shrd_data; + + if (shared_data) { + *shared_data = NULL; + } + + /* create the shared context data */ + LY_ARRAY_NEW_GOTO(ctx, ly_shared_ctx_data, shrd_data, rc, cleanup); + + /* fill */ + shrd_data->ctx = ctx; + + /* pattern hash table */ + shrd_data->pattern_ht = lyht_new(LYHT_MIN_SIZE, sizeof(struct ly_pattern_ht_rec), + ly_ctx_ht_pattern_equal_cb, NULL, 1); + LY_CHECK_ERR_GOTO(!shrd_data->pattern_ht, rc = LY_EMEM, cleanup); + + /* data dictionary */ + shrd_data->data_dict = malloc(sizeof *shrd_data->data_dict); + LY_CHECK_ERR_GOTO(!shrd_data->data_dict, rc = LY_EMEM, cleanup); + lydict_init(shrd_data->data_dict); + + /* leafref set */ + if (ctx->opts & LY_CTX_LEAFREF_LINKING) { + /** + * storing the pointer instead of record itself is needed to avoid invalid memory reads. Hash table can reallocate + * its memory completely during various manipulation function (e.g. remove, insert). In case of using pointers, the + * pointer can be reallocated safely, while record itself remains untouched and can be accessed/modified freely + * */ + shrd_data->leafref_links_ht = lyht_new(1, sizeof(struct lyd_leafref_links_rec *), ly_ctx_ht_leafref_links_equal_cb, NULL, 1); + LY_CHECK_ERR_GOTO(!shrd_data->leafref_links_ht, rc = LY_EMEM, cleanup); + } + + /* ext clb and leafref links locks */ + pthread_mutex_init(&shrd_data->ext_clb_lock, NULL); + pthread_mutex_init(&shrd_data->leafref_links_lock, NULL); + + /* refcount */ + ATOMIC_STORE_RELAXED(shrd_data->refcount, 1); + + if (shared_data) { + *shared_data = shrd_data; + } + +cleanup: + if (rc) { + ly_ctx_shared_data_remove_and_free(shrd_data); + } + return rc; +} + +/** + * @brief Get the shared context data for a specific context. + * + * @param[in] ctx Context whose shared data to get. + * @param[in] lock Whether to lock the data access. + * @param[out] idx Optional index of the shared data in the array. + */ +static struct ly_ctx_shared_data * +_ly_ctx_shared_data_get(const struct ly_ctx *ctx, ly_bool lock) +{ + struct ly_ctx_shared_data *iter; + ly_bool found = 0; + + if (lock) { + /* RD LOCK */ + pthread_rwlock_rdlock(&ly_ctx_data_rwlock); + } + + LY_ARRAY_FOR(ly_shared_ctx_data, struct ly_ctx_shared_data, iter) { + if (iter->ctx == ctx) { + found = 1; + break; + } + } + + if (lock) { + /* RD UNLOCK */ + pthread_rwlock_unlock(&ly_ctx_data_rwlock); + } + + /* pointer to the structure, cannot be changed so lock is not required */ + return found ? iter : NULL; +} + +struct ly_ctx_shared_data * +ly_ctx_shared_data_get(const struct ly_ctx *ctx) +{ + struct ly_ctx_shared_data *shared_data; + + shared_data = _ly_ctx_shared_data_get(ctx, 1); + if (!shared_data) { + /* NULL to avoid infinite loop in LOGERR */ + LOGERR(NULL, LY_EINT, "Context shared data not found."); + assert(0); + } + return shared_data; +} + +struct ly_dict * +ly_ctx_data_dict_get(const struct ly_ctx *ctx) +{ + struct ly_ctx_shared_data *shared_data; + + shared_data = ly_ctx_shared_data_get(ctx); + return shared_data ? shared_data->data_dict : NULL; +} + +LY_ERR +ly_ctx_data_add(const struct ly_ctx *ctx) +{ + LY_ERR rc = LY_SUCCESS; + struct ly_ctx_private_data *private_data; + struct ly_ctx_shared_data *shared_data; + + /* WR LOCK */ + pthread_rwlock_wrlock(&ly_ctx_data_rwlock); + + /* check for duplicates in private context data, not allowed */ + private_data = _ly_ctx_private_data_get(ctx, 0, 1); + if (private_data) { + /* ctx pointers can match only if the context is printed (they have the same memory address) */ + assert(private_data->ctx->opts & LY_CTX_INT_IMMUTABLE); + + /* use NULL as ctx to avoid RD lock while holding WR lock */ + LOGERR(NULL, LY_EEXIST, "Only one printed context per memory chunk and thread is allowed."); + rc = LY_EEXIST; + goto cleanup; + } + + /* create the private context data, freed by the caller in case we fail later on */ + rc = ly_ctx_private_data_create(ctx, &private_data); + if (rc) { + /* NULL to avoid infinite loop in LOGERR */ + LOGERR(NULL, rc, "Failed to create context private data."); + goto cleanup; + } + + /* check for duplicates in shared context data */ + shared_data = _ly_ctx_shared_data_get(ctx, 0); + if (shared_data) { + /* found, we can end */ + ATOMIC_INC_RELAXED(shared_data->refcount); + goto cleanup; + } + + /* create the shared context data */ + rc = ly_ctx_shared_data_create(ctx, NULL); + if (rc) { + /* NULL to avoid infinite loop in LOGERR */ + LOGERR(NULL, rc, "Failed to create context shared data."); + goto cleanup; + } + +cleanup: + /* WR UNLOCK */ + pthread_rwlock_unlock(&ly_ctx_data_rwlock); + return rc; +} + +void +ly_ctx_data_del(const struct ly_ctx *ctx) +{ + struct ly_ctx_private_data *private_data; + struct ly_ctx_shared_data *shared_data; + + /* WR LOCK */ + pthread_rwlock_wrlock(&ly_ctx_data_rwlock); + + /* free private data of all the threads for this context */ + while ((private_data = _ly_ctx_private_data_get(ctx, 0, 0))) { + /* free the private data */ + ly_ctx_private_data_remove_and_free(private_data); + } + + /* get the shared context data */ + shared_data = _ly_ctx_shared_data_get(ctx, 0); + if (!shared_data) { + /* not found, nothing to do */ + goto cleanup; + } + assert(ATOMIC_LOAD_RELAXED(shared_data->refcount)); + + /* decrease refcount */ + ATOMIC_DEC_RELAXED(shared_data->refcount); + if (ATOMIC_LOAD_RELAXED(shared_data->refcount)) { + goto cleanup; + } + + /* free the shared members */ + ly_ctx_shared_data_remove_and_free(shared_data); + +cleanup: + /* WR UNLOCK */ + pthread_rwlock_unlock(&ly_ctx_data_rwlock); +} + +LY_ERR +ly_ctx_get_or_compile_pattern_code(const struct ly_ctx *ctx, const char *pattern, const pcre2_code **pcode) +{ + LY_ERR rc = LY_SUCCESS; + struct ly_ctx_shared_data *ctx_data; + struct ly_pattern_ht_rec rec = {0}, *found_rec = NULL; + uint32_t hash; + pcre2_code *pcode_tmp = NULL; + + assert(ctx && pattern); + + if (pcode) { + *pcode = NULL; + } + + ctx_data = ly_ctx_shared_data_get(ctx); + LY_CHECK_RET(!ctx_data, LY_EINT); + + /* try to find the pattern code in the pattern ht */ + hash = lyht_hash(pattern, strlen(pattern)); + rec.pattern = pattern; + if (!lyht_find(ctx_data->pattern_ht, &rec, hash, (void **)&found_rec)) { + /* found it, return it */ + if (pcode) { + *pcode = found_rec->pcode; + } + goto cleanup; + } + + /* didnt find it, need to compile it */ + LY_CHECK_GOTO(rc = lys_compile_type_pattern_check(ctx, pattern, &pcode_tmp), cleanup); + + /* store the compiled pattern code in the hash table */ + hash = lyht_hash(pattern, strlen(pattern)); + rec.pattern = pattern; + rec.pcode = pcode_tmp; + LY_CHECK_GOTO(rc = lyht_insert_no_check(ctx_data->pattern_ht, &rec, hash, NULL), cleanup); + + if (pcode) { + *pcode = pcode_tmp; + pcode_tmp = NULL; + } + +cleanup: + if (rc) { + /* only free the pcode if we failed, because it belongs to the hash table */ + pcre2_code_free(pcode_tmp); + } + return rc; +} + void * ly_realloc(void *ptr, size_t size) { diff --git a/src/ly_common.h b/src/ly_common.h index 95c904654..5a8602b7e 100644 --- a/src/ly_common.h +++ b/src/ly_common.h @@ -335,35 +335,71 @@ int LY_VCODE_INSTREXP_len(const char *str); *****************************************************************************/ /** - * @brief Context error hash table record. + * @brief Private run-time context data. + * + * The data is thread and context address specific. It is used to store + * thread-specific data related to the context. + * + * No synchronization is needed for this data, it is only accessed by the thread that created it. + */ +struct ly_ctx_private_data { + const struct ly_ctx *ctx; /**< context to which this data belongs */ + pthread_t tid; /**< thread ID of the thread that created this context data */ + + struct ly_err_item *errs; /**< thread-specific errors related to the context */ +}; + +/** + * @brief Shared run-time context data. + * + * It is used to store data that can be shared between multiple threads + * using the same context address, e.g. printed contexts created from the same memory address. + * + * Members need to be protected by locks. */ -struct ly_ctx_err_rec { - struct ly_err_item *err; /** pointer to the error items, if any */ - pthread_t tid; /** pthread thread ID */ +struct ly_ctx_shared_data { + const struct ly_ctx *ctx; /**< context to which this data belongs */ + ATOMIC_T refcount; /**< always 1 when using normal (not-printed) contexts (=> refcount does not have + * to be the same as the number of threads using the same context). Refcount gets + * incremented only when a new (next) printed context + * is created from the same memory address. */ + + struct ly_ht *pattern_ht; /**< ht for storing patterns and their serialized pattern codes, + * these codes can be deserialized into pcre2_code that can then be used directly. + * A pattern is used both as a key and a value to search for. + * This ht is only written to when the context is being compiled, + * afterwards, it is read-only. */ + + pthread_mutex_t ext_clb_lock; /**< lock for accessing the extension callback */ + ly_ext_data_clb ext_clb; /**< optional callback for providing extension-specific run-time data for extensions */ + void *ext_clb_data; /**< optional private data for ext_clb */ + + struct ly_dict *data_dict; /**< dictionary for data trees */ + + pthread_mutex_t leafref_links_lock; /**< lock for accessing the leafref links hash table */ + struct ly_ht *leafref_links_ht; /**< hash table of leafref links between term data nodes */ }; +#define LY_CTX_INT_IMMUTABLE 0x80000000 /**< marks a context that was printed into a fixed-size memory block and + can even be shared between processes so it cannot be changed */ + /** * @brief Context of the YANG schemas */ struct ly_ctx { struct ly_dict dict; /**< dictionary to effectively store strings used in the context related structures */ struct ly_set search_paths; /**< set of directories where to search for schema's imports/includes */ - struct ly_set list; /**< set of loaded YANG schemas */ - ly_module_imp_clb imp_clb; /**< optional callback for retrieving missing included or imported modules */ + struct ly_set modules; /**< set of loaded YANG schemas */ + ly_module_imp_clb imp_clb; /**< optional callback for retrieving missing included or imported models */ void *imp_clb_data; /**< optional private data for ::ly_ctx.imp_clb */ struct lys_glob_unres unres; /**< global unres, should be empty unless there are modules prepared for compilation if ::LY_CTX_EXPLICIT_COMPILE flag is set */ - uint16_t change_count; /**< count of changes of the context, on some changes it could be incremented + uint32_t change_count; /**< count of changes of the context, on some changes it could be incremented more times */ uint32_t mod_hash; /**< hash of the current context, includes name/revision/enabled features/implement state of every loaded module */ - uint16_t flags; /**< context settings, see @ref contextoptions */ + uint32_t opts; /**< context options, see @ref contextoptions */ - ly_ext_data_clb ext_clb; /**< optional callback for providing extension-specific run-time data for extensions */ - void *ext_clb_data; /**< optional private data for ::ly_ctx.ext_clb */ - struct ly_ht *err_ht; /**< hash table of thread-specific list of errors related to the context */ - pthread_mutex_t lyb_hash_lock; /**< lock for storing LYB schema hashes in schema nodes */ - struct ly_ht *leafref_links_ht; /**< hash table of leafref links between term data nodes */ struct ly_set plugins_types; /**< context specific set of type plugins */ struct ly_set plugins_extensions; /**< contets specific set of extension plugins */ }; @@ -375,6 +411,65 @@ struct ly_ctx { */ void ly_ctx_new_change(struct ly_ctx *ctx); +/** + * @brief Add a ctx data for a new context. + * + * Each context has its own thread-specific private data, see ::ly_ctx_private_data. + * Each context also has shared data, see ::ly_ctx_shared_data. + * Shared data can only be shared between printed contexts created from the same memory address. + * + * @param[in] ctx Newly created context. + * @return LY_SUCCESS on success, LY_EEXIST if a printed context created by the same thread and on the same memory address + * already exists, LY_EMEM on memory allocation failure. + */ +LY_ERR ly_ctx_data_add(const struct ly_ctx *ctx); + +/** + * @brief Remove a ctx data of a destroyed context. + * + * @param[in] ctx Destroyed context. + */ +void ly_ctx_data_del(const struct ly_ctx *ctx); + +/** + * @brief Get private (thread-specific) context data or create it if it does not exist. + * + * @param[in] ctx Context whose data to get. + * @return Context data of @p ctx, NULL on memory allocation failure. + */ +struct ly_ctx_private_data *ly_ctx_private_data_get_or_create(const struct ly_ctx *ctx); + +/** + * @brief Get shared (between the same contexts) context data. + * + * The contexts can be the same only if they are printed contexts created from the same memory address, + * although each of these contexts must be created by a different thread. + * + * @param[in] ctx Context whose shared data to get. + * @return Context shared data of @p ctx, NULL if not found. + */ +struct ly_ctx_shared_data *ly_ctx_shared_data_get(const struct ly_ctx *ctx); + +/** + * @brief Get context's data dictionary. + * + * @param[in] ctx Context whose data dictionary to get. + * @return Context's data dictionary, NULL if not found. + */ +struct ly_dict *ly_ctx_data_dict_get(const struct ly_ctx *ctx); + +/** + * @brief Hash table value-equal callback for comparing leafref links hash table record. + */ +ly_bool ly_ctx_ht_leafref_links_equal_cb(void *val1_p, void *val2_p, ly_bool mod, void *cb_data); + +/** + * @brief Callback for freeing leafref links recorcd internal resources. + * + * @param[in] val_p Pointer to leafref links record + */ +void ly_ctx_ht_leafref_links_rec_free(void *val_p); + /** * @brief Get the (only) implemented YANG module specified by its name. * @@ -386,27 +481,83 @@ void ly_ctx_new_change(struct ly_ctx *ctx); */ struct lys_module *ly_ctx_get_module_implemented2(const struct ly_ctx *ctx, const char *name, size_t name_len); +/** + * @brief Get or compile a PCRE2 pattern code. + * + * If the pattern is not found in the context, it is compiled and cached. + * + * @param[in] ctx Context to get or create the pattern code in. + * @param[in] pattern Pattern string to search for or to compile and store. + * @param[out] pcode Optional compiled pattern code. DO NOT FREE IT, it is owned by the context. + * @return LY_ERR value. + */ +LY_ERR ly_ctx_get_or_compile_pattern_code(const struct ly_ctx *ctx, const char *pattern, const pcre2_code **pcode); + /****************************************************************************** - * Generic useful functions. + * Dictionary *****************************************************************************/ +/* + * The following lysdict_*() functions operate on the internal schema dictionary of the given context. + * They do NOT lock a mutex as opposed to the lydict_*() function family, because they do not operate on data. + * This is because there should be no concurrency when parsing modules into the given context. + */ + /** - * @brief Insert string into dictionary. + * @brief Insert string into the internal schema dictionary of @p ctx. Use ::lydict_insert() to + * insert into the data dictionary. * - * @param[in] CTX libyang context. - * @param[in] STRING string to store. - * @param[in] LEN length of the string in WORD to store. - * @param[in,out] DYNAMIC Set to 1 if @p STRING is dynamically allocated, 0 otherwise. - * If set to 1, zerocopy version of lydict_insert is used. - * @param[out] TARGET pointer is set to @p STRING value stored in the dictionary. + * @param[in] ctx Context whose schema dictionary to store the string in. + * @param[in] value String to be stored in the dictionary. + * @param[in] len Number of bytes to store. + * @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 of successful insertion into dictionary, note that the function does not return LY_EEXIST. + * @return LY_EMEM in case of memory allocation failure. */ -#define INSERT_STRING_RET(CTX, STRING, LEN, DYNAMIC, TARGET) \ - if (DYNAMIC) { \ - LY_CHECK_RET(lydict_insert_zc(CTX, (char *)(STRING), &(TARGET))); \ - } else { \ - LY_CHECK_RET(lydict_insert(CTX, LEN ? (STRING) : "", LEN, &(TARGET))); \ - } \ - DYNAMIC = 0 +LY_ERR lysdict_insert(const struct ly_ctx *ctx, const char *value, size_t len, const char **str_p); + +/** + * @brief Insert string into the internal schema dictionary of @p ctx - zerocopy version. + * Use ::lydict_insert_zc() to insert into the data dictionary. + * + * @param[in] ctx Context whose schema dictionary to store the string in. + * @param[in] value String to be stored in the dictionary. + * @param[in] len Number of bytes to store. + * @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 of successful insertion into dictionary, note that the function does not return LY_EEXIST. + * @return LY_EMEM in case of memory allocation failure. + */ +LY_ERR lysdict_insert_zc(const struct ly_ctx *ctx, char *value, const char **str_p); + +/** + * @brief Remove specified string from the internal schema dictionary of @p ctx. It decrements reference + * counter for the string and if it is zero, the string itself is freed. + * + * @param[in] ctx libyang context handler + * @param[in] value String to be freed. Note, that not only the string itself + * must match the stored value, but also the address is being compared and the + * counter is decremented only if it matches. If NULL, function does nothing. + * @return LY_SUCCESS if the value was found and removed (or refcount decreased). + * @return LY_ENOTFOUND if the value was not found. + * @return LY_ERR on other errors. + */ +LY_ERR lysdict_remove(const struct ly_ctx *ctx, const char *value); + +/** + * @brief Duplicate a string in the internal schema dictionary of @p ctx. Only a reference counter is incremented. + * + * @param[in] ctx Context whose schema dictionary to duplicate the string in. + * @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 + */ +LY_ERR lysdict_dup(const struct ly_ctx *ctx, const char *value, const char **str_p); + +/****************************************************************************** + * Generic useful functions. + *****************************************************************************/ /** * @brief Wrapper for realloc() call. The only difference is that if it fails to @@ -690,9 +841,11 @@ LY_ERR ly_strcat(char **dest, const char *format, ...) _FORMAT_PRINTF(2, 3); * @brief Get schema (context) for a mount point. * * @param[in] ext Compiled extension instance where the context is also stored. + * @param[in] parent Data parent node instance of a schema node with @p ext instance. In special cases + * (when not working with data) it can be NULL! * @param[out] ext_ctx Schema to use for parsing the data. * @return LY_ERR value. */ -LY_ERR lyplg_ext_schema_mount_get_ctx(struct lysc_ext_instance *ext, const struct ly_ctx **ext_ctx); +LY_ERR lyplg_ext_schema_mount_get_ctx(struct lysc_ext_instance *ext, const struct lyd_node *parent, const struct ly_ctx **ext_ctx); #endif /* LY_COMMON_H_ */ diff --git a/src/lyb.c b/src/lyb.c index ca4272285..0c8c0d030 100644 --- a/src/lyb.c +++ b/src/lyb.c @@ -78,10 +78,7 @@ lyb_get_hash(const struct lysc_node *node, uint8_t collision_id) return lyb_generate_hash(node, collision_id); } -/** - * @brief Module DFS callback filling all cached hashes of a schema node. - */ -static LY_ERR +LY_ERR lyb_cache_node_hash_cb(struct lysc_node *node, void *UNUSED(data), ly_bool *UNUSED(dfs_continue)) { if (node->hash[0]) { @@ -96,16 +93,3 @@ lyb_cache_node_hash_cb(struct lysc_node *node, void *UNUSED(data), ly_bool *UNUS return LY_SUCCESS; } - -void -lyb_cache_module_hash(const struct lys_module *mod) -{ - /* LOCK */ - pthread_mutex_lock(&mod->ctx->lyb_hash_lock); - - /* store all cached hashes for all the nodes */ - lysc_module_dfs_full(mod, lyb_cache_node_hash_cb, NULL); - - /* UNLOCK */ - pthread_mutex_unlock(&mod->ctx->lyb_hash_lock); -} diff --git a/src/lyb.h b/src/lyb.h index 5fd9f89e2..c4c551165 100644 --- a/src/lyb.h +++ b/src/lyb.h @@ -189,10 +189,8 @@ void lyd_lyb_ctx_free(struct lyd_ctx *lydctx); LYB_HASH lyb_get_hash(const struct lysc_node *node, uint8_t collision_id); /** - * @brief Fill the hash cache of all the schema nodes of a module. - * - * @param[in] mod Module to process. + * @brief Module DFS callback filling all cached hashes of a schema node. */ -void lyb_cache_module_hash(const struct lys_module *mod); +LY_ERR lyb_cache_node_hash_cb(struct lysc_node *node, void *data, ly_bool *dfs_continue); #endif /* LY_LYB_H_ */ diff --git a/src/parser_common.c b/src/parser_common.c index 0b221af72..ad75f6b7c 100644 --- a/src/parser_common.c +++ b/src/parser_common.c @@ -114,11 +114,11 @@ lyd_parser_notif_eventtime_validate(const struct lyd_node *node) /* validate */ value = lyd_get_value(node); - rc = lyplg_type_validate_patterns(patterns, value, strlen(value), &err); + rc = lyplg_type_validate_patterns(ctx, patterns, value, strlen(value), &err); } cleanup: - FREE_ARRAY(&cctx.free_ctx, patterns, lysc_pattern_free); + FREE_ARRAY(cctx.ctx, patterns, lysc_pattern_free); if (rc && err) { ly_err_print(ctx, err); ly_err_free(err); @@ -496,16 +496,16 @@ lys_parser_fill_filepath(struct ly_ctx *ctx, struct ly_in *in, const char **file switch (in->type) { case LY_IN_FILEPATH: if (realpath(in->method.fpath.filepath, path) != NULL) { - lydict_insert(ctx, path, 0, filepath); + lysdict_insert(ctx, path, 0, filepath); } else { - lydict_insert(ctx, in->method.fpath.filepath, 0, filepath); + lysdict_insert(ctx, in->method.fpath.filepath, 0, filepath); } break; case LY_IN_FD: #ifdef __APPLE__ if (fcntl(in->method.fd, F_GETPATH, path) != -1) { - lydict_insert(ctx, path, 0, filepath); + lysdict_insert(ctx, path, 0, filepath); } #elif defined _WIN32 HANDLE h = _get_osfhandle(in->method.fd); @@ -515,13 +515,13 @@ lys_parser_fill_filepath(struct ly_ctx *ctx, struct ly_in *in, const char **file char *buf = calloc(info.FileNameLength + 1 /* trailing NULL */, MB_CUR_MAX); len = wcstombs(buf, info.FileName, info.FileNameLength * MB_CUR_MAX); - lydict_insert(ctx, buf, len, filepath); + lysdict_insert(ctx, buf, len, filepath); } #else /* get URI if there is /proc */ sprintf(proc_path, "/proc/self/fd/%d", in->method.fd); if ((len = readlink(proc_path, path, PATH_MAX - 1)) > 0) { - lydict_insert(ctx, path, len, filepath); + lysdict_insert(ctx, path, len, filepath); } #endif break; @@ -621,8 +621,8 @@ lysp_stmt_dup(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_st } last = child; - LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->stmt, 0, &child->stmt)); - LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &child->arg)); + LY_CHECK_RET(lysdict_insert(PARSER_CTX(ctx), stmt->stmt, 0, &child->stmt)); + LY_CHECK_RET(lysdict_insert(PARSER_CTX(ctx), stmt->arg, 0, &child->arg)); child->format = stmt->format; LY_CHECK_RET(ly_dup_prefix_data(PARSER_CTX(ctx), stmt->format, stmt->prefix_data, &child->prefix_data)); child->flags = stmt->flags; @@ -654,7 +654,7 @@ lysp_stmt_ext(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, enum ly_stmt i LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *exts, e, LY_EMEM); /* store name and insubstmt info */ - LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->stmt, 0, &e->name)); + LY_CHECK_RET(lysdict_insert(PARSER_CTX(ctx), stmt->stmt, 0, &e->name)); e->parent_stmt = insubstmt; e->parent_stmt_index = insubstmt_index; e->parsed = NULL; @@ -662,7 +662,7 @@ lysp_stmt_ext(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, enum ly_stmt i /* get optional argument */ if (stmt->arg) { - LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &e->argument)); + LY_CHECK_RET(lysdict_insert(PARSER_CTX(ctx), stmt->arg, 0, &e->argument)); } return LY_SUCCESS; @@ -691,7 +691,7 @@ lysp_stmt_text_field(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint32_ } LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg)); - LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, value)); + LY_CHECK_RET(lysdict_insert(PARSER_CTX(ctx), stmt->arg, 0, value)); for (const struct lysp_stmt *child = stmt->child; child; child = child->next) { switch (child->kw) { @@ -727,7 +727,7 @@ lysp_stmt_qnames(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp /* allocate new pointer */ LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *qnames, item, LY_EMEM); - LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &item->str)); + LY_CHECK_RET(lysdict_insert(PARSER_CTX(ctx), stmt->arg, 0, &item->str)); item->mod = PARSER_CUR_PMOD(ctx); for (const struct lysp_stmt *child = stmt->child; child; child = child->next) { @@ -764,7 +764,7 @@ lysp_stmt_text_fields(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, const /* allocate new pointer */ LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *texts, item, LY_EMEM); - LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, item)); + LY_CHECK_RET(lysdict_insert(PARSER_CTX(ctx), stmt->arg, 0, item)); for (const struct lysp_stmt *child = stmt->child; child; child = child->next) { switch (child->kw) { @@ -851,7 +851,7 @@ lysp_stmt_when(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_w LY_CHECK_ERR_RET(!when, LOGMEM(PARSER_CTX(ctx)), LY_EMEM); *when_p = when; - LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &when->cond)); + LY_CHECK_RET(lysdict_insert(PARSER_CTX(ctx), stmt->arg, 0, &when->cond)); for (const struct lysp_stmt *child = stmt->child; child; child = child->next) { switch (child->kw) { @@ -976,7 +976,7 @@ static LY_ERR lysp_stmt_restr(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr *restr) { LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg)); - LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &restr->arg.str)); + LY_CHECK_RET(lysdict_insert(PARSER_CTX(ctx), stmt->arg, 0, &restr->arg.str)); restr->arg.mod = PARSER_CUR_PMOD(ctx); for (const struct lysp_stmt *child = stmt->child; child; child = child->next) { @@ -1044,7 +1044,7 @@ lysp_stmt_any(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_no any->nodetype = stmt->kw == LY_STMT_ANYDATA ? LYS_ANYDATA : LYS_ANYXML; any->parent = parent; - LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &any->name)); + LY_CHECK_RET(lysdict_insert(PARSER_CTX(ctx), stmt->arg, 0, &any->name)); /* parse substatements */ for (const struct lysp_stmt *child = stmt->child; child; child = child->next) { @@ -1188,7 +1188,7 @@ lysp_stmt_type_enum(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct l LY_CHECK_RET(lysp_check_enum_name(ctx, stmt->arg, strlen(stmt->arg))); } /* else nothing specific for YANG_BIT */ - LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &enm->name)); + LY_CHECK_RET(lysdict_insert(PARSER_CTX(ctx), stmt->arg, 0, &enm->name)); CHECK_UNIQUENESS(ctx, *enums, name, lyplg_ext_stmt2str(stmt->kw), enm->name); for (const struct lysp_stmt *child = stmt->child; child; child = child->next) { @@ -1361,11 +1361,11 @@ lysp_stmt_type_pattern_modifier(struct lysp_ctx *ctx, const struct lysp_stmt *st buf = malloc(strlen(*pat) + 1); LY_CHECK_ERR_RET(!buf, LOGMEM(PARSER_CTX(ctx)), LY_EMEM); strcpy(buf, *pat); - lydict_remove(PARSER_CTX(ctx), *pat); + lysdict_remove(PARSER_CTX(ctx), *pat); assert(buf[0] == LYSP_RESTR_PATTERN_ACK); buf[0] = LYSP_RESTR_PATTERN_NACK; - LY_CHECK_RET(lydict_insert_zc(PARSER_CTX(ctx), buf, pat)); + LY_CHECK_RET(lysdict_insert_zc(PARSER_CTX(ctx), buf, pat)); for (const struct lysp_stmt *child = stmt->child; child; child = child->next) { switch (child->kw) { @@ -1406,7 +1406,7 @@ lysp_stmt_type_pattern(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struc memmove(buf + 1, stmt->arg, arg_len); buf[0] = LYSP_RESTR_PATTERN_ACK; /* pattern's default regular-match flag */ buf[arg_len + 1] = '\0'; /* terminating NULL byte */ - LY_CHECK_RET(lydict_insert_zc(PARSER_CTX(ctx), buf, &restr->arg.str)); + LY_CHECK_RET(lysdict_insert_zc(PARSER_CTX(ctx), buf, &restr->arg.str)); restr->arg.mod = PARSER_CUR_PMOD(ctx); for (const struct lysp_stmt *child = stmt->child; child; child = child->next) { @@ -1476,7 +1476,7 @@ lysp_stmt_deviation(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct l /* store nodeid */ LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg)); - LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &dev->nodeid)); + LY_CHECK_RET(lysdict_insert(PARSER_CTX(ctx), stmt->arg, 0, &dev->nodeid)); /* parse substatements */ for (const struct lysp_stmt *child = stmt->child; child; child = child->next) { @@ -1642,7 +1642,7 @@ lysp_stmt_argument(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct ly /* store argument name */ LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg)); - LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &ex->argname)); + LY_CHECK_RET(lysdict_insert(PARSER_CTX(ctx), stmt->arg, 0, &ex->argname)); /* parse substatements */ for (const struct lysp_stmt *child = stmt->child; child; child = child->next) { @@ -1679,7 +1679,7 @@ lysp_stmt_extension(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct l /* store name */ LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg)); - LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &ex->name)); + LY_CHECK_RET(lysdict_insert(PARSER_CTX(ctx), stmt->arg, 0, &ex->name)); /* parse substatements */ for (const struct lysp_stmt *child = stmt->child; child; child = child->next) { @@ -1725,7 +1725,7 @@ lysp_stmt_feature(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lys /* store name */ LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg)); - LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &feat->name)); + LY_CHECK_RET(lysdict_insert(PARSER_CTX(ctx), stmt->arg, 0, &feat->name)); /* parse substatements */ for (const struct lysp_stmt *child = stmt->child; child; child = child->next) { @@ -1771,7 +1771,7 @@ lysp_stmt_identity(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct ly /* store name */ LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg)); - LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &ident->name)); + LY_CHECK_RET(lysdict_insert(PARSER_CTX(ctx), stmt->arg, 0, &ident->name)); /* parse substatements */ for (const struct lysp_stmt *child = stmt->child; child; child = child->next) { @@ -1821,7 +1821,7 @@ lysp_stmt_import(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp /* store name */ LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg)); - LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &imp->name)); + LY_CHECK_RET(lysdict_insert(PARSER_CTX(ctx), stmt->arg, 0, &imp->name)); /* parse substatements */ for (const struct lysp_stmt *child = stmt->child; child; child = child->next) { @@ -1839,7 +1839,7 @@ lysp_stmt_import(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp case LY_STMT_REVISION_DATE: LY_CHECK_RET(lysp_stmt_text_field(ctx, stmt, 0, &str, Y_STR_ARG, &imp->exts)); strcpy(imp->rev, str); - lydict_remove(PARSER_CTX(ctx), str); + lysdict_remove(PARSER_CTX(ctx), str); LY_CHECK_RET(lysp_check_date(ctx, imp->rev, LY_REV_SIZE - 1, "revision-date")); break; case LY_STMT_EXTENSION_INSTANCE: @@ -1872,7 +1872,7 @@ lysp_stmt_include(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lys /* store name */ LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg)); - LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &inc->name)); + LY_CHECK_RET(lysdict_insert(PARSER_CTX(ctx), stmt->arg, 0, &inc->name)); /* parse substatements */ for (const struct lysp_stmt *child = stmt->child; child; child = child->next) { @@ -1886,7 +1886,7 @@ lysp_stmt_include(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lys case LY_STMT_REVISION_DATE: LY_CHECK_RET(lysp_stmt_text_field(ctx, stmt, 0, &str, Y_STR_ARG, &inc->exts)); strcpy(inc->rev, str); - lydict_remove(PARSER_CTX(ctx), str); + lysdict_remove(PARSER_CTX(ctx), str); LY_CHECK_RET(lysp_check_date(ctx, inc->rev, LY_REV_SIZE - 1, "revision-date")); break; case LY_STMT_EXTENSION_INSTANCE: @@ -1963,7 +1963,7 @@ lysp_stmt_type(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_t } LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg)); - LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &type->name)); + LY_CHECK_RET(lysdict_insert(PARSER_CTX(ctx), stmt->arg, 0, &type->name)); type->pmod = PARSER_CUR_PMOD(ctx); for (const struct lysp_stmt *child = stmt->child; child; child = child->next) { @@ -1999,7 +1999,7 @@ lysp_stmt_type(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_t LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &str_path, Y_STR_ARG, &type->exts)); ret = ly_path_parse(PARSER_CTX(ctx), NULL, str_path, 0, 1, LY_PATH_BEGIN_EITHER, LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, &type->path); - lydict_remove(PARSER_CTX(ctx), str_path); + lysdict_remove(PARSER_CTX(ctx), str_path); LY_CHECK_RET(ret); type->flags |= LYS_SET_PATH; break; @@ -2061,7 +2061,7 @@ lysp_stmt_leaf(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_n leaf->parent = parent; /* get name */ - LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &leaf->name)); + LY_CHECK_RET(lysdict_insert(PARSER_CTX(ctx), stmt->arg, 0, &leaf->name)); /* parse substatements */ for (const struct lysp_stmt *child = stmt->child; child; child = child->next) { @@ -2313,7 +2313,7 @@ lysp_stmt_leaflist(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct ly llist->parent = parent; /* get name */ - LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &llist->name)); + LY_CHECK_RET(lysdict_insert(PARSER_CTX(ctx), stmt->arg, 0, &llist->name)); /* parse substatements */ for (const struct lysp_stmt *child = stmt->child; child; child = child->next) { @@ -2393,7 +2393,7 @@ lysp_stmt_refine(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *refines, rf, LY_EMEM); - LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &rf->nodeid)); + LY_CHECK_RET(lysdict_insert(PARSER_CTX(ctx), stmt->arg, 0, &rf->nodeid)); for (const struct lysp_stmt *child = stmt->child; child; child = child->next) { switch (child->kw) { @@ -2460,7 +2460,7 @@ lysp_stmt_typedef(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lys LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *typedefs, tpdf, LY_EMEM); - LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &tpdf->name)); + LY_CHECK_RET(lysdict_insert(PARSER_CTX(ctx), stmt->arg, 0, &tpdf->name)); /* parse substatements */ for (const struct lysp_stmt *child = stmt->child; child; child = child->next) { @@ -2527,7 +2527,7 @@ lysp_stmt_inout(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_ } /* initiate structure */ - LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->kw == LY_STMT_INPUT ? "input" : "output", 0, &inout_p->name)); + LY_CHECK_RET(lysdict_insert(PARSER_CTX(ctx), stmt->kw == LY_STMT_INPUT ? "input" : "output", 0, &inout_p->name)); inout_p->nodetype = stmt->kw == LY_STMT_INPUT ? LYS_INPUT : LYS_OUTPUT; inout_p->parent = parent; @@ -2605,7 +2605,7 @@ lysp_stmt_action(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp LY_LIST_NEW_RET(PARSER_CTX(ctx), actions, act, next, LY_EMEM); - LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &act->name)); + LY_CHECK_RET(lysdict_insert(PARSER_CTX(ctx), stmt->arg, 0, &act->name)); act->nodetype = parent ? LYS_ACTION : LYS_RPC; act->parent = parent; @@ -2650,12 +2650,12 @@ lysp_stmt_action(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp if (!act->input.nodetype) { act->input.nodetype = LYS_INPUT; act->input.parent = &act->node; - LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "input", 0, &act->input.name)); + LY_CHECK_RET(lysdict_insert(PARSER_CTX(ctx), "input", 0, &act->input.name)); } if (!act->output.nodetype) { act->output.nodetype = LYS_OUTPUT; act->output.parent = &act->node; - LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "output", 0, &act->output.name)); + LY_CHECK_RET(lysdict_insert(PARSER_CTX(ctx), "output", 0, &act->output.name)); } return LY_SUCCESS; @@ -2681,7 +2681,7 @@ lysp_stmt_notif(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_ LY_LIST_NEW_RET(PARSER_CTX(ctx), notifs, notif, next, LY_EMEM); - LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, ¬if->name)); + LY_CHECK_RET(lysdict_insert(PARSER_CTX(ctx), stmt->arg, 0, ¬if->name)); notif->nodetype = LYS_NOTIF; notif->parent = parent; @@ -2767,7 +2767,7 @@ lysp_stmt_grouping(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct ly LY_LIST_NEW_RET(PARSER_CTX(ctx), groupings, grp, next, LY_EMEM); - LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &grp->name)); + LY_CHECK_RET(lysdict_insert(PARSER_CTX(ctx), stmt->arg, 0, &grp->name)); grp->nodetype = LYS_GROUPING; grp->parent = parent; @@ -2854,7 +2854,7 @@ lysp_stmt_augment(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lys LY_LIST_NEW_RET(PARSER_CTX(ctx), augments, aug, next, LY_EMEM); - LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &aug->nodeid)); + LY_CHECK_RET(lysdict_insert(PARSER_CTX(ctx), stmt->arg, 0, &aug->nodeid)); aug->nodetype = LYS_AUGMENT; aug->parent = parent; @@ -2945,7 +2945,7 @@ lysp_stmt_uses(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_n /* create uses structure */ LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, uses, next, LY_EMEM); - LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &uses->name)); + LY_CHECK_RET(lysdict_insert(PARSER_CTX(ctx), stmt->arg, 0, &uses->name)); uses->nodetype = LYS_USES; uses->parent = parent; @@ -3007,7 +3007,7 @@ lysp_stmt_case(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_n /* create new case structure */ LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, cas, next, LY_EMEM); - LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &cas->name)); + LY_CHECK_RET(lysdict_insert(PARSER_CTX(ctx), stmt->arg, 0, &cas->name)); cas->nodetype = LYS_CASE; cas->parent = parent; @@ -3086,7 +3086,7 @@ lysp_stmt_choice(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp /* create new choice structure */ LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, choice, next, LY_EMEM); - LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &choice->name)); + LY_CHECK_RET(lysdict_insert(PARSER_CTX(ctx), stmt->arg, 0, &choice->name)); choice->nodetype = LYS_CHOICE; choice->parent = parent; @@ -3175,7 +3175,7 @@ lysp_stmt_container(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct l /* create new container structure */ LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, cont, next, LY_EMEM); - LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &cont->name)); + LY_CHECK_RET(lysdict_insert(PARSER_CTX(ctx), stmt->arg, 0, &cont->name)); cont->nodetype = LYS_CONTAINER; cont->parent = parent; @@ -3278,7 +3278,7 @@ lysp_stmt_list(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_n /* create new list structure */ LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, list, next, LY_EMEM); - LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &list->name)); + LY_CHECK_RET(lysdict_insert(PARSER_CTX(ctx), stmt->arg, 0, &list->name)); list->nodetype = LYS_LIST; list->parent = parent; @@ -3538,7 +3538,7 @@ lysp_stmt_parse(struct lysp_ctx *pctx, const struct lysp_stmt *stmt, void **resu LY_CHECK_RET(lysp_stmt_text_field(pctx, stmt, 0, &str_path, Y_STR_ARG, exts)); ret = ly_path_parse(PARSER_CTX(pctx), NULL, str_path, 0, 1, LY_PATH_BEGIN_EITHER, LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, (struct lyxp_expr **)result); - lydict_remove(PARSER_CTX(pctx), str_path); + lysdict_remove(PARSER_CTX(pctx), str_path); break; } case LY_STMT_PATTERN: diff --git a/src/parser_data.h b/src/parser_data.h index 4af6102f7..9dbb71fc5 100644 --- a/src/parser_data.h +++ b/src/parser_data.h @@ -423,13 +423,15 @@ enum lyd_type { * @param[in] in Input handle to read the input from. * @param[in] format Expected format of the data in @p in. * @param[in] data_type Expected operation to parse (@ref datatype). + * @param[in] parse_options Options for parser are set based on @p data_type but either of ::LYD_PARSE_STRICT and + * ::LYD_PARSE_OPAQ can be added, see @ref dataparseroptions. * @param[out] tree Optional full parsed data tree. If @p parent is set, set to NULL. * @param[out] op Optional pointer to the operation (action/RPC/notification) node. * @return LY_ERR value. * @return LY_ENOT if @p data_type is a NETCONF message and the root XML element is not the expected one. */ LIBYANG_API_DECL LY_ERR lyd_parse_op(const struct ly_ctx *ctx, struct lyd_node *parent, struct ly_in *in, LYD_FORMAT format, - enum lyd_type data_type, struct lyd_node **tree, struct lyd_node **op); + enum lyd_type data_type, uint32_t parse_options, struct lyd_node **tree, struct lyd_node **op); /** * @brief Parse extension data into an operation data tree following only the specification from the given extension instance. @@ -466,13 +468,15 @@ LIBYANG_API_DECL LY_ERR lyd_parse_op(const struct ly_ctx *ctx, struct lyd_node * * @param[in] in Input handle to read the input from. * @param[in] format Expected format of the data in @p in. * @param[in] data_type Expected operation to parse (@ref datatype). + * @param[in] parse_options Options for parser are set based on @p data_type but either of ::LYD_PARSE_STRICT and + * ::LYD_PARSE_OPAQ can be added, see @ref dataparseroptions. * @param[out] tree Optional full parsed data tree. If @p parent is set, set to NULL. * @param[out] op Optional pointer to the operation (action/RPC) node. * @return LY_ERR value. * @return LY_ENOT if @p data_type is a NETCONF message and the root XML element is not the expected one. */ LIBYANG_API_DECL LY_ERR lyd_parse_ext_op(const struct lysc_ext_instance *ext, struct lyd_node *parent, struct ly_in *in, - LYD_FORMAT format, enum lyd_type data_type, struct lyd_node **tree, struct lyd_node **op); + LYD_FORMAT format, enum lyd_type data_type, uint32_t parse_options, struct lyd_node **tree, struct lyd_node **op); /** * @brief Fully validate a data tree. diff --git a/src/parser_lyb.c b/src/parser_lyb.c index 66ac68663..ceff905a4 100644 --- a/src/parser_lyb.c +++ b/src/parser_lyb.c @@ -32,6 +32,7 @@ #include "parser_internal.h" #include "plugins_exts.h" #include "plugins_exts/metadata.h" +#include "plugins_internal.h" #include "set.h" #include "tree.h" #include "tree_data.h" @@ -266,9 +267,9 @@ lyb_read_term_value(const struct lysc_node_leaf *term, uint8_t **term_value, uin if (term->type->basetype == LY_TYPE_LEAFREF) { /* Leafref itself is ignored, the target is loaded directly. */ type_lf = (struct lysc_type_leafref *)term->type; - lyb_data_len = type_lf->realtype->plugin->lyb_data_len; + lyb_data_len = LYSC_GET_TYPE_PLG(type_lf->realtype->plugin_ref)->lyb_data_len; } else { - lyb_data_len = term->type->plugin->lyb_data_len; + lyb_data_len = LYSC_GET_TYPE_PLG(term->type->plugin_ref)->lyb_data_len; } if (lyb_data_len < 0) { @@ -413,9 +414,6 @@ lyb_parse_module(struct lylyb_ctx *lybctx, const struct lys_module **mod) goto cleanup; } - /* fill cached hashes, if not already */ - lyb_cache_module_hash(m); - cleanup: *mod = m; free(mod_name); @@ -822,8 +820,10 @@ lyb_parse_schema_nested_ext(struct lyd_lyb_ctx *lybctx, const struct lyd_node *p goto cleanup; } - /* fill cached hashes in the module, it may be from a different context */ - lyb_cache_module_hash((*snode)->module); + if (!((*snode)->module->ctx->opts & LY_CTX_LYB_HASHES)) { + /* generate LYB hashes */ + LY_CHECK_GOTO(rc = ly_ctx_set_options((*snode)->module->ctx, LY_CTX_LYB_HASHES), cleanup); + } cleanup: free(name); @@ -1610,6 +1610,11 @@ lyd_parse_lyb(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, str LY_CHECK_ARG_RET(ctx, !(parse_opts & LYD_PARSE_SUBTREE), LY_EINVAL); + if (!(ctx->opts & LY_CTX_LYB_HASHES)) { + /* generate LYB hashes */ + LY_CHECK_GOTO(rc = ly_ctx_set_options((struct ly_ctx *)ctx, LY_CTX_LYB_HASHES), cleanup); + } + if (subtree_sibling) { *subtree_sibling = 0; } diff --git a/src/parser_yang.c b/src/parser_yang.c index fcf055dab..d6937c4f1 100644 --- a/src/parser_yang.c +++ b/src/parser_yang.c @@ -47,8 +47,8 @@ struct lys_glob_unres; * @param[in] LEN length of the string in WORD to store. */ #define INSERT_WORD_GOTO(CTX, BUF, TARGET, WORD, LEN, RET, LABEL) \ - if (BUF) {LY_CHECK_GOTO(RET = lydict_insert_zc(PARSER_CTX(CTX), WORD, &(TARGET)), LABEL);}\ - else {LY_CHECK_GOTO(RET = lydict_insert(PARSER_CTX(CTX), LEN ? WORD : "", LEN, &(TARGET)), LABEL);} + if (BUF) {LY_CHECK_GOTO(RET = lysdict_insert_zc(PARSER_CTX(CTX), WORD, &(TARGET)), LABEL);}\ + else {LY_CHECK_GOTO(RET = lysdict_insert(PARSER_CTX(CTX), LEN ? WORD : "", LEN, &(TARGET)), LABEL);} /** * @brief Read from the IN structure COUNT items. Also updates the indent value in yang parser context @@ -937,7 +937,7 @@ parse_ext_substmt(struct lysp_yang_ctx *ctx, enum ly_stmt kw, char *word, size_t } /* statement */ - LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), word, word_len, &stmt->stmt)); + LY_CHECK_RET(lysdict_insert(PARSER_CTX(ctx), word, word_len, &stmt->stmt)); /* get optional argument */ LY_CHECK_RET(get_argument(ctx, Y_MAYBE_STR_ARG, &stmt->flags, &word, &buf, &word_len)); @@ -989,7 +989,7 @@ parse_ext(struct lysp_yang_ctx *ctx, const char *ext_name, size_t ext_name_len, } /* store name */ - LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), ext_name, ext_name_len, &e->name)); + LY_CHECK_RET(lysdict_insert(PARSER_CTX(ctx), ext_name, ext_name_len, &e->name)); /* get optional argument */ LY_CHECK_RET(get_argument(ctx, Y_MAYBE_STR_ARG, NULL, &word, &buf, &word_len)); @@ -1722,7 +1722,6 @@ parse_when(struct lysp_yang_ctx *ctx, struct lysp_when **when_p) size_t word_len; enum ly_stmt kw; struct lysp_when *when; - struct lysf_ctx fctx = {.ctx = PARSER_CTX(ctx)}; if (*when_p) { LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "when"); @@ -1760,7 +1759,7 @@ parse_when(struct lysp_yang_ctx *ctx, struct lysp_when **when_p) cleanup: if (ret) { - lysp_when_free(&fctx, when); + lysp_when_free(PARSER_CTX(ctx), when); free(when); } else { *when_p = when; @@ -2137,11 +2136,11 @@ parse_type_pattern_modifier(struct lysp_yang_ctx *ctx, struct lysp_restr *restr) buf = malloc(strlen(restr->arg.str) + 1); LY_CHECK_ERR_GOTO(!buf, LOGMEM(PARSER_CTX(ctx)); ret = LY_EMEM, cleanup); strcpy(buf, restr->arg.str); - lydict_remove(PARSER_CTX(ctx), restr->arg.str); + lysdict_remove(PARSER_CTX(ctx), restr->arg.str); assert(buf[0] == LYSP_RESTR_PATTERN_ACK); buf[0] = LYSP_RESTR_PATTERN_NACK; - ret = lydict_insert_zc(PARSER_CTX(ctx), buf, &restr->arg.str); + ret = lysdict_insert_zc(PARSER_CTX(ctx), buf, &restr->arg.str); buf = NULL; LY_CHECK_GOTO(ret, cleanup); @@ -2197,7 +2196,7 @@ parse_type_pattern(struct lysp_yang_ctx *ctx, struct lysp_restr **patterns) } buf[0] = LYSP_RESTR_PATTERN_ACK; /* pattern's default regular-match flag */ buf[word_len + 1] = '\0'; /* terminating NULL byte */ - LY_CHECK_RET(lydict_insert_zc(PARSER_CTX(ctx), buf, &restr->arg.str)); + LY_CHECK_RET(lysdict_insert_zc(PARSER_CTX(ctx), buf, &restr->arg.str)); restr->arg.mod = PARSER_CUR_PMOD(ctx); YANG_READ_SUBSTMT_FOR_GOTO(ctx, kw, word, word_len, ret, cleanup) { @@ -2302,11 +2301,11 @@ parse_type(struct lysp_yang_ctx *ctx, struct lysp_type *type) * to rely on lysp_module_free because the result of the parsing is stored in a local variable. */ LY_CHECK_ERR_RET(ret = parse_text_field(ctx, type, LY_STMT_PATH, 0, &str_path, Y_STR_ARG, NULL, &type->exts), - lydict_remove(PARSER_CTX(ctx), str_path), ret); + lysdict_remove(PARSER_CTX(ctx), str_path), ret); ret = ly_path_parse(PARSER_CTX(ctx), NULL, str_path, 0, 1, LY_PATH_BEGIN_EITHER, LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, &type->path); /* Moreover, even if successful, the string is removed from the dictionary. */ - lydict_remove(PARSER_CTX(ctx), str_path); + lysdict_remove(PARSER_CTX(ctx), str_path); LY_CHECK_RET(ret); type->flags |= LYS_SET_PATH; break; @@ -2873,7 +2872,7 @@ parse_inout(struct lysp_yang_ctx *ctx, enum ly_stmt inout_kw, struct lysp_node * } /* initiate structure */ - LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), input ? "input" : "output", 0, &inout_p->name)); + LY_CHECK_RET(lysdict_insert(PARSER_CTX(ctx), input ? "input" : "output", 0, &inout_p->name)); inout_p->nodetype = input ? LYS_INPUT : LYS_OUTPUT; inout_p->parent = parent; @@ -2994,12 +2993,12 @@ parse_action(struct lysp_yang_ctx *ctx, struct lysp_node *parent, struct lysp_no if (!act->input.nodetype) { act->input.nodetype = LYS_INPUT; act->input.parent = (struct lysp_node *)act; - LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "input", 0, &act->input.name)); + LY_CHECK_RET(lysdict_insert(PARSER_CTX(ctx), "input", 0, &act->input.name)); } if (!act->output.nodetype) { act->output.nodetype = LYS_OUTPUT; act->output.parent = (struct lysp_node *)act; - LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "output", 0, &act->output.name)); + LY_CHECK_RET(lysdict_insert(PARSER_CTX(ctx), "output", 0, &act->output.name)); } cleanup: @@ -3908,7 +3907,6 @@ parse_deviate(struct lysp_yang_ctx *ctx, struct lysp_deviate **deviates) char *buf = NULL, *word; size_t word_len, dev_mod; enum ly_stmt kw; - struct lysf_ctx fctx = {.ctx = PARSER_CTX(ctx)}; struct lysp_deviate *d = NULL; struct lysp_deviate_add *d_add = NULL; struct lysp_deviate_rpl *d_rpl = NULL; @@ -4117,7 +4115,7 @@ parse_deviate(struct lysp_yang_ctx *ctx, struct lysp_deviate **deviates) cleanup: free(buf); if (ret) { - lysp_deviate_free(&fctx, d); + lysp_deviate_free(PARSER_CTX(ctx), d); free(d); } else { /* insert into siblings */ @@ -4141,7 +4139,6 @@ parse_deviation(struct lysp_yang_ctx *ctx, struct lysp_deviation **deviations) size_t word_len; enum ly_stmt kw; struct lysp_deviation *dev; - struct lysf_ctx fctx = {.ctx = PARSER_CTX(ctx)}; LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *deviations, dev, LY_EMEM); @@ -4183,7 +4180,7 @@ parse_deviation(struct lysp_yang_ctx *ctx, struct lysp_deviation **deviations) cleanup: if (ret) { - lysp_deviation_free(&fctx, dev); + lysp_deviation_free(PARSER_CTX(ctx), dev); LY_ARRAY_DECREMENT_FREE(*deviations); } return ret; @@ -4761,7 +4758,6 @@ yang_parse_submodule(struct lysp_yang_ctx **context, struct ly_ctx *ly_ctx, stru size_t word_len; enum ly_stmt kw; struct lysp_submodule *mod_p = NULL; - struct lysf_ctx fctx = {.ctx = ly_ctx}; assert(context && ly_ctx && main_ctx && in && submod); @@ -4820,7 +4816,7 @@ yang_parse_submodule(struct lysp_yang_ctx **context, struct ly_ctx *ly_ctx, stru cleanup: ly_log_location_revert(0, 0, 0, 1); if (ret) { - lysp_module_free(&fctx, (struct lysp_module *)mod_p); + lysp_module_free(ly_ctx, (struct lysp_module *)mod_p); lysp_yang_ctx_free(*context); *context = NULL; } @@ -4836,7 +4832,6 @@ yang_parse_module(struct lysp_yang_ctx **context, struct ly_in *in, struct lys_m size_t word_len; enum ly_stmt kw; struct lysp_module *mod_p = NULL; - struct lysf_ctx fctx = {.ctx = mod->ctx}; /* create context */ *context = calloc(1, sizeof **context); @@ -4889,7 +4884,7 @@ yang_parse_module(struct lysp_yang_ctx **context, struct ly_in *in, struct lys_m cleanup: ly_log_location_revert(0, 0, 0, 1); if (ret) { - lysp_module_free(&fctx, mod_p); + lysp_module_free(mod->ctx, mod_p); lysp_yang_ctx_free(*context); *context = NULL; } diff --git a/src/parser_yin.c b/src/parser_yin.c index fb10e1784..134245a2f 100644 --- a/src/parser_yin.c +++ b/src/parser_yin.c @@ -44,6 +44,24 @@ struct lys_glob_unres; +/** + * @brief Insert string into dictionary. + * + * @param[in] CTX libyang context. + * @param[in] STRING string to store. + * @param[in] LEN length of the string in WORD to store. + * @param[in,out] DYNAMIC Set to 1 if @p STRING is dynamically allocated, 0 otherwise. + * If set to 1, zerocopy version of lysdict_insert is used. + * @param[out] TARGET pointer is set to @p STRING value stored in the dictionary. + */ +#define INSERT_STRING_RET(CTX, STRING, LEN, DYNAMIC, TARGET) \ + if (DYNAMIC) { \ + LY_CHECK_RET(lysdict_insert_zc(CTX, (char *)(STRING), &(TARGET))); \ + } else { \ + LY_CHECK_RET(lysdict_insert(CTX, LEN ? (STRING) : "", LEN, &(TARGET))); \ + } \ + DYNAMIC = 0 + /** * @brief check if given string is URI of yin namespace. * @@ -626,7 +644,7 @@ yin_parse_path(struct lysp_yin_ctx *ctx, struct lysp_type *type) ret = ly_path_parse(ctx->xmlctx->ctx, NULL, str_path, 0, 1, LY_PATH_BEGIN_EITHER, LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, &type->path); - lydict_remove(ctx->xmlctx->ctx, str_path); + lysdict_remove(ctx->xmlctx->ctx, str_path); LY_CHECK_RET(ret); type->flags |= LYS_SET_PATH; @@ -672,10 +690,10 @@ yin_parse_pattern(struct lysp_yin_ctx *ctx, struct lysp_type *type) saved_value = malloc(len + 2); LY_CHECK_ERR_RET(!saved_value, LOGMEM(ctx->xmlctx->ctx), LY_EMEM); memmove(saved_value + 1, real_value, len); - lydict_remove(ctx->xmlctx->ctx, real_value); + lysdict_remove(ctx->xmlctx->ctx, real_value); saved_value[0] = LYSP_RESTR_PATTERN_ACK; saved_value[len + 1] = '\0'; - LY_CHECK_RET(lydict_insert_zc(ctx->xmlctx->ctx, saved_value, &restr->arg.str)); + LY_CHECK_RET(lysdict_insert_zc(ctx->xmlctx->ctx, saved_value, &restr->arg.str)); restr->arg.mod = PARSER_CUR_PMOD(ctx); type->flags |= LYS_SET_PATTERN; @@ -715,7 +733,7 @@ yin_parse_fracdigits(struct lysp_yin_ctx *ctx, struct lysp_type *type) if ((temp_val[0] == '\0') || (temp_val[0] == '0') || !isdigit(temp_val[0])) { LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits"); - lydict_remove(ctx->xmlctx->ctx, temp_val); + lysdict_remove(ctx->xmlctx->ctx, temp_val); return LY_EVALID; } @@ -723,15 +741,15 @@ yin_parse_fracdigits(struct lysp_yin_ctx *ctx, struct lysp_type *type) num = strtoull(temp_val, &ptr, LY_BASE_DEC); if (*ptr != '\0') { LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits"); - lydict_remove(ctx->xmlctx->ctx, temp_val); + lysdict_remove(ctx->xmlctx->ctx, temp_val); return LY_EVALID; } if ((errno == ERANGE) || (num > LY_TYPE_DEC64_FD_MAX)) { LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits"); - lydict_remove(ctx->xmlctx->ctx, temp_val); + lysdict_remove(ctx->xmlctx->ctx, temp_val); return LY_EVALID; } - lydict_remove(ctx->xmlctx->ctx, temp_val); + lysdict_remove(ctx->xmlctx->ctx, temp_val); type->fraction_digits = num; type->flags |= LYS_SET_FRDIGITS; struct yin_subelement subelems[] = { @@ -928,10 +946,10 @@ yin_pasrse_reqinstance(struct lysp_yin_ctx *ctx, struct lysp_type *type) } else if (strcmp(temp_val, "false") != 0) { LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value", "require-instance", "true", "false"); - lydict_remove(ctx->xmlctx->ctx, temp_val); + lysdict_remove(ctx->xmlctx->ctx, temp_val); return LY_EVALID; } - lydict_remove(ctx->xmlctx->ctx, temp_val); + lysdict_remove(ctx->xmlctx->ctx, temp_val); LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), type, LY_STMT_REQUIRE_INSTANCE, NULL, &type->exts)); @@ -966,20 +984,20 @@ yin_parse_modifier(struct lysp_yin_ctx *ctx, const void *parent, const char **pa if (strcmp(temp_val, "invert-match") != 0) { LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS1, temp_val, "value", "modifier", "invert-match"); - lydict_remove(ctx->xmlctx->ctx, temp_val); + lysdict_remove(ctx->xmlctx->ctx, temp_val); return LY_EVALID; } - lydict_remove(ctx->xmlctx->ctx, temp_val); + lysdict_remove(ctx->xmlctx->ctx, temp_val); /* allocate new value */ modified_val = malloc(strlen(*pat) + 1); LY_CHECK_ERR_RET(!modified_val, LOGMEM(ctx->xmlctx->ctx), LY_EMEM); strcpy(modified_val, *pat); - lydict_remove(ctx->xmlctx->ctx, *pat); + lysdict_remove(ctx->xmlctx->ctx, *pat); /* modify the new value */ modified_val[0] = LYSP_RESTR_PATTERN_NACK; - LY_CHECK_RET(lydict_insert_zc(ctx->xmlctx->ctx, modified_val, pat)); + LY_CHECK_RET(lysdict_insert_zc(ctx->xmlctx->ctx, modified_val, pat)); LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), parent, LY_STMT_MODIFIER, NULL, exts)); @@ -1197,7 +1215,7 @@ yin_parse_value_pos(struct lysp_yin_ctx *ctx, enum ly_stmt parent_stmt, struct l LY_CHECK_GOTO(ret = yin_unres_exts_add(ctx, enm->exts), cleanup); cleanup: - lydict_remove(ctx->xmlctx->ctx, temp_val); + lysdict_remove(ctx->xmlctx->ctx, temp_val); return ret; } @@ -1223,10 +1241,10 @@ yin_parse_belongs_to(struct lysp_yin_ctx *ctx, struct lysp_submodule *submod, st if (PARSER_CUR_PMOD(ctx)->mod->name != belongsto) { LOGVAL_PARSER(ctx, LYVE_SYNTAX_YIN, "Submodule \"belongs-to\" value \"%s\" does not match its module name \"%s\".", belongsto, PARSER_CUR_PMOD(ctx)->mod->name); - lydict_remove(ctx->xmlctx->ctx, belongsto); + lysdict_remove(ctx->xmlctx->ctx, belongsto); return LY_EVALID; } - lydict_remove(ctx->xmlctx->ctx, belongsto); + lysdict_remove(ctx->xmlctx->ctx, belongsto); LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), submod, LY_STMT_BELONGS_TO, NULL, exts)); @@ -1398,7 +1416,7 @@ yin_parse_maxelements(struct lysp_yin_ctx *ctx, uint32_t *max, uint16_t *flags, LY_CHECK_GOTO(ret, cleanup); cleanup: - lydict_remove(ctx->xmlctx->ctx, temp_val); + lysdict_remove(ctx->xmlctx->ctx, temp_val); return ret; } @@ -1427,7 +1445,7 @@ yin_parse_minelements(struct lysp_yin_ctx *ctx, uint32_t *min, uint16_t *flags, if (!temp_val || (temp_val[0] == '\0') || ((temp_val[0] == '0') && (temp_val[1] != '\0'))) { LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "min-elements"); - lydict_remove(ctx->xmlctx->ctx, temp_val); + lysdict_remove(ctx->xmlctx->ctx, temp_val); return LY_EVALID; } @@ -1435,16 +1453,16 @@ yin_parse_minelements(struct lysp_yin_ctx *ctx, uint32_t *min, uint16_t *flags, num = strtoull(temp_val, &ptr, LY_BASE_DEC); if (ptr[0] != 0) { LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "min-elements"); - lydict_remove(ctx->xmlctx->ctx, temp_val); + lysdict_remove(ctx->xmlctx->ctx, temp_val); return LY_EVALID; } if ((errno == ERANGE) || (num > UINT32_MAX)) { LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", "min-elements"); - lydict_remove(ctx->xmlctx->ctx, temp_val); + lysdict_remove(ctx->xmlctx->ctx, temp_val); return LY_EVALID; } *min = num; - lydict_remove(ctx->xmlctx->ctx, temp_val); + lysdict_remove(ctx->xmlctx->ctx, temp_val); LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), min, LY_STMT_MIN_ELEMENTS, NULL, exts)); return LY_SUCCESS; @@ -1523,10 +1541,10 @@ yin_parse_orderedby(struct lysp_yin_ctx *ctx, const void *parent, uint16_t *flag } else { LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value", "ordered-by", "system", "user"); - lydict_remove(ctx->xmlctx->ctx, temp_val); + lysdict_remove(ctx->xmlctx->ctx, temp_val); return LY_EVALID; } - lydict_remove(ctx->xmlctx->ctx, temp_val); + lysdict_remove(ctx->xmlctx->ctx, temp_val); LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), parent, LY_STMT_ORDERED_BY, NULL, exts)); @@ -1826,11 +1844,11 @@ yin_parse_revision(struct lysp_yin_ctx *ctx, struct lysp_revision **revs) LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_DATE, &temp_date, Y_STR_ARG, LY_STMT_REVISION)); /* check value */ if (lysp_check_date((struct lysp_ctx *)ctx, temp_date, strlen(temp_date), "revision")) { - lydict_remove(ctx->xmlctx->ctx, temp_date); + lysdict_remove(ctx->xmlctx->ctx, temp_date); return LY_EVALID; } memcpy(rev->date, temp_date, LY_REV_SIZE); - lydict_remove(ctx->xmlctx->ctx, temp_date); + lysdict_remove(ctx->xmlctx->ctx, temp_date); /* parse content */ struct yin_subelement subelems[] = { @@ -1908,10 +1926,10 @@ yin_parse_revision_date(struct lysp_yin_ctx *ctx, char *rev, struct lysp_ext_ins LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx)); LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_DATE, &temp_rev, Y_STR_ARG, LY_STMT_REVISION_DATE)); LY_CHECK_ERR_RET(lysp_check_date((struct lysp_ctx *)ctx, temp_rev, strlen(temp_rev), "revision-date") != LY_SUCCESS, - lydict_remove(ctx->xmlctx->ctx, temp_rev), LY_EVALID); + lysdict_remove(ctx->xmlctx->ctx, temp_rev), LY_EVALID); strcpy(rev, temp_rev); - lydict_remove(ctx->xmlctx->ctx, temp_rev); + lysdict_remove(ctx->xmlctx->ctx, temp_rev); LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), rev, LY_STMT_REVISION_DATE, NULL, exts)); @@ -1943,10 +1961,10 @@ yin_parse_config(struct lysp_yin_ctx *ctx, uint16_t *flags, struct lysp_ext_inst } else { LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value", "config", "true", "false"); - lydict_remove(ctx->xmlctx->ctx, temp_val); + lysdict_remove(ctx->xmlctx->ctx, temp_val); return LY_EVALID; } - lydict_remove(ctx->xmlctx->ctx, temp_val); + lysdict_remove(ctx->xmlctx->ctx, temp_val); LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), flags, LY_STMT_CONFIG, NULL, exts)); @@ -1979,10 +1997,10 @@ yin_parse_yangversion(struct lysp_yin_ctx *ctx, const void *parent, uint8_t *ver } else { LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_version, "value", "yang-version", "1", "1.1"); - lydict_remove(ctx->xmlctx->ctx, temp_version); + lysdict_remove(ctx->xmlctx->ctx, temp_version); return LY_EVALID; } - lydict_remove(ctx->xmlctx->ctx, temp_version); + lysdict_remove(ctx->xmlctx->ctx, temp_version); LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), parent, LY_STMT_YANG_VERSION, NULL, exts)); @@ -2051,10 +2069,10 @@ yin_parse_mandatory(struct lysp_yin_ctx *ctx, uint16_t *flags, struct lysp_ext_i } else { LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value", "mandatory", "true", "false"); - lydict_remove(ctx->xmlctx->ctx, temp_val); + lysdict_remove(ctx->xmlctx->ctx, temp_val); return LY_EVALID; } - lydict_remove(ctx->xmlctx->ctx, temp_val); + lysdict_remove(ctx->xmlctx->ctx, temp_val); LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), flags, LY_STMT_MANDATORY, NULL, exts)); @@ -2088,10 +2106,10 @@ yin_parse_status(struct lysp_yin_ctx *ctx, uint16_t *flags, struct lysp_ext_inst } else { LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS3, value, "value", "status", "current", "deprecated", "obsolete"); - lydict_remove(ctx->xmlctx->ctx, value); + lysdict_remove(ctx->xmlctx->ctx, value); return LY_EVALID; } - lydict_remove(ctx->xmlctx->ctx, value); + lysdict_remove(ctx->xmlctx->ctx, value); LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), flags, LY_STMT_STATUS, NULL, exts)); @@ -2161,10 +2179,10 @@ yin_parse_yin_element(struct lysp_yin_ctx *ctx, const void *parent, uint16_t *fl } else { LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value", "yin-element", "true", "false"); - lydict_remove(ctx->xmlctx->ctx, temp_val); + lysdict_remove(ctx->xmlctx->ctx, temp_val); return LY_EVALID; } - lydict_remove(ctx->xmlctx->ctx, temp_val); + lysdict_remove(ctx->xmlctx->ctx, temp_val); LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), parent, LY_STMT_YIN_ELEMENT, NULL, exts)); @@ -2655,7 +2673,7 @@ yin_parse_inout(struct lysp_yin_ctx *ctx, enum ly_stmt inout_kw, struct inout_me size_t subelems_size; /* initiate structure */ - LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), (inout_kw == LY_STMT_INPUT) ? "input" : "output", 0, &inout_meta->inout_p->name)); + LY_CHECK_RET(lysdict_insert(PARSER_CTX(ctx), (inout_kw == LY_STMT_INPUT) ? "input" : "output", 0, &inout_meta->inout_p->name)); inout_meta->inout_p->nodetype = (inout_kw == LY_STMT_INPUT) ? LYS_INPUT : LYS_OUTPUT; inout_meta->inout_p->parent = inout_meta->parent; @@ -2736,12 +2754,12 @@ yin_parse_action(struct lysp_yin_ctx *ctx, struct tree_node_meta *act_meta) if (!act->input.nodetype) { act->input.nodetype = LYS_INPUT; act->input.parent = (struct lysp_node *)act; - LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "input", 0, &act->input.name)); + LY_CHECK_RET(lysdict_insert(PARSER_CTX(ctx), "input", 0, &act->input.name)); } if (!act->output.nodetype) { act->output.nodetype = LYS_OUTPUT; act->output.parent = (struct lysp_node *)act; - LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "output", 0, &act->output.name)); + LY_CHECK_RET(lysdict_insert(PARSER_CTX(ctx), "output", 0, &act->output.name)); } /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */ @@ -2838,10 +2856,10 @@ yin_parse_deviate(struct lysp_yin_ctx *ctx, struct lysp_deviate **deviates) } else { LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS4, temp_val, "value", "deviate", "not-supported", "add", "replace", "delete"); - lydict_remove(ctx->xmlctx->ctx, temp_val); + lysdict_remove(ctx->xmlctx->ctx, temp_val); return LY_EVALID; } - lydict_remove(ctx->xmlctx->ctx, temp_val); + lysdict_remove(ctx->xmlctx->ctx, temp_val); if (dev_mod == LYS_DEV_NOT_SUPPORTED) { d = calloc(1, sizeof *d); @@ -2933,7 +2951,6 @@ yin_parse_deviation(struct lysp_yin_ctx *ctx, struct lysp_deviation **deviations { LY_ERR ret = LY_SUCCESS; struct lysp_deviation *dev = NULL; - struct lysf_ctx fctx = {.ctx = PARSER_CTX(ctx)}; /* create new deviation */ LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *deviations, dev, LY_EMEM); @@ -2957,7 +2974,7 @@ yin_parse_deviation(struct lysp_yin_ctx *ctx, struct lysp_deviation **deviations cleanup: if (ret) { - lysp_deviation_free(&fctx, dev); + lysp_deviation_free(PARSER_CTX(ctx), dev); LY_ARRAY_DECREMENT_FREE(*deviations); } return ret; @@ -3240,13 +3257,13 @@ yin_parse_element_generic(struct lysp_yin_ctx *ctx, enum ly_stmt parent_stmt, st ret = LY_EMEM; goto cleanup; } - LY_CHECK_GOTO(ret = lydict_insert_zc(ctx->xmlctx->ctx, id, &(*element)->stmt), cleanup); + LY_CHECK_GOTO(ret = lysdict_insert_zc(ctx->xmlctx->ctx, id, &(*element)->stmt), cleanup); /* store prefix data for the statement */ LY_CHECK_GOTO(ret = ly_store_prefix_data(ctx->xmlctx->ctx, (*element)->stmt, strlen((*element)->stmt), LY_VALUE_XML, &ctx->xmlctx->ns, &(*element)->format, &(*element)->prefix_data), cleanup); } else { - LY_CHECK_GOTO(ret = lydict_insert(ctx->xmlctx->ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, &(*element)->stmt), cleanup); + LY_CHECK_GOTO(ret = lysdict_insert(ctx->xmlctx->ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, &(*element)->stmt), cleanup); } (*element)->kw = yin_match_keyword(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix, @@ -3279,7 +3296,7 @@ yin_parse_element_generic(struct lysp_yin_ctx *ctx, enum ly_stmt parent_stmt, st last = new; last->flags |= LYS_YIN_ATTR; - LY_CHECK_GOTO(ret = lydict_insert(ctx->xmlctx->ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, &last->stmt), cleanup); + LY_CHECK_GOTO(ret = lysdict_insert(ctx->xmlctx->ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, &last->stmt), cleanup); last->kw = LY_STMT_NONE; /* attributes with prefix are ignored */ if (!ctx->xmlctx->prefix) { @@ -3365,7 +3382,7 @@ yin_parse_extension_instance(struct lysp_yin_ctx *ctx, const void *parent, enum LOGMEM(ctx->xmlctx->ctx); return LY_EMEM; } - LY_CHECK_RET(lydict_insert_zc(ctx->xmlctx->ctx, ext_name, &e->name)); + LY_CHECK_RET(lysdict_insert_zc(ctx->xmlctx->ctx, ext_name, &e->name)); /* store prefix data for the name */ LY_CHECK_RET(ly_store_prefix_data(ctx->xmlctx->ctx, e->name, strlen(e->name), LY_VALUE_XML, &ctx->xmlctx->ns, @@ -3389,7 +3406,7 @@ yin_parse_extension_instance(struct lysp_yin_ctx *ctx, const void *parent, enum last_subelem = new_subelem; last_subelem->flags |= LYS_YIN_ATTR; - LY_CHECK_RET(lydict_insert(ctx->xmlctx->ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, &last_subelem->stmt)); + LY_CHECK_RET(lysdict_insert(ctx->xmlctx->ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, &last_subelem->stmt)); LY_CHECK_RET(!last_subelem->stmt, LY_EMEM); LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx)); @@ -3893,7 +3910,6 @@ yin_parse_submodule(struct lysp_yin_ctx **yin_ctx, struct ly_ctx *ctx, struct ly enum ly_stmt kw = LY_STMT_NONE; LY_ERR ret = LY_SUCCESS; struct lysp_submodule *mod_p = NULL; - struct lysf_ctx fctx = {.ctx = ctx}; assert(yin_ctx && ctx && main_ctx && in && submod); @@ -3949,7 +3965,7 @@ yin_parse_submodule(struct lysp_yin_ctx **yin_ctx, struct ly_ctx *ctx, struct ly cleanup: ly_log_location_revert(0, 0, 0, 1); if (ret) { - lysp_module_free(&fctx, (struct lysp_module *)mod_p); + lysp_module_free(ctx, (struct lysp_module *)mod_p); lysp_yin_ctx_free(*yin_ctx); *yin_ctx = NULL; } @@ -3962,7 +3978,6 @@ yin_parse_module(struct lysp_yin_ctx **yin_ctx, struct ly_in *in, struct lys_mod LY_ERR ret = LY_SUCCESS; enum ly_stmt kw = LY_STMT_NONE; struct lysp_module *mod_p = NULL; - struct lysf_ctx fctx = {.ctx = mod->ctx}; /* create context */ *yin_ctx = calloc(1, sizeof **yin_ctx); @@ -4013,7 +4028,7 @@ yin_parse_module(struct lysp_yin_ctx **yin_ctx, struct ly_in *in, struct lys_mod cleanup: ly_log_location_revert(0, 0, 0, 1); if (ret) { - lysp_module_free(&fctx, mod_p); + lysp_module_free(mod->ctx, mod_p); lysp_yin_ctx_free(*yin_ctx); *yin_ctx = NULL; } diff --git a/src/path.c b/src/path.c index d3cea0d7a..2a956f1b4 100644 --- a/src/path.c +++ b/src/path.c @@ -21,6 +21,7 @@ #include #include "compat.h" +#include "dict.h" #include "log.h" #include "ly_common.h" #include "plugins_types.h" @@ -315,7 +316,7 @@ ly_path_parse_deref(const struct ly_ctx *ctx, const struct lysc_node *ctx_node, arg_len = exp->tok_pos[end_token] - exp->tok_pos[begin_token]; LY_CHECK_RET(ly_path_parse(ctx, ctx_node, &exp->expr[exp->tok_pos[begin_token]], arg_len, 1, LY_PATH_BEGIN_EITHER, LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, &arg_expr), LY_EVALID); - lyxp_expr_free(ctx, arg_expr); + lyxp_expr_free(arg_expr); return LY_SUCCESS; } @@ -457,7 +458,7 @@ ly_path_parse(const struct ly_ctx *ctx, const struct lysc_node *ctx_node, const return LY_SUCCESS; error: - lyxp_expr_free(ctx, exp); + lyxp_expr_free(exp); LOG_LOCBACK(ctx_node ? 1 : 0, 0); return ret; } @@ -501,7 +502,7 @@ ly_path_parse_predicate(const struct ly_ctx *ctx, const struct lysc_node *cur_no return LY_SUCCESS; error: - lyxp_expr_free(ctx, exp); + lyxp_expr_free(exp); LOG_LOCBACK(cur_node ? 1 : 0, 0); return ret; } @@ -645,7 +646,7 @@ ly_path_compile_predicate(const struct ly_ctx *ctx, const struct lysc_node *cur_ const struct lysc_node *ctx_node, const struct lyxp_expr *expr, uint32_t *tok_idx, LY_VALUE_FORMAT format, void *prefix_data, struct ly_path_predicate **predicates) { - LY_ERR rc = LY_SUCCESS; + LY_ERR rc = LY_SUCCESS, r; struct ly_path_predicate *p; const struct lysc_node *key; const char *val; @@ -713,15 +714,11 @@ ly_path_compile_predicate(const struct ly_ctx *ctx, const struct lysc_node *cur_ val_len = expr->tok_len[*tok_idx]; } - /* store the value */ + /* do not store the canonical value, only validate */ LOG_LOCSET(key, NULL); - rc = 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); + r = lyd_value_validate2(ctx_node->module->ctx, key, val, val_len, format, prefix_data, NULL, NULL, &p->value); LOG_LOCBACK(1, 0); - LY_CHECK_ERR_GOTO(rc, p->value.realtype = NULL, cleanup); - - /* "allocate" the type to avoid problems when freeing the value after the type was freed */ - LY_ATOMIC_INC_BARRIER(((struct lysc_type *)p->value.realtype)->refcount); + LY_CHECK_ERR_GOTO(r && (r != LY_EINCOMPLETE), rc = r, cleanup); p->type = LY_PATH_PREDTYPE_LIST; ++(*tok_idx); @@ -775,14 +772,13 @@ ly_path_compile_predicate(const struct ly_ctx *ctx, const struct lysc_node *cur_ val_len = expr->tok_len[*tok_idx]; } - /* store the value */ - rc = 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); - LY_CHECK_ERR_GOTO(rc, p->value.realtype = NULL, cleanup); - ++(*tok_idx); + /* do not store the value, only validate */ + LOG_LOCSET(ctx_node, NULL); + r = lyd_value_validate2(ctx_node->module->ctx, ctx_node, val, val_len, format, prefix_data, NULL, NULL, &p->value); + LOG_LOCBACK(1, 0); + LY_CHECK_ERR_GOTO(r && (r != LY_EINCOMPLETE), rc = r, cleanup); - /* "allocate" the type to avoid problems when freeing the value after the type was freed */ - LY_ATOMIC_INC_BARRIER(((struct lysc_type *)p->value.realtype)->refcount); + ++(*tok_idx); /* ']' */ assert(expr->tokens[*tok_idx] == LYXP_TOKEN_BRACK2); @@ -978,8 +974,7 @@ ly_path_dup_predicates(const struct ly_ctx *ctx, const struct ly_path_predicate case LY_PATH_PREDTYPE_LEAFLIST: /* key-predicate or leaf-list-predicate */ (*dup)[u].key = pred[u].key; - pred[u].value.realtype->plugin->duplicate(ctx, &pred[u].value, &(*dup)[u].value); - LY_ATOMIC_INC_BARRIER(((struct lysc_type *)pred[u].value.realtype)->refcount); + lydict_dup(ctx, pred[u].value, &(*dup)[u].value); break; case LY_PATH_PREDTYPE_LIST_VAR: /* key-predicate with a variable */ @@ -1357,7 +1352,7 @@ ly_path_eval_partial(const struct ly_path *path, const struct lyd_node *start, c break; case LY_PATH_PREDTYPE_LEAFLIST: /* we will use hashes to find one leaf-list instance */ - LY_CHECK_RET(lyd_create_term2(path[u].node, &path[u].predicates[0].value, &target)); + LY_CHECK_RET(lyd_create_term_canon(path[u].node, path[u].predicates[0].value, &target)); lyd_find_sibling_first(start, target, &node); lyd_free_tree(target); break; @@ -1471,7 +1466,6 @@ void ly_path_predicates_free(const struct ly_ctx *ctx, struct ly_path_predicate *predicates) { LY_ARRAY_COUNT_TYPE u; - struct lysf_ctx fctx = {.ctx = (struct ly_ctx *)ctx}; if (!predicates) { return; @@ -1484,10 +1478,7 @@ ly_path_predicates_free(const struct ly_ctx *ctx, struct ly_path_predicate *pred break; case LY_PATH_PREDTYPE_LIST: case LY_PATH_PREDTYPE_LEAFLIST: - if (predicates[u].value.realtype) { - predicates[u].value.realtype->plugin->free(ctx, &predicates[u].value); - lysc_type_free(&fctx, (struct lysc_type *)predicates[u].value.realtype); - } + lydict_remove(ctx, predicates[u].value); break; case LY_PATH_PREDTYPE_LIST_VAR: free(predicates[u].variable); diff --git a/src/path.h b/src/path.h index 494a881a5..9592847f6 100644 --- a/src/path.h +++ b/src/path.h @@ -64,7 +64,7 @@ struct ly_path_predicate { struct { const struct lysc_node *key; /**< key node of the predicate, NULL in case of a leaf-list predicate */ union { - struct lyd_value value; /**< stored value representation according to the key's type (realtype ref) */ + const char *value; /**< stored canonical value of the key's type */ char *variable; /**< XPath variable used instead of the value */ }; }; diff --git a/src/plugins.c b/src/plugins.c index 22c49476b..ee0d89b0b 100644 --- a/src/plugins.c +++ b/src/plugins.c @@ -108,7 +108,7 @@ static pthread_mutex_t plugins_guard = PTHREAD_MUTEX_INITIALIZER; * unloaded with the destroy of the last context. Therefore, to reload the list of plugins, all the contexts must be * destroyed and with the creation of a first new context after that, the plugins will be reloaded. */ -static uint32_t context_refcount = 0; +static uint32_t context_refcount; /** * @brief Record describing an implemented extension. @@ -127,17 +127,55 @@ struct lyplg_record { }; #ifndef STATIC -static struct ly_set plugins_handlers = {0}; +static struct ly_set plugins_handlers; #endif -static struct ly_set plugins_types = {0}; -static struct ly_set plugins_extensions = {0}; + +/* global sets of loaded plugins */ +struct ly_set ly_plugins_types; +struct ly_set ly_plugins_extensions; + +/* global counters for the number of static plugins */ +uint32_t ly_static_type_plugins_count; +uint32_t ly_static_ext_plugins_count; + +LIBYANG_API_DEF struct lyplg_type * +lysc_get_type_plugin(uintptr_t plugin_ref) +{ + if (!plugin_ref) { + return NULL; + } + + if (plugin_ref <= ly_static_type_plugins_count) { + /* plugin is static, fetch it from the global list */ + return &((struct lyplg_type_record *)ly_plugins_types.objs[plugin_ref - 1])->plugin; + } else { + /* plugin is dynamic, return the pointer */ + return (struct lyplg_type *)plugin_ref; + } +} + +LIBYANG_API_DEF struct lyplg_ext * +lysc_get_ext_plugin(uintptr_t plugin_ref) +{ + if (!plugin_ref) { + return NULL; + } + + if (plugin_ref <= ly_static_ext_plugins_count) { + /* plugin is static, fetch it from the global list */ + return &((struct lyplg_ext_record *)ly_plugins_extensions.objs[plugin_ref - 1])->plugin; + } else { + /* plugin is dynamic, return the pointer */ + return (struct lyplg_ext *)plugin_ref; + } +} /** * @brief Iterate over list of loaded plugins of the given @p type. * - * @param[in] ctx The context for which the plugin is searched for + * @param[in] ctx Context for which the plugin is searched for. * @param[in] type Type of the plugins to iterate. - * @param[in,out] index The iterator - set to 0 for the first call. + * @param[in,out] index Iterator - set to 0 for the first call. * @return The plugin records, NULL if no more record is available. */ static struct lyplg_record * @@ -148,9 +186,9 @@ plugins_iter(const struct ly_ctx *ctx, enum LYPLG type, uint32_t *index) assert(index); if (type == LYPLG_EXTENSION) { - plugins = ctx ? &ctx->plugins_extensions : &plugins_extensions; + plugins = ctx ? &ctx->plugins_extensions : &ly_plugins_extensions; } else { - plugins = ctx ? &ctx->plugins_types : &plugins_types; + plugins = ctx ? &ctx->plugins_types : &ly_plugins_types; } if (*index == plugins->count) { @@ -161,8 +199,19 @@ plugins_iter(const struct ly_ctx *ctx, enum LYPLG type, uint32_t *index) return plugins->objs[*index - 1]; } +/** + * @brief Find the given @p type plugin record. + * + * @param[in] ctx Context for which the plugin record is searched for, NULL for static plugins. + * @param[in] type Type of the plugin record to find. + * @param[in] module Module name of the plugin record. + * @param[in] revision Revision of the @p module. + * @param[in] name Name of the plugin record. + * @param[out] record_idx Optional output parameter to get the index of the found plugin record. + * @return Found plugin record or NULL if not found. + */ static void * -lyplg_record_find(const struct ly_ctx *ctx, enum LYPLG type, const char *module, const char *revision, const char *name) +lyplg_record_find(const struct ly_ctx *ctx, enum LYPLG type, const char *module, const char *revision, const char *name, uint32_t *record_idx) { uint32_t i = 0; struct lyplg_record *item; @@ -170,6 +219,10 @@ lyplg_record_find(const struct ly_ctx *ctx, enum LYPLG type, const char *module, assert(module); assert(name); + if (record_idx) { + *record_idx = 0; + } + while ((item = plugins_iter(ctx, type, &i)) != NULL) { if (!strcmp(item->module, module) && !strcmp(item->name, name)) { if (item->revision && revision && strcmp(item->revision, revision)) { @@ -178,6 +231,11 @@ lyplg_record_find(const struct ly_ctx *ctx, enum LYPLG type, const char *module, continue; } + if (record_idx) { + /* return the record idx, -1 because the iterator is already increased */ + *record_idx = i - 1; + } + return item; } } @@ -185,40 +243,59 @@ lyplg_record_find(const struct ly_ctx *ctx, enum LYPLG type, const char *module, return NULL; } -struct lyplg_type * -lyplg_type_plugin_find(const struct ly_ctx *ctx, const char *module, const char *revision, const char *name) +/** + * @brief Find the plugin of the given @p type. + * + * @param[in] ctx Context for which the plugin record is searched for, NULL for static plugins. + * @param[in] type Type of the plugin record to find. + * @param[in] module Module name of the plugin. + * @param[in] revision Revision of the @p module. + * @param[in] name Name of the plugin. + * @return Reference to the callbacks plugin structure. Use ::LYSC_GET_TYPE_PLG + * or ::LYSC_GET_EXT_PLG on the returned value to get the actual plugin. 0 if not found. + */ +static uintptr_t +lyplg_plugin_find(const struct ly_ctx *ctx, enum LYPLG type, const char *module, const char *revision, const char *name) { - struct lyplg_record *record = NULL; + struct lyplg_type_record *record = NULL; + uint32_t record_idx = 0, static_plugin_count; if (ctx) { /* try to find context specific plugin */ - record = lyplg_record_find(ctx, LYPLG_TYPE, module, revision, name); + record = lyplg_record_find(ctx, type, module, revision, name, &record_idx); + if (record) { + /* plugin found in the context, hence it is dynamic so return the ptr to it */ + return (uintptr_t)&record->plugin; + } } + /* try to find shared plugin */ + record = lyplg_record_find(NULL, type, module, revision, name, &record_idx); if (!record) { - /* try to find shared plugin */ - record = lyplg_record_find(NULL, LYPLG_TYPE, module, revision, name); + /* not found */ + return 0; } - return record ? &((struct lyplg_type_record *)record)->plugin : NULL; + static_plugin_count = (type == LYPLG_TYPE) ? ly_static_type_plugins_count : ly_static_ext_plugins_count; + if (record_idx < static_plugin_count) { + /* static plugin, return an index with an offset of +1 in order to keep 0 as an invalid index (a NULL ptr) */ + return record_idx + 1; + } else { + /* dynamic plugin, return the pointer to it */ + return (uintptr_t)&record->plugin; + } } -struct lyplg_ext_record * -lyplg_ext_record_find(const struct ly_ctx *ctx, const char *module, const char *revision, const char *name) +uintptr_t +lyplg_type_plugin_find(const struct ly_ctx *ctx, const char *module, const char *revision, const char *name) { - struct lyplg_ext_record *record = NULL; - - if (ctx) { - /* try to find context specific plugin */ - record = lyplg_record_find(ctx, LYPLG_EXTENSION, module, revision, name); - } - - if (!record) { - /* try to find shared plugin */ - record = lyplg_record_find(NULL, LYPLG_EXTENSION, module, revision, name); - } + return lyplg_plugin_find(ctx, LYPLG_TYPE, module, revision, name); +} - return record; +uintptr_t +lyplg_ext_plugin_find(const struct ly_ctx *ctx, const char *module, const char *revision, const char *name) +{ + return lyplg_plugin_find(ctx, LYPLG_EXTENSION, module, revision, name); } /** @@ -245,7 +322,7 @@ plugins_insert(struct ly_ctx *ctx, enum LYPLG type, const void *recs) if (type == LYPLG_EXTENSION) { const struct lyplg_ext_record *rec = (const struct lyplg_ext_record *)recs; - plugins = ctx ? &ctx->plugins_extensions : &plugins_extensions; + plugins = ctx ? &ctx->plugins_extensions : &ly_plugins_extensions; for (uint32_t i = 0; rec[i].name; i++) { LY_CHECK_RET(ly_set_add(plugins, (void *)&rec[i], 0, NULL)); @@ -253,7 +330,7 @@ plugins_insert(struct ly_ctx *ctx, enum LYPLG type, const void *recs) } else { /* LYPLG_TYPE */ const struct lyplg_type_record *rec = (const struct lyplg_type_record *)recs; - plugins = ctx ? &ctx->plugins_types : &plugins_types; + plugins = ctx ? &ctx->plugins_types : &ly_plugins_types; for (uint32_t i = 0; rec[i].name; i++) { LY_CHECK_RET(ly_set_add(plugins, (void *)&rec[i], 0, NULL)); @@ -279,9 +356,10 @@ lyplg_clean_(void) return; } - ly_set_erase(&plugins_types, NULL); - ly_set_erase(&plugins_extensions, NULL); + ly_set_erase(&ly_plugins_types, NULL); + ly_set_erase(&ly_plugins_extensions, NULL); ly_set_erase(&plugins_handlers, lyplg_close_cb); + ly_static_type_plugins_count = ly_static_ext_plugins_count = 0; } #endif @@ -396,8 +474,8 @@ plugins_load_module(const char *pathname) } /* remember the current plugins lists for recovery */ - types_count = plugins_types.count; - extensions_count = plugins_extensions.count; + types_count = ly_plugins_types.count; + extensions_count = ly_plugins_extensions.count; /* type plugin */ ret = plugins_load(dlhandler, pathname, LYPLG_TYPE); @@ -417,11 +495,11 @@ plugins_load_module(const char *pathname) dlclose(dlhandler); /* revert changes in the lists */ - while (plugins_types.count > types_count) { - ly_set_rm_index(&plugins_types, plugins_types.count - 1, NULL); + while (ly_plugins_types.count > types_count) { + ly_set_rm_index(&ly_plugins_types, ly_plugins_types.count - 1, NULL); } - while (plugins_extensions.count > extensions_count) { - ly_set_rm_index(&plugins_extensions, plugins_extensions.count - 1, NULL); + while (ly_plugins_extensions.count > extensions_count) { + ly_set_rm_index(&ly_plugins_extensions, ly_plugins_extensions.count - 1, NULL); } return ret; @@ -480,7 +558,7 @@ plugins_insert_dir(enum LYPLG type) #endif LY_ERR -lyplg_init(ly_bool builtin_type_plugins_only) +lyplg_init(ly_bool builtin_type_plugins_only, ly_bool static_plugins_only) { LY_ERR ret; @@ -532,20 +610,27 @@ lyplg_init(ly_bool builtin_type_plugins_only) /* ietf-netconf-acm */ LY_CHECK_GOTO(ret = plugins_insert(NULL, LYPLG_TYPE, plugins_node_instanceid), error); - - /* internal extensions */ - LY_CHECK_GOTO(ret = plugins_insert(NULL, LYPLG_EXTENSION, plugins_nacm), error); - LY_CHECK_GOTO(ret = plugins_insert(NULL, LYPLG_EXTENSION, plugins_yangdata), error); - LY_CHECK_GOTO(ret = plugins_insert(NULL, LYPLG_EXTENSION, plugins_schema_mount), error); - LY_CHECK_GOTO(ret = plugins_insert(NULL, LYPLG_EXTENSION, plugins_structure), error); } + /* internal extensions */ + LY_CHECK_GOTO(ret = plugins_insert(NULL, LYPLG_EXTENSION, plugins_nacm), error); + LY_CHECK_GOTO(ret = plugins_insert(NULL, LYPLG_EXTENSION, plugins_yangdata), error); + LY_CHECK_GOTO(ret = plugins_insert(NULL, LYPLG_EXTENSION, plugins_schema_mount), error); + LY_CHECK_GOTO(ret = plugins_insert(NULL, LYPLG_EXTENSION, plugins_structure), error); + + /* the global plugin sets contain only static plugins at this point, so assign to the counters here. + * the counters are used to determine whether a plugin is static or not */ + ly_static_type_plugins_count = ly_plugins_types.count; + ly_static_ext_plugins_count = ly_plugins_extensions.count; + #ifndef STATIC - /* external types */ - LY_CHECK_GOTO(ret = plugins_insert_dir(LYPLG_TYPE), error); + if (!static_plugins_only) { + /* external types */ + LY_CHECK_GOTO(ret = plugins_insert_dir(LYPLG_TYPE), error); - /* external extensions */ - LY_CHECK_GOTO(ret = plugins_insert_dir(LYPLG_EXTENSION), error); + /* external extensions */ + LY_CHECK_GOTO(ret = plugins_insert_dir(LYPLG_EXTENSION), error); + } #endif /* initiation done, wake-up possibly waiting threads creating another contexts */ diff --git a/src/plugins_exts.c b/src/plugins_exts.c index af8179211..069e0906f 100644 --- a/src/plugins_exts.c +++ b/src/plugins_exts.c @@ -163,7 +163,7 @@ lys_compile_ext_instance_stmt(struct lysc_ctx *ctx, void **parsed_p, struct lysc case LY_STMT_REFERENCE: case LY_STMT_UNITS: /* just make a copy */ - LY_CHECK_GOTO(rc = lydict_insert(ctx->ctx, *parsed_p, 0, (const char **)substmt->storage_p), cleanup); + LY_CHECK_GOTO(rc = lysdict_insert(ctx->ctx, *parsed_p, 0, (const char **)substmt->storage_p), cleanup); break; case LY_STMT_BIT: @@ -412,7 +412,7 @@ lyplg_ext_print_get_level(const struct lyspr_ctx *ctx) return &((struct lyspr_ctx *)ctx)->level; } -LIBYANG_API_DECL LY_ERR +LIBYANG_API_DEF LY_ERR lyplg_ext_sprinter_ctree_add_ext_nodes(const struct lyspr_tree_ctx *ctx, struct lysc_ext_instance *ext, lyplg_ext_sprinter_ctree_override_clb clb) { @@ -450,7 +450,7 @@ lyplg_ext_sprinter_ctree_add_ext_nodes(const struct lyspr_tree_ctx *ctx, struct return rc; } -LIBYANG_API_DECL LY_ERR +LIBYANG_API_DEF LY_ERR lyplg_ext_sprinter_ptree_add_ext_nodes(const struct lyspr_tree_ctx *ctx, struct lysp_ext_instance *ext, lyplg_ext_sprinter_ptree_override_clb clb) { @@ -488,7 +488,7 @@ lyplg_ext_sprinter_ptree_add_ext_nodes(const struct lyspr_tree_ctx *ctx, struct return rc; } -LIBYANG_API_DECL LY_ERR +LIBYANG_API_DEF LY_ERR lyplg_ext_sprinter_ctree_add_nodes(const struct lyspr_tree_ctx *ctx, struct lysc_node *nodes, lyplg_ext_sprinter_ctree_override_clb clb) { @@ -508,7 +508,7 @@ lyplg_ext_sprinter_ctree_add_nodes(const struct lyspr_tree_ctx *ctx, struct lysc return LY_SUCCESS; } -LIBYANG_API_DECL LY_ERR +LIBYANG_API_DEF LY_ERR lyplg_ext_sprinter_ptree_add_nodes(const struct lyspr_tree_ctx *ctx, struct lysp_node *nodes, lyplg_ext_sprinter_ptree_override_clb clb) { @@ -528,7 +528,7 @@ lyplg_ext_sprinter_ptree_add_nodes(const struct lyspr_tree_ctx *ctx, struct lysp return LY_SUCCESS; } -LIBYANG_API_DECL LY_ERR +LIBYANG_API_DEF 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_RET(NULL, ctx, LY_EINVAL); @@ -539,6 +539,39 @@ lyplg_ext_sprinter_tree_set_priv(const struct lyspr_tree_ctx *ctx, void *plugin_ return LY_SUCCESS; } +LIBYANG_API_DEF int +lyplg_ext_compiled_stmts_storage_size(const struct lysc_ext_substmt *substmts, struct ly_ht *addr_ht) +{ + LY_CHECK_ARG_RET(NULL, substmts, addr_ht, -1); + + return ly_ctx_compiled_ext_stmts_storage_size(substmts, addr_ht); +} + +LIBYANG_API_DEF LY_ERR +lyplg_ext_compiled_stmts_storage_print(const struct lysc_ext_substmt *orig_substmts, struct lysc_ext_substmt *substmts, + struct ly_ht *addr_ht, struct ly_set *ptr_set, void **mem) +{ + LY_CHECK_ARG_RET(NULL, orig_substmts, substmts, addr_ht, ptr_set, mem, LY_EINVAL); + + return ly_ctx_compiled_ext_stmts_storage_print(orig_substmts, substmts, addr_ht, ptr_set, mem); +} + +LIBYANG_API_DEF void * +lyplg_ext_compiled_print_get_addr(const struct ly_ht *addr_ht, const void *addr) +{ + LY_CHECK_ARG_RET(NULL, addr_ht, addr, NULL); + + return ly_ctx_compiled_addr_ht_get(addr_ht, addr, 1); +} + +LIBYANG_API_DEF LY_ERR +lyplg_ext_compiled_print_add_addr(struct ly_ht *addr_ht, const void *orig_addr, const void *addr) +{ + LY_CHECK_ARG_RET(NULL, addr_ht, orig_addr, addr, LY_EINVAL); + + return ly_ctx_compiled_addr_ht_add(addr_ht, orig_addr, addr); +} + LIBYANG_API_DEF const char * lyplg_ext_stmt2str(enum ly_stmt stmt) { @@ -633,6 +666,7 @@ 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; + const char *extp_name; enum ly_stmt match = 0; void **s_p = NULL; @@ -641,8 +675,9 @@ lyplg_ext_parsed_get_storage(const struct lysc_ext_instance *ext, int stmt, uint /* find the parsed ext instance */ LY_ARRAY_FOR(ext->module->parsed->exts, u) { extp = &ext->module->parsed->exts[u]; + extp_name = strchr(extp->name, ':') + 1; - if (ext->def == extp->def->compiled) { + if (!strcmp(ext->def->name, extp_name)) { break; } extp = NULL; @@ -673,17 +708,32 @@ lyplg_ext_parsed_get_storage(const struct lysc_ext_instance *ext, int stmt, uint } LIBYANG_API_DEF LY_ERR -lyplg_ext_get_data(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, void **ext_data, ly_bool *ext_data_free) +lyplg_ext_get_data(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, const struct lyd_node *parent, + void **ext_data, ly_bool *ext_data_free) { LY_ERR rc; + struct ly_ctx_shared_data *ctx_data; - if (!ctx->ext_clb) { + LY_CHECK_ARG_RET(ctx, ctx, ext, ext_data, LY_EINVAL); + + ctx_data = ly_ctx_shared_data_get(ctx); + + /* EXT CLB LOCK */ + pthread_mutex_lock(&ctx_data->ext_clb_lock); + + if (!ctx_data->ext_clb) { lyplg_ext_compile_log(NULL, ext, LY_LLERR, LY_EINVAL, "Failed to get extension data, no callback set."); - return LY_EINVAL; + rc = LY_EINVAL; + goto cleanup; } - if ((rc = ctx->ext_clb(ext, ctx->ext_clb_data, ext_data, ext_data_free))) { + if ((rc = ctx_data->ext_clb(ext, parent, ctx_data->ext_clb_data, ext_data, ext_data_free))) { lyplg_ext_compile_log(NULL, ext, LY_LLERR, rc, "Callback for getting ext data failed."); + goto cleanup; } + +cleanup: + /* EXT CLB UNLOCK */ + pthread_mutex_unlock(&ctx_data->ext_clb_lock); return rc; } diff --git a/src/plugins_exts.h b/src/plugins_exts.h index 4cf80b2a2..1733712ad 100644 --- a/src/plugins_exts.h +++ b/src/plugins_exts.h @@ -4,7 +4,7 @@ * @author Michal Vasko * @brief libyang support for YANG extensions implementation. * - * 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. @@ -405,7 +405,7 @@ struct lysp_ext_instance { const char *argument; /**< optional value of the extension's argument */ LY_VALUE_FORMAT format; /**< prefix format of the extension name/argument (::LY_VALUE_XML is YIN format) */ void *prefix_data; /**< format-specific data for prefix resolution (see ly_resolve_prefix()) */ - struct lysp_ext *def; /**< pointer to the extension definition */ + uintptr_t plugin_ref; /**< reference to extension plugin, use ::lysc_get_ext_plugin() to get the plugin */ void *parent; /**< pointer to the parent statement holding the extension instance(s), use ::lysp_ext_instance#parent_stmt to access the value/structure */ @@ -414,7 +414,6 @@ struct lysp_ext_instance { statement directly and it is an array */ uint16_t flags; /**< ::LYS_INTERNAL value (@ref snodeflags) */ - const struct lyplg_ext_record *record; /**< extension definition plugin record, if any */ struct lysp_ext_substmt *substmts; /**< list of supported known YANG statements with the pointer to their parsed data ([sized array](@ref sizedarrays)) */ void *parsed; /**< private plugin parsed data */ @@ -923,6 +922,89 @@ typedef void (*lyplg_ext_compile_free_clb)(const struct ly_ctx *ctx, struct lysc */ LIBYANG_API_DECL void lyplg_ext_cfree_instance_substatements(const struct ly_ctx *ctx, struct lysc_ext_substmt *substmts); +/* + * compiled size + */ + +/** + * @brief Callback to return the size of the custom compiled structure and substmts array. If there are none, do not + * define this callback. + * + * @param[in] ext Compiled extension structure. + * @param[in,out] addr_ht Hash table with addresses of shared structures that were already accounted for, can be added to. + * @return Total size of the custom compiled structures and the substmts array; + * @return -1 on error. + */ +typedef int (*lyplg_ext_compiled_size_clb)(const struct lysc_ext_instance *ext, struct ly_ht *addr_ht); + +/** + * @brief Get the size of the compiled substatements storage. + * + * @param[in] substmts Compiled extension instance substatements array. + * @param[in,out] addr_ht Hash table with addresses of shared structures that were already accounted for, can be added to. + * @return Total size of the subtmts storage; + * @return -1 on error. + */ +LIBYANG_API_DECL int lyplg_ext_compiled_stmts_storage_size(const struct lysc_ext_substmt *substmts, struct ly_ht *addr_ht); + +/* + * compiled print + */ + +/** + * @brief Callback to print (serialize) the custom compiled structure and substmts array storage. + * + * @param[in] orig_ext Compiled extension structure to print. + * @param[in,out] ext Printed extension structure to modify. + * @param[in,out] mem Memory chunk of the size returned by ::lyplg_ext_compiled_size_clb() to print into, is moved + * after all the printed data. + * @param[in,out] ptr_set Set with pointers to set to printed addresses. + * @param[in,out] addr_ht Hash table with pairs of addresses of shared structures to be printed and their printed + * addresses, can be added to. + * @return LY_SUCCESS on success. + * @return LY_ERR on error. + */ +typedef LY_ERR (*lyplg_ext_compiled_print_clb)(const struct lysc_ext_instance *orig_ext, struct lysc_ext_instance *ext, + struct ly_ht *addr_ht, struct ly_set *ptr_set, void **mem); + +/** + * @brief Print the substatements array storage and assign it to the serialized extension instance substatements array. + * + * @param[in] orig_substmts Extension instance substatements to print. + * @param[in,out] substmts Serialized extension structure substatements whose storage to modify. + * @param[in,out] addr_ht Hash table with pairs of addresses of shared structures to be printed and their printed + * addresses, can be added to. + * @param[in,out] ptr_set Set with pointers to set to printed addresses. + * @param[in,out] mem Memory chunk to print into, is moved after all the printed data. + * @return LY_SUCCESS on success; + * @return LY_ERR on error. + */ +LIBYANG_API_DECL LY_ERR lyplg_ext_compiled_stmts_storage_print(const struct lysc_ext_substmt *orig_substmts, + struct lysc_ext_substmt *substmts, struct ly_ht *addr_ht, struct ly_set *ptr_set, void **mem); + +/** + * @brief Get the printed address of a shared structure, in case it has already been printed. + * + * @param[in] addr_ht Hash table with all the printed addresses of shared structures. + * @param[in] addr Address of the original shared structure to be printed. + * @return Address of the printed shared structure; + * @return NULL if the address was not found. + */ +LIBYANG_API_DECL void *lyplg_ext_compiled_print_get_addr(const struct ly_ht *addr_ht, const void *addr); + +/** + * @brief Add a printed address of a shared structure to be reused by later prints. + * + * @param[in,out] addr_ht Hash table with pairs of addresses of shared structures to be printed and their printed + * addresses, is added to. + * @param[in] orig_addr Address of the original shared structure that was printed. + * @param[in] addr Address of the printed structure to be reused. + * @return LY_SUCCESS on success; + * @return LY_ERR on error. + */ +LIBYANG_API_DECL LY_ERR lyplg_ext_compiled_print_add_addr(struct ly_ht *addr_ht, const void *orig_addr, + const void *addr); + /** * @brief Extension plugin implementing various aspects of a YANG extension. * @@ -948,6 +1030,9 @@ struct lyplg_ext { lyplg_ext_parse_free_clb pfree; /**< free the extension-specific data created by its parsing */ lyplg_ext_compile_free_clb cfree; /**< free the extension-specific data created by its compilation */ + lyplg_ext_compiled_size_clb compiled_size; /**< callback to get size of the custom compiled structure and substmts */ + lyplg_ext_compiled_print_clb compiled_print; /**< callback to print the compiled structure into a pre-allocated + memory chunk */ }; struct lyplg_ext_record { @@ -1013,13 +1098,14 @@ LIBYANG_API_DECL LY_ERR lyplg_ext_parsed_get_storage(const struct lysc_ext_insta * * @param[in] ctx Context with the callback. * @param[in] ext Compiled extension instance. + * @param[in] parent Data parent node instance of a schema node with @p ext instance. * @param[out] ext_data Provided extension instance data. * @param[out] ext_data_free Whether the extension instance should free @p ext_data or not. * @return LY_SUCCESS on success. * @return LY_ERR on error. */ -LIBYANG_API_DECL LY_ERR lyplg_ext_get_data(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, void **ext_data, - ly_bool *ext_data_free); +LIBYANG_API_DECL LY_ERR lyplg_ext_get_data(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, + const struct lyd_node *parent, void **ext_data, ly_bool *ext_data_free); /** * @brief Insert extension instance data into a parent. @@ -1035,20 +1121,66 @@ LIBYANG_API_DECL LY_ERR lyplg_ext_insert(struct lyd_node *parent, struct lyd_nod * @brief Expand parent-reference xpath expressions * * @param[in] ext Context allocated for extension. + * @param[in] parent Data parent node instance of a schema node with @p ext instance. * @param[out] refs Set of schema node matching parent-reference XPaths. * @return LY_ERR value. */ -LIBYANG_API_DECL LY_ERR lyplg_ext_schema_mount_get_parent_ref(const struct lysc_ext_instance *ext, struct ly_set **refs); +LIBYANG_API_DECL LY_ERR lyplg_ext_schema_mount_get_parent_ref(const struct lysc_ext_instance *ext, + const struct lyd_node *parent, struct ly_set **refs); /** * @brief Allocate a new context for a particular instance of the yangmnt:mount-point extension. * Caller is responsible for **freeing** the created context. * * @param[in] ext Compiled extension instance. + * @param[in] parent Data parent node instance of a schema node with @p ext instance. * @param[out] ctx Context with modules loaded from the list found in the extension data. * @return LY_ERR value. */ -LIBYANG_API_DECL LY_ERR lyplg_ext_schema_mount_create_context(const struct lysc_ext_instance *ext, struct ly_ctx **ctx); +LIBYANG_API_DECL LY_ERR lyplg_ext_schema_mount_create_context(const struct lysc_ext_instance *ext, + const struct lyd_node *parent, struct ly_ctx **ctx); + +/** + * @brief Create a shared schema mount context for a schema mount point. + * + * Does nothing if the mount point is not shared or if the context already exists. + * + * For printed contexts (read-only), all shared contexts must be created beforehand + * by calling this function as they cannot be created once the context is printed. + * + * @param[in] ext Compiled extension instance of a schema mount point. + * @param[in] ext_data ietf-yang-schema-mount and ietf-yang-library YANG data for the @p ext mount point. + * @return LY_ENOT if @p ext mount point data was not found in @p ext_data, other LY_ERR value otherwise. +*/ +LIBYANG_API_DECL LY_ERR lyplg_ext_schema_mount_create_shared_context(struct lysc_ext_instance *ext, + const struct lyd_node *ext_data); + +/** + * @brief Destroy all the shared schema mount contexts for a given libyang context. + * + * For standard contexts this is done automatically when the context is destroyed. + * + * For printed contexts (read-only), all shared contexts must be destroyed + * by calling this function as otherwise they will be lost once the original context is destroyed. + * + * @param[in] ext Compiled extension instance of a schema mount point. All the shared schema mount + * contexts that belong to the same libyang context as @p ext will be destroyed. + */ +LIBYANG_API_DECL void lyplg_ext_schema_mount_destroy_shared_contexts(struct lysc_ext_instance *ext); + +/** + * @brief Destroy all the inline contexts for a given libyang context. + * + * For standard contexts this is done automatically when the context is destroyed. + * Useful when using a long-lived libyang context for cleaning up memory after completing + * operations with schema mount extension data that require inline contexts. + * + * Inline contexts are currently not supported in printed contexts. + * + * @param[in] ext Compiled extension instance of a schema mount point. All the inline schema mount + * contexts that belong to the same libyang context as @p ext will be destroyed. + */ +LIBYANG_API_DECL void lyplg_ext_schema_mount_destroy_inline_contexts(struct lysc_ext_instance *ext); /** @} pluginsExtensions */ diff --git a/src/plugins_exts/metadata.c b/src/plugins_exts/metadata.c index baec86f98..e699e120e 100644 --- a/src/plugins_exts/metadata.c +++ b/src/plugins_exts/metadata.c @@ -19,6 +19,7 @@ #include #include +#include "compat.h" #include "libyang.h" #include "plugins_exts.h" @@ -214,6 +215,35 @@ annotation_cfree(const struct ly_ctx *ctx, struct lysc_ext_instance *ext) free(ext->compiled); } +static int +annotation_compiled_size(const struct lysc_ext_instance *ext, struct ly_ht *addr_ht) +{ + int size = 0; + + size += sizeof(struct lysc_ext_metadata); + size += lyplg_ext_compiled_stmts_storage_size(ext->substmts, addr_ht); + + return size; +} + +static LY_ERR +annotation_compiled_print(const struct lysc_ext_instance *orig_ext, struct lysc_ext_instance *ext, + struct ly_ht *addr_ht, struct ly_set *ptr_set, void **mem) +{ + struct lysc_ext_metadata *ann_cdata; + + ann_cdata = ext->compiled = *mem; + *mem = (char *)*mem + sizeof *ann_cdata; + + ext->substmts[1].storage_p = (void **)&ann_cdata->units; + ext->substmts[2].storage_p = (void **)&ann_cdata->flags; + ext->substmts[3].storage_p = (void **)&ann_cdata->type; + ext->substmts[4].storage_p = (void **)&ann_cdata->dsc; + ext->substmts[5].storage_p = (void **)&ann_cdata->ref; + + return lyplg_ext_compiled_stmts_storage_print(orig_ext->substmts, ext->substmts, addr_ht, ptr_set, mem); +} + /** * @brief Plugin descriptions for the Metadata's annotation extension * @@ -227,7 +257,7 @@ const struct lyplg_ext_record plugins_metadata[] = { .revision = "2016-08-05", .name = "annotation", - .plugin.id = "ly2 metadata v1", + .plugin.id = "ly2 metadata", .plugin.parse = annotation_parse, .plugin.compile = annotation_compile, .plugin.printer_info = annotation_printer_info, @@ -238,6 +268,8 @@ const struct lyplg_ext_record plugins_metadata[] = { .plugin.validate = NULL, .plugin.pfree = annotation_pfree, .plugin.cfree = annotation_cfree, + .plugin.compiled_size = annotation_compiled_size, + .plugin.compiled_print = annotation_compiled_print }, {0} /* terminating zeroed record */ }; diff --git a/src/plugins_exts/nacm.c b/src/plugins_exts/nacm.c index df49721a6..8a04d90de 100644 --- a/src/plugins_exts/nacm.c +++ b/src/plugins_exts/nacm.c @@ -4,7 +4,7 @@ * @author Michal Vasko * @brief libyang extension plugin - NACM (RFC 6536) * - * 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. @@ -19,7 +19,9 @@ #include "compat.h" #include "libyang.h" +#include "ly_common.h" #include "plugins_exts.h" +#include "plugins_internal.h" struct nacm_dfs_arg { struct lysc_ext_instance *ext; @@ -55,11 +57,12 @@ nacm_inherit_clb(struct lysc_node *node, void *data, ly_bool *dfs_continue) inherited->parent = node; inherited->parent_stmt = lyplg_ext_nodetype2stmt(node->nodetype); if (arg->ext->argument) { - if ((ret = lydict_insert(node->module->ctx, arg->ext->argument, 0, &inherited->argument))) { + if ((ret = lysdict_insert(node->module->ctx, arg->ext->argument, 0, &inherited->argument))) { return ret; } } - /* copy the pointer to the static variables */ + + /* copy the NACM value */ inherited->compiled = arg->ext->compiled; } @@ -80,6 +83,7 @@ nacm_parse(struct lysp_ctx *pctx, struct lysp_ext_instance *ext) { struct lysp_node *parent = NULL; LY_ARRAY_COUNT_TYPE u; + struct lyplg_ext *ext_plugin, *parent_ext_plugin; /* check that the extension is instantiated at an allowed place - data node */ if (!(ext->parent_stmt & LY_STMT_NODE_MASK)) { @@ -99,9 +103,12 @@ nacm_parse(struct lysp_ctx *pctx, struct lysp_ext_instance *ext) return LY_ENOT; } + ext_plugin = LYSC_GET_EXT_PLG(ext->plugin_ref); + /* check for duplication */ LY_ARRAY_FOR(parent->exts, u) { - if ((&parent->exts[u] != ext) && parent->exts[u].record && !strcmp(parent->exts[u].record->plugin.id, ext->record->plugin.id)) { + parent_ext_plugin = LYSC_GET_EXT_PLG(parent->exts[u].plugin_ref); + if ((&parent->exts[u] != ext) && parent_ext_plugin && !strcmp(parent_ext_plugin->id, ext_plugin->id)) { /* duplication of a NACM extension on a single node * We check for all NACM plugins since we want to catch even the situation that there is default-deny-all * AND default-deny-write */ @@ -128,14 +135,11 @@ nacm_compile(struct lysc_ctx *UNUSED(cctx), const struct lysp_ext_instance *UNUS { struct nacm_dfs_arg dfs_arg; - static const uint8_t nacm_deny_all = 1; - static const uint8_t nacm_deny_write = 2; - /* store the NACM flag */ if (!strcmp(ext->def->name, "default-deny-write")) { - ext->compiled = (void *)&nacm_deny_write; + ext->compiled = (void *)2; } else if (!strcmp(ext->def->name, "default-deny-all")) { - ext->compiled = (void *)&nacm_deny_all; + ext->compiled = (void *)1; } else { return LY_EINT; } @@ -146,6 +150,22 @@ nacm_compile(struct lysc_ctx *UNUSED(cctx), const struct lysp_ext_instance *UNUS return lysc_tree_dfs_full(ext->parent, nacm_inherit_clb, &dfs_arg); } +static int +nacm_compiled_size(const struct lysc_ext_instance *UNUSED(ext), struct ly_ht *UNUSED(addr_ht)) +{ + return 0; +} + +static LY_ERR +nacm_compiled_print(const struct lysc_ext_instance *orig_ext, struct lysc_ext_instance *ext, + struct ly_ht *UNUSED(addr_ht), struct ly_set *UNUSED(ptr_set), void **UNUSED(mem)) +{ + /* copy the NACM extension "value" */ + ext->compiled = orig_ext->compiled; + + return LY_SUCCESS; +} + /** * @brief Plugin descriptions for the NACM's default-deny-write and default-deny-all extensions * @@ -159,7 +179,7 @@ const struct lyplg_ext_record plugins_nacm[] = { .revision = "2012-02-22", .name = "default-deny-write", - .plugin.id = "ly2 NACM v1", + .plugin.id = "ly2 NACM", .plugin.parse = nacm_parse, .plugin.compile = nacm_compile, .plugin.printer_info = NULL, @@ -169,13 +189,15 @@ const struct lyplg_ext_record plugins_nacm[] = { .plugin.snode = NULL, .plugin.validate = NULL, .plugin.pfree = NULL, - .plugin.cfree = NULL + .plugin.cfree = NULL, + .plugin.compiled_size = nacm_compiled_size, + .plugin.compiled_print = nacm_compiled_print }, { .module = "ietf-netconf-acm", .revision = "2018-02-14", .name = "default-deny-write", - .plugin.id = "ly2 NACM v1", + .plugin.id = "ly2 NACM", .plugin.parse = nacm_parse, .plugin.compile = nacm_compile, .plugin.printer_info = NULL, @@ -185,13 +207,15 @@ const struct lyplg_ext_record plugins_nacm[] = { .plugin.snode = NULL, .plugin.validate = NULL, .plugin.pfree = NULL, - .plugin.cfree = NULL + .plugin.cfree = NULL, + .plugin.compiled_size = nacm_compiled_size, + .plugin.compiled_print = nacm_compiled_print }, { .module = "ietf-netconf-acm", .revision = "2012-02-22", .name = "default-deny-all", - .plugin.id = "ly2 NACM v1", + .plugin.id = "ly2 NACM", .plugin.parse = nacm_parse, .plugin.compile = nacm_compile, .plugin.printer_info = NULL, @@ -201,13 +225,15 @@ const struct lyplg_ext_record plugins_nacm[] = { .plugin.snode = NULL, .plugin.validate = NULL, .plugin.pfree = NULL, - .plugin.cfree = NULL + .plugin.cfree = NULL, + .plugin.compiled_size = nacm_compiled_size, + .plugin.compiled_print = nacm_compiled_print }, { .module = "ietf-netconf-acm", .revision = "2018-02-14", .name = "default-deny-all", - .plugin.id = "ly2 NACM v1", + .plugin.id = "ly2 NACM", .plugin.parse = nacm_parse, .plugin.compile = nacm_compile, .plugin.printer_info = NULL, @@ -217,7 +243,9 @@ const struct lyplg_ext_record plugins_nacm[] = { .plugin.snode = NULL, .plugin.validate = NULL, .plugin.pfree = NULL, - .plugin.cfree = NULL + .plugin.cfree = NULL, + .plugin.compiled_size = nacm_compiled_size, + .plugin.compiled_print = nacm_compiled_print }, {0} /* terminating zeroed item */ }; diff --git a/src/plugins_exts/schema_mount.c b/src/plugins_exts/schema_mount.c index be9153020..3afeab040 100644 --- a/src/plugins_exts/schema_mount.c +++ b/src/plugins_exts/schema_mount.c @@ -1,9 +1,10 @@ /** * @file schema_mount.c * @author Tadeas Vintrlik + * @author Michal Vasko * @brief libyang extension plugin - Schema Mount (RFC 8528) * - * Copyright (c) 2021 CESNET, z.s.p.o. + * Copyright (c) 2021 - 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. @@ -21,13 +22,16 @@ #include #include "compat.h" +#include "context.h" #include "dict.h" #include "libyang.h" #include "log.h" #include "ly_common.h" #include "parser_data.h" #include "plugins_exts.h" +#include "plugins_internal.h" #include "plugins_types.h" +#include "tree.h" #include "tree_data.h" #include "tree_schema.h" @@ -35,26 +39,26 @@ * @brief Internal schema mount data structure for holding all the contexts of parsed data. */ struct lyplg_ext_sm { - pthread_mutex_t lock; /**< lock for accessing this shared structure */ + pthread_mutex_t lock; /**< lock for accessing this shared structure */ struct lyplg_ext_sm_shared { struct { - struct ly_ctx *ctx; /**< context shared between all data of this mount point */ - const char *mount_point; /**< mount point name */ - const char *content_id; /**< yang-library content-id (alternatively module-set-id), - stored in the dictionary of the ext instance context */ - } *schemas; /**< array of shared schema schemas */ - uint32_t schema_count; /**< length of schemas array */ - uint32_t ref_count; /**< number of references to this structure (mount-points with the same name - in the module) */ - } *shared; /**< shared schema mount points */ + struct ly_ctx *ctx; /**< context shared between all data of this mount point */ + char *mount_point; /**< mount point name */ + char *content_id; /**< yang-library content-id (alternatively module-set-id), + stored in the dictionary of the ext instance context */ + } *schemas; /**< array of shared schema schemas */ + uint32_t schema_count; /**< length of schemas array */ + uint32_t ref_count; /**< number of references to this structure (mount-points with the same name + in the module) */ + } *shared; /**< shared schema mount points */ struct lyplg_ext_sm_inln { struct { - struct ly_ctx *ctx; /**< context created for inline schema data, may be reused if possible */ - } *schemas; /**< array of inline schemas */ - uint32_t schema_count; /**< length of schemas array */ - } inln; /**< inline mount points */ + struct ly_ctx *ctx; /**< context created for inline schema data, may be reused if possible */ + } *schemas; /**< array of inline schemas */ + uint32_t schema_count; /**< length of schemas array */ + } inln; /**< inline mount points */ }; struct sprinter_tree_priv { @@ -403,20 +407,26 @@ schema_mount_get_ctx_shared(struct lysc_ext_instance *ext, const struct lyd_node assert(sm_data && sm_data->shared); + if (ext_ctx) { + *ext_ctx = NULL; + } + /* get yang-library content-id or module-set-id */ if ((r = schema_mount_get_content_id(ext, ext_data, &content_id))) { return r; } - /* LOCK */ - if ((r = pthread_mutex_lock(&sm_data->lock))) { - lyplg_ext_compile_log(NULL, ext, LY_LLERR, LY_ESYS, "Mutex lock failed (%s).", strerror(r)); - return LY_ESYS; + /* LOCK (dont lock if pctx since its memory is not writable) */ + if (!ly_ctx_is_printed(ext->module->ctx)) { + if ((r = pthread_mutex_lock(&sm_data->lock))) { + lyplg_ext_compile_log(NULL, ext, LY_LLERR, LY_ESYS, "Mutex lock failed (%s).", strerror(r)); + return LY_ESYS; + } } /* try to find this mount point */ for (i = 0; i < sm_data->shared->schema_count; ++i) { - if (ext->argument == sm_data->shared->schemas[i].mount_point) { + if (!strcmp(ext->argument, sm_data->shared->schemas[i].mount_point)) { break; } } @@ -431,6 +441,16 @@ schema_mount_get_ctx_shared(struct lysc_ext_instance *ext, const struct lyd_node goto cleanup; } } else { + if (ly_ctx_is_printed(ext->module->ctx)) { + /* printed context, a shared mount point ctx should have already been created + * and it is not possible to create a new one once the context is printed */ + lyplg_ext_compile_log(NULL, ext, LY_LLERR, LY_EVALID, + "Shared-schema mount point \"%s\" not found and cannot be created in printed context.", + ext->argument); + rc = LY_EVALID; + goto cleanup; + } + /* no schema found, create it */ if ((r = schema_mount_create_ctx(ext, ext_data, config, &new_ctx))) { rc = r; @@ -448,20 +468,142 @@ schema_mount_get_ctx_shared(struct lysc_ext_instance *ext, const struct lyd_node /* fill entry */ sm_data->shared->schemas[i].ctx = new_ctx; - sm_data->shared->schemas[i].mount_point = ext->argument; - lydict_insert(ext->module->ctx, content_id, 0, &sm_data->shared->schemas[i].content_id); + sm_data->shared->schemas[i].mount_point = strdup(ext->argument); + sm_data->shared->schemas[i].content_id = strdup(content_id); + if (!sm_data->shared->schemas[i].mount_point || !sm_data->shared->schemas[i].content_id) { + ly_ctx_destroy(new_ctx); + free(sm_data->shared->schemas[i].mount_point); + free(sm_data->shared->schemas[i].content_id); + EXT_LOGERR_MEM_GOTO(NULL, ext, rc, cleanup); + } } /* use the context */ - *ext_ctx = sm_data->shared->schemas[i].ctx; + if (ext_ctx) { + *ext_ctx = sm_data->shared->schemas[i].ctx; + } cleanup: /* UNLOCK */ - pthread_mutex_unlock(&sm_data->lock); + if (!ly_ctx_is_printed(ext->module->ctx)) { + pthread_mutex_unlock(&sm_data->lock); + } return rc; } +LIBYANG_API_DEF LY_ERR +lyplg_ext_schema_mount_create_shared_context(struct lysc_ext_instance *ext, const struct lyd_node *ext_data) +{ + LY_ERR ret = LY_SUCCESS; + ly_bool config = 1, shared = 0; + + LY_CHECK_ARG_RET(NULL, ext, ext_data, LY_EINVAL); + + /* get the mount point */ + ret = schema_mount_get_smount(ext, ext_data, &config, &shared); + if (ret) { + goto cleanup; + } + + if (!shared) { + /* we dont care about inline mount points */ + goto cleanup; + } + + /* create the context if it is not created yet */ + ret = schema_mount_get_ctx_shared(ext, ext_data, config, NULL); + if (ret) { + goto cleanup; + } + +cleanup: + return ret; +} + +LIBYANG_API_DEF void +lyplg_ext_schema_mount_destroy_shared_contexts(struct lysc_ext_instance *ext) +{ + int r; + uint32_t i; + struct lyplg_ext_sm *sm_data; + ly_bool ctx_is_printed; + + LY_CHECK_ARG_RET(NULL, ext, ); + + sm_data = ext->compiled; + ctx_is_printed = ly_ctx_is_printed(ext->module->ctx); + + /* LOCK (dont lock if pctx since its memory is not writable) */ + if (!ctx_is_printed) { + if ((r = pthread_mutex_lock(&sm_data->lock))) { + lyplg_ext_compile_log(NULL, ext, LY_LLERR, LY_ESYS, "Mutex lock failed (%s).", strerror(r)); + return; + } + } + + /* free all the shared schemas of this ext */ + for (i = 0; i < sm_data->shared->schema_count; ++i) { + /* ctx can be destroyed whether printed or not */ + ly_ctx_destroy(sm_data->shared->schemas[i].ctx); + + if (!ctx_is_printed) { + /* these members can be freed only if the context is not printed */ + free(sm_data->shared->schemas[i].mount_point); + sm_data->shared->schemas[i].mount_point = NULL; + free(sm_data->shared->schemas[i].content_id); + sm_data->shared->schemas[i].content_id = NULL; + } + } + + if (!ctx_is_printed) { + free(sm_data->shared->schemas); + sm_data->shared->schemas = NULL; + sm_data->shared->schema_count = 0; + + /* UNLOCK */ + pthread_mutex_unlock(&sm_data->lock); + } +} + +LIBYANG_API_DEF void +lyplg_ext_schema_mount_destroy_inline_contexts(struct lysc_ext_instance *ext) +{ + int r; + struct lyplg_ext_sm *sm_data; + uint32_t i; + + LY_CHECK_ARG_RET(NULL, ext, ); + + sm_data = ext->compiled; + + if (ly_ctx_is_printed(ext->module->ctx)) { + /* inline mount points not supported in printed context */ + assert(sm_data->inln.schema_count == 0); + LOGVRB("Inline mount points not supported in printed context, " + "skipping cleanup of inline mount points."); + return; + } + + /* LOCK */ + if ((r = pthread_mutex_lock(&sm_data->lock))) { + lyplg_ext_compile_log(NULL, ext, LY_LLERR, LY_ESYS, "Mutex lock failed (%s).", strerror(r)); + return; + } + + /* free all inline schemas */ + for (i = 0; i < sm_data->inln.schema_count; ++i) { + ly_ctx_destroy(sm_data->inln.schemas[i].ctx); + sm_data->inln.schemas[i].ctx = NULL; + } + free(sm_data->inln.schemas); + sm_data->inln.schemas = NULL; + sm_data->inln.schema_count = 0; + + /* UNLOCK */ + pthread_mutex_unlock(&sm_data->lock); +} + /** * @brief Check whether ietf-yang-library data describe an existing context meaning whether it includes * at least exactly all the mentioned modules. @@ -576,6 +718,15 @@ schema_mount_get_ctx_inline(struct lysc_ext_instance *ext, const struct lyd_node assert(sm_data && sm_data->shared); + if (ly_ctx_is_printed(ext->module->ctx)) { + /* compiled print (::schema_mount_compiled_print()) doesnt print any inline contexts, + * so they cannot be found nor created at this point + * (in the future they could be printed and possibly found here and used) */ + lyplg_ext_compile_log(NULL, ext, LY_LLERR, LY_EVALID, + "Inline-schema mount point \"%s\" not allowed in printed context.", ext->argument); + return LY_EVALID; + } + /* LOCK */ if ((r = pthread_mutex_lock(&sm_data->lock))) { lyplg_ext_compile_log(NULL, ext, LY_LLERR, LY_ESYS, "Mutex lock failed (%s).", strerror(r)); @@ -624,8 +775,16 @@ schema_mount_get_ctx_inline(struct lysc_ext_instance *ext, const struct lyd_node return rc; } +/** + * @brief Get schema (context) for a mount point. + * + * @param[in] ext Compiled extension instance. + * @param[in] parent Data parent node instance of a schema node with @p ext instance. + * @param[out] ext_ctx Schema to use for parsing the data. + * @return LY_ERR value. + */ LY_ERR -lyplg_ext_schema_mount_get_ctx(struct lysc_ext_instance *ext, const struct ly_ctx **ext_ctx) +lyplg_ext_schema_mount_get_ctx(struct lysc_ext_instance *ext, const struct lyd_node *parent, const struct ly_ctx **ext_ctx) { LY_ERR ret = LY_SUCCESS, r; struct lyd_node *iter, *ext_data = NULL; @@ -634,7 +793,7 @@ lyplg_ext_schema_mount_get_ctx(struct lysc_ext_instance *ext, const struct ly_ct *ext_ctx = NULL; /* get operational data with ietf-yang-library and ietf-yang-schema-mount data */ - if ((r = lyplg_ext_get_data(ext->module->ctx, ext, (void **)&ext_data, &ext_data_free))) { + if ((r = lyplg_ext_get_data(ext->module->ctx, ext, parent, (void **)&ext_data, &ext_data_free))) { ret = r; goto cleanup; } @@ -686,7 +845,7 @@ schema_mount_snode(struct lysc_ext_instance *ext, const struct lyd_node *parent, const struct ly_ctx *ext_ctx = NULL; /* get context based on ietf-yang-library data */ - if ((r = lyplg_ext_schema_mount_get_ctx(ext, &ext_ctx))) { + if ((r = lyplg_ext_schema_mount_get_ctx(ext, parent, &ext_ctx))) { return r; } @@ -834,7 +993,8 @@ schema_mount_dup_parent_ref(const struct lysc_ext_instance *ext, const struct ly } LIBYANG_API_DEF LY_ERR -lyplg_ext_schema_mount_get_parent_ref(const struct lysc_ext_instance *ext, struct ly_set **refs) +lyplg_ext_schema_mount_get_parent_ref(const struct lysc_ext_instance *ext, const struct lyd_node *parent, + struct ly_set **refs) { LY_ERR rc; struct ly_set *pref_set = NULL; @@ -844,7 +1004,7 @@ lyplg_ext_schema_mount_get_parent_ref(const struct lysc_ext_instance *ext, struc ly_bool ext_data_free; /* get operational data with ietf-yang-library and ietf-yang-schema-mount data */ - if ((rc = lyplg_ext_get_data(ext->module->ctx, ext, (void **)&ext_data, &ext_data_free))) { + if ((rc = lyplg_ext_get_data(ext->module->ctx, ext, parent, (void **)&ext_data, &ext_data_free))) { return rc; } @@ -909,7 +1069,7 @@ schema_mount_validate(struct lysc_ext_instance *ext, struct lyd_node *sibling, c } /* get operational data with ietf-yang-library and ietf-yang-schema-mount data */ - if ((ret = lyplg_ext_get_data(ext->module->ctx, ext, (void **)&ext_data, &ext_data_free))) { + if ((ret = lyplg_ext_get_data(ext->module->ctx, ext, lyd_parent(sibling), (void **)&ext_data, &ext_data_free))) { goto cleanup; } @@ -1027,7 +1187,7 @@ schema_mount_validate(struct lysc_ext_instance *ext, struct lyd_node *sibling, c * Implementation of ::lyplg_ext_compile_free_clb callback set as ::lyext_plugin::cfree. */ static void -schema_mount_cfree(const struct ly_ctx *ctx, struct lysc_ext_instance *ext) +schema_mount_cfree(const struct ly_ctx *UNUSED(ctx), struct lysc_ext_instance *ext) { struct lyplg_ext_sm *sm_data = ext->compiled; uint32_t i; @@ -1039,7 +1199,8 @@ schema_mount_cfree(const struct ly_ctx *ctx, struct lysc_ext_instance *ext) if (!--sm_data->shared->ref_count) { for (i = 0; i < sm_data->shared->schema_count; ++i) { ly_ctx_destroy(sm_data->shared->schemas[i].ctx); - lydict_remove(ctx, sm_data->shared->schemas[i].content_id); + free(sm_data->shared->schemas[i].mount_point); + free(sm_data->shared->schemas[i].content_id); } free(sm_data->shared->schemas); free(sm_data->shared); @@ -1055,13 +1216,32 @@ schema_mount_cfree(const struct ly_ctx *ctx, struct lysc_ext_instance *ext) } LIBYANG_API_DEF LY_ERR -lyplg_ext_schema_mount_create_context(const struct lysc_ext_instance *ext, struct ly_ctx **ctx) +lyplg_ext_schema_mount_create_context(const struct lysc_ext_instance *ext, const struct lyd_node *parent, + struct ly_ctx **ctx) { struct lyd_node *ext_data = NULL; - ly_bool ext_data_free = 0, config; + struct ly_ctx_shared_data *ctx_data; + struct lyplg_ext_sm *sm_data; + ly_bool ext_data_free = 0, config, shared, builtin_plugins_only, static_plugins_only; LY_ERR rc = LY_SUCCESS; + uint32_t i; + ly_ext_data_clb ext_data_clb; + + LY_CHECK_ARG_RET(NULL, ext, ctx, LY_EINVAL); + + sm_data = ext->compiled; - if (!ext->module->ctx->ext_clb) { + ctx_data = ly_ctx_shared_data_get(ext->def->module->ctx); + + /* EXT CLB LOCK */ + pthread_mutex_lock(&ctx_data->ext_clb_lock); + + ext_data_clb = ctx_data->ext_clb; + + /* EXT CLB UNLOCK */ + pthread_mutex_unlock(&ctx_data->ext_clb_lock); + + if (!ext_data_clb) { return LY_EINVAL; } @@ -1070,12 +1250,40 @@ lyplg_ext_schema_mount_create_context(const struct lysc_ext_instance *ext, struc } /* get operational data with ietf-yang-library and ietf-yang-schema-mount data */ - if ((rc = lyplg_ext_get_data(ext->module->ctx, ext, (void **)&ext_data, &ext_data_free))) { + if ((rc = lyplg_ext_get_data(ext->module->ctx, ext, parent, (void **)&ext_data, &ext_data_free))) { return rc; } /* learn about this mount point */ - if ((rc = schema_mount_get_smount(ext, ext_data, &config, NULL))) { + if ((rc = schema_mount_get_smount(ext, ext_data, &config, &shared))) { + goto cleanup; + } + + /* check if it already exists */ + if (shared) { + for (i = 0; i < sm_data->shared->schema_count; ++i) { + if (!strcmp(sm_data->shared->schemas[i].mount_point, ext->argument)) { + /* found, mock the context creation so it can later be safely destroyed */ + builtin_plugins_only = (ext->module->ctx->opts & LY_CTX_BUILTIN_PLUGINS_ONLY) ? 1 : 0; + static_plugins_only = (ext->module->ctx->opts & LY_CTX_STATIC_PLUGINS_ONLY) ? 1 : 0; + LY_CHECK_ERR_GOTO(lyplg_init(builtin_plugins_only, static_plugins_only), + LOGINT(NULL); rc = LY_EINT, cleanup); + + if ((rc = ly_ctx_data_add(sm_data->shared->schemas[i].ctx))) { + goto cleanup; + } + + /* context can be reused */ + *ctx = sm_data->shared->schemas[i].ctx; + goto cleanup; + } + } + } + + /* context not found, check if the ext ctx is printed - mount points cannot be created in printed contexts */ + if (ly_ctx_is_printed(ext->module->ctx)) { + LOGERR(ext->module->ctx, LY_EINVAL, "Mount points cannot be created in printed contexts."); + rc = LY_EINVAL; goto cleanup; } @@ -1199,12 +1407,12 @@ schema_mount_sprinter_ctree(struct lysc_ext_instance *ext, const struct lyspr_tr return LY_SUCCESS; } - if (lyplg_ext_schema_mount_create_context(ext, &ext_ctx)) { + if (lyplg_ext_schema_mount_create_context(ext, NULL, &ext_ctx)) { /* Void mount point */ return LY_SUCCESS; } - rc = lyplg_ext_schema_mount_get_parent_ref(ext, &refs); + rc = lyplg_ext_schema_mount_get_parent_ref(ext, NULL, &refs); LY_CHECK_GOTO(rc, cleanup); /* build new list of modules to print. This list will omit internal @@ -1227,7 +1435,7 @@ schema_mount_sprinter_ctree(struct lysc_ext_instance *ext, const struct lyspr_tr } /* Add data nodes, rpcs and notifications. */ - if ((ext_ctx->flags & LY_CTX_SET_PRIV_PARSED) && mod->compiled) { + if ((ext_ctx->opts & LY_CTX_SET_PRIV_PARSED) && mod->compiled) { /* For compiled module. */ rc = lyplg_ext_sprinter_ctree_add_nodes(ctx, mod->compiled->data, schema_mount_sprinter_tree_cnode_override_mounted); @@ -1296,6 +1504,101 @@ schema_mount_sprinter_ctree(struct lysc_ext_instance *ext, const struct lyspr_tr return rc; } +static int +schema_mount_compiled_size(const struct lysc_ext_instance *ext, struct ly_ht *addr_ht) +{ + struct lyplg_ext_sm *sm_data = ext->compiled; + uint32_t i, hash; + int size = 0; + + if (!sm_data) { + return 0; + } + + size += sizeof *sm_data; + + /* ht addr check, make sure the shared context is stored only once */ + hash = lyht_hash((const char *)&sm_data->shared, sizeof sm_data->shared); + if (lyht_insert(addr_ht, &sm_data->shared, hash, NULL) == LY_EEXIST) { + return size; + } + + size += sizeof *sm_data->shared; + size += sm_data->shared->schema_count * sizeof *sm_data->shared->schemas; + for (i = 0; i < sm_data->shared->schema_count; ++i) { + size += ly_ctx_compiled_size(sm_data->shared->schemas[i].ctx); + size += strlen(sm_data->shared->schemas[i].mount_point) + 1; + size += strlen(sm_data->shared->schemas[i].content_id) + 1; + } + + /* inlined contexts cannot be reused and will not be printed */ + + return size; +} + +static LY_ERR +schema_mount_compiled_print(const struct lysc_ext_instance *orig_ext, struct lysc_ext_instance *ext, + struct ly_ht *addr_ht, struct ly_set *UNUSED(ptr_set), void **mem) +{ + const struct lyplg_ext_sm *orig_sm_data = orig_ext->compiled; + struct lyplg_ext_sm *sm_data; + pthread_mutexattr_t attr; + uint32_t i; + void *ctx_mem; + + /* sm_data */ + ext->compiled = sm_data = *mem; + *mem = (char *)*mem + sizeof *sm_data; + + pthread_mutexattr_init(&attr); + pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED); + pthread_mutex_init(&sm_data->lock, &attr); + pthread_mutexattr_destroy(&attr); + memset(&sm_data->inln, 0, sizeof sm_data->inln); + + /* use previously printed shared schema, if any */ + sm_data->shared = lyplg_ext_compiled_print_get_addr(addr_ht, orig_sm_data->shared); + if (sm_data->shared) { + return LY_SUCCESS; + } + + /* sm_data->shared */ + sm_data->shared = *mem; + *mem = (char *)*mem + sizeof *sm_data->shared; + + sm_data->shared->schema_count = orig_sm_data->shared->schema_count; + sm_data->shared->ref_count = orig_sm_data->shared->ref_count; + + /* sm_data->shared->schemas */ + if (orig_sm_data->shared->schemas) { + sm_data->shared->schemas = *mem; + *mem = (char *)*mem + sm_data->shared->schema_count * sizeof *sm_data->shared->schemas; + + for (i = 0; i < sm_data->shared->schema_count; ++i) { + /* ctx */ + ctx_mem = *mem; + LY_CHECK_RET(ly_ctx_compiled_print(orig_sm_data->shared->schemas[i].ctx, ctx_mem, mem)); + LY_CHECK_RET(ly_ctx_new_printed(ctx_mem, &sm_data->shared->schemas[i].ctx)); + sm_data->shared->schemas[i].ctx = ctx_mem; + + /* mount_point */ + strcpy(*mem, orig_sm_data->shared->schemas[i].mount_point); + sm_data->shared->schemas[i].mount_point = *mem; + *mem = (char *)*mem + strlen(sm_data->shared->schemas[i].mount_point) + 1; + + /* content_id */ + strcpy(*mem, orig_sm_data->shared->schemas[i].content_id); + sm_data->shared->schemas[i].content_id = *mem; + *mem = (char *)*mem + strlen(sm_data->shared->schemas[i].content_id) + 1; + } + } + + /* store the shared schema to be reused by other extension instances */ + LY_CHECK_RET(lyplg_ext_compiled_print_add_addr(addr_ht, orig_sm_data->shared, sm_data->shared)); + + return LY_SUCCESS; +} + /** * @brief Plugin descriptions for the Yang Schema Mount extension. * @@ -1309,7 +1612,7 @@ const struct lyplg_ext_record plugins_schema_mount[] = { .revision = "2019-01-14", .name = "mount-point", - .plugin.id = "ly2 schema mount v1", + .plugin.id = "ly2 schema mount", .plugin.parse = schema_mount_parse, .plugin.compile = schema_mount_compile, .plugin.printer_info = NULL, @@ -1319,7 +1622,9 @@ const struct lyplg_ext_record plugins_schema_mount[] = { .plugin.snode = schema_mount_snode, .plugin.validate = schema_mount_validate, .plugin.pfree = NULL, - .plugin.cfree = schema_mount_cfree + .plugin.cfree = schema_mount_cfree, + .plugin.compiled_size = schema_mount_compiled_size, + .plugin.compiled_print = schema_mount_compiled_print, }, {0} /* terminating zeroed item */ }; diff --git a/src/plugins_exts/structure.c b/src/plugins_exts/structure.c index f05e63540..aaa1e8fc9 100644 --- a/src/plugins_exts/structure.c +++ b/src/plugins_exts/structure.c @@ -3,7 +3,7 @@ * @author Michal Vasko * @brief libyang extension plugin - structure (RFC 8791) * - * Copyright (c) 2022 CESNET, z.s.p.o. + * Copyright (c) 2022 - 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. @@ -19,6 +19,7 @@ #include "compat.h" #include "libyang.h" +#include "ly_common.h" #include "plugins_exts.h" struct lysp_ext_instance_structure { @@ -206,11 +207,11 @@ structure_compile(struct lysc_ctx *cctx, const struct lysp_ext_instance *extp, s LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[4].stmt = LY_STMT_TYPEDEF; - ext->substmts[4].storage_p = 0; + ext->substmts[4].storage_p = NULL; LY_ARRAY_INCREMENT(ext->substmts); ext->substmts[5].stmt = LY_STMT_GROUPING; - ext->substmts[5].storage_p = 0; + ext->substmts[5].storage_p = NULL; /* data-def-stmt */ LY_ARRAY_INCREMENT(ext->substmts); @@ -295,6 +296,43 @@ structure_cfree(const struct ly_ctx *ctx, struct lysc_ext_instance *ext) free(ext->compiled); } +static int +structure_compiled_size(const struct lysc_ext_instance *ext, struct ly_ht *addr_ht) +{ + int size = 0; + + size += sizeof(struct lysc_ext_instance_structure); + size += lyplg_ext_compiled_stmts_storage_size(ext->substmts, addr_ht); + + return size; +} + +static LY_ERR +structure_compiled_print(const struct lysc_ext_instance *orig_ext, struct lysc_ext_instance *ext, struct ly_ht *addr_ht, + struct ly_set *ptr_set, void **mem) +{ + struct lysc_ext_instance_structure *struct_cdata; + + struct_cdata = ext->compiled = *mem; + *mem = (char *)*mem + sizeof *struct_cdata; + + ext->substmts[0].storage_p = (void **)&struct_cdata->musts; + ext->substmts[1].storage_p = (void **)&struct_cdata->flags; + ext->substmts[2].storage_p = (void **)&struct_cdata->dsc; + ext->substmts[3].storage_p = (void **)&struct_cdata->ref; + + ext->substmts[6].storage_p = (void **)&struct_cdata->child; + ext->substmts[7].storage_p = (void **)&struct_cdata->child; + ext->substmts[8].storage_p = (void **)&struct_cdata->child; + ext->substmts[9].storage_p = (void **)&struct_cdata->child; + ext->substmts[10].storage_p = (void **)&struct_cdata->child; + ext->substmts[11].storage_p = (void **)&struct_cdata->child; + ext->substmts[12].storage_p = (void **)&struct_cdata->child; + ext->substmts[13].storage_p = (void **)&struct_cdata->child; + + return lyplg_ext_compiled_stmts_storage_print(orig_ext->substmts, ext->substmts, addr_ht, ptr_set, mem); +} + /** * @brief Parse augment-structure extension instances. * @@ -403,7 +441,7 @@ structure_aug_parse(struct lysp_ctx *pctx, struct lysp_ext_instance *ext) } aug_pdata->aug->nodetype = LYS_AUGMENT; aug_pdata->aug->flags = aug_pdata->flags; - if (lydict_insert(ctx, ext->argument, 0, &aug_pdata->aug->nodeid)) { + if (lysdict_insert(ctx, ext->argument, 0, &aug_pdata->aug->nodeid)) { goto emem; } aug_pdata->aug->child = aug_pdata->child; @@ -526,7 +564,7 @@ const struct lyplg_ext_record plugins_structure[] = { .revision = "2020-06-17", .name = "structure", - .plugin.id = "ly2 structure v1", + .plugin.id = "ly2 structure", .plugin.parse = structure_parse, .plugin.compile = structure_compile, .plugin.printer_info = structure_printer_info, @@ -536,14 +574,16 @@ const struct lyplg_ext_record plugins_structure[] = { .plugin.snode = NULL, .plugin.validate = NULL, .plugin.pfree = structure_pfree, - .plugin.cfree = structure_cfree + .plugin.cfree = structure_cfree, + .plugin.compiled_size = structure_compiled_size, + .plugin.compiled_print = structure_compiled_print }, { .module = "ietf-yang-structure-ext", .revision = "2020-06-17", .name = "augment-structure", - .plugin.id = "ly2 structure v1", + .plugin.id = "ly2 structure", .plugin.parse = structure_aug_parse, .plugin.compile = NULL, .plugin.printer_info = NULL, @@ -553,7 +593,9 @@ const struct lyplg_ext_record plugins_structure[] = { .plugin.snode = NULL, .plugin.validate = NULL, .plugin.pfree = structure_pfree, - .plugin.cfree = NULL + .plugin.cfree = NULL, + .plugin.compiled_size = NULL, + .plugin.compiled_print = NULL }, {0} /* terminating zeroed record */ }; diff --git a/src/plugins_exts/yangdata.c b/src/plugins_exts/yangdata.c index 1736abcd8..917ce19dd 100644 --- a/src/plugins_exts/yangdata.c +++ b/src/plugins_exts/yangdata.c @@ -4,7 +4,7 @@ * @author Michal Vasko * @brief libyang extension plugin - yang-data (RFC 8040) * - * Copyright (c) 2021 - 2022 CESNET, z.s.p.o. + * Copyright (c) 2021 - 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. @@ -248,6 +248,23 @@ yangdata_sprinter_ptree(struct lysp_ext_instance *ext, const struct lyspr_tree_c return rc; } +static int +yandgata_compiled_size(const struct lysc_ext_instance *ext, struct ly_ht *addr_ht) +{ + return lyplg_ext_compiled_stmts_storage_size(ext->substmts, addr_ht); +} + +static LY_ERR +yangdata_compiled_print(const struct lysc_ext_instance *orig_ext, struct lysc_ext_instance *ext, struct ly_ht *addr_ht, + struct ly_set *ptr_set, void **mem) +{ + ext->substmts[0].storage_p = (void **)&ext->compiled; + ext->substmts[1].storage_p = (void **)&ext->compiled; + ext->substmts[2].storage_p = (void **)&ext->compiled; + + return lyplg_ext_compiled_stmts_storage_print(orig_ext->substmts, ext->substmts, addr_ht, ptr_set, mem); +} + /** * @brief Plugin descriptions for the yang-data extension * @@ -261,7 +278,7 @@ const struct lyplg_ext_record plugins_yangdata[] = { .revision = "2017-01-26", .name = "yang-data", - .plugin.id = "ly2 yang-data v1", + .plugin.id = "ly2 yang-data", .plugin.parse = yangdata_parse, .plugin.compile = yangdata_compile, .plugin.printer_info = yangdata_printer_info, @@ -271,7 +288,9 @@ const struct lyplg_ext_record plugins_yangdata[] = { .plugin.snode = NULL, .plugin.validate = NULL, .plugin.pfree = yangdata_pfree, - .plugin.cfree = yangdata_cfree + .plugin.cfree = yangdata_cfree, + .plugin.compiled_size = yandgata_compiled_size, + .plugin.compiled_print = yangdata_compiled_print }, {0} /* terminating zeroed record */ }; diff --git a/src/plugins_internal.h b/src/plugins_internal.h index 2ba54f136..29ffbfada 100644 --- a/src/plugins_internal.h +++ b/src/plugins_internal.h @@ -4,7 +4,7 @@ * @author Michal Vasko * @brief internal functions to support extension and type 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. @@ -43,17 +43,62 @@ #define LY_TYPE_INT32_STR "32bit integer" /**< text representation of ::LY_TYPE_INT32 */ #define LY_TYPE_INT64_STR "64bit integer" /**< text representation of ::LY_TYPE_INT64 */ +/** + * @brief Shared (= not context specific) type plugins set. + */ +extern struct ly_set ly_plugins_types; + +/** + * @brief Shared (= not context specific) extension plugins set. + */ +extern struct ly_set ly_plugins_extensions; + +/** + * @brief Count of static type plugins. + */ +extern uint32_t ly_static_type_plugins_count; + +/** + * @brief Count of static extension plugins. + */ +extern uint32_t ly_static_ext_plugins_count; + +/** + * @brief Get a type plugin. + * + * @param[in] PLUGIN_REF Reference to a type plugin. Either an index of a static plugin (offset by +1) + * or a pointer to an external plugin. + * @return Type plugin. + */ +#define LYSC_GET_TYPE_PLG(PLUGIN_REF) \ + (((uintptr_t)(PLUGIN_REF) <= (uintptr_t)ly_static_type_plugins_count) ? \ + (struct lyplg_type *)&((struct lyplg_type_record *)ly_plugins_types.objs[(PLUGIN_REF) - 1])->plugin : \ + (struct lyplg_type *)(PLUGIN_REF)) + +/** + * @brief Get an extension plugin. + * + * @param[in] PLUGIN_REF Reference to an extension plugin. Either an index of a static plugin (offset by +1) + * or a pointer to an external plugin. + * @return Extension plugin. + */ +#define LYSC_GET_EXT_PLG(PLUGIN_REF) \ + (((uintptr_t)(PLUGIN_REF) <= (uintptr_t)ly_static_ext_plugins_count) ? \ + (struct lyplg_ext *)&((struct lyplg_ext_record *)ly_plugins_extensions.objs[(PLUGIN_REF) - 1])->plugin : \ + (struct lyplg_ext *)(PLUGIN_REF)) + /** * @brief Initiate libyang plugins. * * Covers both the types and extensions plugins. * * @param[in] builtin_type_plugins_only Whether to load only built-in YANG type plugins and no included extension plugins. + * @param[in] static_plugins_only Whether to load only static (libyang built-in) plugins, meaning no external directories with plugins. * @return LY_SUCCESS in case of success * @return LY_EINT in case of internal error * @return LY_EMEM in case of memory allocation failure. */ -LY_ERR lyplg_init(ly_bool builtin_type_plugins_only); +LY_ERR lyplg_init(ly_bool builtin_type_plugins_only, ly_bool static_plugins_only); /** * @brief Remove (unload) all the plugins currently available. @@ -63,26 +108,28 @@ void lyplg_clean(void); /** * @brief Find a type plugin. * - * @param[in] ctx The optional context for which the plugin should be find. If NULL, only shared plugins will be searched + * @param[in] ctx Optional context for which the plugin should be find. If NULL, only shared plugins will be searched * @param[in] module Name of the module where the type is defined. Must not be NULL, in case of plugins for * built-in types, the module is "". * @param[in] revision Revision of the module for which the plugin is implemented. NULL is not a wildcard, it matches * only the plugins with NULL revision specified. * @param[in] name Name of the type which the plugin implements. - * @return Found type plugin, NULL if none found. + * @return ID of the found type plugin, 0 if none found. The type plugin can be obtained + * by passing the returned ID to ::lysc_get_type_plugin() or ::LYSC_GET_TYPE_PLG. */ -struct lyplg_type *lyplg_type_plugin_find(const struct ly_ctx *ctx, const char *module, const char *revision, const char *name); +uintptr_t lyplg_type_plugin_find(const struct ly_ctx *ctx, const char *module, const char *revision, const char *name); /** * @brief Find an extension plugin. * - * @param[in] ctx The optional context for which the plugin should be find. If NULL, only shared plugins will be searched + * @param[in] ctx Optional context for which the plugin should be find. If NULL, only shared plugins will be searched * @param[in] module Name of the module where the extension is defined. * @param[in] revision Revision of the module for which the plugin is implemented. NULL is not a wildcard, it matches * only the plugins with NULL revision specified. * @param[in] name Name of the extension which the plugin implements. - * @return Found extension record, NULL if none found. + * @return ID of the found extension plugin, 0 if none found. The extension plugin can be obtained + * by passing the returned ID to ::lysc_get_ext_plugin() or ::LYSC_GET_EXT_PLG. */ -struct lyplg_ext_record *lyplg_ext_record_find(const struct ly_ctx *ctx, const char *module, const char *revision, const char *name); +uintptr_t lyplg_ext_plugin_find(const struct ly_ctx *ctx, const char *module, const char *revision, const char *name); #endif /* LY_PLUGINS_INTERNAL_H_ */ diff --git a/src/plugins_types.c b/src/plugins_types.c index fb6f75a7e..4158837fb 100644 --- a/src/plugins_types.c +++ b/src/plugins_types.c @@ -524,17 +524,23 @@ lyplg_type_parse_dec64(uint8_t fraction_digits, const char *value, size_t value_ } LIBYANG_API_DEF LY_ERR -lyplg_type_validate_patterns(struct lysc_pattern **patterns, const char *str, size_t str_len, struct ly_err_item **err) +lyplg_type_validate_patterns(const struct ly_ctx *ctx, struct lysc_pattern **patterns, const char *str, size_t str_len, struct ly_err_item **err) { LY_ERR r; LY_ARRAY_COUNT_TYPE u; + const pcre2_code *pcode; LY_CHECK_ARG_RET(NULL, str, err, LY_EINVAL); *err = NULL; LY_ARRAY_FOR(patterns, u) { - r = ly_pattern_code_match(patterns[u]->code, str, str_len, err); + /* get (or compile) the compiled pattern. The pattern might not be found, because + * if ctx is printed, it did not inherit compiled patterns from the original context. */ + LY_CHECK_RET(ly_ctx_get_or_compile_pattern_code(ctx, patterns[u]->expr, &pcode)); + + /* match the pattern */ + r = ly_pattern_code_match(pcode, str, str_len, err); LY_CHECK_RET(r && (r != LY_ENOT), r); if (((r == LY_ENOT) && !patterns[u]->inverted) || ((r == LY_SUCCESS) && patterns[u]->inverted)) { @@ -871,7 +877,7 @@ lyplg_type_lypath_new(const struct ly_ctx *ctx, const char *value, size_t value_ } cleanup: - lyxp_expr_free(ctx, exp); + lyxp_expr_free(exp); if (ret) { /* generate error, spend the context error, if any */ e = e ? e->next : (struct ly_err_item *)ly_err_last(ctx); @@ -888,11 +894,51 @@ lyplg_type_lypath_new(const struct ly_ctx *ctx, const char *value, size_t value_ } LIBYANG_API_DEF void -lyplg_type_lypath_free(const struct ly_ctx *UNUSED(ctx), struct ly_path *path) +lyplg_type_lypath_free(struct ly_path *path) { ly_path_free(path); } +LIBYANG_API_DEF LY_ERR +lyplg_type_print_val(const struct lysc_node *node, const char *canon, LY_VALUE_FORMAT format, void *prefix_data, + const char **value) +{ + LY_ERR r; + const struct lysc_type *type; + struct lyd_value storage = {0}; + struct ly_err_item *err = NULL; + const char *v; + ly_bool dyn; + struct lyplg_type *type_plg; + + type = ((struct lysc_node_leaf *)node)->type; + type_plg = LYSC_GET_TYPE_PLG(type->plugin_ref); + + /* store the value */ + r = type_plg->store(node->module->ctx, type, canon, strlen(canon), LYPLG_TYPE_STORE_ONLY, LY_VALUE_CANON, + NULL, LYD_HINT_DATA, node, &storage, NULL, &err); + if (r && (r != LY_EINCOMPLETE)) { + if (err) { + ly_err_print(node->module->ctx, err); + ly_err_free(err); + } + return r; + } + + /* print it in the specific format */ + v = type_plg->print(node->module->ctx, &storage, format, prefix_data, &dyn, NULL); + + /* store it in the dictionary, storage will be freed */ + if (dyn) { + lydict_insert_zc(node->module->ctx, (char *)v, value); + } else { + lydict_dup(node->module->ctx, v, value); + } + + type_plg->free(node->module->ctx, &storage); + return LY_SUCCESS; +} + LIBYANG_API_DEF LY_ERR lyplg_type_make_implemented(struct lys_module *mod, const char **features, struct lys_glob_unres *unres) { @@ -1015,6 +1061,7 @@ lyplg_type_resolve_leafref(const struct lysc_type_leafref *lref, const struct ly const char *val_str, *xp_err_msg; uint32_t i; int r; + struct lyplg_type *type_plg; LY_CHECK_ARG_RET(NULL, lref, node, value, errmsg, LY_EINVAL); @@ -1061,6 +1108,8 @@ lyplg_type_resolve_leafref(const struct lysc_type_leafref *lref, const struct ly goto cleanup; } + type_plg = LYSC_GET_TYPE_PLG(lref->plugin_ref); + /* check the result */ if (target_path) { /* no or exact match(es) */ @@ -1075,7 +1124,7 @@ lyplg_type_resolve_leafref(const struct lysc_type_leafref *lref, const struct ly continue; } - if (!lref->plugin->compare(LYD_CTX(node), &((struct lyd_node_term *)set.val.nodes[i].node)->value, value)) { + if (!type_plg->compare(LYD_CTX(node), &((struct lyd_node_term *)set.val.nodes[i].node)->value, value)) { break; } } @@ -1100,7 +1149,7 @@ lyplg_type_resolve_leafref(const struct lysc_type_leafref *lref, const struct ly continue; } - if (!lref->plugin->compare(LYD_CTX(node), &((struct lyd_node_term *)set.val.nodes[i].node)->value, value)) { + if (!type_plg->compare(LYD_CTX(node), &((struct lyd_node_term *)set.val.nodes[i].node)->value, value)) { rc = ly_set_add(*targets, set.val.nodes[i].node, 0, NULL); LY_CHECK_GOTO(rc, cleanup); } @@ -1108,7 +1157,7 @@ lyplg_type_resolve_leafref(const struct lysc_type_leafref *lref, const struct ly } cleanup: - lyxp_expr_free(LYD_CTX(node), target_path); + lyxp_expr_free(target_path); lyxp_set_free_content(&set); return rc; } diff --git a/src/plugins_types.h b/src/plugins_types.h index 06acc3802..24f2ec1ee 100644 --- a/src/plugins_types.h +++ b/src/plugins_types.h @@ -1,9 +1,10 @@ /** * @file plugins_types.h * @author Radek Krejci + * @author Michal Vasko * @brief API for (user) types plugins * - * Copyright (c) 2019 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. @@ -438,15 +439,27 @@ LIBYANG_API_DECL LY_ERR lyplg_type_lypath_new(const struct ly_ctx *ctx, const ch uint32_t options, LY_VALUE_FORMAT format, void *prefix_data, const struct lysc_node *ctx_node, struct lys_glob_unres *unres, struct ly_path **path, struct ly_err_item **err); +/** + * @brief Convert canonical value into a value in a specific format. + * + * @param[in] node Node with the type. + * @param[in] canon Canonical value. + * @param[in] format Value format. + * @param[in] prefix_data Format-specific data for resolving prefixes. + * @param[out] value Printed value in @p format. + * @return LY_ERR value on error. + */ +LIBYANG_API_DECL LY_ERR lyplg_type_print_val(const struct lysc_node *node, const char *canon, LY_VALUE_FORMAT format, + void *prefix_data, const char **value); + /** * @brief Free ly_path structure used by instanceid value representation. * * The ly_path representation can be created by ::lyplg_type_lypath_new(). * - * @param[in] ctx libyang context. - * @param[in] path The structure ([sized array](@ref sizedarrays)) to free. + * @param[in] path Path structure ([sized array](@ref sizedarrays)) to free. */ -LIBYANG_API_DECL void lyplg_type_lypath_free(const struct ly_ctx *ctx, struct ly_path *path); +LIBYANG_API_DECL void lyplg_type_lypath_free(struct ly_path *path); /** * @brief Print xpath1.0 value in the specific format. @@ -1264,6 +1277,7 @@ LIBYANG_API_DECL LY_ERR lyplg_type_validate_range(LY_DATA_TYPE basetype, struct /** * @brief Data type validator for pattern-restricted string values. * + * @param[in] ctx libyang context. * @param[in] patterns ([Sized array](@ref sizedarrays)) of the compiled list of pointers to the pattern restrictions. * The array can be found in the ::lysc_type_str.patterns structure. * @param[in] str String to validate. @@ -1273,7 +1287,7 @@ LIBYANG_API_DECL LY_ERR lyplg_type_validate_range(LY_DATA_TYPE basetype, struct * @return LY_EVALID when @p does not match any of the patterns. * @return LY_ESYS in case of PCRE2 error. */ -LIBYANG_API_DECL LY_ERR lyplg_type_validate_patterns(struct lysc_pattern **patterns, const char *str, size_t str_len, +LIBYANG_API_DECL LY_ERR lyplg_type_validate_patterns(const struct ly_ctx *ctx, struct lysc_pattern **patterns, const char *str, size_t str_len, struct ly_err_item **err); /** diff --git a/src/plugins_types/binary.c b/src/plugins_types/binary.c index a0204385d..ff47b3082 100644 --- a/src/plugins_types/binary.c +++ b/src/plugins_types/binary.c @@ -471,7 +471,7 @@ const struct lyplg_type_record plugins_binary[] = { .revision = NULL, .name = LY_TYPE_BINARY_STR, - .plugin.id = "libyang 2 - binary, version 1", + .plugin.id = "ly2 binary", .plugin.store = lyplg_type_store_binary, .plugin.validate = NULL, .plugin.compare = lyplg_type_compare_binary, diff --git a/src/plugins_types/bits.c b/src/plugins_types/bits.c index badf2b1e9..47012a324 100644 --- a/src/plugins_types/bits.c +++ b/src/plugins_types/bits.c @@ -507,7 +507,7 @@ const struct lyplg_type_record plugins_bits[] = { .revision = NULL, .name = LY_TYPE_BITS_STR, - .plugin.id = "libyang 2 - bits, version 1", + .plugin.id = "ly2 bits", .plugin.store = lyplg_type_store_bits, .plugin.validate = NULL, .plugin.compare = lyplg_type_compare_bits, diff --git a/src/plugins_types/boolean.c b/src/plugins_types/boolean.c index 3e055d278..bef336ea3 100644 --- a/src/plugins_types/boolean.c +++ b/src/plugins_types/boolean.c @@ -159,7 +159,7 @@ const struct lyplg_type_record plugins_boolean[] = { .revision = NULL, .name = LY_TYPE_BOOL_STR, - .plugin.id = "libyang 2 - boolean, version 1", + .plugin.id = "ly2 boolean", .plugin.store = lyplg_type_store_boolean, .plugin.validate = NULL, .plugin.compare = lyplg_type_compare_boolean, diff --git a/src/plugins_types/date_and_time.c b/src/plugins_types/date_and_time.c index 1d013c15f..0d6cc25d3 100644 --- a/src/plugins_types/date_and_time.c +++ b/src/plugins_types/date_and_time.c @@ -386,7 +386,7 @@ const struct lyplg_type_record plugins_date_and_time[] = { .revision = "2013-07-15", .name = "date-and-time", - .plugin.id = "libyang 2 - date-and-time, version 1", + .plugin.id = "ly2 date-and-time", .plugin.store = lyplg_type_store_date_and_time, .plugin.validate = NULL, .plugin.compare = lyplg_type_compare_date_and_time, diff --git a/src/plugins_types/decimal64.c b/src/plugins_types/decimal64.c index a6ac54b55..9dc4e4826 100644 --- a/src/plugins_types/decimal64.c +++ b/src/plugins_types/decimal64.c @@ -237,7 +237,7 @@ const struct lyplg_type_record plugins_decimal64[] = { .revision = NULL, .name = LY_TYPE_DEC64_STR, - .plugin.id = "libyang 2 - decimal64, version 1", + .plugin.id = "ly2 decimal64", .plugin.store = lyplg_type_store_decimal64, .plugin.validate = NULL, .plugin.compare = lyplg_type_compare_decimal64, diff --git a/src/plugins_types/empty.c b/src/plugins_types/empty.c index b7b82dcfd..7ad10683b 100644 --- a/src/plugins_types/empty.c +++ b/src/plugins_types/empty.c @@ -89,7 +89,7 @@ const struct lyplg_type_record plugins_empty[] = { .revision = NULL, .name = LY_TYPE_EMPTY_STR, - .plugin.id = "libyang 2 - empty, version 1", + .plugin.id = "ly2 empty", .plugin.store = lyplg_type_store_empty, .plugin.validate = NULL, .plugin.compare = lyplg_type_compare_simple, diff --git a/src/plugins_types/enumeration.c b/src/plugins_types/enumeration.c index 462b7e3bc..561c73022 100644 --- a/src/plugins_types/enumeration.c +++ b/src/plugins_types/enumeration.c @@ -201,7 +201,7 @@ const struct lyplg_type_record plugins_enumeration[] = { .revision = NULL, .name = LY_TYPE_ENUM_STR, - .plugin.id = "libyang 2 - enumeration, version 1", + .plugin.id = "ly2 enumeration", .plugin.store = lyplg_type_store_enum, .plugin.validate = NULL, .plugin.compare = lyplg_type_compare_simple, diff --git a/src/plugins_types/hex_string.c b/src/plugins_types/hex_string.c index b013cf407..e83156ce5 100644 --- a/src/plugins_types/hex_string.c +++ b/src/plugins_types/hex_string.c @@ -90,7 +90,7 @@ lyplg_type_store_hex_string(const struct ly_ctx *ctx, const struct lysc_type *ty } /* validate pattern restrictions */ - ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err); + ret = lyplg_type_validate_patterns(ctx, type_str->patterns, value, value_len, err); LY_CHECK_GOTO(ret, cleanup); } @@ -118,7 +118,7 @@ const struct lyplg_type_record plugins_hex_string[] = { .revision = "2013-07-15", .name = "phys-address", - .plugin.id = "libyang 2 - hex-string, version 1", + .plugin.id = "ly2 hex-string", .plugin.store = lyplg_type_store_hex_string, .plugin.validate = NULL, .plugin.compare = lyplg_type_compare_simple, @@ -133,7 +133,7 @@ const struct lyplg_type_record plugins_hex_string[] = { .revision = "2013-07-15", .name = "mac-address", - .plugin.id = "libyang 2 - hex-string, version 1", + .plugin.id = "ly2 hex-string", .plugin.store = lyplg_type_store_hex_string, .plugin.validate = NULL, .plugin.compare = lyplg_type_compare_simple, @@ -148,7 +148,7 @@ const struct lyplg_type_record plugins_hex_string[] = { .revision = "2013-07-15", .name = "hex-string", - .plugin.id = "libyang 2 - hex-string, version 1", + .plugin.id = "ly2 hex-string", .plugin.store = lyplg_type_store_hex_string, .plugin.validate = NULL, .plugin.compare = lyplg_type_compare_simple, @@ -163,7 +163,7 @@ const struct lyplg_type_record plugins_hex_string[] = { .revision = "2013-07-15", .name = "uuid", - .plugin.id = "libyang 2 - hex-string, version 1", + .plugin.id = "ly2 hex-string", .plugin.store = lyplg_type_store_hex_string, .plugin.validate = NULL, .plugin.compare = lyplg_type_compare_simple, diff --git a/src/plugins_types/identityref.c b/src/plugins_types/identityref.c index 29db55f40..52e96912a 100644 --- a/src/plugins_types/identityref.c +++ b/src/plugins_types/identityref.c @@ -219,7 +219,7 @@ identityref_check_ident(const struct lysc_ident *ident, const char *value, "Invalid identityref \"%.*s\" value - identity found in non-implemented module \"%s\".", (int)value_len, (char *)value, ident->module->name); } - } else if (lys_identity_iffeature_value(ident) == LY_ENOT) { + } else if (ident->module->parsed && (lys_identity_iffeature_value(ident) == LY_ENOT)) { ret = ly_err_new(err, LY_EVALID, LYVE_DATA, NULL, NULL, "Invalid identityref \"%.*s\" value - identity is disabled by if-feature.", (int)value_len, value); @@ -354,7 +354,7 @@ const struct lyplg_type_record plugins_identityref[] = { .revision = NULL, .name = LY_TYPE_IDENT_STR, - .plugin.id = "libyang 2 - identityref, version 1", + .plugin.id = "ly2 identityref", .plugin.store = lyplg_type_store_identityref, .plugin.validate = NULL, .plugin.compare = lyplg_type_compare_identityref, diff --git a/src/plugins_types/instanceid.c b/src/plugins_types/instanceid.c index 46bb4baef..59da3ab9c 100644 --- a/src/plugins_types/instanceid.c +++ b/src/plugins_types/instanceid.c @@ -52,7 +52,7 @@ instanceid_path2str(const struct ly_path *path, LY_VALUE_FORMAT format, void *pr char *result = NULL, quot; const struct lys_module *mod = NULL, *local_mod = NULL; struct ly_set *mods = NULL; - ly_bool inherit_prefix = 0, d; + ly_bool inherit_prefix = 0; const char *strval; switch (format) { @@ -98,8 +98,8 @@ instanceid_path2str(const struct ly_path *path, LY_VALUE_FORMAT format, void *pr break; case LY_PATH_PREDTYPE_LIST: /* key-predicate */ - strval = pred->value.realtype->plugin->print(path[u].node->module->ctx, &pred->value, format, prefix_data, - &d, NULL); + ret = lyplg_type_print_val(pred->key, pred->value, format, prefix_data, &strval); + LY_CHECK_GOTO(ret, cleanup); /* default quote */ quot = '\''; @@ -113,14 +113,12 @@ instanceid_path2str(const struct ly_path *path, LY_VALUE_FORMAT format, void *pr ret = ly_strcat(&result, "[%s:%s=%c%s%c]", lyplg_type_get_prefix(pred->key->module, format, prefix_data), pred->key->name, quot, strval, quot); } - if (d) { - free((char *)strval); - } + lydict_remove(pred->key->module->ctx, strval); break; case LY_PATH_PREDTYPE_LEAFLIST: /* leaf-list-predicate */ - strval = pred->value.realtype->plugin->print(path[u].node->module->ctx, &pred->value, format, prefix_data, - &d, NULL); + ret = lyplg_type_print_val(path[u].node, pred->value, format, prefix_data, &strval); + LY_CHECK_GOTO(ret, cleanup); /* default quote */ quot = '\''; @@ -128,9 +126,7 @@ instanceid_path2str(const struct ly_path *path, LY_VALUE_FORMAT format, void *pr quot = '"'; } ret = ly_strcat(&result, "[.=%c%s%c]", quot, strval, quot); - if (d) { - free((char *)strval); - } + lydict_remove(path[u].node->module->ctx, strval); break; case LY_PATH_PREDTYPE_LIST_VAR: LOGINT(path[u].node->module->ctx); @@ -253,13 +249,10 @@ lyplg_type_validate_instanceid(const struct ly_ctx *ctx, const struct lysc_type } LIBYANG_API_DEF const void * -lyplg_type_print_instanceid(const struct ly_ctx *ctx, const struct lyd_value *value, LY_VALUE_FORMAT format, +lyplg_type_print_instanceid(const struct ly_ctx *UNUSED(ctx), const struct lyd_value *value, LY_VALUE_FORMAT format, void *prefix_data, ly_bool *dynamic, size_t *value_len) { - char *ret = NULL; - struct ly_path *p = NULL; - const struct ly_path *target; - struct ly_err_item *err; + char *ret; if ((format == LY_VALUE_CANON) || (format == LY_VALUE_JSON) || (format == LY_VALUE_LYB)) { if (dynamic) { @@ -271,25 +264,9 @@ lyplg_type_print_instanceid(const struct ly_ctx *ctx, const struct lyd_value *va 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(target, format, prefix_data, &ret)) { - goto cleanup; + if (instanceid_path2str(value->target, format, prefix_data, &ret)) { + return NULL; } *dynamic = 1; @@ -297,8 +274,6 @@ lyplg_type_print_instanceid(const struct ly_ctx *ctx, const struct lyd_value *va *value_len = strlen(ret); } -cleanup: - ly_path_free(p); return ret; } @@ -306,7 +281,6 @@ 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); @@ -314,21 +288,9 @@ lyplg_type_dup_instanceid(const struct ly_ctx *ctx, const struct lyd_value *orig ret = lydict_insert(ctx, original->_canonical, 0, &dup->_canonical); LY_CHECK_GOTO(ret, error); - if (!original->target) { - /* schema default value, needs to be compiled */ - if (lyplg_type_lypath_new(ctx, original->_canonical, strlen(original->_canonical), 0, LY_VALUE_JSON, NULL, NULL, - NULL, &dup->target, &err)) { - if (err) { - ly_err_print(ctx, err); - ly_err_free(err); - } - goto error; - } - } else { - /* copy path */ - ret = ly_path_dup(ctx, original->target, &dup->target); - LY_CHECK_GOTO(ret, error); - } + /* copy path */ + ret = ly_path_dup(ctx, original->target, &dup->target); + LY_CHECK_GOTO(ret, error); dup->realtype = original->realtype; return LY_SUCCESS; @@ -359,7 +321,7 @@ const struct lyplg_type_record plugins_instanceid[] = { .revision = NULL, .name = LY_TYPE_INST_STR, - .plugin.id = "libyang 2 - instance-identifier, version 1", + .plugin.id = "ly2 instance-identifier", .plugin.store = lyplg_type_store_instanceid, .plugin.validate = lyplg_type_validate_instanceid, .plugin.compare = lyplg_type_compare_simple, diff --git a/src/plugins_types/instanceid_keys.c b/src/plugins_types/instanceid_keys.c index 12d28e5d4..9a2a0ff05 100644 --- a/src/plugins_types/instanceid_keys.c +++ b/src/plugins_types/instanceid_keys.c @@ -161,7 +161,7 @@ lyplg_type_store_instanceid_keys(const struct ly_ctx *ctx, const struct lysc_typ } /* pattern restrictions */ - ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err); + ret = lyplg_type_validate_patterns(ctx, type_str->patterns, value, value_len, err); LY_CHECK_GOTO(ret, cleanup); /* parse instance-identifier keys, with optional prefix even though it should be mandatory */ @@ -239,7 +239,7 @@ const struct lyplg_type_record plugins_instanceid_keys[] = { .revision = NULL, .name = "instance-identifier-keys", - .plugin.id = "libyang 2 - instance-identifier-keys, version 1", + .plugin.id = "ly2 instance-identifier-keys", .plugin.store = lyplg_type_store_instanceid_keys, .plugin.validate = NULL, .plugin.compare = lyplg_type_compare_simple, diff --git a/src/plugins_types/integer.c b/src/plugins_types/integer.c index ac165acdb..082c24b10 100644 --- a/src/plugins_types/integer.c +++ b/src/plugins_types/integer.c @@ -565,7 +565,7 @@ const struct lyplg_type_record plugins_integer[] = { .revision = NULL, .name = LY_TYPE_UINT8_STR, - .plugin.id = "libyang 2 - integers, version 1", + .plugin.id = "ly2 integers", .plugin.store = lyplg_type_store_uint, .plugin.validate = NULL, .plugin.compare = lyplg_type_compare_uint, @@ -579,7 +579,7 @@ const struct lyplg_type_record plugins_integer[] = { .revision = NULL, .name = LY_TYPE_UINT16_STR, - .plugin.id = "libyang 2 - integers, version 1", + .plugin.id = "ly2 integers", .plugin.store = lyplg_type_store_uint, .plugin.validate = NULL, .plugin.compare = lyplg_type_compare_uint, @@ -593,7 +593,7 @@ const struct lyplg_type_record plugins_integer[] = { .revision = NULL, .name = LY_TYPE_UINT32_STR, - .plugin.id = "libyang 2 - integers, version 1", + .plugin.id = "ly2 integers", .plugin.store = lyplg_type_store_uint, .plugin.validate = NULL, .plugin.compare = lyplg_type_compare_uint, @@ -607,7 +607,7 @@ const struct lyplg_type_record plugins_integer[] = { .revision = NULL, .name = LY_TYPE_UINT64_STR, - .plugin.id = "libyang 2 - integers, version 1", + .plugin.id = "ly2 integers", .plugin.store = lyplg_type_store_uint, .plugin.validate = NULL, .plugin.compare = lyplg_type_compare_uint, @@ -621,7 +621,7 @@ const struct lyplg_type_record plugins_integer[] = { .revision = NULL, .name = LY_TYPE_INT8_STR, - .plugin.id = "libyang 2 - integers, version 1", + .plugin.id = "ly2 integers", .plugin.store = lyplg_type_store_int, .plugin.validate = NULL, .plugin.compare = lyplg_type_compare_int, @@ -635,7 +635,7 @@ const struct lyplg_type_record plugins_integer[] = { .revision = NULL, .name = LY_TYPE_INT16_STR, - .plugin.id = "libyang 2 - integers, version 1", + .plugin.id = "ly2 integers", .plugin.store = lyplg_type_store_int, .plugin.validate = NULL, .plugin.compare = lyplg_type_compare_int, @@ -649,7 +649,7 @@ const struct lyplg_type_record plugins_integer[] = { .revision = NULL, .name = LY_TYPE_INT32_STR, - .plugin.id = "libyang 2 - integers, version 1", + .plugin.id = "ly2 integers", .plugin.store = lyplg_type_store_int, .plugin.validate = NULL, .plugin.compare = lyplg_type_compare_int, @@ -663,7 +663,7 @@ const struct lyplg_type_record plugins_integer[] = { .revision = NULL, .name = LY_TYPE_INT64_STR, - .plugin.id = "libyang 2 - integers, version 1", + .plugin.id = "ly2 integers", .plugin.store = lyplg_type_store_int, .plugin.validate = NULL, .plugin.compare = lyplg_type_compare_int, diff --git a/src/plugins_types/ipv4_address.c b/src/plugins_types/ipv4_address.c index 0ed6d36a1..c5b263b16 100644 --- a/src/plugins_types/ipv4_address.c +++ b/src/plugins_types/ipv4_address.c @@ -180,7 +180,7 @@ lyplg_type_store_ipv4_address(const struct ly_ctx *ctx, const struct lysc_type * } /* pattern restrictions */ - ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err); + ret = lyplg_type_validate_patterns(ctx, type_str->patterns, value, value_len, err); LY_CHECK_GOTO(ret, cleanup); } @@ -392,7 +392,7 @@ const struct lyplg_type_record plugins_ipv4_address[] = { .revision = "2013-07-15", .name = "ipv4-address", - .plugin.id = "libyang 2 - ipv4-address, version 1", + .plugin.id = "ly2 ipv4-address", .plugin.store = lyplg_type_store_ipv4_address, .plugin.validate = NULL, .plugin.compare = lyplg_type_compare_ipv4_address, diff --git a/src/plugins_types/ipv4_address_no_zone.c b/src/plugins_types/ipv4_address_no_zone.c index 5a0f00900..55eff628c 100644 --- a/src/plugins_types/ipv4_address_no_zone.c +++ b/src/plugins_types/ipv4_address_no_zone.c @@ -209,7 +209,7 @@ const struct lyplg_type_record plugins_ipv4_address_no_zone[] = { .revision = "2013-07-15", .name = "ipv4-address-no-zone", - .plugin.id = "libyang 2 - ipv4-address-no-zone, version 1", + .plugin.id = "ly2 ipv4-address-no-zone", .plugin.store = lyplg_type_store_ipv4_address_no_zone, .plugin.validate = NULL, .plugin.compare = lyplg_type_compare_ipv4_address_no_zone, diff --git a/src/plugins_types/ipv4_prefix.c b/src/plugins_types/ipv4_prefix.c index 4d1916ef8..71fcc8385 100644 --- a/src/plugins_types/ipv4_prefix.c +++ b/src/plugins_types/ipv4_prefix.c @@ -165,7 +165,7 @@ lyplg_type_store_ipv4_prefix(const struct ly_ctx *ctx, const struct lysc_type *t } /* pattern restrictions */ - ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err); + ret = lyplg_type_validate_patterns(ctx, type_str->patterns, value, value_len, err); LY_CHECK_GOTO(ret, cleanup); } @@ -339,7 +339,7 @@ const struct lyplg_type_record plugins_ipv4_prefix[] = { .revision = "2013-07-15", .name = "ipv4-prefix", - .plugin.id = "libyang 2 - ipv4-prefix, version 1", + .plugin.id = "ly2 ipv4-prefix", .plugin.store = lyplg_type_store_ipv4_prefix, .plugin.validate = NULL, .plugin.compare = lyplg_type_compare_ipv4_prefix, diff --git a/src/plugins_types/ipv6_address.c b/src/plugins_types/ipv6_address.c index 147df3e45..6c6c8ec84 100644 --- a/src/plugins_types/ipv6_address.c +++ b/src/plugins_types/ipv6_address.c @@ -181,7 +181,7 @@ lyplg_type_store_ipv6_address(const struct ly_ctx *ctx, const struct lysc_type * } /* pattern restrictions */ - ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err); + ret = lyplg_type_validate_patterns(ctx, type_str->patterns, value, value_len, err); LY_CHECK_GOTO(ret, cleanup); } @@ -394,7 +394,7 @@ const struct lyplg_type_record plugins_ipv6_address[] = { .revision = "2013-07-15", .name = "ipv6-address", - .plugin.id = "libyang 2 - ipv6-address, version 1", + .plugin.id = "ly2 ipv6-address", .plugin.store = lyplg_type_store_ipv6_address, .plugin.validate = NULL, .plugin.compare = lyplg_type_compare_ipv6_address, diff --git a/src/plugins_types/ipv6_address_no_zone.c b/src/plugins_types/ipv6_address_no_zone.c index 76d47ae25..7d977396c 100644 --- a/src/plugins_types/ipv6_address_no_zone.c +++ b/src/plugins_types/ipv6_address_no_zone.c @@ -300,7 +300,7 @@ const struct lyplg_type_record plugins_ipv6_address_no_zone[] = { .revision = "2013-07-15", .name = "ipv6-address-no-zone", - .plugin.id = "libyang 2 - ipv6-address-no-zone, version 1", + .plugin.id = "ly2 ipv6-address-no-zone", .plugin.store = lyplg_type_store_ipv6_address_no_zone, .plugin.validate = NULL, .plugin.compare = lyplg_type_compare_ipv6_address_no_zone, diff --git a/src/plugins_types/ipv6_prefix.c b/src/plugins_types/ipv6_prefix.c index 4643e8523..c1f449877 100644 --- a/src/plugins_types/ipv6_prefix.c +++ b/src/plugins_types/ipv6_prefix.c @@ -179,7 +179,7 @@ lyplg_type_store_ipv6_prefix(const struct ly_ctx *ctx, const struct lysc_type *t } /* pattern restrictions */ - ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err); + ret = lyplg_type_validate_patterns(ctx, type_str->patterns, value, value_len, err); LY_CHECK_GOTO(ret, cleanup); } @@ -353,7 +353,7 @@ const struct lyplg_type_record plugins_ipv6_prefix[] = { .revision = "2013-07-15", .name = "ipv6-prefix", - .plugin.id = "libyang 2 - ipv6-prefix, version 1", + .plugin.id = "ly2 ipv6-prefix", .plugin.store = lyplg_type_store_ipv6_prefix, .plugin.validate = NULL, .plugin.compare = lyplg_type_compare_ipv6_prefix, diff --git a/src/plugins_types/leafref.c b/src/plugins_types/leafref.c index 5863895f9..deb8cc424 100644 --- a/src/plugins_types/leafref.c +++ b/src/plugins_types/leafref.c @@ -47,8 +47,8 @@ lyplg_type_store_leafref(const struct ly_ctx *ctx, const struct lysc_type *type, assert(type_lr->realtype); /* store the value as the real type of the leafref target */ - rc = type_lr->realtype->plugin->store(ctx, type_lr->realtype, value, value_len, options, format, prefix_data, - hints, ctx_node, storage, unres, err); + rc = LYSC_GET_TYPE_PLG(type_lr->realtype->plugin_ref)->store(ctx, type_lr->realtype, value, value_len, options, + format, prefix_data, hints, ctx_node, storage, unres, err); if (rc == LY_EINCOMPLETE) { /* it is irrelevant whether the target type needs some resolving */ rc = LY_SUCCESS; @@ -104,32 +104,32 @@ lyplg_type_validate_leafref(const struct ly_ctx *ctx, const struct lysc_type *ty LIBYANG_API_DEF LY_ERR lyplg_type_compare_leafref(const struct ly_ctx *ctx, const struct lyd_value *val1, const struct lyd_value *val2) { - return val1->realtype->plugin->compare(ctx, val1, val2); + return LYSC_GET_TYPE_PLG(val1->realtype->plugin_ref)->compare(ctx, val1, val2); } LIBYANG_API_DEF int lyplg_type_sort_leafref(const struct ly_ctx *ctx, const struct lyd_value *val1, const struct lyd_value *val2) { - return val1->realtype->plugin->sort(ctx, val1, val2); + return LYSC_GET_TYPE_PLG(val1->realtype->plugin_ref)->sort(ctx, val1, val2); } LIBYANG_API_DEF const void * lyplg_type_print_leafref(const struct ly_ctx *ctx, const struct lyd_value *value, LY_VALUE_FORMAT format, void *prefix_data, ly_bool *dynamic, size_t *value_len) { - return value->realtype->plugin->print(ctx, value, format, prefix_data, dynamic, value_len); + return LYSC_GET_TYPE_PLG(value->realtype->plugin_ref)->print(ctx, value, format, prefix_data, dynamic, value_len); } LIBYANG_API_DEF LY_ERR lyplg_type_dup_leafref(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup) { - return original->realtype->plugin->duplicate(ctx, original, dup); + return LYSC_GET_TYPE_PLG(original->realtype->plugin_ref)->duplicate(ctx, original, dup); } LIBYANG_API_DEF void lyplg_type_free_leafref(const struct ly_ctx *ctx, struct lyd_value *value) { - value->realtype->plugin->free(ctx, value); + LYSC_GET_TYPE_PLG(value->realtype->plugin_ref)->free(ctx, value); } /** @@ -145,7 +145,7 @@ const struct lyplg_type_record plugins_leafref[] = { .revision = NULL, .name = LY_TYPE_LEAFREF_STR, - .plugin.id = "libyang 2 - leafref, version 1", + .plugin.id = "ly2 leafref", .plugin.store = lyplg_type_store_leafref, .plugin.validate = lyplg_type_validate_leafref, .plugin.compare = lyplg_type_compare_leafref, diff --git a/src/plugins_types/lyds_tree.c b/src/plugins_types/lyds_tree.c index 4dc73fb7b..04741432e 100644 --- a/src/plugins_types/lyds_tree.c +++ b/src/plugins_types/lyds_tree.c @@ -132,7 +132,7 @@ const struct lyplg_type_record plugins_lyds_tree[] = { .revision = NULL, .name = "lyds_tree", - .plugin.id = "libyang 2 - lyds_tree, version 1", + .plugin.id = "ly2 lyds_tree", .plugin.store = lyplg_type_store_lyds, .plugin.validate = NULL, .plugin.compare = lyplg_type_compare_lyds, diff --git a/src/plugins_types/node_instanceid.c b/src/plugins_types/node_instanceid.c index ab141d5f3..67dcdda71 100644 --- a/src/plugins_types/node_instanceid.c +++ b/src/plugins_types/node_instanceid.c @@ -52,7 +52,7 @@ node_instanceid_path2str(const struct ly_path *path, LY_VALUE_FORMAT format, voi char *result = NULL, quot; const struct lys_module *mod = NULL, *local_mod = NULL; struct ly_set *mods; - ly_bool inherit_prefix = 0, d; + ly_bool inherit_prefix = 0; const char *strval; if (!path) { @@ -104,8 +104,8 @@ node_instanceid_path2str(const struct ly_path *path, LY_VALUE_FORMAT format, voi break; case LY_PATH_PREDTYPE_LIST: /* key-predicate */ - strval = pred->value.realtype->plugin->print(path[u].node->module->ctx, &pred->value, format, prefix_data, - &d, NULL); + ret = lyplg_type_print_val(pred->key, pred->value, format, prefix_data, &strval); + LY_CHECK_GOTO(ret, cleanup); /* default quote */ quot = '\''; @@ -119,14 +119,12 @@ node_instanceid_path2str(const struct ly_path *path, LY_VALUE_FORMAT format, voi ret = ly_strcat(&result, "[%s:%s=%c%s%c]", lyplg_type_get_prefix(pred->key->module, format, prefix_data), pred->key->name, quot, strval, quot); } - if (d) { - free((char *)strval); - } + lydict_remove(pred->key->module->ctx, strval); break; case LY_PATH_PREDTYPE_LEAFLIST: /* leaf-list-predicate */ - strval = pred->value.realtype->plugin->print(path[u].node->module->ctx, &pred->value, format, prefix_data, - &d, NULL); + ret = lyplg_type_print_val(path[u].node, pred->value, format, prefix_data, &strval); + LY_CHECK_GOTO(ret, cleanup); /* default quote */ quot = '\''; @@ -134,9 +132,7 @@ node_instanceid_path2str(const struct ly_path *path, LY_VALUE_FORMAT format, voi quot = '"'; } ret = ly_strcat(&result, "[.=%c%s%c]", quot, strval, quot); - if (d) { - free((char *)strval); - } + lydict_remove(path[u].node->module->ctx, strval); break; case LY_PATH_PREDTYPE_LIST_VAR: /* key-predicate with a variable */ @@ -256,7 +252,7 @@ lyplg_type_store_node_instanceid(const struct ly_ctx *ctx, const struct lysc_typ } cleanup: - lyxp_expr_free(ctx, exp); + lyxp_expr_free(exp); if (options & LYPLG_TYPE_STORE_DYNAMIC) { free((void *)value); } @@ -338,7 +334,7 @@ const struct lyplg_type_record plugins_node_instanceid[] = { .revision = "2012-02-22", .name = "node-instance-identifier", - .plugin.id = "libyang 2 - node-instance-identifier, version 1", + .plugin.id = "ly2 node-instance-identifier", .plugin.store = lyplg_type_store_node_instanceid, .plugin.validate = NULL, .plugin.compare = lyplg_type_compare_simple, @@ -353,7 +349,7 @@ const struct lyplg_type_record plugins_node_instanceid[] = { .revision = "2018-02-14", .name = "node-instance-identifier", - .plugin.id = "libyang 2 - node-instance-identifier, version 1", + .plugin.id = "ly2 node-instance-identifier", .plugin.store = lyplg_type_store_node_instanceid, .plugin.validate = NULL, .plugin.compare = lyplg_type_compare_simple, diff --git a/src/plugins_types/string.c b/src/plugins_types/string.c index d1888f398..45f85c639 100644 --- a/src/plugins_types/string.c +++ b/src/plugins_types/string.c @@ -102,7 +102,7 @@ lyplg_type_store_string(const struct ly_ctx *ctx, const struct lysc_type *type, } /* pattern restrictions */ - ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err); + ret = lyplg_type_validate_patterns(ctx, type_str->patterns, value, value_len, err); LY_CHECK_GOTO(ret, cleanup); } @@ -130,7 +130,7 @@ const struct lyplg_type_record plugins_string[] = { .revision = NULL, .name = LY_TYPE_STRING_STR, - .plugin.id = "libyang 2 - string, version 1", + .plugin.id = "ly2 string", .plugin.store = lyplg_type_store_string, .plugin.validate = NULL, .plugin.compare = lyplg_type_compare_simple, diff --git a/src/plugins_types/time_period.c b/src/plugins_types/time_period.c index e2fbcd6f3..98c47c12c 100644 --- a/src/plugins_types/time_period.c +++ b/src/plugins_types/time_period.c @@ -86,7 +86,7 @@ const struct lyplg_type_record plugins_time_period[] = { .revision = "2024-07-09", .name = "time-period", - .plugin.id = "libyang 2 - time-period, version 1", + .plugin.id = "ly2 time-period", .plugin.store = lyplg_type_store_string, .plugin.validate = NULL, .plugin.compare = lyplg_type_compare_simple, diff --git a/src/plugins_types/union.c b/src/plugins_types/union.c index 47aea3136..55525a358 100644 --- a/src/plugins_types/union.c +++ b/src/plugins_types/union.c @@ -220,6 +220,7 @@ union_store_type(const struct ly_ctx *ctx, struct lysc_type_union *type_u, uint3 LY_VALUE_FORMAT format; void *prefix_data; uint32_t opts = 0, ti; + struct lyplg_type *type_plg; *err = NULL; @@ -227,9 +228,11 @@ union_store_type(const struct ly_ctx *ctx, struct lysc_type_union *type_u, uint3 lyb_parse_union(subvalue->original, subvalue->orig_len, &ti, &value, &value_len); if (ti != type_idx) { /* value of another type, first store the value properly and then use its JSON value for parsing */ - rc = type_u->types[ti]->plugin->store(ctx, type_u->types[ti], value, value_len, LYPLG_TYPE_STORE_ONLY, - subvalue->format, subvalue->prefix_data, subvalue->hints, subvalue->ctx_node, &subvalue->value, unres, err); - if (rc && (rc != LY_EINCOMPLETE)) { + type_plg = LYSC_GET_TYPE_PLG(type_u->types[ti]->plugin_ref); + rc = type_plg->store(ctx, type_u->types[ti], value, value_len, + LYPLG_TYPE_STORE_ONLY, subvalue->format, subvalue->prefix_data, subvalue->hints, + subvalue->ctx_node, &subvalue->value, unres, err); + if ((rc != LY_SUCCESS) && (rc != LY_EINCOMPLETE)) { /* clear any leftover/freed garbage */ memset(&subvalue->value, 0, sizeof subvalue->value); @@ -239,14 +242,15 @@ union_store_type(const struct ly_ctx *ctx, struct lysc_type_union *type_u, uint3 } assert(subvalue->value.realtype); - value = subvalue->value.realtype->plugin->print(ctx, &subvalue->value, LY_VALUE_JSON, NULL, &dynamic, &value_len); + value = LYSC_GET_TYPE_PLG(subvalue->value.realtype->plugin_ref)->print(ctx, &subvalue->value, + LY_VALUE_JSON, NULL, &dynamic, &value_len); /* to avoid leaks, free subvalue->value, but we need the value, which may be stored there */ if (!dynamic) { value = strndup(value, value_len); dynamic = 1; } - type_u->types[ti]->plugin->free(ctx, &subvalue->value); + type_plg->free(ctx, &subvalue->value); format = LY_VALUE_JSON; prefix_data = NULL; @@ -265,9 +269,11 @@ union_store_type(const struct ly_ctx *ctx, struct lysc_type_union *type_u, uint3 opts |= LYPLG_TYPE_STORE_ONLY; } - rc = type->plugin->store(ctx, type, value, value_len, opts, format, prefix_data, subvalue->hints, - subvalue->ctx_node, &subvalue->value, unres, err); - if (rc && (rc != LY_EINCOMPLETE)) { + type_plg = LYSC_GET_TYPE_PLG(type->plugin_ref); + + rc = type_plg->store(ctx, type, value, value_len, opts, format, prefix_data, + subvalue->hints, subvalue->ctx_node, &subvalue->value, unres, err); + if ((rc != LY_SUCCESS) && (rc != LY_EINCOMPLETE)) { /* clear any leftover/freed garbage */ memset(&subvalue->value, 0, sizeof subvalue->value); @@ -278,10 +284,10 @@ union_store_type(const struct ly_ctx *ctx, struct lysc_type_union *type_u, uint3 if (validate && (rc == LY_EINCOMPLETE)) { /* we need the value validated */ - rc = type->plugin->validate(ctx, type, ctx_node, tree, &subvalue->value, err); + rc = type_plg->validate(ctx, type, ctx_node, tree, &subvalue->value, err); if (rc) { /* validate failed, we need to free the stored value */ - type->plugin->free(ctx, &subvalue->value); + type_plg->free(ctx, &subvalue->value); goto cleanup; } } @@ -320,6 +326,7 @@ union_find_type(const struct ly_ctx *ctx, struct lysc_type_union *type_u, struct char *msg = NULL, *err_app_tag = NULL; int msg_len = 0; ly_bool use_err_app_tag = 0; + struct lyplg_type *type_plg; *err = NULL; @@ -370,9 +377,11 @@ union_find_type(const struct ly_ctx *ctx, struct lysc_type_union *type_u, struct } } - msg = ly_realloc(msg, msg_len + 4 + strlen(type_u->types[u]->plugin->id) + 2 + strlen(errs[u]->msg) + 2); + type_plg = LYSC_GET_TYPE_PLG(type_u->types[u]->plugin_ref); + + msg = ly_realloc(msg, msg_len + 4 + strlen(type_plg->id) + 2 + strlen(errs[u]->msg) + 2); LY_CHECK_ERR_GOTO(!msg, ret = LY_EMEM, cleanup); - msg_len += sprintf(msg + msg_len, " %s: %s\n", type_u->types[u]->plugin->id, errs[u]->msg); + msg_len += sprintf(msg + msg_len, " %s: %s\n", type_plg->id, errs[u]->msg); } if (!use_err_app_tag) { @@ -511,14 +520,16 @@ lyplg_type_validate_union(const struct ly_ctx *ctx, const struct lysc_type *type struct lyd_value orig = {0}; uint32_t type_idx; ly_bool validated = 0; + struct lyplg_type *subvalue_type_plg; *err = NULL; /* because of types that do not store their own type as realtype (leafref), we are not able to call their * validate callback (there is no way to get the type) but even if possible, the value may be invalid * for the type, so we may have to perform union value storing again from scratch, but keep a value backup */ - LY_CHECK_RET(subvalue->value.realtype->plugin->duplicate(ctx, &subvalue->value, &orig)); - subvalue->value.realtype->plugin->free(ctx, &subvalue->value); + subvalue_type_plg = LYSC_GET_TYPE_PLG(subvalue->value.realtype->plugin_ref); + LY_CHECK_RET(subvalue_type_plg->duplicate(ctx, &subvalue->value, &orig)); + subvalue_type_plg->free(ctx, &subvalue->value); if (subvalue->format == LY_VALUE_LYB) { /* use the specific type to store and validate the value */ @@ -548,7 +559,7 @@ lyplg_type_validate_union(const struct ly_ctx *ctx, const struct lysc_type *type LY_CHECK_RET(lydict_insert(ctx, subvalue->value._canonical, 0, &storage->_canonical)); /* free backup value */ - orig.realtype->plugin->free(ctx, &orig); + LYSC_GET_TYPE_PLG(orig.realtype->plugin_ref)->free(ctx, &orig); return LY_SUCCESS; } @@ -558,7 +569,8 @@ lyplg_type_compare_union(const struct ly_ctx *ctx, const struct lyd_value *val1, if (val1->subvalue->value.realtype != val2->subvalue->value.realtype) { return LY_ENOT; } - return val1->subvalue->value.realtype->plugin->compare(ctx, &val1->subvalue->value, &val2->subvalue->value); + return LYSC_GET_TYPE_PLG(val1->subvalue->value.realtype->plugin_ref)->compare(ctx, + &val1->subvalue->value, &val2->subvalue->value); } LIBYANG_API_DEF int @@ -569,7 +581,8 @@ lyplg_type_sort_union(const struct ly_ctx *ctx, const struct lyd_value *val1, co struct lysc_type **types, *type; if (val1->subvalue->value.realtype == val2->subvalue->value.realtype) { - return val1->subvalue->value.realtype->plugin->sort(ctx, &val1->subvalue->value, &val2->subvalue->value); + return LYSC_GET_TYPE_PLG(val1->subvalue->value.realtype->plugin_ref)->sort(ctx, + &val1->subvalue->value, &val2->subvalue->value); } /* compare according to the order of types */ @@ -628,14 +641,14 @@ lyb_union_print(const struct ly_ctx *ctx, struct lysc_type_union *type_u, struct assert(subvalue->ctx_node); ctx = subvalue->ctx_node->module->ctx; } - subvalue->value.realtype->plugin->free(ctx, &subvalue->value); + LYSC_GET_TYPE_PLG(subvalue->value.realtype->plugin_ref)->free(ctx, &subvalue->value); r = union_find_type(ctx, type_u, subvalue, 0, 0, NULL, NULL, &type_idx, NULL, &err); ly_err_free(err); LY_CHECK_RET((r != LY_SUCCESS) && (r != LY_EINCOMPLETE), NULL); /* Print subvalue in LYB format. */ - pval = (void *)subvalue->value.realtype->plugin->print(NULL, &subvalue->value, LY_VALUE_LYB, prefix_data, &dynamic, - &pval_len); + pval = (void *)LYSC_GET_TYPE_PLG(subvalue->value.realtype->plugin_ref)->print(NULL, &subvalue->value, LY_VALUE_LYB, + prefix_data, &dynamic, &pval_len); LY_CHECK_RET(!pval, NULL); /* Create LYB data. */ @@ -682,7 +695,8 @@ lyplg_type_print_union(const struct ly_ctx *ctx, const struct lyd_value *value, } assert(format != LY_VALUE_LYB); - ret = (void *)subvalue->value.realtype->plugin->print(ctx, &subvalue->value, format, prefix_data, dynamic, value_len); + ret = (void *)LYSC_GET_TYPE_PLG(subvalue->value.realtype->plugin_ref)->print(ctx, &subvalue->value, + format, prefix_data, dynamic, value_len); if (!value->_canonical && (format == LY_VALUE_CANON)) { /* the canonical value is supposed to be stored now */ lydict_insert(ctx, subvalue->value._canonical, 0, (const char **)&value->_canonical); @@ -708,7 +722,7 @@ lyplg_type_dup_union(const struct ly_ctx *ctx, const struct lyd_value *original, LY_CHECK_ERR_GOTO(!dup_val, LOGMEM(ctx); ret = LY_EMEM, cleanup); dup->subvalue = dup_val; - ret = orig_val->value.realtype->plugin->duplicate(ctx, &orig_val->value, &dup_val->value); + ret = LYSC_GET_TYPE_PLG(orig_val->value.realtype->plugin_ref)->duplicate(ctx, &orig_val->value, &dup_val->value); LY_CHECK_GOTO(ret, cleanup); if (orig_val->orig_len) { @@ -744,7 +758,7 @@ lyplg_type_free_union(const struct ly_ctx *ctx, struct lyd_value *value) LYD_VALUE_GET(value, val); if (val) { if (val->value.realtype) { - val->value.realtype->plugin->free(ctx, &val->value); + LYSC_GET_TYPE_PLG(val->value.realtype->plugin_ref)->free(ctx, &val->value); } lyplg_type_prefix_data_free(val->format, val->prefix_data); free(val->original); @@ -766,7 +780,7 @@ const struct lyplg_type_record plugins_union[] = { .revision = NULL, .name = LY_TYPE_UNION_STR, - .plugin.id = "libyang 2 - union,version 1", + .plugin.id = "ly2 union", .plugin.store = lyplg_type_store_union, .plugin.validate = lyplg_type_validate_union, .plugin.compare = lyplg_type_compare_union, diff --git a/src/plugins_types/xpath1.0.c b/src/plugins_types/xpath1.0.c index 0c5dfce2d..f2bcb8f9c 100644 --- a/src/plugins_types/xpath1.0.c +++ b/src/plugins_types/xpath1.0.c @@ -504,7 +504,7 @@ lyplg_type_free_xpath10(const struct ly_ctx *ctx, struct lyd_value *value) value->_canonical = NULL; LYD_VALUE_GET(value, val); if (val) { - lyxp_expr_free(ctx, val->exp); + lyxp_expr_free(val->exp); lyplg_type_prefix_data_free(val->format, val->prefix_data); LYPLG_TYPE_VAL_INLINE_DESTROY(val); @@ -524,7 +524,7 @@ const struct lyplg_type_record plugins_xpath10[] = { .revision = "2013-07-15", .name = "xpath1.0", - .plugin.id = "libyang 2 - xpath1.0, version 1", + .plugin.id = "ly2 xpath1.0", .plugin.store = lyplg_type_store_xpath10, .plugin.validate = lyplg_type_validate_xpath10, .plugin.compare = lyplg_type_compare_simple, diff --git a/src/printer_context.c b/src/printer_context.c new file mode 100644 index 000000000..eb02dd13b --- /dev/null +++ b/src/printer_context.c @@ -0,0 +1,2008 @@ +/** + * @file printer_context.c + * @author Michal Vasko + * @brief Compiled context printer + * + * 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 +#include +#include +#include + +#include "compat.h" +#include "hash_table_internal.h" +#include "log.h" +#include "ly_common.h" +#include "plugins_exts.h" +#include "plugins_internal.h" +#include "tree_schema_internal.h" +#include "xpath.h" + +/** + * @brief Get the size of a sized array. + * + * @param[in] ARRAY Sized array. + * @return Size of @p ARRAY. + */ +#define CTXS_SIZED_ARRAY(ARRAY) \ + (ARRAY ? sizeof(LY_ARRAY_COUNT_TYPE) : 0) + LY_ARRAY_COUNT(ARRAY) * sizeof *ARRAY + +/** + * @brief Print (serialize) a sized array. + * + * @param[in] ORIG_ARRAY Sized array to print. + * @param[in,out] ARRAY Printed sized array. + * @param[in,out] MEM Memory to use. + */ +#define CTXP_SIZED_ARRAY(ORIG_ARRAY, ARRAY, MEM) \ + if (ORIG_ARRAY) { \ + LY_ARRAY_COUNT_TYPE count = LY_ARRAY_COUNT(ORIG_ARRAY); \ + memcpy(*MEM, &count, sizeof count); \ + *MEM = (char *)*MEM + sizeof count; \ + \ + ARRAY = *MEM; \ + *MEM = (char *)*MEM + count * sizeof *ORIG_ARRAY; \ + } else { \ + ARRAY = NULL; \ + } + +/** + * @brief Print a structure that is optional (may be NULL). + * + * @param[in] FUNC Function to call to fill the structure. + * @param[in] ORIG_PTR Pointer to the structure to print. + * @param[in] PTR Pointer to the printed structure. + * @param[in] ADDR_HT addr_ht. + * @param[in] PTR_SET ptr_set. + * @param[in,out] MEM mem. + */ +#define CTXP_OPTIONAL_STRUCT(FUNC, ORIG_PTR, PTR, ADDR_HT, PTR_SET, MEM) \ + if (ORIG_PTR) { \ + PTR = *MEM; \ + *MEM = (char *)*MEM + sizeof *PTR; \ + FUNC(ORIG_PTR, PTR, ADDR_HT, PTR_SET, MEM); \ + } else { \ + PTR = NULL; \ + } + +/** + * @brief Alignment of all the printed data, ensures all memory access is aligned to this number (B) + */ +#define CTXP_MEM_ALIGN 8 + +/** + * @brief Adjust data size to an aligned size to make sure the following data is aligned. + * + * @param[in,out] SIZE Data size that is adjusted. + */ +#define CTXP_MEM_SIZE(SIZE) ((SIZE) + ((~(SIZE) + 1) & (CTXP_MEM_ALIGN - 1))) + +static void +ctxs_dict_ht(const struct ly_ht *ht, int *size) +{ + uint32_t i, j; + struct ly_ht_rec *rec; + struct ly_dict_rec *dict_rec; + + /* hash table */ + *size += sizeof *ht; + + /* hlists */ + *size += ht->size * sizeof *ht->hlists; + + /* records (with string pointers) */ + *size += ht->size * ht->rec_size; + + LYHT_ITER_ALL_RECS(ht, i, j, rec) { + dict_rec = (struct ly_dict_rec *)&rec->val; + + /* strings */ + *size += CTXP_MEM_SIZE(strlen(dict_rec->value) + 1); + } +} + +static void +ctxs_exts(const struct lysc_ext_instance *exts, struct ly_ht *ht, int *size) +{ + LY_ARRAY_COUNT_TYPE u; + struct lyplg_ext *ext_plg; + + /* sized array */ + *size += CTXS_SIZED_ARRAY(exts); + + LY_ARRAY_FOR(exts, u) { + ctxs_exts(exts[u].exts, ht, size); + + /* substmts */ + *size += CTXS_SIZED_ARRAY(exts[u].substmts); + + /* compiled, substmts storage */ + if (exts[u].def->plugin_ref && (ext_plg = LYSC_GET_EXT_PLG(exts[u].def->plugin_ref)) && ext_plg->compiled_size) { + *size += ext_plg->compiled_size(&exts[u], ht); + } + } +} + +static void +ctxs_prefixes(const struct lysc_prefix *prefixes, int *size) +{ + LY_ARRAY_COUNT_TYPE u; + + *size += CTXS_SIZED_ARRAY(prefixes); + LY_ARRAY_FOR(prefixes, u) { + /* string not in the dictionary */ + if (prefixes[u].prefix) { + *size += CTXP_MEM_SIZE(strlen(prefixes[u].prefix) + 1); + } + } +} + +static void +ctxs_expr(const struct lyxp_expr *exp, int *size) +{ + uint32_t i, j; + + *size += sizeof *exp; + + *size += strlen(exp->expr) + 1; + *size += exp->used * sizeof *exp->tokens; + *size += exp->used * sizeof *exp->tok_pos; + *size += exp->used * sizeof *exp->tok_len; + *size += exp->used * sizeof *exp->repeat; + for (i = 0; i < exp->used; ++i) { + if (!exp->repeat[i]) { + continue; + } + + for (j = 0; exp->repeat[i][j]; ++j) {} + *size += (j + 1) * sizeof **exp->repeat; + } +} + +static void +ctxs_musts(const struct lysc_must *musts, struct ly_ht *ht, int *size) +{ + LY_ARRAY_COUNT_TYPE u; + + *size += CTXS_SIZED_ARRAY(musts); + LY_ARRAY_FOR(musts, u) { + ctxs_expr(musts[u].cond, size); + ctxs_prefixes(musts[u].prefixes, size); + ctxs_exts(musts[u].exts, ht, size); + } +} + +static void +ctxs_when(const struct lysc_when *when, struct ly_ht *ht, int *size) +{ + uint32_t hash; + + /* ht check, make sure the structure is stored only once */ + hash = lyht_hash((const char *)&when, sizeof when); + if (lyht_insert(ht, &when, hash, NULL) == LY_EEXIST) { + return; + } + + *size += sizeof *when; + + ctxs_expr(when->cond, size); + ctxs_prefixes(when->prefixes, size); + ctxs_exts(when->exts, ht, size); +} + +static void +ctxs_whens(const struct lysc_when **whens, struct ly_ht *ht, int *size) +{ + LY_ARRAY_COUNT_TYPE u; + + *size += CTXS_SIZED_ARRAY(whens); + LY_ARRAY_FOR(whens, u) { + ctxs_when(whens[u], ht, size); + } +} + +static void +ctxs_range(const struct lysc_range *range, struct ly_ht *ht, int *size) +{ + if (!range) { + return; + } + + *size += sizeof *range; + + *size += CTXS_SIZED_ARRAY(range->parts); + ctxs_exts(range->exts, ht, size); +} + +static void +ctxs_patterns(const struct lysc_pattern **patterns, struct ly_ht *ht, int *size) +{ + uint32_t hash; + LY_ARRAY_COUNT_TYPE u; + + *size += CTXS_SIZED_ARRAY(patterns); + LY_ARRAY_FOR(patterns, u) { + /* ht check, make sure the structure is stored only once */ + hash = lyht_hash((const char *)&patterns[u], sizeof patterns[u]); + if (lyht_insert(ht, (void *)patterns[u], hash, NULL) == LY_EEXIST) { + continue; + } + + *size += sizeof *patterns[u]; + ctxs_exts(patterns[u]->exts, ht, size); + } +} + +static void +ctxs_enums(const struct lysc_type_bitenum_item *enums, struct ly_ht *ht, int *size) +{ + LY_ARRAY_COUNT_TYPE u; + + *size += CTXS_SIZED_ARRAY(enums); + LY_ARRAY_FOR(enums, u) { + ctxs_exts(enums[u].exts, ht, size); + } +} + +static void +ctxs_type(const struct lysc_type *type, struct ly_ht *ht, int *size) +{ + uint32_t hash; + const struct lysc_type_num *type_num; + const struct lysc_type_dec *type_dec; + const struct lysc_type_str *type_str; + const struct lysc_type_enum *type_enum_bits; + const struct lysc_type_leafref *type_lref; + const struct lysc_type_identityref *type_identref; + const struct lysc_type_instanceid *type_instid; + const struct lysc_type_union *type_union; + const struct lysc_type_bin *type_bin; + LY_ARRAY_COUNT_TYPE u; + + /* ht check, make sure the structure is stored only once */ + hash = lyht_hash((const char *)&type, sizeof type); + if (lyht_insert(ht, &type, hash, NULL) == LY_EEXIST) { + return; + } + + /* common members */ + ctxs_exts(type->exts, ht, size); + + switch (type->basetype) { + case LY_TYPE_BINARY: + type_bin = (const struct lysc_type_bin *)type; + *size += sizeof *type_bin; + + ctxs_range(type_bin->length, ht, size); + break; + case LY_TYPE_UINT8: + case LY_TYPE_UINT16: + case LY_TYPE_UINT32: + case LY_TYPE_UINT64: + case LY_TYPE_INT8: + case LY_TYPE_INT16: + case LY_TYPE_INT32: + case LY_TYPE_INT64: + type_num = (const struct lysc_type_num *)type; + *size += sizeof *type_num; + + ctxs_range(type_num->range, ht, size); + break; + case LY_TYPE_STRING: + type_str = (const struct lysc_type_str *)type; + *size += sizeof *type_str; + + ctxs_range(type_str->length, ht, size); + ctxs_patterns((const struct lysc_pattern **)type_str->patterns, ht, size); + break; + case LY_TYPE_BITS: + case LY_TYPE_ENUM: + type_enum_bits = (const struct lysc_type_enum *)type; + *size += sizeof *type_enum_bits; + + ctxs_enums(type_enum_bits->enums, ht, size); + break; + case LY_TYPE_BOOL: + case LY_TYPE_EMPTY: + *size += sizeof *type; + break; + case LY_TYPE_DEC64: + type_dec = (const struct lysc_type_dec *)type; + *size += sizeof *type_dec; + + ctxs_range(type_dec->range, ht, size); + break; + case LY_TYPE_IDENT: + type_identref = (const struct lysc_type_identityref *)type; + *size += sizeof *type_identref; + + *size += CTXS_SIZED_ARRAY(type_identref->bases); + break; + case LY_TYPE_INST: + type_instid = (const struct lysc_type_instanceid *)type; + *size += sizeof *type_instid; + break; + case LY_TYPE_LEAFREF: + type_lref = (const struct lysc_type_leafref *)type; + *size += sizeof *type_lref; + + ctxs_expr(type_lref->path, size); + ctxs_prefixes(type_lref->prefixes, size); + ctxs_type(type_lref->realtype, ht, size); + break; + case LY_TYPE_UNION: + type_union = (const struct lysc_type_union *)type; + *size += sizeof *type_union; + + *size += CTXS_SIZED_ARRAY(type_union->types); + LY_ARRAY_FOR(type_union->types, u) { + ctxs_type(type_union->types[u], ht, size); + } + break; + case LY_TYPE_UNKNOWN: + LOGINT(NULL); + break; + } +} + +static void +ctxs_node(const struct lysc_node *node, struct ly_ht *ht, int *size) +{ + const struct lysc_node_container *cont; + const struct lysc_node_choice *choic; + const struct lysc_node_leaf *leaf; + const struct lysc_node_leaflist *llist; + const struct lysc_node_list *list; + const struct lysc_node_anydata *any; + const struct lysc_node_case *cas; + const struct lysc_node_action *act; + const struct lysc_node_notif *notif; + const struct lysc_node *child; + LY_ARRAY_COUNT_TYPE u; + + /* common members */ + ctxs_exts(node->exts, ht, size); + + switch (node->nodetype) { + case LYS_CONTAINER: + cont = (const struct lysc_node_container *)node; + *size += sizeof *cont; + + LY_LIST_FOR(cont->child, child) { + ctxs_node(child, ht, size); + } + ctxs_musts(cont->musts, ht, size); + ctxs_whens((const struct lysc_when **)cont->when, ht, size); + LY_LIST_FOR((const struct lysc_node *)cont->actions, child) { + ctxs_node(child, ht, size); + } + LY_LIST_FOR((const struct lysc_node *)cont->notifs, child) { + ctxs_node(child, ht, size); + } + break; + case LYS_CHOICE: + choic = (const struct lysc_node_choice *)node; + *size += sizeof *choic; + + LY_LIST_FOR((const struct lysc_node *)choic->cases, child) { + ctxs_node(child, ht, size); + } + ctxs_whens((const struct lysc_when **)choic->when, ht, size); + break; + case LYS_LEAF: + leaf = (const struct lysc_node_leaf *)node; + *size += sizeof *leaf; + + ctxs_musts(leaf->musts, ht, size); + ctxs_whens((const struct lysc_when **)leaf->when, ht, size); + ctxs_type(leaf->type, ht, size); + ctxs_prefixes(leaf->dflt.prefixes, size); + break; + case LYS_LEAFLIST: + llist = (const struct lysc_node_leaflist *)node; + *size += sizeof *llist; + + ctxs_musts(llist->musts, ht, size); + ctxs_whens((const struct lysc_when **)llist->when, ht, size); + ctxs_type(llist->type, ht, size); + *size += CTXS_SIZED_ARRAY(llist->dflts); + LY_ARRAY_FOR(llist->dflts, u) { + ctxs_prefixes(llist->dflts[u].prefixes, size); + } + break; + case LYS_LIST: + list = (const struct lysc_node_list *)node; + *size += sizeof *list; + + LY_LIST_FOR(list->child, child) { + ctxs_node(child, ht, size); + } + ctxs_musts(list->musts, ht, size); + ctxs_whens((const struct lysc_when **)list->when, ht, size); + LY_LIST_FOR((const struct lysc_node *)list->actions, child) { + ctxs_node(child, ht, size); + } + LY_LIST_FOR((const struct lysc_node *)list->notifs, child) { + ctxs_node(child, ht, size); + } + *size += CTXS_SIZED_ARRAY(list->uniques); + LY_ARRAY_FOR(list->uniques, u) { + *size += sizeof(LY_ARRAY_COUNT_TYPE) + LY_ARRAY_COUNT(list->uniques[u]) * sizeof **list->uniques; + } + break; + case LYS_ANYXML: + case LYS_ANYDATA: + any = (const struct lysc_node_anydata *)node; + *size += sizeof *any; + + ctxs_musts(any->musts, ht, size); + ctxs_whens((const struct lysc_when **)any->when, ht, size); + break; + case LYS_CASE: + cas = (const struct lysc_node_case *)node; + *size += sizeof *cas; + + LY_LIST_FOR(cas->child, child) { + ctxs_node(child, ht, size); + } + ctxs_whens((const struct lysc_when **)cas->when, ht, size); + break; + case LYS_RPC: + case LYS_ACTION: + act = (const struct lysc_node_action *)node; + *size += sizeof *act; + + ctxs_whens((const struct lysc_when **)act->when, ht, size); + LY_LIST_FOR(act->input.child, child) { + ctxs_node(child, ht, size); + } + ctxs_musts(act->input.musts, ht, size); + LY_LIST_FOR(act->output.child, child) { + ctxs_node(child, ht, size); + } + ctxs_musts(act->output.musts, ht, size); + break; + case LYS_NOTIF: + notif = (const struct lysc_node_notif *)node; + *size += sizeof *notif; + + LY_LIST_FOR(notif->child, child) { + ctxs_node(child, ht, size); + } + ctxs_musts(notif->musts, ht, size); + ctxs_whens((const struct lysc_when **)notif->when, ht, size); + break; + default: + LOGINT(NULL); + break; + } +} + +static void +ctxs_compiled(const struct lysc_module *compiled, struct ly_ht *ht, int *size) +{ + const struct lysc_node *node; + + if (!compiled) { + return; + } + + /* compiled module */ + *size += sizeof *compiled; + + *size += CTXS_SIZED_ARRAY(compiled->features); + LY_LIST_FOR(compiled->data, node) { + ctxs_node(node, ht, size); + } + LY_LIST_FOR((const struct lysc_node *)compiled->rpcs, node) { + ctxs_node(node, ht, size); + } + LY_LIST_FOR((const struct lysc_node *)compiled->notifs, node) { + ctxs_node(node, ht, size); + } + ctxs_exts(compiled->exts, ht, size); +} + +static void +ctxs_extensions(const struct lysc_ext *extensions, struct ly_ht *ht, int *size) +{ + LY_ARRAY_COUNT_TYPE u; + + /* sized array */ + *size += CTXS_SIZED_ARRAY(extensions); + + LY_ARRAY_FOR(extensions, u) { + ctxs_exts(extensions[u].exts, ht, size); + } +} + +static void +ctxs_identities(const struct lysc_ident *identities, struct ly_ht *ht, int *size) +{ + LY_ARRAY_COUNT_TYPE u; + + /* sized array */ + *size += CTXS_SIZED_ARRAY(identities); + + LY_ARRAY_FOR(identities, u) { + *size += CTXS_SIZED_ARRAY(identities[u].derived); + ctxs_exts(identities[u].exts, ht, size); + } +} + +static void +ctxs_module(const struct lys_module *mod, struct ly_ht *ht, int *size) +{ + /* module */ + *size += sizeof *mod; + + /* compiled module */ + ctxs_compiled(mod->compiled, ht, size); + + /* extensions, identities, submodules */ + ctxs_extensions(mod->extensions, ht, size); + ctxs_identities(mod->identities, ht, size); + *size += CTXS_SIZED_ARRAY(mod->submodules); + + /* augmented_by, deviated_by */ + *size += CTXS_SIZED_ARRAY(mod->augmented_by); + *size += CTXS_SIZED_ARRAY(mod->deviated_by); +} + +void +ly_ctx_compiled_size_context(const struct ly_ctx *ctx, struct ly_ht *addr_ht, int *size) +{ + uint32_t i; + const struct lys_module *mod; + + /* context */ + *size += sizeof *ctx; + + /* dictionary ht (with all the strings) */ + ctxs_dict_ht(ctx->dict.hash_tab, size); + + /* module set */ + *size += ctx->modules.count * sizeof ctx->modules.objs; + for (i = 0; i < ctx->modules.count; ++i) { + mod = ctx->modules.objs[i]; + + /* modules */ + ctxs_module(mod, addr_ht, size); + } +} + +int +ly_ctx_compiled_ext_stmts_storage_size(const struct lysc_ext_substmt *substmts, struct ly_ht *addr_ht) +{ + LY_ARRAY_COUNT_TYPE u; + int size = 0; + uint32_t hash; + const struct lysc_node *node; + + LY_ARRAY_FOR(substmts, u) { + if (!substmts[u].storage_p) { + /* nothing is compiled */ + continue; + } + + switch (substmts[u].stmt) { + case LY_STMT_NOTIFICATION: + case LY_STMT_INPUT: + case LY_STMT_OUTPUT: + case LY_STMT_ACTION: + case LY_STMT_RPC: + case LY_STMT_ANYDATA: + case LY_STMT_ANYXML: + case LY_STMT_CASE: + case LY_STMT_CHOICE: + case LY_STMT_CONTAINER: + case LY_STMT_LEAF: + case LY_STMT_LEAF_LIST: + case LY_STMT_LIST: + case LY_STMT_USES: + node = *(const struct lysc_node **)substmts[u].storage_p; + + /* ht check, make sure the node list is stored only once */ + hash = lyht_hash((const char *)&node, sizeof node); + if (lyht_insert(addr_ht, &node, hash, NULL) == LY_EEXIST) { + break; + } + + LY_LIST_FOR(node, node) { + ctxs_node(node, addr_ht, &size); + } + break; + case LY_STMT_ARGUMENT: + case LY_STMT_CONTACT: + case LY_STMT_DESCRIPTION: + case LY_STMT_ERROR_APP_TAG: + case LY_STMT_ERROR_MESSAGE: + case LY_STMT_KEY: + case LY_STMT_MODIFIER: + case LY_STMT_NAMESPACE: + case LY_STMT_ORGANIZATION: + case LY_STMT_PRESENCE: + case LY_STMT_REFERENCE: + case LY_STMT_UNITS: + /* string, in the dictionary */ + break; + case LY_STMT_BIT: + case LY_STMT_ENUM: + ctxs_enums(*substmts[u].storage_p, addr_ht, &size); + break; + case LY_STMT_CONFIG: + case LY_STMT_MANDATORY: + case LY_STMT_ORDERED_BY: + case LY_STMT_STATUS: + case LY_STMT_FRACTION_DIGITS: + case LY_STMT_REQUIRE_INSTANCE: + case LY_STMT_MAX_ELEMENTS: + case LY_STMT_MIN_ELEMENTS: + case LY_STMT_POSITION: + case LY_STMT_VALUE: + /* number stored directly */ + break; + case LY_STMT_EXTENSION_INSTANCE: + ctxs_exts(*substmts[u].storage_p, addr_ht, &size); + break; + case LY_STMT_IDENTITY: + ctxs_identities(*substmts[u].storage_p, addr_ht, &size); + break; + case LY_STMT_LENGTH: + case LY_STMT_RANGE: + ctxs_range(*substmts[u].storage_p, addr_ht, &size); + break; + case LY_STMT_MUST: + ctxs_musts(*substmts[u].storage_p, addr_ht, &size); + break; + case LY_STMT_PATTERN: + ctxs_patterns(*substmts[u].storage_p, addr_ht, &size); + break; + case LY_STMT_TYPE: + ctxs_type(*substmts[u].storage_p, addr_ht, &size); + break; + case LY_STMT_WHEN: + ctxs_when(*substmts[u].storage_p, addr_ht, &size); + break; + case LY_STMT_IF_FEATURE: + /* not compiled, but can be a substatement */ + break; + case LY_STMT_NONE: + case LY_STMT_AUGMENT: + case LY_STMT_GROUPING: + case LY_STMT_BASE: + case LY_STMT_BELONGS_TO: + case LY_STMT_DEFAULT: + case LY_STMT_DEVIATE: + case LY_STMT_DEVIATION: + case LY_STMT_EXTENSION: + case LY_STMT_FEATURE: + case LY_STMT_IMPORT: + case LY_STMT_INCLUDE: + case LY_STMT_MODULE: + case LY_STMT_PATH: + case LY_STMT_PREFIX: + case LY_STMT_REFINE: + case LY_STMT_REVISION: + case LY_STMT_REVISION_DATE: + case LY_STMT_SUBMODULE: + case LY_STMT_TYPEDEF: + case LY_STMT_UNIQUE: + case LY_STMT_YANG_VERSION: + case LY_STMT_YIN_ELEMENT: + case LY_STMT_SYNTAX_SEMICOLON: + case LY_STMT_SYNTAX_LEFT_BRACE: + case LY_STMT_SYNTAX_RIGHT_BRACE: + case LY_STMT_ARG_TEXT: + case LY_STMT_ARG_VALUE: + /* not compiled, unreachable */ + LOGINT(NULL); + size = -1; + goto cleanup; + } + } + +cleanup: + return size; +} + +static void ctxp_node(const struct lysc_node *orig_node, struct lysc_node *node, struct ly_ht *addr_ht, + struct ly_set *ptr_set, void **mem); + +static void +ctxp_mutex(pthread_mutex_t *mutex) +{ + pthread_mutexattr_t attr; + + pthread_mutexattr_init(&attr); + pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED); + pthread_mutex_init(mutex, &attr); + pthread_mutexattr_destroy(&attr); +} + +static void +ctxp_set(const struct ly_set *orig_set, struct ly_set *set, void **mem) +{ + set->size = orig_set->count; + set->count = orig_set->count; + set->objs = *mem; + *mem = (char *)*mem + (set->count * sizeof set->objs); +} + +static void +ctxp_dict_ht(const struct ly_ht *orig_ht, struct ly_ht *ht, struct ly_ht *addr_ht, void **mem) +{ + uint32_t i, j; + struct ly_ht_rec *rec; + struct ly_dict_rec *dict_rec; + int len; + void *orig_addr; + + /* hash table, must not be modified in the context */ + *ht = *orig_ht; + ht->val_equal = orig_ht->val_equal; + ht->cb_data = NULL; + + /* hlists */ + ht->hlists = *mem; + *mem = (char *)*mem + ht->size * sizeof *ht->hlists; + + memcpy(ht->hlists, orig_ht->hlists, ht->size * sizeof *ht->hlists); + + /* records */ + ht->recs = *mem; + *mem = (char *)*mem + ht->size * ht->rec_size; + + memcpy(ht->recs, orig_ht->recs, ht->size * ht->rec_size); + + LYHT_ITER_ALL_RECS(ht, i, j, rec) { + dict_rec = (struct ly_dict_rec *)&rec->val; + + /* strings */ + len = strlen(dict_rec->value) + 1; + orig_addr = dict_rec->value; + + dict_rec->value = *mem; + *mem = (char *)*mem + CTXP_MEM_SIZE(len); + + memcpy(dict_rec->value, orig_addr, len); + + /* shared */ + ly_ctx_compiled_addr_ht_add(addr_ht, orig_addr, dict_rec->value); + } +} + +static void +ctxp_ext(const struct lysc_ext_instance *orig_ext, struct lysc_ext_instance *ext, struct ly_ht *addr_ht, + struct ly_set *ptr_set, void **mem) +{ + LY_ARRAY_COUNT_TYPE u; + struct lyplg_ext *ext_plg; + + if (orig_ext->exts) { + /* may be referenced in the parent */ + ly_ctx_compiled_addr_ht_add(addr_ht, orig_ext, ext); + } + + /* def, argument, module, only a reference */ + ext->def = orig_ext->def; + ly_set_add(ptr_set, &ext->def, 1, NULL); + ext->argument = ly_ctx_compiled_addr_ht_get(addr_ht, orig_ext->argument, 0); + ext->module = orig_ext->module; + ly_set_add(ptr_set, &ext->module, 1, NULL); + + /* exts */ + CTXP_SIZED_ARRAY(orig_ext->exts, ext->exts, mem); + LY_ARRAY_FOR(orig_ext->exts, u) { + ctxp_ext(&orig_ext->exts[u], &ext->exts[u], addr_ht, ptr_set, mem); + } + + /* parent, only a reference */ + ext->parent = orig_ext->parent; + ly_set_add(ptr_set, &ext->parent, 1, NULL); + ext->parent_stmt = orig_ext->parent_stmt; + ext->parent_stmt_index = orig_ext->parent_stmt_index; + + /* substmts */ + CTXP_SIZED_ARRAY(orig_ext->substmts, ext->substmts, mem); + LY_ARRAY_FOR(orig_ext->substmts, u) { + ext->substmts[u].stmt = orig_ext->substmts[u].stmt; + ext->substmts[u].storage_p = NULL; + } + + /* compiled, substmts storage, use the plugin */ + if (ext->def->plugin_ref && (ext_plg = LYSC_GET_EXT_PLG(ext->def->plugin_ref))->compiled_print) { + ext_plg->compiled_print(orig_ext, ext, addr_ht, ptr_set, mem); + } else { + ext->compiled = NULL; + } +} + +static void +ctxp_expr(const struct lyxp_expr *orig_exp, struct lyxp_expr *exp, void **mem) +{ + uint32_t i, len; + + exp->expr = *mem; + *mem = (char *)*mem + strlen(orig_exp->expr) + 1; + memcpy(exp->expr, orig_exp->expr, strlen(orig_exp->expr) + 1); + + exp->tokens = *mem; + *mem = (char *)*mem + orig_exp->used * sizeof *exp->tokens; + memcpy(exp->tokens, orig_exp->tokens, orig_exp->used * sizeof *exp->tokens); + + exp->tok_pos = *mem; + *mem = (char *)*mem + orig_exp->used * sizeof *exp->tok_pos; + memcpy(exp->tok_pos, orig_exp->tok_pos, orig_exp->used * sizeof *exp->tok_pos); + + exp->tok_len = *mem; + *mem = (char *)*mem + orig_exp->used * sizeof *exp->tok_len; + memcpy(exp->tok_len, orig_exp->tok_len, orig_exp->used * sizeof *exp->tok_len); + + exp->repeat = *mem; + *mem = (char *)*mem + orig_exp->used * sizeof *exp->repeat; + for (i = 0; i < orig_exp->used; ++i) { + if (orig_exp->repeat[i]) { + for (len = 0; orig_exp->repeat[i][len]; ++len) {} + ++len; + + exp->repeat[i] = *mem; + *mem = (char *)*mem + len * sizeof **exp->repeat; + memcpy(exp->repeat[i], orig_exp->repeat[i], len * sizeof **exp->repeat); + } else { + exp->repeat[i] = NULL; + } + } + + exp->used = orig_exp->used; + exp->size = orig_exp->used; +} + +static void +ctxp_prefix(const struct lysc_prefix *orig_prefix, struct lysc_prefix *prefix, struct ly_ht *UNUSED(addr_ht), + struct ly_set *ptr_set, void **mem) +{ + int size; + + if (orig_prefix->prefix) { + size = strlen(orig_prefix->prefix) + 1; + + prefix->prefix = *mem; + *mem = (char *)*mem + CTXP_MEM_SIZE(size); + memcpy(prefix->prefix, orig_prefix->prefix, size); + } else { + prefix->prefix = NULL; + } + + prefix->mod = orig_prefix->mod; + ly_set_add(ptr_set, &prefix->mod, 1, NULL); +} + +static void +ctxp_must(const struct lysc_must *orig_must, struct lysc_must *must, struct ly_ht *addr_ht, struct ly_set *ptr_set, + void **mem) +{ + LY_ARRAY_COUNT_TYPE u; + + if (orig_must->exts) { + /* may be referenced in the parent */ + ly_ctx_compiled_addr_ht_add(addr_ht, orig_must, must); + } + + must->cond = *mem; + *mem = (char *)*mem + sizeof *must->cond; + ctxp_expr(orig_must->cond, must->cond, mem); + + CTXP_SIZED_ARRAY(orig_must->prefixes, must->prefixes, mem); + LY_ARRAY_FOR(orig_must->prefixes, u) { + ctxp_prefix(&orig_must->prefixes[u], &must->prefixes[u], addr_ht, ptr_set, mem); + } + + must->dsc = ly_ctx_compiled_addr_ht_get(addr_ht, orig_must->dsc, 0); + must->ref = ly_ctx_compiled_addr_ht_get(addr_ht, orig_must->ref, 0); + must->emsg = ly_ctx_compiled_addr_ht_get(addr_ht, orig_must->emsg, 0); + must->eapptag = ly_ctx_compiled_addr_ht_get(addr_ht, orig_must->eapptag, 0); + + CTXP_SIZED_ARRAY(orig_must->exts, must->exts, mem); + LY_ARRAY_FOR(orig_must->exts, u) { + ctxp_ext(&orig_must->exts[u], &must->exts[u], addr_ht, ptr_set, mem); + } +} + +static void +ctxp_when(const struct lysc_when *orig_when, struct lysc_when **when, struct ly_ht *addr_ht, struct ly_set *ptr_set, + void **mem) +{ + LY_ARRAY_COUNT_TYPE u; + struct lysc_when *w; + + /* may have already been printed */ + w = ly_ctx_compiled_addr_ht_get(addr_ht, orig_when, 1); + if (w) { + *when = w; + return; + } + + w = *mem; + *mem = (char *)*mem + sizeof *w; + + if (orig_when->exts) { + /* may be referenced in the parent */ + ly_ctx_compiled_addr_ht_add(addr_ht, orig_when, w); + } + + w->cond = *mem; + *mem = (char *)*mem + sizeof *w->cond; + ctxp_expr(orig_when->cond, w->cond, mem); + + w->context = ly_ctx_compiled_addr_ht_get(addr_ht, orig_when->context, 0); + CTXP_SIZED_ARRAY(orig_when->prefixes, w->prefixes, mem); + LY_ARRAY_FOR(orig_when->prefixes, u) { + ctxp_prefix(&orig_when->prefixes[u], &w->prefixes[u], addr_ht, ptr_set, mem); + } + + w->dsc = ly_ctx_compiled_addr_ht_get(addr_ht, orig_when->dsc, 0); + w->ref = ly_ctx_compiled_addr_ht_get(addr_ht, orig_when->ref, 0); + + CTXP_SIZED_ARRAY(orig_when->exts, w->exts, mem); + LY_ARRAY_FOR(orig_when->exts, u) { + ctxp_ext(&orig_when->exts[u], &w->exts[u], addr_ht, ptr_set, mem); + } + + w->refcount = orig_when->refcount; + w->flags = orig_when->flags; + + /* shared */ + ly_ctx_compiled_addr_ht_add(addr_ht, orig_when, w); + *when = w; +} + +static void +ctxp_children(const struct lysc_node *orig_child, struct lysc_node **child, struct ly_ht *addr_ht, + struct ly_set *ptr_set, void **mem) +{ + struct lysc_node *ch; + int node_size; + + *child = NULL; + + LY_LIST_FOR(orig_child, orig_child) { + switch (orig_child->nodetype) { + case LYS_CONTAINER: + node_size = sizeof(struct lysc_node_container); + break; + case LYS_CHOICE: + node_size = sizeof(struct lysc_node_choice); + break; + case LYS_LEAF: + node_size = sizeof(struct lysc_node_leaf); + break; + case LYS_LEAFLIST: + node_size = sizeof(struct lysc_node_leaflist); + break; + case LYS_LIST: + node_size = sizeof(struct lysc_node_list); + break; + case LYS_ANYXML: + case LYS_ANYDATA: + node_size = sizeof(struct lysc_node_anydata); + break; + case LYS_CASE: + node_size = sizeof(struct lysc_node_case); + break; + case LYS_RPC: + case LYS_ACTION: + node_size = sizeof(struct lysc_node_action); + break; + case LYS_NOTIF: + node_size = sizeof(struct lysc_node_notif); + break; + default: + LOGINT(NULL); + return; + } + + ch = *mem; + *mem = (char *)*mem + node_size; + + ly_ctx_compiled_addr_ht_add(addr_ht, orig_child, ch); + ctxp_node(orig_child, ch, addr_ht, ptr_set, mem); + + if (!*child) { + *child = ch; + } + } +} + +static void +ctxp_range(const struct lysc_range *orig_range, struct lysc_range *range, struct ly_ht *addr_ht, struct ly_set *ptr_set, + void **mem) +{ + LY_ARRAY_COUNT_TYPE u; + + if (orig_range->exts) { + /* may be referenced in the parent */ + ly_ctx_compiled_addr_ht_add(addr_ht, orig_range, range); + } + + CTXP_SIZED_ARRAY(orig_range->parts, range->parts, mem); + LY_ARRAY_FOR(orig_range->parts, u) { + range->parts[u].min_64 = orig_range->parts[u].min_64; + range->parts[u].max_64 = orig_range->parts[u].max_64; + } + + range->dsc = ly_ctx_compiled_addr_ht_get(addr_ht, orig_range->dsc, 0); + range->ref = ly_ctx_compiled_addr_ht_get(addr_ht, orig_range->ref, 0); + range->emsg = ly_ctx_compiled_addr_ht_get(addr_ht, orig_range->emsg, 0); + range->eapptag = ly_ctx_compiled_addr_ht_get(addr_ht, orig_range->eapptag, 0); + + CTXP_SIZED_ARRAY(orig_range->exts, range->exts, mem); + LY_ARRAY_FOR(orig_range->exts, u) { + ctxp_ext(&orig_range->exts[u], &range->exts[u], addr_ht, ptr_set, mem); + } +} + +static void +ctxp_pattern(const struct lysc_pattern *orig_pattern, struct lysc_pattern **pattern, struct ly_ht *addr_ht, + struct ly_set *ptr_set, void **mem) +{ + LY_ARRAY_COUNT_TYPE u; + struct lysc_pattern *p; + + /* may have already been printed */ + p = ly_ctx_compiled_addr_ht_get(addr_ht, orig_pattern, 1); + if (p) { + *pattern = p; + return; + } + + p = *mem; + *mem = (char *)*mem + sizeof *p; + + if (orig_pattern->exts) { + /* may be referenced in the parent */ + ly_ctx_compiled_addr_ht_add(addr_ht, orig_pattern, p); + } + + p->expr = ly_ctx_compiled_addr_ht_get(addr_ht, orig_pattern->expr, 0); + + p->dsc = ly_ctx_compiled_addr_ht_get(addr_ht, orig_pattern->dsc, 0); + p->ref = ly_ctx_compiled_addr_ht_get(addr_ht, orig_pattern->ref, 0); + p->emsg = ly_ctx_compiled_addr_ht_get(addr_ht, orig_pattern->emsg, 0); + p->eapptag = ly_ctx_compiled_addr_ht_get(addr_ht, orig_pattern->eapptag, 0); + + CTXP_SIZED_ARRAY(orig_pattern->exts, p->exts, mem); + LY_ARRAY_FOR(orig_pattern->exts, u) { + ctxp_ext(&orig_pattern->exts[u], &p->exts[u], addr_ht, ptr_set, mem); + } + + p->inverted = orig_pattern->inverted; + p->refcount = orig_pattern->refcount; + + /* shared */ + ly_ctx_compiled_addr_ht_add(addr_ht, orig_pattern, p); + *pattern = p; +} + +static void +ctxp_enum(const struct lysc_type_bitenum_item *orig_enum, struct lysc_type_bitenum_item *en, struct ly_ht *addr_ht, + struct ly_set *ptr_set, void **mem) +{ + LY_ARRAY_COUNT_TYPE u; + + if (orig_enum->exts) { + /* may be referenced in the parent */ + ly_ctx_compiled_addr_ht_add(addr_ht, orig_enum, en); + } + + en->name = ly_ctx_compiled_addr_ht_get(addr_ht, orig_enum->name, 0); + en->dsc = ly_ctx_compiled_addr_ht_get(addr_ht, orig_enum->dsc, 0); + en->ref = ly_ctx_compiled_addr_ht_get(addr_ht, orig_enum->ref, 0); + + CTXP_SIZED_ARRAY(orig_enum->exts, en->exts, mem); + LY_ARRAY_FOR(orig_enum->exts, u) { + ctxp_ext(&orig_enum->exts[u], &en->exts[u], addr_ht, ptr_set, mem); + } + + en->value = orig_enum->value; + en->flags = orig_enum->flags; +} + +static void +ctxp_type(const struct lysc_type *orig_type, struct lysc_type **type, struct ly_ht *addr_ht, struct ly_set *ptr_set, + void **mem) +{ + struct lysc_type *t; + const struct lysc_type_num *orig_type_num; + struct lysc_type_num *t_num; + const struct lysc_type_dec *orig_type_dec; + struct lysc_type_dec *t_dec; + const struct lysc_type_str *orig_type_str; + struct lysc_type_str *t_str; + const struct lysc_type_enum *orig_type_enum_bits; + struct lysc_type_enum *t_enum_bits; + const struct lysc_type_leafref *orig_type_lref; + struct lysc_type_leafref *t_lref; + const struct lysc_type_identityref *orig_type_identref; + struct lysc_type_identityref *t_identref; + const struct lysc_type_instanceid *orig_type_instid; + struct lysc_type_instanceid *t_instid; + const struct lysc_type_union *orig_type_union; + struct lysc_type_union *t_union; + const struct lysc_type_bin *orig_type_bin; + struct lysc_type_bin *t_bin; + LY_ARRAY_COUNT_TYPE u; + + /* may have already been printed */ + t = ly_ctx_compiled_addr_ht_get(addr_ht, orig_type, 1); + if (t) { + *type = t; + return; + } + + switch (orig_type->basetype) { + case LY_TYPE_BINARY: + orig_type_bin = (const struct lysc_type_bin *)orig_type; + t = *mem; + *mem = (char *)*mem + sizeof *orig_type_bin; + t_bin = (struct lysc_type_bin *)t; + + CTXP_OPTIONAL_STRUCT(ctxp_range, orig_type_bin->length, t_bin->length, addr_ht, ptr_set, mem); + break; + case LY_TYPE_UINT8: + case LY_TYPE_UINT16: + case LY_TYPE_UINT32: + case LY_TYPE_UINT64: + case LY_TYPE_INT8: + case LY_TYPE_INT16: + case LY_TYPE_INT32: + case LY_TYPE_INT64: + orig_type_num = (const struct lysc_type_num *)orig_type; + t = *mem; + *mem = (char *)*mem + sizeof *orig_type_num; + t_num = (struct lysc_type_num *)t; + + CTXP_OPTIONAL_STRUCT(ctxp_range, orig_type_num->range, t_num->range, addr_ht, ptr_set, mem); + break; + case LY_TYPE_STRING: + orig_type_str = (const struct lysc_type_str *)orig_type; + t = *mem; + *mem = (char *)*mem + sizeof *orig_type_str; + t_str = (struct lysc_type_str *)t; + + CTXP_OPTIONAL_STRUCT(ctxp_range, orig_type_str->length, t_str->length, addr_ht, ptr_set, mem); + CTXP_SIZED_ARRAY(orig_type_str->patterns, t_str->patterns, mem); + LY_ARRAY_FOR(orig_type_str->patterns, u) { + ctxp_pattern(orig_type_str->patterns[u], &t_str->patterns[u], addr_ht, ptr_set, mem); + } + break; + case LY_TYPE_BITS: + case LY_TYPE_ENUM: + orig_type_enum_bits = (const struct lysc_type_enum *)orig_type; + t = *mem; + *mem = (char *)*mem + sizeof *orig_type_enum_bits; + t_enum_bits = (struct lysc_type_enum *)t; + + CTXP_SIZED_ARRAY(orig_type_enum_bits->enums, t_enum_bits->enums, mem); + LY_ARRAY_FOR(orig_type_enum_bits->enums, u) { + ctxp_enum(&orig_type_enum_bits->enums[u], &t_enum_bits->enums[u], addr_ht, ptr_set, mem); + } + break; + case LY_TYPE_BOOL: + case LY_TYPE_EMPTY: + /* no additional members */ + t = *mem; + *mem = (char *)*mem + sizeof *orig_type; + break; + case LY_TYPE_DEC64: + orig_type_dec = (const struct lysc_type_dec *)orig_type; + t = *mem; + *mem = (char *)*mem + sizeof *orig_type_dec; + t_dec = (struct lysc_type_dec *)t; + + t_dec->fraction_digits = orig_type_dec->fraction_digits; + CTXP_OPTIONAL_STRUCT(ctxp_range, orig_type_dec->range, t_dec->range, addr_ht, ptr_set, mem); + break; + case LY_TYPE_IDENT: + orig_type_identref = (const struct lysc_type_identityref *)orig_type; + t = *mem; + *mem = (char *)*mem + sizeof *orig_type_identref; + t_identref = (struct lysc_type_identityref *)t; + + CTXP_SIZED_ARRAY(orig_type_identref->bases, t_identref->bases, mem); + LY_ARRAY_FOR(orig_type_identref->bases, u) { + /* reference */ + t_identref->bases[u] = orig_type_identref->bases[u]; + ly_set_add(ptr_set, &t_identref->bases[u], 1, NULL); + } + break; + case LY_TYPE_INST: + orig_type_instid = (const struct lysc_type_instanceid *)orig_type; + t = *mem; + *mem = (char *)*mem + sizeof *orig_type_instid; + t_instid = (struct lysc_type_instanceid *)t; + + t_instid->require_instance = orig_type_instid->require_instance; + break; + case LY_TYPE_LEAFREF: + orig_type_lref = (const struct lysc_type_leafref *)orig_type; + t = *mem; + *mem = (char *)*mem + sizeof *orig_type_lref; + t_lref = (struct lysc_type_leafref *)t; + + t_lref->path = *mem; + *mem = (char *)*mem + sizeof *t_lref->path; + ctxp_expr(orig_type_lref->path, t_lref->path, mem); + + CTXP_SIZED_ARRAY(orig_type_lref->prefixes, t_lref->prefixes, mem); + LY_ARRAY_FOR(orig_type_lref->prefixes, u) { + ctxp_prefix(&orig_type_lref->prefixes[u], &t_lref->prefixes[u], addr_ht, ptr_set, mem); + } + + ctxp_type(orig_type_lref->realtype, &t_lref->realtype, addr_ht, ptr_set, mem); + t_lref->require_instance = orig_type_lref->require_instance; + break; + case LY_TYPE_UNION: + orig_type_union = (const struct lysc_type_union *)orig_type; + t = *mem; + *mem = (char *)*mem + sizeof *orig_type_union; + t_union = (struct lysc_type_union *)t; + + CTXP_SIZED_ARRAY(orig_type_union->types, t_union->types, mem); + LY_ARRAY_FOR(orig_type_union->types, u) { + ctxp_type(orig_type_union->types[u], &t_union->types[u], addr_ht, ptr_set, mem); + } + break; + case LY_TYPE_UNKNOWN: + LOGINT(NULL); + break; + } + + /* common members */ + t->name = ly_ctx_compiled_addr_ht_get(addr_ht, orig_type->name, 0); + + CTXP_SIZED_ARRAY(orig_type->exts, t->exts, mem); + LY_ARRAY_FOR(orig_type->exts, u) { + ctxp_ext(&orig_type->exts[u], &t->exts[u], addr_ht, ptr_set, mem); + } + + /* static structures in the shared library */ + t->plugin_ref = orig_type->plugin_ref; + + t->basetype = orig_type->basetype; + t->refcount = orig_type->refcount; + + /* shared */ + ly_ctx_compiled_addr_ht_add(addr_ht, orig_type, t); + *type = t; +} + +static void +ctxp_dflt(const struct lysc_value *orig_dflt, struct lysc_value *dflt, struct ly_ht *addr_ht, struct ly_set *ptr_set, + void **mem) +{ + LY_ARRAY_COUNT_TYPE u; + + dflt->str = ly_ctx_compiled_addr_ht_get(addr_ht, orig_dflt->str, 0); + + CTXP_SIZED_ARRAY(orig_dflt->prefixes, dflt->prefixes, mem); + LY_ARRAY_FOR(orig_dflt->prefixes, u) { + ctxp_prefix(&orig_dflt->prefixes[u], &dflt->prefixes[u], addr_ht, ptr_set, mem); + } +} + +static void +ctxp_node(const struct lysc_node *orig_node, struct lysc_node *node, struct ly_ht *addr_ht, struct ly_set *ptr_set, + void **mem) +{ + const struct lysc_node_container *orig_cont; + struct lysc_node_container *cont; + const struct lysc_node_choice *orig_choic; + struct lysc_node_choice *choic; + const struct lysc_node_leaf *orig_leaf; + struct lysc_node_leaf *leaf; + const struct lysc_node_leaflist *orig_llist; + struct lysc_node_leaflist *llist; + const struct lysc_node_list *orig_list; + struct lysc_node_list *list; + const struct lysc_node_anydata *orig_any; + struct lysc_node_anydata *any; + const struct lysc_node_case *orig_cas; + struct lysc_node_case *cas; + const struct lysc_node_action *orig_act; + struct lysc_node_action *act; + const struct lysc_node_notif *orig_notif; + struct lysc_node_notif *notif; + LY_ARRAY_COUNT_TYPE u, v; + + /* + * common members + */ + node->nodetype = orig_node->nodetype; + node->flags = orig_node->flags; + memcpy(node->hash, orig_node->hash, sizeof node->hash); + + /* pointers, references */ + node->module = ly_ctx_compiled_addr_ht_get(addr_ht, orig_node->module, 0); + node->parent = ly_ctx_compiled_addr_ht_get(addr_ht, orig_node->parent, 0); + node->next = orig_node->next; + ly_set_add(ptr_set, &node->next, 1, NULL); + node->prev = orig_node->prev; + ly_set_add(ptr_set, &node->prev, 1, NULL); + + /* strings */ + node->name = ly_ctx_compiled_addr_ht_get(addr_ht, orig_node->name, 0); + node->dsc = ly_ctx_compiled_addr_ht_get(addr_ht, orig_node->dsc, 0); + node->ref = ly_ctx_compiled_addr_ht_get(addr_ht, orig_node->ref, 0); + + /* exts */ + CTXP_SIZED_ARRAY(orig_node->exts, node->exts, mem); + LY_ARRAY_FOR(orig_node->exts, u) { + ctxp_ext(&orig_node->exts[u], &node->exts[u], addr_ht, ptr_set, mem); + } + + /* priv */ + node->priv = NULL; + + switch (orig_node->nodetype) { + case LYS_CONTAINER: + orig_cont = (const struct lysc_node_container *)orig_node; + cont = (struct lysc_node_container *)node; + + /* children */ + ctxp_children(orig_cont->child, &cont->child, addr_ht, ptr_set, mem); + + /* musts */ + CTXP_SIZED_ARRAY(orig_cont->musts, cont->musts, mem); + LY_ARRAY_FOR(orig_cont->musts, u) { + ctxp_must(&orig_cont->musts[u], &cont->musts[u], addr_ht, ptr_set, mem); + } + + /* when */ + CTXP_SIZED_ARRAY(orig_cont->when, cont->when, mem); + LY_ARRAY_FOR(orig_cont->when, u) { + ctxp_when(orig_cont->when[u], &cont->when[u], addr_ht, ptr_set, mem); + } + + /* actions, notifs */ + ctxp_children((const struct lysc_node *)orig_cont->actions, (struct lysc_node **)&cont->actions, addr_ht, + ptr_set, mem); + ctxp_children((const struct lysc_node *)orig_cont->notifs, (struct lysc_node **)&cont->notifs, addr_ht, ptr_set, + mem); + break; + case LYS_CHOICE: + orig_choic = (const struct lysc_node_choice *)orig_node; + choic = (struct lysc_node_choice *)node; + + /* cases */ + ctxp_children((const struct lysc_node *)orig_choic->cases, (struct lysc_node **)&choic->cases, addr_ht, ptr_set, + mem); + + /* when */ + CTXP_SIZED_ARRAY(orig_choic->when, choic->when, mem); + LY_ARRAY_FOR(orig_choic->when, u) { + ctxp_when(orig_choic->when[u], &choic->when[u], addr_ht, ptr_set, mem); + } + + /* dflt */ + choic->dflt = orig_choic->dflt; + ly_set_add(ptr_set, &choic->dflt, 1, NULL); + break; + case LYS_LEAF: + orig_leaf = (const struct lysc_node_leaf *)orig_node; + leaf = (struct lysc_node_leaf *)node; + + /* musts */ + CTXP_SIZED_ARRAY(orig_leaf->musts, leaf->musts, mem); + LY_ARRAY_FOR(orig_leaf->musts, u) { + ctxp_must(&orig_leaf->musts[u], &leaf->musts[u], addr_ht, ptr_set, mem); + } + + /* when */ + CTXP_SIZED_ARRAY(orig_leaf->when, leaf->when, mem); + LY_ARRAY_FOR(orig_leaf->when, u) { + ctxp_when(orig_leaf->when[u], &leaf->when[u], addr_ht, ptr_set, mem); + } + + /* type */ + ctxp_type(orig_leaf->type, &leaf->type, addr_ht, ptr_set, mem); + + /* dflt */ + ctxp_dflt(&orig_leaf->dflt, &leaf->dflt, addr_ht, ptr_set, mem); + break; + case LYS_LEAFLIST: + orig_llist = (const struct lysc_node_leaflist *)orig_node; + llist = (struct lysc_node_leaflist *)node; + + /* musts */ + CTXP_SIZED_ARRAY(orig_llist->musts, llist->musts, mem); + LY_ARRAY_FOR(orig_llist->musts, u) { + ctxp_must(&orig_llist->musts[u], &llist->musts[u], addr_ht, ptr_set, mem); + } + + /* when */ + CTXP_SIZED_ARRAY(orig_llist->when, llist->when, mem); + LY_ARRAY_FOR(orig_llist->when, u) { + ctxp_when(orig_llist->when[u], &llist->when[u], addr_ht, ptr_set, mem); + } + + /* type */ + ctxp_type(orig_llist->type, &llist->type, addr_ht, ptr_set, mem); + + /* dflts */ + CTXP_SIZED_ARRAY(orig_llist->dflts, llist->dflts, mem); + LY_ARRAY_FOR(orig_llist->dflts, u) { + ctxp_dflt(&orig_llist->dflts[u], &llist->dflts[u], addr_ht, ptr_set, mem); + } + + /* min, max */ + llist->min = orig_llist->min; + llist->max = orig_llist->max; + break; + case LYS_LIST: + orig_list = (const struct lysc_node_list *)orig_node; + list = (struct lysc_node_list *)node; + + /* children */ + ctxp_children(orig_list->child, &list->child, addr_ht, ptr_set, mem); + + /* musts */ + CTXP_SIZED_ARRAY(orig_list->musts, list->musts, mem); + LY_ARRAY_FOR(orig_list->musts, u) { + ctxp_must(&orig_list->musts[u], &list->musts[u], addr_ht, ptr_set, mem); + } + + /* when */ + CTXP_SIZED_ARRAY(orig_list->when, list->when, mem); + LY_ARRAY_FOR(orig_list->when, u) { + ctxp_when(orig_list->when[u], &list->when[u], addr_ht, ptr_set, mem); + } + + /* actions, notifs */ + ctxp_children((const struct lysc_node *)orig_list->actions, (struct lysc_node **)&list->actions, addr_ht, + ptr_set, mem); + ctxp_children((const struct lysc_node *)orig_list->notifs, (struct lysc_node **)&list->notifs, addr_ht, ptr_set, + mem); + + /* uniques */ + CTXP_SIZED_ARRAY(orig_list->uniques, list->uniques, mem); + LY_ARRAY_FOR(orig_list->uniques, u) { + CTXP_SIZED_ARRAY(orig_list->uniques[u], list->uniques[u], mem); + LY_ARRAY_FOR(orig_list->uniques[u], v) { + list->uniques[u][v] = ly_ctx_compiled_addr_ht_get(addr_ht, orig_list->uniques[u][v], 0); + } + } + + /* min, max */ + list->min = orig_list->min; + list->max = orig_list->max; + break; + case LYS_ANYXML: + case LYS_ANYDATA: + orig_any = (const struct lysc_node_anydata *)orig_node; + any = (struct lysc_node_anydata *)node; + + /* musts */ + CTXP_SIZED_ARRAY(orig_any->musts, any->musts, mem); + LY_ARRAY_FOR(orig_any->musts, u) { + ctxp_must(&orig_any->musts[u], &any->musts[u], addr_ht, ptr_set, mem); + } + + /* when */ + CTXP_SIZED_ARRAY(orig_any->when, any->when, mem); + LY_ARRAY_FOR(orig_any->when, u) { + ctxp_when(orig_any->when[u], &any->when[u], addr_ht, ptr_set, mem); + } + break; + case LYS_CASE: + orig_cas = (const struct lysc_node_case *)orig_node; + cas = (struct lysc_node_case *)node; + + /* children */ + ctxp_children(orig_cas->child, &cas->child, addr_ht, ptr_set, mem); + + /* when */ + CTXP_SIZED_ARRAY(orig_cas->when, cas->when, mem); + LY_ARRAY_FOR(orig_cas->when, u) { + ctxp_when(orig_cas->when[u], &cas->when[u], addr_ht, ptr_set, mem); + } + break; + case LYS_RPC: + case LYS_ACTION: + orig_act = (const struct lysc_node_action *)orig_node; + act = (struct lysc_node_action *)node; + + /* when */ + CTXP_SIZED_ARRAY(orig_act->when, act->when, mem); + LY_ARRAY_FOR(orig_act->when, u) { + ctxp_when(orig_act->when[u], &act->when[u], addr_ht, ptr_set, mem); + } + + /* input */ + ly_ctx_compiled_addr_ht_add(addr_ht, &orig_act->input, &act->input); + + /* the input itself, just to fill the common members */ + ctxp_node(&orig_act->input.node, &act->input.node, addr_ht, ptr_set, mem); + + /* input children */ + ctxp_children(orig_act->input.child, &act->input.child, addr_ht, ptr_set, mem); + + /* input musts */ + CTXP_SIZED_ARRAY(orig_act->input.musts, act->input.musts, mem); + LY_ARRAY_FOR(orig_act->input.musts, u) { + ctxp_must(&orig_act->input.musts[u], &act->input.musts[u], addr_ht, ptr_set, mem); + } + + /* output */ + ly_ctx_compiled_addr_ht_add(addr_ht, &orig_act->output, &act->output); + + /* the output itself, just to fill the common members */ + ctxp_node(&orig_act->output.node, &act->output.node, addr_ht, ptr_set, mem); + + /* output children */ + ctxp_children(orig_act->output.child, &act->output.child, addr_ht, ptr_set, mem); + + /* output musts */ + CTXP_SIZED_ARRAY(orig_act->output.musts, act->output.musts, mem); + LY_ARRAY_FOR(orig_act->output.musts, u) { + ctxp_must(&orig_act->output.musts[u], &act->output.musts[u], addr_ht, ptr_set, mem); + } + break; + case LYS_NOTIF: + orig_notif = (const struct lysc_node_notif *)orig_node; + notif = (struct lysc_node_notif *)node; + + /* children */ + ctxp_children(orig_notif->child, ¬if->child, addr_ht, ptr_set, mem); + + /* musts */ + CTXP_SIZED_ARRAY(orig_notif->musts, notif->musts, mem); + LY_ARRAY_FOR(orig_notif->musts, u) { + ctxp_must(&orig_notif->musts[u], ¬if->musts[u], addr_ht, ptr_set, mem); + } + + /* when */ + CTXP_SIZED_ARRAY(orig_notif->when, notif->when, mem); + LY_ARRAY_FOR(orig_notif->when, u) { + ctxp_when(orig_notif->when[u], ¬if->when[u], addr_ht, ptr_set, mem); + } + break; + case LYS_INPUT: + case LYS_OUTPUT: + /* nothing to do, only the common members were filled */ + break; + default: + LOGINT(NULL); + break; + } +} + +static void +ctxp_compiled(const struct lysc_module *orig_compiled, struct lysc_module *compiled, struct ly_ht *addr_ht, + struct ly_set *ptr_set, void **mem) +{ + LY_ARRAY_COUNT_TYPE u; + + if (orig_compiled->exts) { + /* may be referenced in the parent */ + ly_ctx_compiled_addr_ht_add(addr_ht, orig_compiled, compiled); + } + + /* mod */ + compiled->mod = ly_ctx_compiled_addr_ht_get(addr_ht, orig_compiled->mod, 0); + + /* features */ + CTXP_SIZED_ARRAY(orig_compiled->features, compiled->features, mem); + LY_ARRAY_FOR(orig_compiled->features, u) { + compiled->features[u] = ly_ctx_compiled_addr_ht_get(addr_ht, orig_compiled->features[u], 0); + } + + /* data, referenced */ + ctxp_children(orig_compiled->data, &compiled->data, addr_ht, ptr_set, mem); + + /* rpcs, referenced */ + ctxp_children((const struct lysc_node *)orig_compiled->rpcs, (struct lysc_node **)&compiled->rpcs, addr_ht, ptr_set, mem); + + /* notifs, referenced */ + ctxp_children((const struct lysc_node *)orig_compiled->notifs, (struct lysc_node **)&compiled->notifs, addr_ht, ptr_set, mem); + + /* exts */ + CTXP_SIZED_ARRAY(orig_compiled->exts, compiled->exts, mem); + LY_ARRAY_FOR(orig_compiled->exts, u) { + ctxp_ext(&orig_compiled->exts[u], &compiled->exts[u], addr_ht, ptr_set, mem); + } +} + +static void +ctxp_extension(const struct lysc_ext *orig_extension, struct lysc_ext *extension, struct ly_ht *addr_ht, + struct ly_set *ptr_set, void **mem) +{ + LY_ARRAY_COUNT_TYPE u; + + extension->name = ly_ctx_compiled_addr_ht_get(addr_ht, orig_extension->name, 0); + extension->argname = ly_ctx_compiled_addr_ht_get(addr_ht, orig_extension->argname, 0); + + CTXP_SIZED_ARRAY(orig_extension->exts, extension->exts, mem); + LY_ARRAY_FOR(orig_extension->exts, u) { + ctxp_ext(&orig_extension->exts[u], &extension->exts[u], addr_ht, ptr_set, mem); + } + + /* static structures in the shared library */ + extension->plugin_ref = orig_extension->plugin_ref; + + extension->module = ly_ctx_compiled_addr_ht_get(addr_ht, orig_extension->module, 0); + extension->flags = orig_extension->flags; +} + +static void +ctxp_identity(const struct lysc_ident *orig_ident, struct lysc_ident *ident, struct ly_ht *addr_ht, + struct ly_set *ptr_set, void **mem) +{ + LY_ARRAY_COUNT_TYPE u; + + ident->name = ly_ctx_compiled_addr_ht_get(addr_ht, orig_ident->name, 0); + ident->dsc = ly_ctx_compiled_addr_ht_get(addr_ht, orig_ident->dsc, 0); + ident->ref = ly_ctx_compiled_addr_ht_get(addr_ht, orig_ident->ref, 0); + ident->module = ly_ctx_compiled_addr_ht_get(addr_ht, orig_ident->module, 0); + + /* reference */ + CTXP_SIZED_ARRAY(orig_ident->derived, ident->derived, mem); + LY_ARRAY_FOR(orig_ident->derived, u) { + ident->derived[u] = orig_ident->derived[u]; + ly_set_add(ptr_set, &ident->derived[u], 1, NULL); + } + + CTXP_SIZED_ARRAY(orig_ident->exts, ident->exts, mem); + LY_ARRAY_FOR(orig_ident->exts, u) { + ctxp_ext(&orig_ident->exts[u], &ident->exts[u], addr_ht, ptr_set, mem); + } + + ident->flags = orig_ident->flags; +} + +static void +ctxp_submodule(const struct lysc_submodule *orig_submod, struct lysc_submodule *submod, struct ly_ht *addr_ht) +{ + submod->name = ly_ctx_compiled_addr_ht_get(addr_ht, orig_submod->name, 0); + submod->revision = ly_ctx_compiled_addr_ht_get(addr_ht, orig_submod->revision, 0); + submod->filepath = ly_ctx_compiled_addr_ht_get(addr_ht, orig_submod->filepath, 0); +} + +static void +ctxp_module(const struct lys_module *orig_mod, struct lys_module *mod, struct ly_ht *addr_ht, struct ly_set *ptr_set, + void **mem) +{ + LY_ARRAY_COUNT_TYPE u; + + /* ctx */ + mod->ctx = ly_ctx_compiled_addr_ht_get(addr_ht, orig_mod->ctx, 0); + + /* strings */ + mod->name = ly_ctx_compiled_addr_ht_get(addr_ht, orig_mod->name, 0); + mod->revision = ly_ctx_compiled_addr_ht_get(addr_ht, orig_mod->revision, 0); + mod->ns = ly_ctx_compiled_addr_ht_get(addr_ht, orig_mod->ns, 0); + mod->prefix = ly_ctx_compiled_addr_ht_get(addr_ht, orig_mod->prefix, 0); + mod->filepath = ly_ctx_compiled_addr_ht_get(addr_ht, orig_mod->filepath, 0); + mod->org = ly_ctx_compiled_addr_ht_get(addr_ht, orig_mod->org, 0); + mod->contact = ly_ctx_compiled_addr_ht_get(addr_ht, orig_mod->contact, 0); + mod->dsc = ly_ctx_compiled_addr_ht_get(addr_ht, orig_mod->dsc, 0); + mod->ref = ly_ctx_compiled_addr_ht_get(addr_ht, orig_mod->ref, 0); + + /* no parsed modules */ + mod->parsed = NULL; + + /* compiled */ + CTXP_OPTIONAL_STRUCT(ctxp_compiled, orig_mod->compiled, mod->compiled, addr_ht, ptr_set, mem); + + /* extensions, referenced */ + CTXP_SIZED_ARRAY(orig_mod->extensions, mod->extensions, mem); + LY_ARRAY_FOR(orig_mod->extensions, u) { + ly_ctx_compiled_addr_ht_add(addr_ht, &orig_mod->extensions[u], &mod->extensions[u]); + ctxp_extension(&orig_mod->extensions[u], &mod->extensions[u], addr_ht, ptr_set, mem); + } + + /* identities, referenced */ + CTXP_SIZED_ARRAY(orig_mod->identities, mod->identities, mem); + LY_ARRAY_FOR(orig_mod->identities, u) { + ly_ctx_compiled_addr_ht_add(addr_ht, &orig_mod->identities[u], &mod->identities[u]); + ctxp_identity(&orig_mod->identities[u], &mod->identities[u], addr_ht, ptr_set, mem); + } + + /* submodules */ + CTXP_SIZED_ARRAY(orig_mod->submodules, mod->submodules, mem); + LY_ARRAY_FOR(orig_mod->submodules, u) { + ctxp_submodule(&orig_mod->submodules[u], &mod->submodules[u], addr_ht); + } + + /* augmented_by, reference */ + CTXP_SIZED_ARRAY(orig_mod->augmented_by, mod->augmented_by, mem); + LY_ARRAY_FOR(orig_mod->augmented_by, u) { + mod->augmented_by[u] = orig_mod->augmented_by[u]; + ly_set_add(ptr_set, &mod->augmented_by[u], 1, NULL); + } + + /* deviated_by, reference */ + CTXP_SIZED_ARRAY(orig_mod->deviated_by, mod->deviated_by, mem); + LY_ARRAY_FOR(orig_mod->deviated_by, u) { + mod->deviated_by[u] = orig_mod->deviated_by[u]; + ly_set_add(ptr_set, &mod->deviated_by[u], 1, NULL); + } + + /* flags */ + mod->implemented = orig_mod->implemented; + mod->to_compile = orig_mod->to_compile; + mod->latest_revision = orig_mod->latest_revision; +} + +void +ly_ctx_compiled_print_context(const struct ly_ctx *orig_ctx, struct ly_ctx *ctx, struct ly_ht *addr_ht, + struct ly_set *ptr_set, void **mem) +{ + uint32_t i; + + /* dictionary */ + ctx->dict.hash_tab = *mem; + *mem = (char *)*mem + sizeof *ctx->dict.hash_tab; + + ctxp_dict_ht(orig_ctx->dict.hash_tab, ctx->dict.hash_tab, addr_ht, mem); + ctxp_mutex(&ctx->dict.lock); + + /* no search paths */ + memset(&ctx->search_paths, 0, sizeof ctx->search_paths); + + /* modules, referenced, 2 loops because of augments (forward reference) */ + ctxp_set(&orig_ctx->modules, &ctx->modules, mem); + for (i = 0; i < ctx->modules.count; ++i) { + /* allocate the shared module and store its new address in HT so it can be referenced */ + ctx->modules.objs[i] = *mem; + *mem = (char *)*mem + sizeof(struct lys_module); + ly_ctx_compiled_addr_ht_add(addr_ht, orig_ctx->modules.objs[i], ctx->modules.objs[i]); + } + for (i = 0; i < ctx->modules.count; ++i) { + /* parse the modules */ + ctxp_module(orig_ctx->modules.objs[i], ctx->modules.objs[i], addr_ht, ptr_set, mem); + } + + /* no imp cb */ + ctx->imp_clb = NULL; + ctx->imp_clb_data = NULL; + + /* no unres */ + memset(&ctx->unres, 0, sizeof ctx->unres); + + /* change_count and options */ + ctx->change_count = orig_ctx->change_count; + ctx->opts = orig_ctx->opts; + + /* ctx hash */ + ctx->mod_hash = orig_ctx->mod_hash; + + /* no dynamic plugin support */ + memset(&ctx->plugins_types, 0, sizeof ctx->plugins_types); + memset(&ctx->plugins_extensions, 0, sizeof ctx->plugins_extensions); +} + +LY_ERR +ly_ctx_compiled_ext_stmts_storage_print(const struct lysc_ext_substmt *orig_substmts, struct lysc_ext_substmt *substmts, + struct ly_ht *addr_ht, struct ly_set *ptr_set, void **mem) +{ + LY_ERR rc = LY_SUCCESS; + LY_ARRAY_COUNT_TYPE u, v; + const struct lysc_node *node; + + LY_ARRAY_FOR(orig_substmts, u) { + assert(orig_substmts[u].stmt == substmts[u].stmt); + + if (!orig_substmts[u].storage_p) { + /* nothing is compiled */ + continue; + } + + switch (orig_substmts[u].stmt) { + case LY_STMT_NOTIFICATION: + case LY_STMT_INPUT: + case LY_STMT_OUTPUT: + case LY_STMT_ACTION: + case LY_STMT_RPC: + case LY_STMT_ANYDATA: + case LY_STMT_ANYXML: + case LY_STMT_CASE: + case LY_STMT_CHOICE: + case LY_STMT_CONTAINER: + case LY_STMT_LEAF: + case LY_STMT_LEAF_LIST: + case LY_STMT_LIST: + case LY_STMT_USES: + node = *(const struct lysc_node **)orig_substmts[u].storage_p; + + /* ht check, make sure the node list is stored only once */ + if (ly_ctx_compiled_addr_ht_get(addr_ht, node, 1)) { + break; + } + + ctxp_children(node, (struct lysc_node **)substmts[u].storage_p, addr_ht, ptr_set, mem); + break; + case LY_STMT_ARGUMENT: + case LY_STMT_CONTACT: + case LY_STMT_DESCRIPTION: + case LY_STMT_ERROR_APP_TAG: + case LY_STMT_ERROR_MESSAGE: + case LY_STMT_KEY: + case LY_STMT_MODIFIER: + case LY_STMT_NAMESPACE: + case LY_STMT_ORGANIZATION: + case LY_STMT_PRESENCE: + case LY_STMT_REFERENCE: + case LY_STMT_UNITS: + /* string, in the dictionary */ + *substmts[u].storage_p = ly_ctx_compiled_addr_ht_get(addr_ht, *orig_substmts[u].storage_p, 0); + break; + case LY_STMT_BIT: + case LY_STMT_ENUM: { + const struct lysc_type_bitenum_item *orig_enums = *orig_substmts[u].storage_p; + struct lysc_type_bitenum_item *enums = *substmts[u].storage_p; + + CTXP_SIZED_ARRAY(orig_enums, enums, mem); + LY_ARRAY_FOR(orig_enums, v) { + ctxp_enum(&orig_enums[v], &enums[v], addr_ht, ptr_set, mem); + } + break; + } + case LY_STMT_CONFIG: + case LY_STMT_MANDATORY: + case LY_STMT_ORDERED_BY: + case LY_STMT_STATUS: + memcpy(orig_substmts[u].storage_p, substmts[u].storage_p, sizeof(uint16_t)); + break; + case LY_STMT_EXTENSION_INSTANCE: { + const struct lysc_ext_instance *orig_exts = *orig_substmts[u].storage_p; + struct lysc_ext_instance *exts = *substmts[u].storage_p; + + CTXP_SIZED_ARRAY(orig_exts, exts, mem); + LY_ARRAY_FOR(orig_exts, v) { + ctxp_ext(&orig_exts[v], &exts[v], addr_ht, ptr_set, mem); + } + break; + } + case LY_STMT_FRACTION_DIGITS: + case LY_STMT_REQUIRE_INSTANCE: + memcpy(orig_substmts[u].storage_p, substmts[u].storage_p, sizeof(uint8_t)); + break; + case LY_STMT_IDENTITY: { + const struct lysc_ident *orig_identities = *orig_substmts[u].storage_p; + struct lysc_ident *identities = *substmts[u].storage_p; + + CTXP_SIZED_ARRAY(orig_identities, identities, mem); + LY_ARRAY_FOR(orig_identities, v) { + ctxp_identity(&orig_identities[v], &identities[v], addr_ht, ptr_set, mem); + } + break; + } + case LY_STMT_LENGTH: + case LY_STMT_RANGE: + *substmts[u].storage_p = *mem; + *mem = (char *)*mem + sizeof(struct lysc_range); + ctxp_range(*orig_substmts[u].storage_p, *substmts[u].storage_p, addr_ht, ptr_set, mem); + break; + case LY_STMT_MAX_ELEMENTS: + case LY_STMT_MIN_ELEMENTS: + memcpy(orig_substmts[u].storage_p, substmts[u].storage_p, sizeof(uint32_t)); + break; + case LY_STMT_MUST: { + const struct lysc_must *orig_musts = *orig_substmts[u].storage_p; + struct lysc_must *musts = *substmts[u].storage_p; + + CTXP_SIZED_ARRAY(orig_musts, musts, mem); + LY_ARRAY_FOR(orig_musts, v) { + ctxp_must(&orig_musts[v], &musts[v], addr_ht, ptr_set, mem); + } + break; + } + case LY_STMT_PATTERN: { + const struct lysc_pattern **orig_patterns = *orig_substmts[u].storage_p; + struct lysc_pattern **patterns = *substmts[u].storage_p; + + CTXP_SIZED_ARRAY(orig_patterns, patterns, mem); + LY_ARRAY_FOR(orig_patterns, v) { + ctxp_pattern(orig_patterns[v], &patterns[v], addr_ht, ptr_set, mem); + } + break; + } + case LY_STMT_POSITION: + case LY_STMT_VALUE: + memcpy(orig_substmts[u].storage_p, substmts[u].storage_p, sizeof(uint64_t)); + break; + case LY_STMT_TYPE: + ctxp_type(*orig_substmts[u].storage_p, (struct lysc_type **)substmts[u].storage_p, addr_ht, ptr_set, mem); + break; + case LY_STMT_WHEN: + ctxp_when(*orig_substmts[u].storage_p, (struct lysc_when **)substmts[u].storage_p, addr_ht, ptr_set, mem); + break; + case LY_STMT_IF_FEATURE: + /* not compiled, but can be a substatement */ + break; + case LY_STMT_NONE: + case LY_STMT_AUGMENT: + case LY_STMT_GROUPING: + case LY_STMT_BASE: + case LY_STMT_BELONGS_TO: + case LY_STMT_DEFAULT: + case LY_STMT_DEVIATE: + case LY_STMT_DEVIATION: + case LY_STMT_EXTENSION: + case LY_STMT_FEATURE: + case LY_STMT_IMPORT: + case LY_STMT_INCLUDE: + case LY_STMT_MODULE: + case LY_STMT_PATH: + case LY_STMT_PREFIX: + case LY_STMT_REFINE: + case LY_STMT_REVISION: + case LY_STMT_REVISION_DATE: + case LY_STMT_SUBMODULE: + case LY_STMT_TYPEDEF: + case LY_STMT_UNIQUE: + case LY_STMT_YANG_VERSION: + case LY_STMT_YIN_ELEMENT: + case LY_STMT_SYNTAX_SEMICOLON: + case LY_STMT_SYNTAX_LEFT_BRACE: + case LY_STMT_SYNTAX_RIGHT_BRACE: + case LY_STMT_ARG_TEXT: + case LY_STMT_ARG_VALUE: + /* not compiled, unreachable */ + LOGINT(NULL); + rc = LY_EINT; + goto cleanup; + } + } + +cleanup: + return rc; +} + +void * +ly_ctx_compiled_addr_ht_get(const struct ly_ht *addr_ht, const void *addr, ly_bool ignore_not_found) +{ + struct ctxp_ht_addr val = {0}, *val_p; + uint32_t hash; + + if (!addr) { + return NULL; + } + + val.orig_addr = addr; + hash = lyht_hash((const char *)&addr, sizeof addr); + + /* try to find the orig_addr */ + if (lyht_find(addr_ht, &val, hash, (void **)&val_p) == LY_ENOTFOUND) { + if (!ignore_not_found) { + assert(0); + LOGINT(NULL); + } + return NULL; + } + + return (void *)val_p->addr; +} + +LY_ERR +ly_ctx_compiled_addr_ht_add(struct ly_ht *addr_ht, const void *orig_addr, const void *addr) +{ + struct ctxp_ht_addr val; + uint32_t hash; + + val.orig_addr = orig_addr; + val.addr = addr; + hash = lyht_hash((const char *)&orig_addr, sizeof orig_addr); + + /* insert the value */ + return lyht_insert(addr_ht, &val, hash, NULL); +} diff --git a/src/printer_json.c b/src/printer_json.c index 233bc0254..d2b270f6c 100644 --- a/src/printer_json.c +++ b/src/printer_json.c @@ -25,6 +25,7 @@ #include "out_internal.h" #include "parser_data.h" #include "plugins_exts/metadata.h" +#include "plugins_internal.h" #include "plugins_types.h" #include "printer_data.h" #include "printer_internal.h" @@ -327,8 +328,8 @@ json_print_member2(struct jsonpr_ctx *pctx, const struct lyd_node *parent, LY_VA name_str = ""; } - /* print the member */ - if (module_name && (!parent || (node_prefix(parent) != module_name))) { + /* print the member, strcmp because node prefix is in the schema dict, module_name in data dict */ + if (module_name && (!parent || strcmp(node_prefix(parent), module_name))) { ly_print_(pctx->out, "%*s\"%s%s:%s\":%s", INDENT, is_attr ? "@" : "", module_name, name_str, DO_FORMAT ? " " : ""); } else { ly_print_(pctx->out, "%*s\"%s%s\":%s", INDENT, is_attr ? "@" : "", name_str, DO_FORMAT ? " " : ""); @@ -354,7 +355,7 @@ json_print_value(struct jsonpr_ctx *pctx, const struct ly_ctx *ctx, const struct LY_DATA_TYPE basetype; const char *value; - value = val->realtype->plugin->print(ctx, val, LY_VALUE_JSON, (void *)local_mod, &dynamic, NULL); + value = LYSC_GET_TYPE_PLG(val->realtype->plugin_ref)->print(ctx, val, LY_VALUE_JSON, (void *)local_mod, &dynamic, NULL); LY_CHECK_RET(!value, LY_EINVAL); basetype = val->realtype->basetype; diff --git a/src/printer_lyb.c b/src/printer_lyb.c index f13ef1593..b5c29081f 100644 --- a/src/printer_lyb.c +++ b/src/printer_lyb.c @@ -28,6 +28,7 @@ #include "out.h" #include "out_internal.h" #include "plugins_exts/metadata.h" +#include "plugins_internal.h" #include "printer_data.h" #include "printer_internal.h" #include "set.h" @@ -496,9 +497,6 @@ lyb_print_module(struct ly_out *out, const struct lys_module *mod, struct lylyb_ } LY_CHECK_GOTO(rc = lyb_write_number(revision, sizeof revision, out, lybctx), cleanup); - /* fill cached hashes, if not already */ - lyb_cache_module_hash(mod); - cleanup: return rc; } @@ -621,15 +619,18 @@ lyb_print_term_value(struct lyd_node_term *term, struct ly_out *out, struct lyly size_t value_len = 0; int32_t lyb_data_len; lyplg_type_print_clb print; + struct lyplg_type *type_plg; + + assert(term->value.realtype && term->value.realtype->plugin_ref && + LYSC_GET_TYPE_PLG(term->value.realtype->plugin_ref)->print && term->schema); - assert(term->value.realtype && term->value.realtype->plugin && term->value.realtype->plugin->print && - term->schema); + type_plg = LYSC_GET_TYPE_PLG(term->value.realtype->plugin_ref); /* Get length of LYB data to print. */ - lyb_data_len = term->value.realtype->plugin->lyb_data_len; + lyb_data_len = type_plg->lyb_data_len; /* Get value and also print its length only if size is not fixed. */ - print = term->value.realtype->plugin->print; + print = type_plg->print; if (lyb_data_len < 0) { /* Variable-length data. */ @@ -1165,6 +1166,11 @@ lyb_print_node(struct ly_out *out, const struct lyd_node **printed_node, struct } if (node->flags & LYD_EXT) { + /* extension context which may not have hashes generated */ + if (!(LYD_CTX(node)->opts & LY_CTX_LYB_HASHES)) { + LY_CHECK_RET(ly_ctx_set_options((struct ly_ctx *)LYD_CTX(node), LY_CTX_LYB_HASHES)); + } + /* write schema node name */ LY_CHECK_RET(lyb_write_string(node->schema->name, 0, sizeof(uint16_t), out, lybctx->lybctx)); } else { @@ -1250,6 +1256,11 @@ lyb_print_data(struct ly_out *out, const struct lyd_node *root, uint32_t options ret = LY_EINVAL; goto cleanup; } + + if (!(ctx->opts & LY_CTX_LYB_HASHES)) { + /* generate LYB hashes */ + LY_CHECK_GOTO(ret = ly_ctx_set_options((struct ly_ctx *)ctx, LY_CTX_LYB_HASHES), cleanup); + } } /* LYB magic number */ diff --git a/src/printer_tree.c b/src/printer_tree.c index f58ded5f4..951749d3b 100644 --- a/src/printer_tree.c +++ b/src/printer_tree.c @@ -94,6 +94,7 @@ #include "ly_common.h" #include "out_internal.h" #include "plugins_exts.h" +#include "plugins_internal.h" #include "plugins_types.h" #include "printer_internal.h" #include "printer_schema.h" @@ -1862,7 +1863,7 @@ trp_ext_is_present(ly_bool lysc_tree, const void *node) if (lysc_tree) { cn = (const struct lysc_node *)node; LY_ARRAY_FOR(cn->exts, i) { - if (!(cn->exts && cn->exts->def->plugin && cn->exts->def->plugin->printer_ctree)) { + if (!cn->exts[i].def->plugin_ref || !LYSC_GET_EXT_PLG(cn->exts[i].def->plugin_ref)->printer_ctree) { continue; } if (!trp_ext_parent_is_valid(1, &cn->exts[i])) { @@ -1874,7 +1875,7 @@ trp_ext_is_present(ly_bool lysc_tree, const void *node) } else { pn = (const struct lysp_node *)node; LY_ARRAY_FOR(pn->exts, i) { - if (!(pn->exts && pn->exts->record && pn->exts->record->plugin.printer_ptree)) { + if (!pn->exts[i].plugin_ref || !LYSC_GET_EXT_PLG(pn->exts[i].plugin_ref)->printer_ptree) { continue; } if (!trp_ext_parent_is_valid(0, &pn->exts[i])) { @@ -2192,9 +2193,9 @@ tro_set_node_overr(ly_bool lysc_tree, const void *node, ly_bool erase_node_overr } no = &plc->node_overr; if (!plc->ctx && lysc_tree && (ce = trp_ext_is_present(lysc_tree, node))) { - rc = ce->def->plugin->printer_ctree(ce, NULL, &no->flags, &no->add_opts); + rc = LYSC_GET_EXT_PLG(ce->def->plugin_ref)->printer_ctree(ce, NULL, &no->flags, &no->add_opts); } else if (!plc->ctx && (pe = trp_ext_is_present(lysc_tree, node))) { - rc = pe->record->plugin.printer_ptree(pe, NULL, &no->flags, &no->add_opts); + rc = LYSC_GET_EXT_PLG(pe->plugin_ref)->printer_ptree(pe, NULL, &no->flags, &no->add_opts); } else if (plc->ctx) { if (plc->schema && plc->schema->compiled && plc->schema->cn_overr) { rc = plc->schema->cn_overr(node, plc->ctx->plugin_priv, &plc->filtered, &no->flags, &no->add_opts); @@ -2607,7 +2608,7 @@ tro_get_ext_section(struct trt_tree_ctx *tc, void *ext, struct lyspr_tree_ctx *p ret.has_node = plug_ctx->schemas->ctree ? 1 : 0; } else { pe = ext; - ret.section_name = pe->def->name; + ret.section_name = strchr(pe->name, ':') + 1; ret.argument = pe->argument; ret.has_node = plug_ctx->schemas->ptree ? 1 : 0; } @@ -3841,7 +3842,7 @@ trb_ext_iter_next(ly_bool lysc_tree, void *exts, LY_ARRAY_COUNT_TYPE *i) if (lysc_tree) { ce = exts; while (*i < LY_ARRAY_COUNT(ce)) { - if (ce->def->plugin && trp_ext_parent_is_valid(1, &ce[*i])) { + if (ce->def->plugin_ref && trp_ext_parent_is_valid(1, &ce[*i])) { ext = &ce[*i]; break; } @@ -3915,7 +3916,7 @@ tro_ext_printer_tree(ly_bool compiled, void *ext, const struct lyspr_tree_ctx *p if (compiled) { ext_comp = ext; - plugin = ext_comp->def->plugin; + plugin = LYSC_GET_EXT_PLG(ext_comp->def->plugin_ref); if (!plugin->printer_ctree) { *ignore = 1; return LY_SUCCESS; @@ -3923,7 +3924,7 @@ tro_ext_printer_tree(ly_bool compiled, void *ext, const struct lyspr_tree_ctx *p return plugin->printer_ctree(ext, plug_ctx, &flags, &add_opts); } else { ext_pars = ext; - plugin = &ext_pars->record->plugin; + plugin = LYSC_GET_EXT_PLG(ext_pars->plugin_ref); if (!plugin->printer_ptree) { *ignore = 1; return LY_SUCCESS; @@ -4664,7 +4665,7 @@ tree_print_module(struct ly_out *out, const struct lys_module *module, uint32_t } line_length = line_length == 0 ? SIZE_MAX : line_length; - if ((module->ctx->flags & LY_CTX_SET_PRIV_PARSED) && module->compiled) { + if ((module->ctx->opts & LY_CTX_SET_PRIV_PARSED) && module->compiled) { trm_lysc_tree_ctx(module, new_out, line_length, &pc, &tc); } else { trm_lysp_tree_ctx(module, new_out, line_length, &pc, &tc); @@ -4690,7 +4691,7 @@ tree_print_compiled_node(struct ly_out *out, const struct lysc_node *node, uint3 assert(out && node); - if (!(node->module->ctx->flags & LY_CTX_SET_PRIV_PARSED)) { + if (!(node->module->ctx->opts & LY_CTX_SET_PRIV_PARSED)) { return LY_EINVAL; } diff --git a/src/printer_xml.c b/src/printer_xml.c index 3e11fe14b..af9eaeca0 100644 --- a/src/printer_xml.c +++ b/src/printer_xml.c @@ -26,6 +26,7 @@ #include "out_internal.h" #include "parser_data.h" #include "plugins_exts/metadata.h" +#include "plugins_internal.h" #include "plugins_types.h" #include "printer_data.h" #include "printer_internal.h" @@ -233,7 +234,8 @@ xml_print_meta(struct xmlpr_ctx *pctx, const struct lyd_node *node) ly_set_add(&ns_list, NULL, 0, NULL); /* print the value */ - value = meta->value.realtype->plugin->print(LYD_CTX(node), &meta->value, LY_VALUE_XML, &ns_list, &dynamic, NULL); + value = LYSC_GET_TYPE_PLG(meta->value.realtype->plugin_ref)->print(LYD_CTX(node), + &meta->value, LY_VALUE_XML, &ns_list, &dynamic, NULL); /* print namespaces connected with the value's prefixes */ for (i = 1; i < ns_list.count; ++i) { @@ -358,8 +360,8 @@ xml_print_term(struct xmlpr_ctx *pctx, const struct lyd_node_term *node) } /* print the value */ - value = ((struct lysc_node_leaf *)node->schema)->type->plugin->print(LYD_CTX(node), &node->value, LY_VALUE_XML, - &ns_list, &dynamic, NULL); + value = LYSC_GET_TYPE_PLG(((struct lysc_node_leaf *)node->schema)->type->plugin_ref)->print(LYD_CTX(node), + &node->value, LY_VALUE_XML, &ns_list, &dynamic, NULL); LY_CHECK_ERR_GOTO(!value, rc = LY_EINVAL, cleanup); /* print node opening */ diff --git a/src/printer_yang.c b/src/printer_yang.c index 1ed081ed7..033306472 100644 --- a/src/printer_yang.c +++ b/src/printer_yang.c @@ -29,6 +29,7 @@ #include "out.h" #include "out_internal.h" #include "plugins_exts.h" +#include "plugins_internal.h" #include "plugins_types.h" #include "printer_internal.h" #include "printer_schema.h" @@ -294,7 +295,7 @@ yprp_extension_instance(struct lys_ypr_ctx *pctx, enum ly_stmt substmt, uint8_t ypr_open(pctx->out, flag); - if (ext->def->argname) { + if (ext->argument) { ly_print_(pctx->out, "%*s%s \"", INDENT, ext->name); ypr_encode(pctx->out, ext->argument, -1); ly_print_(pctx->out, "\""); @@ -356,6 +357,7 @@ yprc_extension_instances(struct lys_ypr_ctx *pctx, enum ly_stmt substmt, uint8_t { LY_ARRAY_COUNT_TYPE u; ly_bool inner_flag; + struct lyplg_ext *ext_plg; LY_ARRAY_FOR(exts, u) { if ((exts[u].parent_stmt != substmt) || (exts[u].parent_stmt_index != substmt_index)) { @@ -375,8 +377,8 @@ yprc_extension_instances(struct lys_ypr_ctx *pctx, enum ly_stmt substmt, uint8_t inner_flag = 0; yprc_extension_instances(pctx, LY_STMT_EXTENSION_INSTANCE, 0, exts[u].exts, &inner_flag); - if (exts[u].def->plugin && exts[u].def->plugin->printer_info) { - exts[u].def->plugin->printer_info(&pctx->printer_ctx, &exts[u], &inner_flag); + if (exts[u].def->plugin_ref && (ext_plg = LYSC_GET_EXT_PLG(exts[u].def->plugin_ref))->printer_info) { + ext_plg->printer_info(&pctx->printer_ctx, &exts[u], &inner_flag); } LEVEL--; @@ -952,20 +954,6 @@ yprp_type(struct lys_ypr_ctx *pctx, const struct lysp_type *type) ypr_close(pctx, flag); } -static void -yprc_dflt_value(struct lys_ypr_ctx *pctx, const struct ly_ctx *ly_pctx, const struct lyd_value *value, - struct lysc_ext_instance *exts) -{ - ly_bool dynamic; - const char *str; - - str = value->realtype->plugin->print(ly_pctx, value, LY_VALUE_JSON, NULL, &dynamic, NULL); - ypr_substmt(pctx, LY_STMT_DEFAULT, 0, str, 0, exts); - if (dynamic) { - free((void *)str); - } -} - static void yprc_type(struct lys_ypr_ctx *pctx, const struct lysc_type *type) { @@ -1613,8 +1601,8 @@ yprc_leaf(struct lys_ypr_ctx *pctx, const struct lysc_node *node) yprc_must(pctx, &leaf->musts[u], NULL); } - if (leaf->dflt) { - yprc_dflt_value(pctx, node->module->ctx, leaf->dflt, leaf->exts); + if (leaf->dflt.str) { + ypr_substmt(pctx, LY_STMT_DEFAULT, 0, leaf->dflt.str, 0, leaf->exts); } yprc_node_common2(pctx, node, NULL); @@ -1680,7 +1668,7 @@ yprc_leaflist(struct lys_ypr_ctx *pctx, const struct lysc_node *node) yprc_must(pctx, &llist->musts[u], NULL); } LY_ARRAY_FOR(llist->dflts, u) { - yprc_dflt_value(pctx, node->module->ctx, llist->dflts[u], llist->exts); + ypr_substmt(pctx, LY_STMT_DEFAULT, 0, llist->dflts[u].str, 0, llist->exts); } ypr_config(pctx, node->flags, node->exts, NULL); diff --git a/src/printer_yin.c b/src/printer_yin.c index a46037387..57ea6618c 100644 --- a/src/printer_yin.c +++ b/src/printer_yin.c @@ -127,6 +127,7 @@ yprp_extension_instance(struct lys_ypr_ctx *pctx, enum ly_stmt substmt, uint8_t { struct lysp_stmt *stmt; int8_t inner_flag; + struct lysp_ext *ext_def; if ((ext->flags & LYS_INTERNAL) || (ext->parent_stmt != substmt) || (ext->parent_stmt_index != substmt_index)) { return; @@ -135,9 +136,14 @@ yprp_extension_instance(struct lys_ypr_ctx *pctx, enum ly_stmt substmt, uint8_t ypr_close_parent(pctx, flag); inner_flag = 0; - ypr_open(pctx, ext->name, (ext->def->flags & LYS_YINELEM_TRUE) ? NULL : ext->def->argname, ext->argument, inner_flag); + /* we need the definition */ + if (lysp_ext_find_definition(pctx->module->ctx, ext, NULL, &ext_def)) { + return; + } + + ypr_open(pctx, ext->name, (ext_def->flags & LYS_YINELEM_TRUE) ? NULL : ext_def->argname, ext->argument, inner_flag); LEVEL++; - if (ext->def->flags & LYS_YINELEM_TRUE) { + if (ext_def->flags & LYS_YINELEM_TRUE) { const char *prefix, *name, *id; size_t prefix_len, name_len; @@ -146,9 +152,9 @@ yprp_extension_instance(struct lys_ypr_ctx *pctx, enum ly_stmt substmt, uint8_t /* we need to use the same namespace as for the extension instance element */ id = ext->name; ly_parse_nodeid(&id, &prefix, &prefix_len, &name, &name_len); - ly_print_(pctx->out, "%*s<%.*s:%s>", INDENT, (int)prefix_len, prefix, ext->def->argname); + ly_print_(pctx->out, "%*s<%.*s:%s>", INDENT, (int)prefix_len, prefix, ext_def->argname); lyxml_dump_text(pctx->out, ext->argument, 0); - ly_print_(pctx->out, "\n", (int)prefix_len, prefix, ext->def->argname); + ly_print_(pctx->out, "\n", (int)prefix_len, prefix, ext_def->argname); } LY_LIST_FOR(ext->child, stmt) { if (stmt->flags & (LYS_YIN_ATTR | LYS_YIN_ARGUMENT)) { diff --git a/src/schema_compile.c b/src/schema_compile.c index 904f00dad..e8728d4dd 100644 --- a/src/schema_compile.c +++ b/src/schema_compile.c @@ -30,6 +30,7 @@ #include "in.h" #include "log.h" #include "ly_common.h" +#include "lyb.h" #include "parser_schema.h" #include "path.h" #include "plugins.h" @@ -109,55 +110,11 @@ lysc_update_path(struct lysc_ctx *ctx, const struct lys_module *parent_module, c ly_log_location(NULL, NULL, ctx->path, NULL); } -/** - * @brief Fill in the prepared compiled extensions definition structure according to the parsed extension definition. - * - * @param[in] ctx Compile context. - * @param[in] extp Parsed extension instance. - * @param[out] ext Compiled extension definition. - * @return LY_ERR value. - */ -static LY_ERR -lys_compile_extension(struct lysc_ctx *ctx, struct lysp_ext_instance *extp, struct lysc_ext **ext) -{ - LY_ERR ret = LY_SUCCESS; - struct lysp_ext *ep = extp->def; - - if (!ep->compiled) { - lysc_update_path(ctx, NULL, "{extension}"); - lysc_update_path(ctx, NULL, ep->name); - - /* compile the extension definition */ - *ext = ep->compiled = calloc(1, sizeof **ext); - DUP_STRING_GOTO(ctx->ctx, ep->name, (*ext)->name, ret, cleanup); - DUP_STRING_GOTO(ctx->ctx, ep->argname, (*ext)->argname, ret, cleanup); - LY_CHECK_GOTO(ret = lysp_ext_find_definition(ctx->ctx, extp, (const struct lys_module **)&(*ext)->module, NULL), - cleanup); - - /* compile nested extensions */ - COMPILE_EXTS_GOTO(ctx, ep->exts, (*ext)->exts, *ext, ret, cleanup); - - lysc_update_path(ctx, NULL, NULL); - lysc_update_path(ctx, NULL, NULL); - - /* find extension definition plugin */ - (*ext)->plugin = extp->record ? (struct lyplg_ext *)&extp->record->plugin : NULL; - } - - *ext = ep->compiled; - -cleanup: - if (ret) { - lysc_update_path(ctx, NULL, NULL); - lysc_update_path(ctx, NULL, NULL); - } - return ret; -} - LY_ERR lys_compile_ext(struct lysc_ctx *ctx, struct lysp_ext_instance *extp, struct lysc_ext_instance *ext, void *parent) { LY_ERR ret = LY_SUCCESS; + struct lyplg_ext *ext_plg; DUP_STRING_GOTO(ctx->ctx, extp->argument, ext->argument, ret, cleanup); ext->module = ctx->cur_mod; @@ -169,20 +126,20 @@ lys_compile_ext(struct lysc_ctx *ctx, struct lysp_ext_instance *extp, struct lys "{extension}"); lysc_update_path(ctx, NULL, extp->name); - /* compile extension if not already */ - LY_CHECK_GOTO(ret = lys_compile_extension(ctx, extp, &ext->def), cleanup); + /* find the compiled extension definition */ + LY_CHECK_GOTO(ret = lysc_ext_find_definition(ctx->ctx, extp, &ext->def), cleanup); /* compile nested extensions */ COMPILE_EXTS_GOTO(ctx, extp->exts, ext->exts, ext, ret, cleanup); /* compile this extension */ - if (ext->def->plugin && ext->def->plugin->compile) { + if (ext->def->plugin_ref && (ext_plg = LYSC_GET_EXT_PLG(ext->def->plugin_ref))->compile) { if (ext->argument) { lysc_update_path(ctx, ext->module, ext->argument); } - ret = ext->def->plugin->compile(ctx, extp, ext); + ret = ext_plg->compile(ctx, extp, ext); if (ret == LY_ENOT) { - lysc_ext_instance_free(&ctx->free_ctx, ext); + lysc_ext_instance_free(ctx->ctx, ext); } if (ext->argument) { lysc_update_path(ctx, NULL, NULL); @@ -471,7 +428,7 @@ lys_compile_expr_implement(const struct ly_ctx *ctx, const struct lyxp_expr *exp if (!mod->implemented) { /* implement if not implemented */ - imp_f = (ctx->flags & LY_CTX_ENABLE_IMP_FEATURES) ? all_f : NULL; + imp_f = (ctx->opts & LY_CTX_ENABLE_IMP_FEATURES) ? all_f : NULL; LY_CHECK_RET(lys_implement((struct lys_module *)mod, imp_f, unres)); } if (!mod->compiled) { @@ -766,7 +723,7 @@ lys_compile_unres_must(struct lysc_ctx *ctx, const struct lysc_node *node, const * @param[in] items Sized array of bits/enums. */ static void -lys_compile_unres_disabled_bitenum_remove(struct lysf_ctx *ctx, struct lysc_type_bitenum_item *items) +lys_compile_unres_disabled_bitenum_remove(const struct ly_ctx *ctx, struct lysc_type_bitenum_item *items) { LY_ARRAY_COUNT_TYPE u = 0, last_u; @@ -816,7 +773,7 @@ lys_compile_unres_disabled_bitenum(struct lysc_ctx *ctx, struct lysc_node_leaf * if ((t[u]->basetype == LY_TYPE_BITS) || (t[u]->basetype == LY_TYPE_ENUM)) { /* remove all disabled items */ ent = (struct lysc_type_enum *)(t[u]); - lys_compile_unres_disabled_bitenum_remove(&ctx->free_ctx, ent->enums); + lys_compile_unres_disabled_bitenum_remove(ctx->ctx, ent->enums); if (LY_ARRAY_COUNT(ent->enums)) { has_value = 1; @@ -926,32 +883,40 @@ lys_compile_unres_leafref(struct lysc_ctx *ctx, const struct lysc_node *node, st * @param[in] type Type of the default value. * @param[in] dflt Default value. * @param[in] dflt_pmod Parsed module of the @p dflt to resolve possible prefixes. - * @param[in,out] storage Storage for the compiled default value. + * @param[out] value Default value. * @param[in,out] unres Global unres structure for newly implemented modules. * @return LY_ERECOMPILE if the whole dep set needs to be recompiled for the value to be checked. * @return LY_ERR value. */ static LY_ERR lys_compile_unres_dflt(struct lysc_ctx *ctx, struct lysc_node *node, struct lysc_type *type, const char *dflt, - const struct lysp_module *dflt_pmod, struct lyd_value *storage, struct lys_glob_unres *unres) + const struct lysp_module *dflt_pmod, struct lysc_value *value, struct lys_glob_unres *unres) { - LY_ERR ret; + LY_ERR rc = LY_SUCCESS; uint32_t options; - struct lyd_value *val; + struct lyd_value storage = {0}, *val; struct ly_err_item *err = NULL; - - options = (ctx->ctx->flags & LY_CTX_REF_IMPLEMENTED) ? LYPLG_TYPE_STORE_IMPLEMENT : 0; - ret = type->plugin->store(ctx->ctx, type, dflt, strlen(dflt), options, LY_VALUE_SCHEMA, (void *)dflt_pmod, - LYD_HINT_SCHEMA, node, storage, unres, &err); - if (ret == LY_ERECOMPILE) { + LY_VALUE_FORMAT format; + struct lyplg_type *type_plg; + + options = (ctx->ctx->opts & LY_CTX_REF_IMPLEMENTED) ? LYPLG_TYPE_STORE_IMPLEMENT : 0; + type_plg = LYSC_GET_TYPE_PLG(type->plugin_ref); + rc = type_plg->store(ctx->ctx, type, dflt, strlen(dflt), options, LY_VALUE_SCHEMA, (void *)dflt_pmod, + LYD_HINT_SCHEMA, node, &storage, unres, &err); + if (rc == LY_ERECOMPILE) { /* fine, but we need to recompile */ - return LY_ERECOMPILE; - } else if (ret == LY_EINCOMPLETE) { + return rc; + } else if (rc == LY_EINCOMPLETE) { /* we have no data so we will not be resolving it */ - ret = LY_SUCCESS; + rc = LY_SUCCESS; } - if (ret) { + if (!rc) { + /* store the original value with the resolved prefixes */ + LY_CHECK_GOTO(rc = lysdict_insert(ctx->ctx, dflt, 0, &value->str), cleanup); + LY_CHECK_GOTO(rc = lyplg_type_prefix_data_new(ctx->ctx, dflt, strlen(dflt), LY_VALUE_SCHEMA, dflt_pmod, &format, + (void **)&value->prefixes), cleanup); + } else { LOG_LOCSET(node, NULL); if (err) { LOGVAL(ctx->ctx, LYVE_SEMANTICS, "Invalid default - value does not fit the type (%s).", err->msg); @@ -960,14 +925,13 @@ lys_compile_unres_dflt(struct lysc_ctx *ctx, struct lysc_node *node, struct lysc LOGVAL(ctx->ctx, LYVE_SEMANTICS, "Invalid default - value does not fit the type."); } LOG_LOCBACK(1, 0); - return ret; } - LY_ATOMIC_INC_BARRIER(((struct lysc_type *)storage->realtype)->refcount); - if (storage->realtype->basetype == LY_TYPE_UNION) { - val = &storage->subvalue->value; +cleanup: + if (storage.realtype->basetype == LY_TYPE_UNION) { + val = &storage.subvalue->value; } else { - val = storage; + val = &storage; } if (val->realtype->basetype == LY_TYPE_INST) { /* ly_path includes references to other nodes, in case they are in foreign modules, the context would @@ -975,7 +939,8 @@ lys_compile_unres_dflt(struct lysc_ctx *ctx, struct lysc_node *node, struct lysc ly_path_free(val->target); val->target = NULL; } - return LY_SUCCESS; + type_plg->free(ctx->ctx, &storage); + return rc; } /** @@ -991,27 +956,15 @@ static LY_ERR lys_compile_unres_leaf_dlft(struct lysc_ctx *ctx, struct lysc_node_leaf *leaf, struct lysp_qname *dflt, struct lys_glob_unres *unres) { - LY_ERR ret; - - assert(!leaf->dflt); + assert(!leaf->dflt.str); if (leaf->flags & (LYS_MAND_TRUE | LYS_KEY)) { /* ignore default values for keys and mandatory leaves */ return LY_SUCCESS; } - /* allocate the default value */ - leaf->dflt = calloc(1, sizeof *leaf->dflt); - LY_CHECK_ERR_RET(!leaf->dflt, LOGMEM(ctx->ctx), LY_EMEM); - /* store the default value */ - ret = lys_compile_unres_dflt(ctx, &leaf->node, leaf->type, dflt->str, dflt->mod, leaf->dflt, unres); - if (ret) { - free(leaf->dflt); - leaf->dflt = NULL; - } - - return ret; + return lys_compile_unres_dflt(ctx, &leaf->node, leaf->type, dflt->str, dflt->mod, &leaf->dflt, unres); } /** @@ -1028,7 +981,6 @@ static LY_ERR lys_compile_unres_llist_dflts(struct lysc_ctx *ctx, struct lysc_node_leaflist *llist, struct lysp_qname *dflt, struct lysp_qname *dflts, struct lys_glob_unres *unres) { - LY_ERR ret; LY_ARRAY_COUNT_TYPE orig_count, u, v; assert(dflt || dflts); @@ -1042,17 +994,13 @@ lys_compile_unres_llist_dflts(struct lysc_ctx *ctx, struct lysc_node_leaflist *l /* fill each new default value */ if (dflts) { LY_ARRAY_FOR(dflts, u) { - llist->dflts[orig_count + u] = calloc(1, sizeof **llist->dflts); - ret = lys_compile_unres_dflt(ctx, &llist->node, llist->type, dflts[u].str, dflts[u].mod, - llist->dflts[orig_count + u], unres); - LY_CHECK_ERR_RET(ret, free(llist->dflts[orig_count + u]), ret); + LY_CHECK_RET(lys_compile_unres_dflt(ctx, &llist->node, llist->type, dflts[u].str, dflts[u].mod, + &llist->dflts[orig_count + u], unres)); LY_ARRAY_INCREMENT(llist->dflts); } } else { - llist->dflts[orig_count] = calloc(1, sizeof **llist->dflts); - ret = lys_compile_unres_dflt(ctx, &llist->node, llist->type, dflt->str, dflt->mod, - llist->dflts[orig_count], unres); - LY_CHECK_ERR_RET(ret, free(llist->dflts[orig_count]), ret); + LY_CHECK_RET(lys_compile_unres_dflt(ctx, &llist->node, llist->type, dflt->str, dflt->mod, + &llist->dflts[orig_count], unres)); LY_ARRAY_INCREMENT(llist->dflts); } @@ -1061,10 +1009,9 @@ lys_compile_unres_llist_dflts(struct lysc_ctx *ctx, struct lysc_node_leaflist *l /* configuration data values must be unique - so check the default values */ for (u = orig_count; u < LY_ARRAY_COUNT(llist->dflts); ++u) { for (v = 0; v < u; ++v) { - if (!llist->dflts[u]->realtype->plugin->compare(ctx->ctx, llist->dflts[u], llist->dflts[v])) { + if (llist->dflts[u].str == llist->dflts[v].str) { LOGVAL(ctx->ctx, LYVE_SEMANTICS, "Configuration leaf-list has multiple defaults of the same value \"%s\".", - (char *)llist->dflts[u]->realtype->plugin->print(ctx->ctx, llist->dflts[u], LY_VALUE_CANON, - NULL, NULL, NULL)); + llist->dflts[u].str); return LY_EVALID; } } @@ -1172,7 +1119,7 @@ lys_compile_unres_depset_implement(struct ly_ctx *ctx, struct lys_glob_unres *un w = ds_unres->whens.objs[wi]; LY_CHECK_RET(lys_compile_expr_implement(ctx, w->when->cond, LY_VALUE_SCHEMA_RESOLVED, w->when->prefixes, - ctx->flags & LY_CTX_REF_IMPLEMENTED, unres, &mod)); + ctx->opts & LY_CTX_REF_IMPLEMENTED, unres, &mod)); if (mod) { LOGWRN(ctx, "When condition \"%s\" check skipped because referenced module \"%s\" is not implemented.", w->when->cond->expr, mod->name); @@ -1193,7 +1140,7 @@ lys_compile_unres_depset_implement(struct ly_ctx *ctx, struct lys_glob_unres *un musts = lysc_node_musts(m->node); LY_ARRAY_FOR(musts, u) { LY_CHECK_RET(lys_compile_expr_implement(ctx, musts[u].cond, LY_VALUE_SCHEMA_RESOLVED, musts[u].prefixes, - ctx->flags & LY_CTX_REF_IMPLEMENTED, unres, &mod)); + ctx->opts & LY_CTX_REF_IMPLEMENTED, unres, &mod)); if (mod) { LOGWRN(ctx, "Must condition \"%s\" check skipped because referenced module \"%s\" is not implemented.", musts[u].cond->expr, mod->name); @@ -1367,7 +1314,7 @@ lys_compile_unres_depset(struct ly_ctx *ctx, struct lys_glob_unres *unres) typeiter->basetype == LY_TYPE_LEAFREF; typeiter = ((struct lysc_type_leafref *)typeiter)->realtype) {} - lysc_type_free(&cctx.free_ctx, lref->realtype); + lysc_type_free(cctx.ctx, lref->realtype); lref->realtype = typeiter; ++lref->realtype->refcount; } @@ -1453,7 +1400,7 @@ lys_compile_unres_depset(struct ly_ctx *ctx, struct lys_glob_unres *unres) LYSC_CTX_INIT_PMOD(cctx, node->module->parsed, NULL); - lysc_node_free(&cctx.free_ctx, node, 1); + lysc_node_free(cctx.ctx, node, 1); } /* also check if the leafref target has not been disabled */ @@ -1481,7 +1428,6 @@ lys_compile_unres_depset(struct ly_ctx *ctx, struct lys_glob_unres *unres) } cleanup: - assert(!cctx.free_ctx.ext_set.count); return ret; } @@ -1523,7 +1469,6 @@ static LY_ERR lys_compile_depset_r(struct ly_ctx *ctx, struct ly_set *dep_set, struct lys_glob_unres *unres) { LY_ERR ret = LY_SUCCESS; - struct lysf_ctx fctx = {.ctx = ctx}; struct lys_module *mod; uint32_t i; @@ -1536,7 +1481,7 @@ lys_compile_depset_r(struct ly_ctx *ctx, struct ly_set *dep_set, struct lys_glob assert(mod->implemented); /* free the compiled module, if any */ - lysc_module_free(&fctx, mod->compiled); + lysc_module_free(ctx, mod->compiled); mod->compiled = NULL; /* (re)compile the module */ @@ -1570,7 +1515,6 @@ 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); return ret; } @@ -1712,6 +1656,32 @@ lys_compile_unres_mod_erase(struct lysc_ctx *ctx, ly_bool error) } } +/** + * @brief Compile (copy) all enabled features of a parsed module. + * + * @param[in] mod Module with the parsed and compiled module. + * @return LY_ERR value. + */ +static LY_ERR +lys_compile_enabled_features(struct lys_module *mod) +{ + LY_ERR rc = LY_SUCCESS; + struct lysp_feature *f = NULL; + uint32_t idx = 0; + const char **feat_p; + + /* copy enabled features */ + while ((f = lysp_feature_next(f, mod->parsed, &idx))) { + if (f->flags & LYS_FENABLED) { + LY_ARRAY_NEW_GOTO(mod->ctx, mod->compiled->features, feat_p, rc, cleanup); + LY_CHECK_GOTO(rc = lysdict_dup(mod->ctx, f->name, feat_p), cleanup); + } + } + +cleanup: + return rc; +} + LY_ERR lys_compile(struct lys_module *mod, struct lys_depset_unres *unres) { @@ -1736,6 +1706,9 @@ lys_compile(struct lys_module *mod, struct lys_depset_unres *unres) LY_CHECK_ERR_RET(!mod_c, LOGMEM(mod->ctx), LY_EMEM); mod_c->mod = mod; + /* copy the enabled features */ + LY_CHECK_GOTO(ret = lys_compile_enabled_features(mod), cleanup); + /* compile augments and deviations of our module from other modules so they can be applied during compilation */ LY_CHECK_GOTO(ret = lys_precompile_own_augments(&ctx), cleanup); LY_CHECK_GOTO(ret = lys_precompile_own_deviations(&ctx), cleanup); @@ -1821,18 +1794,76 @@ lys_compile(struct lys_module *mod, struct lys_depset_unres *unres) /* finish compilation for all unresolved module items in the context */ LY_CHECK_GOTO(ret = lys_compile_unres_mod(&ctx), cleanup); - ly_ctx_new_change(mod->ctx); + if (mod->ctx->opts & LY_CTX_LYB_HASHES) { + /* generate schema hashes for all the schema nodes */ + lysc_module_dfs_full(mod, lyb_cache_node_hash_cb, NULL); + } cleanup: ly_log_location_revert(0, 0, 1, 0); lys_compile_unres_mod_erase(&ctx, ret); if (ret) { - lysc_module_free(&ctx.free_ctx, mod_c); + lysc_module_free(ctx.ctx, mod_c); mod->compiled = NULL; } return ret; } +LY_ERR +lys_compile_extensions(struct lys_module *mod) +{ + LY_ERR rc = LY_SUCCESS; + struct lysc_ctx ctx = {0}; + LY_ARRAY_COUNT_TYPE u; + struct lysp_ext *ep; + struct lysc_ext *ec; + + if (!mod->parsed->extensions) { + return LY_SUCCESS; + } + + LYSC_CTX_INIT_PMOD(ctx, mod->parsed, NULL); + + /* allocate the array */ + LY_ARRAY_CREATE_RET(mod->ctx, mod->extensions, LY_ARRAY_COUNT(mod->parsed->extensions), LY_EMEM); + + /* compile all extension definitions */ + LY_ARRAY_FOR(mod->parsed->extensions, u) { + ep = &mod->parsed->extensions[u]; + ec = &mod->extensions[u]; + + /* compile the extension definition */ + DUP_STRING_GOTO(ctx.ctx, ep->name, ec->name, rc, cleanup); + DUP_STRING_GOTO(ctx.ctx, ep->argname, ec->argname, rc, cleanup); + ec->module = mod; + ec->plugin_ref = ep->plugin_ref; + + LY_ARRAY_INCREMENT(mod->extensions); + } + + /* compile all nested extension instances, which can reference the compiled definitions */ + LY_ARRAY_FOR(mod->parsed->extensions, u) { + ep = &mod->parsed->extensions[u]; + ec = &mod->extensions[u]; + + lysc_update_path(&ctx, NULL, "{extension}"); + lysc_update_path(&ctx, NULL, ep->name); + + /* compile nested extensions */ + COMPILE_EXTS_GOTO(&ctx, ep->exts, ec->exts, ec, rc, cleanup); + + lysc_update_path(&ctx, NULL, NULL); + lysc_update_path(&ctx, NULL, NULL); + } + +cleanup: + if (rc) { + lysc_update_path(&ctx, NULL, NULL); + lysc_update_path(&ctx, NULL, NULL); + } + return rc; +} + LY_ERR lys_compile_identities(struct lys_module *mod) { diff --git a/src/schema_compile.h b/src/schema_compile.h index 8f67ce361..401443acc 100644 --- a/src/schema_compile.h +++ b/src/schema_compile.h @@ -54,7 +54,6 @@ struct lysc_ctx { struct lys_depset_unres *unres; /**< dependency set unres sets */ uint32_t path_len; /**< number of path bytes used */ uint32_t compile_opts; /**< various @ref scflags. */ - struct lysf_ctx free_ctx; /**< freeing context for errors/recompilation */ #define LYSC_CTX_BUFSIZE 4078 char path[LYSC_CTX_BUFSIZE];/**< Path identifying the schema node currently being processed */ @@ -69,8 +68,7 @@ struct lysc_ctx { #define LYSC_CTX_INIT_CTX(CCTX, CTX) \ (CCTX).ctx = (CTX); \ (CCTX).path_len = 1; \ - (CCTX).path[0] = '/'; \ - (CCTX).free_ctx.ctx = (CTX) + (CCTX).path[0] = '/' /** * @brief Initalize local compilation context using a parsed module. @@ -85,8 +83,7 @@ struct lysc_ctx { (CCTX).pmod = (PMOD); \ (CCTX).ext = (EXT); \ (CCTX).path_len = 1; \ - (CCTX).path[0] = '/'; \ - (CCTX).free_ctx.ctx = (PMOD)->mod->ctx + (CCTX).path[0] = '/' /** * @brief Structure for unresolved items that may depend on any implemented module data in the dependency set @@ -162,9 +159,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_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_STRING(CTX, ORIG, DUP, RET) RET = lysdict_dup(CTX, ORIG, &(DUP)) +#define DUP_STRING_RET(CTX, ORIG, DUP) LY_CHECK_RET(lysdict_dup(CTX, ORIG, &(DUP))) +#define DUP_STRING_GOTO(CTX, ORIG, DUP, RET, GOTO) LY_CHECK_GOTO(RET = lysdict_dup(CTX, ORIG, &(DUP)), GOTO) #define DUP_ARRAY(CTX, ORIG_ARRAY, NEW_ARRAY, DUP_FUNC) \ if (ORIG_ARRAY) { \ @@ -300,13 +297,21 @@ LY_ERR lys_compile_identity_bases(struct lysc_ctx *ctx, const struct lysp_module struct lysc_ident *ident, struct lysc_ident ***bases); /** - * @brief Perform a complet compilation of identites in a module and all its submodules. + * @brief Perform a complete compilation of identites in a module and all its submodules. * * @param[in] mod Module to process. * @return LY_ERR value. */ LY_ERR lys_compile_identities(struct lys_module *mod); +/** + * @brief Compile parsed extension definitions. + * + * @param[in] mod Module to process. + * @return LY_ERR value. + */ +LY_ERR lys_compile_extensions(struct lys_module *mod); + /** * @brief Compile schema into a validated schema linking all the references. Must have been implemented before. * diff --git a/src/schema_compile_amend.c b/src/schema_compile_amend.c index 6179220b3..3a923ba6b 100644 --- a/src/schema_compile_amend.c +++ b/src/schema_compile_amend.c @@ -26,6 +26,7 @@ #include "dict.h" #include "log.h" #include "ly_common.h" +#include "plugins_internal.h" #include "schema_compile.h" #include "schema_compile_node.h" #include "schema_features.h" @@ -53,8 +54,8 @@ lysc_nodeid_free(const struct ly_ctx *ctx, struct lysc_nodeid *nodeid) } for (i = 0; i < nodeid->count; ++i) { - lydict_remove(ctx, nodeid->prefix[i]); - lydict_remove(ctx, nodeid->name[i]); + lysdict_remove(ctx, nodeid->prefix[i]); + lysdict_remove(ctx, nodeid->name[i]); } free(nodeid->prefix); free(nodeid->name); @@ -124,7 +125,7 @@ lys_precompile_nodeid(const struct ly_ctx *ctx, const char *str, struct lysc_nod ptr = ly_strnchr(name, ':', len); if (ptr) { /* store prefix */ - rc = lydict_insert(ctx, name, ptr - name, &(*nodeid)->prefix[(*nodeid)->count - 1]); + rc = lysdict_insert(ctx, name, ptr - name, &(*nodeid)->prefix[(*nodeid)->count - 1]); LY_CHECK_GOTO(rc, cleanup); /* move name */ @@ -133,14 +134,14 @@ lys_precompile_nodeid(const struct ly_ctx *ctx, const char *str, struct lysc_nod } /* store name */ - rc = lydict_insert(ctx, name, len, &(*nodeid)->name[(*nodeid)->count - 1]); + rc = lysdict_insert(ctx, name, len, &(*nodeid)->name[(*nodeid)->count - 1]); LY_CHECK_GOTO(rc, cleanup); ++i; } cleanup: - lyxp_expr_free(ctx, exp); + lyxp_expr_free(exp); if (rc) { lysc_nodeid_free(ctx, *nodeid); *nodeid = NULL; @@ -279,7 +280,7 @@ lys_nodeid_mod_check(struct lysc_ctx *ctx, const char *str, ly_bool abs, struct } cleanup: - lyxp_expr_free(ctx->ctx, e); + lyxp_expr_free(e); lysc_nodeid_free(ctx->ctx, ni); return ret; } @@ -472,24 +473,24 @@ lysp_ext_dup(const struct ly_ctx *ctx, const struct lysp_module *pmod, void *par LY_ERR ret = LY_SUCCESS; struct ly_set pmods = {0}; struct lysp_ctx pctx = {.parsed_mods = &pmods}; + struct lyplg_ext *ext_plg; DUP_STRING_GOTO(ctx, orig_ext->name, ext->name, ret, cleanup); DUP_STRING_GOTO(ctx, orig_ext->argument, ext->argument, ret, cleanup); ext->format = orig_ext->format; LY_CHECK_GOTO(ret = ly_dup_prefix_data(ctx, orig_ext->format, orig_ext->prefix_data, &ext->prefix_data), cleanup); - ext->def = orig_ext->def; + ext->plugin_ref = orig_ext->plugin_ref; ext->parent = parent; ext->parent_stmt = parent_stmt; ext->parent_stmt_index = orig_ext->parent_stmt_index; ext->flags = orig_ext->flags; - ext->record = orig_ext->record; LY_CHECK_GOTO(ret = lysp_ext_children_dup(ctx, orig_ext->child, &ext->child), cleanup); - if (ext->record && ext->record->plugin.parse) { + if (ext->plugin_ref && (ext_plg = LYSC_GET_EXT_PLG(ext->plugin_ref))->parse) { /* parse again */ LY_CHECK_GOTO(ret = ly_set_add(&pmods, pmod, 1, NULL), cleanup); - LY_CHECK_GOTO(ret = ext->record->plugin.parse(&pctx, ext), cleanup); + LY_CHECK_GOTO(ret = ext_plg->parse(&pctx, ext), cleanup); } cleanup: @@ -915,7 +916,7 @@ lys_apply_refine(struct lysc_ctx *ctx, struct lysp_refine *rfn, const struct lys case LYS_LEAF: AMEND_CHECK_CARDINALITY(rfn->dflts, 1, "refine", "default"); - lydict_remove(ctx->ctx, ((struct lysp_node_leaf *)target)->dflt.str); + lysdict_remove(ctx->ctx, ((struct lysp_node_leaf *)target)->dflt.str); LY_CHECK_GOTO(ret = lysp_qname_dup(ctx->ctx, &rfn->dflts[0], &((struct lysp_node_leaf *)target)->dflt), cleanup); break; case LYS_LEAFLIST: @@ -936,7 +937,7 @@ lys_apply_refine(struct lysc_ctx *ctx, struct lysp_refine *rfn, const struct lys case LYS_CHOICE: AMEND_CHECK_CARDINALITY(rfn->dflts, 1, "refine", "default"); - lydict_remove(ctx->ctx, ((struct lysp_node_choice *)target)->dflt.str); + lysdict_remove(ctx->ctx, ((struct lysp_node_choice *)target)->dflt.str); LY_CHECK_GOTO(ret = lysp_qname_dup(ctx->ctx, &rfn->dflts[0], &((struct lysp_node_choice *)target)->dflt), cleanup); break; default: @@ -946,13 +947,13 @@ lys_apply_refine(struct lysc_ctx *ctx, struct lysp_refine *rfn, const struct lys /* description */ if (rfn->dsc) { - lydict_remove(ctx->ctx, target->dsc); + lysdict_remove(ctx->ctx, target->dsc); DUP_STRING_GOTO(ctx->ctx, rfn->dsc, target->dsc, ret, cleanup); } /* reference */ if (rfn->ref) { - lydict_remove(ctx->ctx, target->ref); + lysdict_remove(ctx->ctx, target->ref); DUP_STRING_GOTO(ctx->ctx, rfn->ref, target->ref, ret, cleanup); } @@ -990,7 +991,7 @@ lys_apply_refine(struct lysc_ctx *ctx, struct lysp_refine *rfn, const struct lys AMEND_WRONG_NODETYPE("refine", "replace", "presence"); } - lydict_remove(ctx->ctx, ((struct lysp_node_container *)target)->presence); + lysdict_remove(ctx->ctx, ((struct lysp_node_container *)target)->presence); DUP_STRING_GOTO(ctx->ctx, rfn->presence, ((struct lysp_node_container *)target)->presence, ret, cleanup); } @@ -1344,7 +1345,7 @@ lys_apply_deviate_delete(struct lysc_ctx *ctx, struct lysp_deviate_del *d, struc } DEV_CHECK_PRESENCE_VALUE(struct lysp_node_leaf *, units, "deleting", "units", d->units); - lydict_remove(ctx->ctx, ((struct lysp_node_leaf *)target)->units); + lysdict_remove(ctx->ctx, ((struct lysp_node_leaf *)target)->units); ((struct lysp_node_leaf *)target)->units = NULL; } @@ -1355,7 +1356,7 @@ lys_apply_deviate_delete(struct lysc_ctx *ctx, struct lysp_deviate_del *d, struc AMEND_WRONG_NODETYPE("deviation", "delete", "must"); } - DEV_DEL_ARRAY(musts, *musts, .arg.str, .arg.str, lysp_restr_free, &ctx->free_ctx, "must"); + DEV_DEL_ARRAY(musts, *musts, .arg.str, .arg.str, lysp_restr_free, ctx->ctx, "must"); } /* *unique-stmt */ @@ -1375,7 +1376,7 @@ lys_apply_deviate_delete(struct lysc_ctx *ctx, struct lysp_deviate_del *d, struc AMEND_CHECK_CARDINALITY(d->dflts, 1, "deviation", "default"); DEV_CHECK_PRESENCE_VALUE(struct lysp_node_leaf *, dflt.str, "deleting", "default", d->dflts[0].str); - lydict_remove(ctx->ctx, ((struct lysp_node_leaf *)target)->dflt.str); + lysdict_remove(ctx->ctx, ((struct lysp_node_leaf *)target)->dflt.str); ((struct lysp_node_leaf *)target)->dflt.str = NULL; break; case LYS_LEAFLIST: @@ -1386,7 +1387,7 @@ lys_apply_deviate_delete(struct lysc_ctx *ctx, struct lysp_deviate_del *d, struc AMEND_CHECK_CARDINALITY(d->dflts, 1, "deviation", "default"); DEV_CHECK_PRESENCE_VALUE(struct lysp_node_choice *, dflt.str, "deleting", "default", d->dflts[0].str); - lydict_remove(ctx->ctx, ((struct lysp_node_choice *)target)->dflt.str); + lysdict_remove(ctx->ctx, ((struct lysp_node_choice *)target)->dflt.str); ((struct lysp_node_choice *)target)->dflt.str = NULL; break; default: @@ -1429,7 +1430,7 @@ lys_apply_deviate_replace(struct lysc_ctx *ctx, struct lysp_deviate_rpl *d, stru AMEND_WRONG_NODETYPE("deviation", "replace", "type"); } - lysp_type_free(&ctx->free_ctx, &((struct lysp_node_leaf *)target)->type); + lysp_type_free(ctx->ctx, &((struct lysp_node_leaf *)target)->type); lysp_type_dup(ctx->ctx, ctx->pmod, d->type, &((struct lysp_node_leaf *)target)->type); } @@ -1444,7 +1445,7 @@ lys_apply_deviate_replace(struct lysc_ctx *ctx, struct lysp_deviate_rpl *d, stru } DEV_CHECK_PRESENCE(struct lysp_node_leaf *, units, "replacing", "units", d->units); - lydict_remove(ctx->ctx, ((struct lysp_node_leaf *)target)->units); + lysdict_remove(ctx->ctx, ((struct lysp_node_leaf *)target)->units); DUP_STRING_GOTO(ctx->ctx, d->units, ((struct lysp_node_leaf *)target)->units, ret, cleanup); } @@ -1454,13 +1455,13 @@ lys_apply_deviate_replace(struct lysc_ctx *ctx, struct lysp_deviate_rpl *d, stru case LYS_LEAF: DEV_CHECK_PRESENCE(struct lysp_node_leaf *, dflt.str, "replacing", "default", d->dflt.str); - lydict_remove(ctx->ctx, ((struct lysp_node_leaf *)target)->dflt.str); + lysdict_remove(ctx->ctx, ((struct lysp_node_leaf *)target)->dflt.str); LY_CHECK_GOTO(ret = lysp_qname_dup(ctx->ctx, &d->dflt, &((struct lysp_node_leaf *)target)->dflt), cleanup); break; case LYS_CHOICE: DEV_CHECK_PRESENCE(struct lysp_node_choice *, dflt.str, "replacing", "default", d->dflt.str); - lydict_remove(ctx->ctx, ((struct lysp_node_choice *)target)->dflt.str); + lysdict_remove(ctx->ctx, ((struct lysp_node_choice *)target)->dflt.str); LY_CHECK_GOTO(ret = lysp_qname_dup(ctx->ctx, &d->dflt, &((struct lysp_node_choice *)target)->dflt), cleanup); break; default: @@ -1814,7 +1815,7 @@ lysp_dev_node_free(struct lysc_ctx *cctx, struct lysp_node *dev_pnode) case LYS_INPUT: case LYS_OUTPUT: ((struct lysp_node_action_inout *)dev_pnode)->child = NULL; - lysp_node_free(&cctx->free_ctx, dev_pnode); + lysp_node_free(cctx->ctx, dev_pnode); free(dev_pnode); return; default: @@ -1822,7 +1823,7 @@ lysp_dev_node_free(struct lysc_ctx *cctx, struct lysp_node *dev_pnode) return; } - lysp_node_free(&cctx->free_ctx, dev_pnode); + lysp_node_free(cctx->ctx, dev_pnode); } LY_ERR @@ -2550,7 +2551,7 @@ lys_precompile_augments_deviations(struct lys_module *mod, struct lys_glob_unres if (!m->implemented) { /* implement the target module */ - imp_f = (mod->ctx->flags & LY_CTX_ENABLE_IMP_FEATURES) ? all_f : NULL; + imp_f = (mod->ctx->opts & LY_CTX_ENABLE_IMP_FEATURES) ? all_f : NULL; r = lys_implement(m, imp_f, unres); if (r == LY_ERECOMPILE) { /* implement all the modules right away to save possible later recompilation */ @@ -2581,8 +2582,8 @@ lys_precompile_augments_deviations_revert(struct ly_ctx *ctx, const struct lys_m LY_ARRAY_COUNT_TYPE u, count; struct lys_module *m; - for (i = 0; i < ctx->list.count; ++i) { - m = ctx->list.objs[i]; + for (i = 0; i < ctx->modules.count; ++i) { + m = ctx->modules.objs[i]; if (m->augmented_by) { count = LY_ARRAY_COUNT(m->augmented_by); diff --git a/src/schema_compile_node.c b/src/schema_compile_node.c index 5498b208e..1ee469751 100644 --- a/src/schema_compile_node.c +++ b/src/schema_compile_node.c @@ -389,7 +389,7 @@ lysc_range_dup(struct lysc_ctx *ctx, const struct lysc_range *orig, struct ly_se error: if (dup) { - lysc_range_free(&ctx->free_ctx, dup); + lysc_range_free(ctx->ctx, dup); free(dup); } return NULL; @@ -1063,20 +1063,20 @@ lys_compile_type_range(struct lysc_ctx *ctx, const struct lysp_restr *range_p, L /* we rewrite the following values as the types chain is being processed */ if (range_p->eapptag) { - lydict_remove(ctx->ctx, (*range)->eapptag); - LY_CHECK_GOTO(ret = lydict_insert(ctx->ctx, range_p->eapptag, 0, &(*range)->eapptag), cleanup); + lysdict_remove(ctx->ctx, (*range)->eapptag); + LY_CHECK_GOTO(ret = lysdict_insert(ctx->ctx, range_p->eapptag, 0, &(*range)->eapptag), cleanup); } if (range_p->emsg) { - lydict_remove(ctx->ctx, (*range)->emsg); - LY_CHECK_GOTO(ret = lydict_insert(ctx->ctx, range_p->emsg, 0, &(*range)->emsg), cleanup); + lysdict_remove(ctx->ctx, (*range)->emsg); + LY_CHECK_GOTO(ret = lysdict_insert(ctx->ctx, range_p->emsg, 0, &(*range)->emsg), cleanup); } if (range_p->dsc) { - lydict_remove(ctx->ctx, (*range)->dsc); - LY_CHECK_GOTO(ret = lydict_insert(ctx->ctx, range_p->dsc, 0, &(*range)->dsc), cleanup); + lysdict_remove(ctx->ctx, (*range)->dsc); + LY_CHECK_GOTO(ret = lysdict_insert(ctx->ctx, range_p->dsc, 0, &(*range)->dsc), cleanup); } if (range_p->ref) { - lydict_remove(ctx->ctx, (*range)->ref); - LY_CHECK_GOTO(ret = lydict_insert(ctx->ctx, range_p->ref, 0, &(*range)->ref), cleanup); + lysdict_remove(ctx->ctx, (*range)->ref); + LY_CHECK_GOTO(ret = lysdict_insert(ctx->ctx, range_p->ref, 0, &(*range)->ref), cleanup); } /* extensions are taken only from the last range by the caller */ @@ -1387,19 +1387,20 @@ lys_compile_type_patterns(struct lysc_ctx *ctx, const struct lysp_restr *pattern *pattern = calloc(1, sizeof **pattern); ++(*pattern)->refcount; - ret = lys_compile_type_pattern_check(ctx->ctx, &patterns_p[u].arg.str[1], &(*pattern)->code); - LY_CHECK_RET(ret); + /* compile and insert the pattern into the context hash table, if it wasnt already compiled */ + LY_CHECK_GOTO(ret = ly_ctx_get_or_compile_pattern_code(ctx->ctx, &patterns_p[u].arg.str[1], NULL), done); if (patterns_p[u].arg.str[0] == LYSP_RESTR_PATTERN_NACK) { (*pattern)->inverted = 1; } - LY_CHECK_GOTO(ret = lydict_insert(ctx->ctx, &patterns_p[u].arg.str[1], 0, &(*pattern)->expr), done); + LY_CHECK_GOTO(ret = lysdict_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); DUP_STRING_GOTO(ctx->ctx, patterns_p[u].ref, (*pattern)->ref, ret, done); COMPILE_EXTS_GOTO(ctx, patterns_p[u].exts, (*pattern)->exts, (*pattern), ret, done); } + done: return ret; } @@ -1669,7 +1670,7 @@ lys_compile_type_union(struct lysc_ctx *ctx, struct lysp_type *ptypes, struct ly --additional; /* free the replaced union subtype */ - lysc_type_free(&ctx->free_ctx, (struct lysc_type *)un_aux); + lysc_type_free(ctx->ctx, (struct lysc_type *)un_aux); un_aux = NULL; } else { LY_ARRAY_INCREMENT(utypes); @@ -1681,7 +1682,7 @@ lys_compile_type_union(struct lysc_ctx *ctx, struct lysp_type *ptypes, struct ly error: if (un_aux) { - lysc_type_free(&ctx->free_ctx, (struct lysc_type *)un_aux); + lysc_type_free(ctx->ctx, (struct lysc_type *)un_aux); } *utypes_p = utypes; return ret; @@ -1752,7 +1753,7 @@ lys_new_type(const struct ly_ctx *ctx, LY_DATA_TYPE basetype, const char *tpdf_n LY_CHECK_ERR_GOTO(!t, LOGMEM(ctx); rc = LY_EMEM, cleanup); if (tpdf_name) { - rc = lydict_insert(ctx, tpdf_name, 0, &t->name); + rc = lysdict_insert(ctx, tpdf_name, 0, &t->name); LY_CHECK_GOTO(rc, cleanup); } @@ -1777,7 +1778,7 @@ lys_new_type(const struct ly_ctx *ctx, LY_DATA_TYPE basetype, const char *tpdf_n * @param[in] basetype Base YANG built-in type of the type to compile. * @param[in] tpdfname Name of the type's typedef, serves as a flag - if it is leaf/leaf-list's type, it is NULL. * @param[in] base Latest base (compiled) type from which the current type is being derived. - * @param[in] plugin Type plugin to use. + * @param[in] plugin_ref Reference to the type plugin to use. * @param[in] tpdf_chain Chain of the used typedefs, traversed backwards. * @param[in] tpdf_chain_last Index of the last (backwards) typedef in @p tpdf_chain to use. * @param[out] type Compiled type. @@ -1786,7 +1787,7 @@ lys_new_type(const struct ly_ctx *ctx, LY_DATA_TYPE basetype, const char *tpdf_n static LY_ERR lys_compile_type_(struct lysc_ctx *ctx, struct lysp_node *context_pnode, uint16_t context_flags, const char *context_name, const struct lysp_type *type_p, LY_DATA_TYPE basetype, const char *tpdfname, const struct lysc_type *base, - struct lyplg_type *plugin, struct ly_set *tpdf_chain, uint32_t tpdf_chain_last, struct lysc_type **type) + uintptr_t plugin_ref, struct ly_set *tpdf_chain, uint32_t tpdf_chain_last, struct lysc_type **type) { LY_ERR rc = LY_SUCCESS; struct lysc_type_bin *bin; @@ -1807,7 +1808,7 @@ lys_compile_type_(struct lysc_ctx *ctx, struct lysp_node *context_pnode, uint16_ LY_CHECK_GOTO(rc, cleanup); (*type)->basetype = basetype; - (*type)->plugin = plugin; + (*type)->plugin_ref = plugin_ref; switch (basetype) { case LY_TYPE_BINARY: @@ -2136,7 +2137,7 @@ lys_compile_type_(struct lysc_ctx *ctx, struct lysp_node *context_pnode, uint16_ cleanup: if (rc) { LY_ATOMIC_INC_BARRIER((*type)->refcount); - lysc_type_free(&ctx->free_ctx, *type); + lysc_type_free(ctx->ctx, *type); *type = NULL; } return rc; @@ -2154,7 +2155,7 @@ lys_compile_type(struct lysc_ctx *ctx, struct lysp_node *context_pnode, uint16_t struct lysc_type_union *base_un; LY_ARRAY_COUNT_TYPE u; struct ly_set tpdf_chain = {0}; - struct lyplg_type *plugin; + uintptr_t plugin_ref = 0; *type = NULL; if (dflt) { @@ -2193,7 +2194,7 @@ lys_compile_type(struct lysc_ctx *ctx, struct lysp_node *context_pnode, uint16_t if (tctx->tpdf->type.compiled && (tctx->tpdf->type.compiled->refcount == 1)) { /* context recompilation - everything was freed previously (the only reference is from the parsed type itself) * and we need now recompile the type again in the updated context. */ - lysc_type_free(&ctx->free_ctx, tctx->tpdf->type.compiled); + lysc_type_free(ctx->ctx, tctx->tpdf->type.compiled); ((struct lysp_tpdf *)tctx->tpdf)->type.compiled = NULL; } @@ -2277,20 +2278,19 @@ lys_compile_type(struct lysc_ctx *ctx, struct lysp_node *context_pnode, uint16_t } /* try to find loaded user type plugins */ - plugin = lyplg_type_plugin_find(ctx->ctx, tctx->tpdf->type.pmod->mod->name, tctx->tpdf->type.pmod->mod->revision, + plugin_ref = lyplg_type_plugin_find(ctx->ctx, tctx->tpdf->type.pmod->mod->name, tctx->tpdf->type.pmod->mod->revision, tctx->tpdf->name); - if (!plugin && base) { - /* use the base type implementation if available */ - plugin = base->plugin; + if (!plugin_ref && base) { + plugin_ref = base->plugin_ref; } - if (!plugin) { + if (!plugin_ref) { /* use the internal built-in type implementation */ - plugin = lyplg_type_plugin_find(ctx->ctx, "", NULL, ly_data_type2str[basetype]); + plugin_ref = lyplg_type_plugin_find(ctx->ctx, "", NULL, ly_data_type2str[basetype]); } - assert(plugin); + assert(plugin_ref); if ((basetype != LY_TYPE_LEAFREF) && (u != tpdf_chain.count - 1) && !tctx->tpdf->type.flags && - !tctx->tpdf->type.exts && (plugin == base->plugin)) { + !tctx->tpdf->type.exts && (plugin_ref == base->plugin_ref)) { /* no change, reuse the compiled base */ ((struct lysp_tpdf *)tctx->tpdf)->type.compiled = base; LY_ATOMIC_INC_BARRIER(base->refcount); @@ -2311,7 +2311,7 @@ lys_compile_type(struct lysc_ctx *ctx, struct lysp_node *context_pnode, uint16_t /* compile the typedef type */ ret = lys_compile_type_(ctx, tctx->node, tctx->tpdf->flags, tctx->tpdf->name, &tctx->tpdf->type, basetype, - tctx->tpdf->name, base, plugin, &tpdf_chain, u + 1, &base); + tctx->tpdf->name, base, plugin_ref, &tpdf_chain, u + 1, &base); LY_CHECK_GOTO(ret, cleanup); /* store separately compiled typedef type to be reused */ @@ -2342,9 +2342,13 @@ lys_compile_type(struct lysc_ctx *ctx, struct lysp_node *context_pnode, uint16_t /* process the type definition in leaf */ if (type_p->flags || type_p->exts || !base || has_leafref) { /* leaf type has changes that need to be compiled into the type */ - plugin = base ? base->plugin : lyplg_type_plugin_find(ctx->ctx, "", NULL, ly_data_type2str[basetype]); + if (base) { + plugin_ref = base->plugin_ref; + } else { + plugin_ref = lyplg_type_plugin_find(ctx->ctx, "", NULL, ly_data_type2str[basetype]); + } ret = lys_compile_type_(ctx, context_pnode, context_flags, context_name, (struct lysp_type *)type_p, basetype, - NULL, base, plugin, &tpdf_chain, 0, type); + NULL, base, plugin_ref, &tpdf_chain, 0, type); LY_CHECK_GOTO(ret, cleanup); } else { /* no changes of the type in the leaf, just use the base compiled type */ @@ -2714,7 +2718,7 @@ lys_compile_node_(struct lysc_ctx *ctx, struct lysp_node *pnode, struct lysc_nod node->module = ctx->cur_mod; node->parent = parent; node->prev = node; - node->priv = ctx->ctx->flags & LY_CTX_SET_PRIV_PARSED ? pnode : NULL; + node->priv = ctx->ctx->opts & LY_CTX_SET_PRIV_PARSED ? pnode : NULL; /* compile any deviations for this node */ LY_CHECK_GOTO(ret = lys_compile_node_deviations_refines(ctx, pnode, parent, &dev_pnode, ¬_supported), error); @@ -2785,7 +2789,7 @@ lys_compile_node_(struct lysc_ctx *ctx, struct lysp_node *pnode, struct lysc_nod goto cleanup; error: - lysc_node_free(&ctx->free_ctx, node, 0); + lysc_node_free(ctx->ctx, node, 0); cleanup: if (ret && dev_pnode) { @@ -3044,7 +3048,7 @@ lys_compile_node_leaf(struct lysc_ctx *ctx, struct lysp_node *pnode, struct lysc LY_CHECK_GOTO(ret, done); if (leaf_p->units) { - LY_CHECK_GOTO(ret = lydict_insert(ctx->ctx, leaf_p->units, 0, &leaf->units), done); + LY_CHECK_GOTO(ret = lysdict_insert(ctx->ctx, leaf_p->units, 0, &leaf->units), done); leaf->flags |= LYS_SET_UNITS; } @@ -3090,7 +3094,7 @@ lys_compile_node_leaflist(struct lysc_ctx *ctx, struct lysp_node *pnode, struct LY_CHECK_GOTO(ret, done); if (llist_p->units) { - LY_CHECK_GOTO(ret = lydict_insert(ctx->ctx, llist_p->units, 0, &llist->units), done); + LY_CHECK_GOTO(ret = lysdict_insert(ctx->ctx, llist_p->units, 0, &llist->units), done); llist->flags |= LYS_SET_UNITS; } @@ -3498,11 +3502,9 @@ lys_compile_node_list(struct lysc_ctx *ctx, struct lysp_node *pnode, struct lysc LY_CHECK_RET(lysc_check_status(ctx, list->flags, list->module, list->name, key->flags, key->module, key->name)); /* ignore default values of the key */ - if (key->dflt) { - key->dflt->realtype->plugin->free(ctx->ctx, key->dflt); - lysc_type_free(&ctx->free_ctx, (struct lysc_type *)key->dflt->realtype); - free(key->dflt); - key->dflt = NULL; + if (key->dflt.str) { + lysc_value_free(ctx->ctx, &key->dflt); + memset(&key->dflt, 0, sizeof key->dflt); } /* mark leaf as key */ key->flags |= LYS_KEY; @@ -3678,7 +3680,7 @@ lys_compile_node_choice_child(struct lysc_ctx *ctx, struct lysp_node *child_p, s assert(cs_c); } - if (ctx->ctx->flags & LY_CTX_SET_PRIV_PARSED) { + if (ctx->ctx->opts & LY_CTX_SET_PRIV_PARSED) { /* compiled case node cannot point to his corresponding parsed node * because it exists temporarily so it must be set to NULL */ @@ -3696,7 +3698,7 @@ lys_compile_node_choice_child(struct lysc_ctx *ctx, struct lysp_node *child_p, s revert_sh_case: /* free the parsed shorthand case and correct pointers back */ cs_p->child = NULL; - lysp_node_free(&ctx->free_ctx, (struct lysp_node *)cs_p); + lysp_node_free(ctx->ctx, (struct lysp_node *)cs_p); child_p->next = child_p_next; } @@ -4273,8 +4275,8 @@ lys_compile_grouping(struct lysc_ctx *ctx, struct lysp_node *pnode, struct lysp_ ctx->path[1] = '\0'; cleanup: - lysc_node_container_free(&ctx->free_ctx, &fake_container); - FREE_ARRAY(&ctx->free_ctx, fake_container.exts, lysc_ext_instance_free); + lysc_node_container_free(ctx->ctx, &fake_container); + FREE_ARRAY(ctx->ctx, fake_container.exts, lysc_ext_instance_free); return rc; } diff --git a/src/schema_features.c b/src/schema_features.c index 555226783..cd4dac66b 100644 --- a/src/schema_features.c +++ b/src/schema_features.c @@ -510,7 +510,6 @@ lys_eval_iffeatures(const struct ly_ctx *ctx, const struct lysp_qname *iffeature LY_ERR ret; LY_ARRAY_COUNT_TYPE u; struct lysc_iffeature iff; - struct lysf_ctx fctx = {.ctx = (struct ly_ctx *)ctx}; /* enabled by default */ *enabled = 1; @@ -525,7 +524,7 @@ lys_eval_iffeatures(const struct ly_ctx *ctx, const struct lysp_qname *iffeature LY_CHECK_RET(lys_compile_iffeature(ctx, &iffeatures[u], &iff)); ret = lysc_iffeature_value(&iff); - lysc_iffeature_free(&fctx, &iff); + lysc_iffeature_free(ctx, &iff); if (ret == LY_ENOT) { *enabled = 0; break; diff --git a/src/tree_data.c b/src/tree_data.c index 517b1694c..7cfc9ba12 100644 --- a/src/tree_data.c +++ b/src/tree_data.c @@ -296,13 +296,14 @@ lyd_parse_data_path(const struct ly_ctx *ctx, const char *path, LYD_FORMAT forma */ static LY_ERR lyd_parse_op_(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, struct lyd_node *parent, - struct ly_in *in, LYD_FORMAT format, enum lyd_type data_type, struct lyd_node **tree, struct lyd_node **op) + struct ly_in *in, LYD_FORMAT format, uint32_t parse_opts, enum lyd_type data_type, struct lyd_node **tree, + struct lyd_node **op) { LY_ERR rc = LY_SUCCESS; struct lyd_ctx *lydctx = NULL; struct ly_set parsed = {0}; struct lyd_node *first = NULL, *envp = NULL; - uint32_t i, parse_opts, val_opts, int_opts = 0; + uint32_t i, val_opts, int_opts = 0; ly_bool proto_msg = 0; if (!ctx) { @@ -320,8 +321,7 @@ lyd_parse_op_(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, str /* remember input position */ in->func_start = in->current; - /* set parse and validation opts */ - parse_opts = LYD_PARSE_ONLY | LYD_PARSE_STRICT; + /* set validation opts */ val_opts = 0; switch (data_type) { @@ -443,22 +443,28 @@ lyd_parse_op_(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, str LIBYANG_API_DEF LY_ERR lyd_parse_op(const struct ly_ctx *ctx, struct lyd_node *parent, struct ly_in *in, LYD_FORMAT format, - enum lyd_type data_type, struct lyd_node **tree, struct lyd_node **op) + enum lyd_type data_type, uint32_t parse_options, struct lyd_node **tree, struct lyd_node **op) { - LY_CHECK_ARG_RET(ctx, ctx || parent, in, data_type, parent || tree || op, LY_EINVAL); + LY_CHECK_ARG_RET(ctx, ctx || parent, in, !(parse_options & ~(LYD_PARSE_STRICT | LYD_PARSE_OPAQ)), data_type, + parent || tree || op, LY_EINVAL); - return lyd_parse_op_(ctx, NULL, parent, in, format, data_type, tree, op); + parse_options |= LYD_PARSE_ONLY; + + return lyd_parse_op_(ctx, NULL, parent, in, format, parse_options, data_type, tree, op); } LIBYANG_API_DEF LY_ERR lyd_parse_ext_op(const struct lysc_ext_instance *ext, struct lyd_node *parent, struct ly_in *in, LYD_FORMAT format, - enum lyd_type data_type, struct lyd_node **tree, struct lyd_node **op) + enum lyd_type data_type, uint32_t parse_options, struct lyd_node **tree, struct lyd_node **op) { const struct ly_ctx *ctx = ext ? ext->module->ctx : NULL; - LY_CHECK_ARG_RET(ctx, ext, in, data_type, parent || tree || op, LY_EINVAL); + LY_CHECK_ARG_RET(ctx, ext, in, !(parse_options & ~(LYD_PARSE_STRICT | LYD_PARSE_OPAQ)), data_type, + parent || tree || op, LY_EINVAL); + + parse_options |= LYD_PARSE_ONLY; - return lyd_parse_op_(ctx, ext, parent, in, format, data_type, tree, op); + return lyd_parse_op_(ctx, ext, parent, in, format, parse_options, data_type, tree, op); } struct lyd_node * @@ -1333,8 +1339,8 @@ lyd_get_meta_annotation(const struct lys_module *mod, const char *name, size_t n } LY_ARRAY_FOR(mod->compiled->exts, u) { - plugin = mod->compiled->exts[u].def->plugin; - if (plugin && !strncmp(plugin->id, "ly2 metadata", 12) && + plugin = LYSC_GET_EXT_PLG(mod->compiled->exts[u].def->plugin_ref); + if (plugin && !strcmp(plugin->id, "ly2 metadata") && !ly_strncmp(mod->compiled->exts[u].argument, name, name_len)) { return &mod->compiled->exts[u]; } @@ -1877,7 +1883,7 @@ lyd_compare_meta(const struct lyd_meta *meta1, const struct lyd_meta *meta2) return LY_ENOT; } - return meta1->value.realtype->plugin->compare(ctx, &meta1->value, &meta2->value); + return LYSC_GET_TYPE_PLG(meta1->value.realtype->plugin_ref)->compare(ctx, &meta1->value, &meta2->value); } /** @@ -2253,7 +2259,7 @@ lyd_dup_r(const struct lyd_node *node, const struct ly_ctx *trg_ctx, struct lyd_ term->hash = orig->hash; if (trg_ctx == LYD_CTX(node)) { - rc = orig->value.realtype->plugin->duplicate(trg_ctx, &orig->value, &term->value); + rc = LYSC_GET_TYPE_PLG(orig->value.realtype->plugin_ref)->duplicate(trg_ctx, &orig->value, &term->value); LY_CHECK_ERR_GOTO(rc, LOGERR(trg_ctx, rc, "Value duplication failed."), cleanup); } else { /* store canonical value in the target context */ @@ -2556,7 +2562,7 @@ lyd_dup_meta_single_to_ctx(const struct ly_ctx *parent_ctx, const struct lyd_met /* annotation */ mt->annotation = meta->annotation; /* duplication of value */ - ret = meta->value.realtype->plugin->duplicate(parent_ctx, &meta->value, &mt->value); + ret = LYSC_GET_TYPE_PLG(meta->value.realtype->plugin_ref)->duplicate(parent_ctx, &meta->value, &mt->value); } LY_CHECK_ERR_GOTO(ret, LOGERR(LYD_CTX(parent), LY_EINT, "Value duplication failed."), finish); LY_CHECK_GOTO(ret = lydict_insert(parent_ctx, meta->name, 0, &mt->name), finish); @@ -3549,7 +3555,7 @@ lyd_eval_xpath4(const struct lyd_node *ctx_node, const struct lyd_node *tree, co cleanup: lyxp_set_free_content(&xp_set); - lyxp_expr_free((struct ly_ctx *)LYD_CTX(tree), exp); + lyxp_expr_free(exp); return ret; } @@ -3680,7 +3686,7 @@ lyd_trim_xpath(struct lyd_node **tree, const char *xpath, const struct lyxp_var cleanup: lyxp_set_free_content(&xp_set); - lyxp_expr_free(ctx, exp); + lyxp_expr_free(exp); lyht_free(parent_ht, NULL); ly_set_erase(&free_set, NULL); return ret; @@ -3709,7 +3715,7 @@ lyd_find_path(const struct lyd_node *ctx_node, const char *path, ly_bool output, ret = ly_path_eval_partial(lypath, ctx_node, NULL, 0, NULL, match); cleanup: - lyxp_expr_free(LYD_CTX(ctx_node), expr); + lyxp_expr_free(expr); ly_path_free(lypath); return ret; } @@ -3739,7 +3745,7 @@ lyd_find_target(const struct ly_path *path, const struct lyd_node *tree, struct LY_ERR lyd_get_or_create_leafref_links_record(const struct lyd_node_term *node, struct lyd_leafref_links_rec **record, ly_bool create) { - struct ly_ht *ht; + struct ly_ctx_shared_data *ctx_data; LY_ERR ret = LY_SUCCESS; uint32_t hash; struct lyd_leafref_links_rec rec = {0}; @@ -3755,26 +3761,31 @@ lyd_get_or_create_leafref_links_record(const struct lyd_node_term *node, struct return LY_EDENIED; } + ctx_data = ly_ctx_shared_data_get(LYD_CTX(node)); rec.node = node; - ht = LYD_CTX(node)->leafref_links_ht; hash = lyht_hash((const char *)&node, sizeof node); - if (lyht_find(ht, &rec_p, hash, (void **)&rec_p2) == LY_ENOTFOUND) { - if (create) { - rec_p = calloc(1, sizeof rec); - rec_p->node = node; - LY_CHECK_ERR_RET(!rec_p, LOGMEM(LYD_CTX(node)), LY_EMEM); - ret = lyht_insert_no_check(ht, &rec_p, hash, (void **)&rec_p2); - LY_CHECK_ERR_GOTO(ret, free(rec_p), cleanup); - } else { - return LY_ENOTFOUND; - } + /* LL LOCK */ + pthread_mutex_lock(&ctx_data->leafref_links_lock); + + ret = lyht_find(ctx_data->leafref_links_ht, &rec_p, hash, (void **)&rec_p2); + if ((ret == LY_ENOTFOUND) && create) { + /* create a new record */ + rec_p = calloc(1, sizeof rec); + rec_p->node = node; + LY_CHECK_ERR_GOTO(!rec_p, LOGMEM(LYD_CTX(node)), cleanup); + ret = lyht_insert_no_check(ctx_data->leafref_links_ht, &rec_p, hash, (void **)&rec_p2); + LY_CHECK_ERR_GOTO(ret, free(rec_p), cleanup); } cleanup: if (!ret) { *record = *rec_p2; } + + /* LL UNLOCK */ + pthread_mutex_unlock(&ctx_data->leafref_links_lock); + return ret; } diff --git a/src/tree_data_common.c b/src/tree_data_common.c index 96a6e68ad..30babc7f6 100644 --- a/src/tree_data_common.c +++ b/src/tree_data_common.c @@ -32,6 +32,7 @@ #include "metadata.h" #include "parser_data.h" #include "plugins_exts.h" +#include "plugins_internal.h" #include "printer_data.h" #include "schema_compile_node.h" #include "set.h" @@ -510,7 +511,7 @@ lyd_value_store(const struct ly_ctx *ctx, struct lyd_value *val, const struct ly size_t value_len, ly_bool is_utf8, ly_bool store_only, ly_bool *dynamic, LY_VALUE_FORMAT format, void *prefix_data, uint32_t hints, const struct lysc_node *ctx_node, ly_bool *incomplete) { - LY_ERR ret; + LY_ERR r; struct ly_err_item *err = NULL; uint32_t options = 0; @@ -532,23 +533,24 @@ lyd_value_store(const struct ly_ctx *ctx, struct lyd_value *val, const struct ly options |= LYPLG_TYPE_STORE_ONLY; } - ret = type->plugin->store(ctx, type, value, value_len, options, format, prefix_data, hints, ctx_node, val, NULL, &err); + r = LYSC_GET_TYPE_PLG(type->plugin_ref)->store(ctx, type, value, value_len, options, + format, prefix_data, hints, ctx_node, val, NULL, &err); if (dynamic) { *dynamic = 0; } - if (ret == LY_EINCOMPLETE) { + if (r == LY_EINCOMPLETE) { if (incomplete) { *incomplete = 1; } - } else if (ret) { + } else if (r) { if (err) { ly_err_print_build_path(ctx, NULL, ctx_node, err); ly_err_free(err); } else { LOGVAL(ctx, LYVE_OTHER, "Storing value failed."); } - return ret; + return r; } return LY_SUCCESS; @@ -560,17 +562,19 @@ lyd_value_validate_incomplete(const struct ly_ctx *ctx, const struct lysc_type * { LY_ERR ret; struct ly_err_item *err = NULL; + struct lyplg_type *type_plg; - assert(type->plugin->validate); + type_plg = LYSC_GET_TYPE_PLG(type->plugin_ref); + assert(type_plg && type_plg->validate); - ret = type->plugin->validate(ctx, type, ctx_node, tree, val, &err); + ret = type_plg->validate(ctx, type, ctx_node, tree, val, &err); if (ret) { if (err) { ly_err_print_build_path(ctx, ctx_node, NULL, err); ly_err_free(err); } else { LOGVAL(ctx, LYVE_OTHER, "Resolving value \"%s\" failed.", - (char *)type->plugin->print(ctx, val, LY_VALUE_CANON, NULL, NULL, NULL)); + (char *)type_plg->print(ctx, val, LY_VALUE_CANON, NULL, NULL, NULL)); } return ret; } @@ -595,11 +599,10 @@ ly_value_validate(const struct ly_ctx *ctx, const struct lysc_node *node, const } type = ((struct lysc_node_leaf *)node)->type; - rc = type->plugin->store(ctx ? ctx : node->module->ctx, type, value, value_len, 0, format, prefix_data, hints, node, - &storage, NULL, &err); + rc = LYSC_GET_TYPE_PLG(type->plugin_ref)->store(ctx ? ctx : node->module->ctx, type, value, + value_len, 0, format, prefix_data, hints, node, &storage, NULL, &err); if (rc == LY_EINCOMPLETE) { - /* actually success since we do not provide the context tree and call validation with - * LY_TYPE_OPTS_INCOMPLETE_DATA */ + /* actually success */ rc = LY_SUCCESS; } else if (rc && err) { if (ctx) { @@ -610,7 +613,7 @@ ly_value_validate(const struct ly_ctx *ctx, const struct lysc_node *node, const } if (!rc) { - type->plugin->free(ctx ? ctx : node->module->ctx, &storage); + LYSC_GET_TYPE_PLG(type->plugin_ref)->free(ctx ? ctx : node->module->ctx, &storage); } return rc; } @@ -618,14 +621,23 @@ ly_value_validate(const struct ly_ctx *ctx, const struct lysc_node *node, const LIBYANG_API_DEF LY_ERR lyd_value_validate(const struct ly_ctx *ctx, const struct lysc_node *schema, const char *value, size_t value_len, const struct lyd_node *ctx_node, const struct lysc_type **realtype, const char **canonical) +{ + LY_CHECK_ARG_RET(ctx, schema, !value_len || value, LY_EINVAL); + + return lyd_value_validate2(ctx, schema, value, value_len, LY_VALUE_JSON, NULL, ctx_node, realtype, canonical); +} + +LY_ERR +lyd_value_validate2(const struct ly_ctx *ctx, const struct lysc_node *schema, const char *value, size_t value_len, + LY_VALUE_FORMAT format, void *prefix_data, const struct lyd_node *ctx_node, const struct lysc_type **realtype, + const char **canonical) { LY_ERR rc; struct ly_err_item *err = NULL; struct lysc_type *type; struct lyd_value val = {0}; ly_bool stored = 0, log = 1; - - LY_CHECK_ARG_RET(ctx, schema, !value_len || value, LY_EINVAL); + struct lyplg_type *type_plg; if (!ctx) { ctx = schema->module->ctx; @@ -636,16 +648,18 @@ lyd_value_validate(const struct ly_ctx *ctx, const struct lysc_node *schema, con } type = ((struct lysc_node_leaf *)schema)->type; + type_plg = LYSC_GET_TYPE_PLG(type->plugin_ref); + /* store */ - rc = type->plugin->store(ctx, type, value, value_len, 0, LY_VALUE_JSON, NULL, - LYD_HINT_DATA, schema, &val, NULL, &err); + rc = type_plg->store(ctx, type, value, value_len, 0, format, + prefix_data, LYD_HINT_DATA, schema, &val, NULL, &err); if (!rc || (rc == LY_EINCOMPLETE)) { stored = 1; } if (ctx_node && (rc == LY_EINCOMPLETE)) { /* resolve */ - rc = type->plugin->validate(ctx, type, ctx_node, ctx_node, &val, &err); + rc = type_plg->validate(ctx, type, ctx_node, ctx_node, &val, &err); } if (rc && (rc != LY_EINCOMPLETE) && err) { @@ -668,13 +682,14 @@ lyd_value_validate(const struct ly_ctx *ctx, const struct lysc_node *schema, con if (canonical) { /* return canonical value */ - lydict_insert(ctx, val.realtype->plugin->print(ctx, &val, LY_VALUE_CANON, NULL, NULL, NULL), 0, canonical); + lydict_dup(ctx, LYSC_GET_TYPE_PLG(val.realtype->plugin_ref)->print(ctx, &val, + LY_VALUE_CANON, NULL, NULL, NULL), canonical); } } if (stored) { /* free value */ - type->plugin->free(ctx ? ctx : schema->module->ctx, &val); + type_plg->free(ctx, &val); } return rc; } @@ -686,6 +701,7 @@ lyd_value_compare(const struct lyd_node_term *node, const char *value, size_t va struct ly_ctx *ctx; struct lysc_type *type; struct lyd_value val = {0}; + struct lyplg_type *type_plg; LY_CHECK_ARG_RET(node ? node->schema->module->ctx : NULL, node, value, LY_EINVAL); @@ -699,9 +715,10 @@ lyd_value_compare(const struct lyd_node_term *node, const char *value, size_t va LY_CHECK_RET(ret); /* compare values */ - ret = type->plugin->compare(ctx, &node->value, &val); + type_plg = LYSC_GET_TYPE_PLG(type->plugin_ref); + ret = type_plg->compare(ctx, &node->value, &val); - type->plugin->free(ctx, &val); + type_plg->free(ctx, &val); return ret; } @@ -710,23 +727,20 @@ lyd_is_default(const struct lyd_node *node) { const struct lysc_node_leaf *leaf; const struct lysc_node_leaflist *llist; - const struct lyd_node_term *term; LY_ARRAY_COUNT_TYPE u; if (!(node->schema->nodetype & LYD_NODE_TERM)) { return 0; } - term = (const struct lyd_node_term *)node; - if (node->schema->nodetype == LYS_LEAF) { leaf = (const struct lysc_node_leaf *)node->schema; - if (!leaf->dflt) { + if (!leaf->dflt.str) { return 0; } /* compare with the default value */ - if (!leaf->type->plugin->compare(LYD_CTX(node), &term->value, leaf->dflt)) { + if (!lysc_value_cmp(node->schema, node, &leaf->dflt, lyd_get_value(node))) { return 1; } } else { @@ -737,7 +751,7 @@ lyd_is_default(const struct lyd_node *node) LY_ARRAY_FOR(llist->dflts, u) { /* compare with each possible default value */ - if (!llist->type->plugin->compare(LYD_CTX(node), &term->value, llist->dflts[u])) { + if (!lysc_value_cmp(node->schema, node, &llist->dflts[u], lyd_get_value(node))) { return 1; } } @@ -980,7 +994,7 @@ lyd_value_get_canonical(const struct ly_ctx *ctx, const struct lyd_value *value) LY_CHECK_ARG_RET(ctx, ctx, value, NULL); return value->_canonical ? value->_canonical : - (const char *)value->realtype->plugin->print(ctx, value, LY_VALUE_CANON, NULL, NULL, NULL); + (const char *)LYSC_GET_TYPE_PLG(value->realtype->plugin_ref)->print(ctx, value, LY_VALUE_CANON, NULL, NULL, NULL); } LIBYANG_API_DEF LY_ERR @@ -1329,12 +1343,12 @@ ly_nested_ext_schema(const struct lyd_node *parent, const struct lysc_node *spar nested_exts = sparent->exts; } LY_ARRAY_FOR(nested_exts, u) { - if (!nested_exts[u].def->plugin) { + if (!nested_exts[u].def->plugin_ref) { /* no plugin */ continue; } - ext_snode_cb = nested_exts[u].def->plugin->snode; + ext_snode_cb = LYSC_GET_EXT_PLG(nested_exts[u].def->plugin_ref)->snode; if (!ext_snode_cb) { /* not an extension with nested data */ continue; @@ -1841,7 +1855,7 @@ ly_time_ts2str(const struct timespec *ts, char **str) } LY_ERR -ly_pattern_code_match(pcre2_code *pcode, const char *str, size_t str_len, struct ly_err_item **err) +ly_pattern_code_match(const pcre2_code *pcode, const char *str, size_t str_len, struct ly_err_item **err) { int r, match_opts; pcre2_match_data *match_data = NULL; diff --git a/src/tree_data_free.c b/src/tree_data_free.c index 893dfec46..811c924c0 100644 --- a/src/tree_data_free.c +++ b/src/tree_data_free.c @@ -20,6 +20,7 @@ #include "log.h" #include "ly_common.h" #include "plugins_exts/metadata.h" +#include "plugins_internal.h" #include "plugins_types.h" #include "tree.h" #include "tree_data.h" @@ -64,7 +65,7 @@ lyd_free_meta(struct lyd_meta *meta, ly_bool siblings) iter = iter->next; lydict_remove(meta->annotation->module->ctx, meta->name); - meta->value.realtype->plugin->free(meta->annotation->module->ctx, &meta->value); + LYSC_GET_TYPE_PLG(meta->value.realtype->plugin_ref)->free(meta->annotation->module->ctx, &meta->value); free(meta); } } @@ -175,7 +176,7 @@ lyd_free_leafref_links_rec(struct lyd_leafref_links_rec *rec) void lyd_free_leafref_nodes(const struct lyd_node_term *node) { - struct ly_ht *ht; + struct ly_ctx_shared_data *ctx_data; uint32_t hash; struct lyd_leafref_links_rec *rec; @@ -189,9 +190,17 @@ lyd_free_leafref_nodes(const struct lyd_node_term *node) lyd_free_leafref_links_rec(rec); /* free entry itself from hash table */ - ht = LYD_CTX(node)->leafref_links_ht; + ctx_data = ly_ctx_shared_data_get(LYD_CTX(node)); hash = lyht_hash((const char *)&node, sizeof node); - lyht_remove(ht, &rec, hash); + + /* LL LOCK */ + pthread_mutex_lock(&ctx_data->leafref_links_lock); + + lyht_remove(ctx_data->leafref_links_ht, &rec, hash); + + /* LL UNLOCK */ + pthread_mutex_unlock(&ctx_data->leafref_links_lock); + free(rec); } @@ -235,7 +244,7 @@ lyd_free_subtree(struct lyd_node *node) } else if (node->schema->nodetype & LYD_NODE_TERM) { struct lyd_node_term *node_term = (struct lyd_node_term *)node; - ((struct lysc_node_leaf *)node->schema)->type->plugin->free(LYD_CTX(node), &node_term->value); + LYSC_GET_TYPE_PLG(((struct lysc_node_leaf *)node->schema)->type->plugin_ref)->free(LYD_CTX(node), &node_term->value); lyd_free_leafref_nodes(node_term); } diff --git a/src/tree_data_hash.c b/src/tree_data_hash.c index 9be655ca4..d82e9203f 100644 --- a/src/tree_data_hash.c +++ b/src/tree_data_hash.c @@ -21,6 +21,7 @@ #include "hash_table.h" #include "log.h" #include "ly_common.h" +#include "plugins_internal.h" #include "plugins_types.h" #include "tree.h" #include "tree_data.h" @@ -55,7 +56,8 @@ lyd_hash(struct lyd_node *node) for (iter = list->child; iter && iter->schema && (iter->schema->flags & LYS_KEY); iter = iter->next) { struct lyd_node_term *key = (struct lyd_node_term *)iter; - hash_key = key->value.realtype->plugin->print(NULL, &key->value, LY_VALUE_LYB, NULL, &dyn, &key_len); + hash_key = LYSC_GET_TYPE_PLG(key->value.realtype->plugin_ref)->print(NULL, &key->value, + LY_VALUE_LYB, NULL, &dyn, &key_len); node->hash = lyht_hash_multi(node->hash, hash_key, key_len); if (dyn) { free((void *)hash_key); @@ -66,7 +68,8 @@ lyd_hash(struct lyd_node *node) /* leaf-list adds its hash key */ struct lyd_node_term *llist = (struct lyd_node_term *)node; - hash_key = llist->value.realtype->plugin->print(NULL, &llist->value, LY_VALUE_LYB, NULL, &dyn, &key_len); + hash_key = LYSC_GET_TYPE_PLG(llist->value.realtype->plugin_ref)->print(NULL, &llist->value, + LY_VALUE_LYB, NULL, &dyn, &key_len); node->hash = lyht_hash_multi(node->hash, hash_key, key_len); if (dyn) { free((void *)hash_key); diff --git a/src/tree_data_internal.h b/src/tree_data_internal.h index 03f82bca3..9c67e73cb 100644 --- a/src/tree_data_internal.h +++ b/src/tree_data_internal.h @@ -238,10 +238,9 @@ const char *ly_format2str(LY_VALUE_FORMAT format); * @param[in] format Input format of @p value. * @param[in] prefix_data Format-specific data for resolving any prefixes (see ::ly_resolve_prefix). * @param[in] hints [Value hints](@ref lydvalhints) from the parser regarding the value type. - * @param[out] incomplete Whether the value needs to be resolved. + * @param[out] incomplete Whether the value needs to be resolved, optional. * @param[out] node Created node. * @return LY_SUCCESS on success. - * @return LY_EINCOMPLETE in case data tree is needed to finish the validation. * @return LY_ERR value if an error occurred. */ LY_ERR lyd_create_term(const struct lysc_node *schema, const char *value, size_t value_len, ly_bool is_utf8, @@ -249,17 +248,17 @@ LY_ERR lyd_create_term(const struct lysc_node *schema, const char *value, size_t ly_bool *incomplete, struct lyd_node **node); /** - * @brief Create a term (leaf/leaf-list) node from a parsed value by duplicating it. + * @brief Create a term (leaf/leaf-list) node from a canonical string value. * * Hash is calculated and new node flag is set. * * @param[in] schema Schema node of the new data node. - * @param[in] val Parsed value to use. + * @param[in] value Canonical string value to use. * @param[out] node Created node. * @return LY_SUCCESS on success. * @return LY_ERR value if an error occurred. */ -LY_ERR lyd_create_term2(const struct lysc_node *schema, const struct lyd_value *val, struct lyd_node **node); +LY_ERR lyd_create_term_canon(const struct lysc_node *schema, const char *value, struct lyd_node **node); /** * @brief Create an inner (container/list/RPC/action/notification) node. @@ -631,6 +630,30 @@ LY_ERR lyd_value_validate_incomplete(const struct ly_ctx *ctx, const struct lysc LY_ERR ly_value_validate(const struct ly_ctx *ctx, const struct lysc_node *node, const char *value, size_t value_len, LY_VALUE_FORMAT format, void *prefix_data, uint32_t hints); +/** + * @brief Check type restrictions applicable to the particular leaf/leaf-list with the given string @p value. + * + * The given node is not modified in any way - it is just checked if the @p value can be set to the node. + * + * @param[in] ctx libyang context for logging (function does not log errors when @p ctx is NULL) + * @param[in] schema Schema node of the @p value. + * @param[in] value String value to be checked, it is expected to be in JSON format. + * @param[in] value_len Length of the given @p value (mandatory). + * @param[in] format Value prefix format. + * @param[in] prefix_data Format-specific data for resolving any prefixes (see ::ly_resolve_prefix). + * @param[in] ctx_node Optional data tree context node for the value (leafref target, instance-identifier). + * If not set and is required for the validation to complete, ::LY_EINCOMPLETE is be returned. + * @param[out] realtype Optional real type of @p value. + * @param[out] canonical Optional canonical value of @p value (in the dictionary). + * @return LY_SUCCESS on success + * @return LY_EINCOMPLETE in case the @p ctx_node is not provided and it was needed to finish the validation + * (e.g. due to require-instance). + * @return LY_ERR value if an error occurred. + */ +LY_ERR lyd_value_validate2(const struct ly_ctx *ctx, const struct lysc_node *schema, const char *value, size_t value_len, + LY_VALUE_FORMAT format, void *prefix_data, const struct lyd_node *ctx_node, const struct lysc_type **realtype, + const char **canonical); + /** * @defgroup datahash Data nodes hash manipulation * @ingroup datatree @@ -774,6 +797,6 @@ void lyd_unlink_ignore_lyds(struct lyd_node **first_sibling, struct lyd_node *no * @return LY_ENOT if the string does not match; * @return LY_ERR on error. */ -LY_ERR ly_pattern_code_match(pcre2_code *pcode, const char *str, size_t str_len, struct ly_err_item **err); +LY_ERR ly_pattern_code_match(const pcre2_code *pcode, const char *str, size_t str_len, struct ly_err_item **err); #endif /* LY_TREE_DATA_INTERNAL_H_ */ diff --git a/src/tree_data_new.c b/src/tree_data_new.c index d8341175a..d8266a8f5 100644 --- a/src/tree_data_new.c +++ b/src/tree_data_new.c @@ -79,33 +79,9 @@ lyd_create_term(const struct lysc_node *schema, const char *value, size_t value_ } LY_ERR -lyd_create_term2(const struct lysc_node *schema, const struct lyd_value *val, struct lyd_node **node) +lyd_create_term_canon(const struct lysc_node *schema, const char *value, struct lyd_node **node) { - LY_ERR ret; - struct lyd_node_term *term; - struct lysc_type *type; - - assert(schema->nodetype & LYD_NODE_TERM); - assert(val && val->realtype); - - term = calloc(1, sizeof *term); - LY_CHECK_ERR_RET(!term, LOGMEM(schema->module->ctx), LY_EMEM); - - term->schema = schema; - term->prev = &term->node; - term->flags = LYD_NEW; - - type = ((struct lysc_node_leaf *)schema)->type; - ret = type->plugin->duplicate(schema->module->ctx, val, &term->value); - if (ret) { - LOGERR(schema->module->ctx, ret, "Value duplication failed."); - free(term); - return ret; - } - lyd_hash(&term->node); - - *node = &term->node; - return ret; + return lyd_create_term(schema, value, strlen(value), 1, 1, NULL, LY_VALUE_CANON, NULL, LYD_HINT_DATA, NULL, node); } LY_ERR @@ -140,9 +116,8 @@ lyd_create_list(const struct lysc_node *schema, const struct ly_path_predicate * { LY_ERR ret = LY_SUCCESS; struct lyd_node *list = NULL, *key; - const struct lyd_value *value; - struct lyd_value val = {0}; struct lyxp_var *var; + const char *value; LY_ARRAY_COUNT_TYPE u; assert((schema->nodetype == LYS_LIST) && !(schema->flags & LYS_KEYLESS)); @@ -160,24 +135,14 @@ lyd_create_list(const struct lysc_node *schema, const struct ly_path_predicate * goto cleanup; } - /* store the value */ - LOG_LOCSET(predicates[u].key, NULL); - ret = lyd_value_store(schema->module->ctx, &val, ((struct lysc_node_leaf *)predicates[u].key)->type, - var->value, strlen(var->value), 0, store_only, NULL, LY_VALUE_JSON, NULL, LYD_HINT_DATA, predicates[u].key, NULL); - LOG_LOCBACK(1, 0); - LY_CHECK_GOTO(ret, cleanup); - - value = &val; + value = var->value; } else { assert(predicates[u].type == LY_PATH_PREDTYPE_LIST); - value = &predicates[u].value; + value = predicates[u].value; } - ret = lyd_create_term2(predicates[u].key, value, &key); - if (val.realtype) { - val.realtype->plugin->free(schema->module->ctx, &val); - memset(&val, 0, sizeof val); - } + ret = lyd_create_term(predicates[u].key, value, strlen(value), 1, store_only, NULL, LY_VALUE_JSON, NULL, + LYD_HINT_DATA, NULL, &key); LY_CHECK_GOTO(ret, cleanup); lyd_insert_node(list, NULL, key, LYD_INSERT_NODE_DEFAULT); } @@ -218,7 +183,7 @@ lyd_create_list2(const struct lysc_node *schema, const char *keys, size_t keys_l cleanup: LOG_LOCBACK(1, 0); - lyxp_expr_free(schema->module->ctx, expr); + lyxp_expr_free(expr); ly_path_predicates_free(schema->module->ctx, predicates); return ret; } @@ -1253,6 +1218,10 @@ lyd_change_node_value(struct lyd_node_term *term, struct lyd_value *val, ly_bool { LY_ERR rc = LY_SUCCESS; struct lyd_node *target, *first; + struct lyplg_type *realtype_plg, *schema_type_plg; + + realtype_plg = LYSC_GET_TYPE_PLG(term->value.realtype->plugin_ref); + schema_type_plg = LYSC_GET_TYPE_PLG(((struct lysc_node_leaf *)term->schema)->type->plugin_ref); if (term->schema->nodetype == LYS_LEAFLIST) { target = (struct lyd_node *)term; @@ -1260,11 +1229,11 @@ lyd_change_node_value(struct lyd_node_term *term, struct lyd_value *val, ly_bool target = (struct lyd_node *)term->parent; } else { /* just change the value */ - term->value.realtype->plugin->free(LYD_CTX(term), &term->value); + realtype_plg->free(LYD_CTX(term), &term->value); if (use_val) { term->value = *val; } else { - rc = ((struct lysc_node_leaf *)term->schema)->type->plugin->duplicate(LYD_CTX(term), val, &term->value); + rc = schema_type_plg->duplicate(LYD_CTX(term), val, &term->value); } /* leaf that is not a key, its value is not used for its hash so it does not change */ @@ -1280,11 +1249,11 @@ lyd_change_node_value(struct lyd_node_term *term, struct lyd_value *val, ly_bool lyd_unlink_tree(target); /* change value */ - term->value.realtype->plugin->free(LYD_CTX(term), &term->value); + realtype_plg->free(LYD_CTX(term), &term->value); if (use_val) { term->value = *val; } else { - rc = ((struct lysc_node_leaf *)term->schema)->type->plugin->duplicate(LYD_CTX(term), val, &term->value); + rc = schema_type_plg->duplicate(LYD_CTX(term), val, &term->value); } /* update hash */ @@ -1297,11 +1266,11 @@ lyd_change_node_value(struct lyd_node_term *term, struct lyd_value *val, ly_bool lyd_unlink_hash(target); /* change value */ - term->value.realtype->plugin->free(LYD_CTX(term), &term->value); + realtype_plg->free(LYD_CTX(term), &term->value); if (use_val) { term->value = *val; } else { - LY_CHECK_RET(((struct lysc_node_leaf *)term->schema)->type->plugin->duplicate(LYD_CTX(term), val, &term->value)); + LY_CHECK_RET(schema_type_plg->duplicate(LYD_CTX(term), val, &term->value)); } /* update hash */ @@ -1321,12 +1290,14 @@ lyd_change_term_val(struct lyd_node *term, struct lyd_value *val, ly_bool use_va struct lysc_type *type; struct lyd_node_term *t; ly_bool dflt_change, val_change; + struct lyplg_type *type_plg; t = (struct lyd_node_term *)term; type = ((struct lysc_node_leaf *)term->schema)->type; + type_plg = LYSC_GET_TYPE_PLG(type->plugin_ref); /* compare original and new value */ - if (type->plugin->compare(LYD_CTX(term), &t->value, val)) { + if (type_plg->compare(LYD_CTX(term), &t->value, val)) { /* since they are different, they cannot both be default */ assert(!(term->flags & LYD_DEFAULT) || !is_dflt); @@ -1336,7 +1307,7 @@ lyd_change_term_val(struct lyd_node *term, struct lyd_value *val, ly_bool use_va } else { /* same values, free the new stored one */ if (use_val) { - type->plugin->free(LYD_CTX(term), val); + type_plg->free(LYD_CTX(term), val); } val_change = 0; } @@ -1568,9 +1539,9 @@ lyd_new_path_check_find_lypath(struct ly_path *path, const char *str_path, const { LY_ERR r; struct ly_path_predicate *pred; - struct lyd_value val; const struct lysc_node *schema = NULL; LY_ARRAY_COUNT_TYPE u, new_count; + const char *canon; int create = 0; assert(path); @@ -1608,15 +1579,14 @@ lyd_new_path_check_find_lypath(struct ly_path *path, const char *str_path, const r = lyd_value_validate(NULL, schema, value, value_len, NULL, NULL, NULL); } if (!r) { - /* try to store the value */ - LY_CHECK_RET(lyd_value_store(schema->module->ctx, &val, ((struct lysc_node_leaflist *)schema)->type, - value, value_len, 0, 0, NULL, format, NULL, LYD_HINT_DATA, schema, NULL)); - ++((struct lysc_type *)val.realtype)->refcount; + /* validate the value and store the canonical value */ + r = lyd_value_validate2(NULL, schema, value, value_len, format, NULL, NULL, NULL, &canon); + LY_CHECK_RET(r && r != LY_EINCOMPLETE, r); /* store the new predicate so that it is used when searching for this instance */ LY_ARRAY_NEW_RET(schema->module->ctx, path[u].predicates, pred, LY_EMEM); pred->type = LY_PATH_PREDTYPE_LEAFLIST; - pred->value = val; + pred->value = canon; } /* else we have opaq flag and the value is not valid, leave no predicate and then create an opaque node */ } } @@ -1669,7 +1639,7 @@ lyd_new_path_(struct lyd_node *parent, const struct ly_ctx *ctx, const struct ly struct ly_path *p = NULL; struct lyd_node *nparent = NULL, *nnode = NULL, *node = NULL, *cur_parent, *iter; const struct lysc_node *schema; - const struct lyd_value *val = NULL; + const char *val = NULL; ly_bool store_only = (options & LYD_NEW_VAL_STORE_ONLY) ? 1 : 0; ly_bool any_use_value = (options & LYD_NEW_ANY_USE_VALUE) ? 1 : 0; LY_ARRAY_COUNT_TYPE path_idx = 0, orig_count = 0; @@ -1813,12 +1783,13 @@ lyd_new_path_(struct lyd_node *parent, const struct ly_ctx *ctx, const struct ly /* get value to set */ if (p[path_idx].predicates && (p[path_idx].predicates[0].type == LY_PATH_PREDTYPE_LEAFLIST)) { - val = &p[path_idx].predicates[0].value; + val = p[path_idx].predicates[0].value; } /* create a leaf-list instance */ if (val) { - LY_CHECK_GOTO(ret = lyd_create_term2(schema, val, &node), cleanup); + LY_CHECK_GOTO(ret = lyd_create_term(schema, val, strlen(val), 0, store_only, NULL, format, NULL, + LYD_HINT_DATA, NULL, &node), cleanup); } else { LY_CHECK_GOTO(ret = lyd_create_term(schema, value, value_len, 0, store_only, NULL, format, NULL, LYD_HINT_DATA, NULL, &node), cleanup); @@ -1887,7 +1858,7 @@ lyd_new_path_(struct lyd_node *parent, const struct ly_ctx *ctx, const struct ly } cleanup: - lyxp_expr_free(ctx, exp); + lyxp_expr_free(exp); if (p) { while (orig_count > LY_ARRAY_COUNT(p)) { LY_ARRAY_INCREMENT(p); @@ -1949,12 +1920,12 @@ lyd_new_implicit(struct lyd_node *parent, struct lyd_node **first, const struct const struct lys_module *mod, struct ly_set *node_when, struct ly_set *node_types, struct ly_set *ext_node, uint32_t impl_opts, struct ly_ht *getnext_ht, struct lyd_node **diff) { - LY_ERR ret; const struct lysc_node *snode, **choices, **snodes; struct lyd_node *node = NULL; - struct lyd_value **dflts; + struct lysc_value *dflts; LY_ARRAY_COUNT_TYPE u; uint32_t i; + ly_bool incomplete; assert(first && (parent || sparent || mod)); @@ -2025,17 +1996,15 @@ lyd_new_implicit(struct lyd_node *parent, struct lyd_node **first, const struct } break; case LYS_LEAF: - if (!(impl_opts & LYD_IMPLICIT_NO_DEFAULTS) && ((struct lysc_node_leaf *)snode)->dflt && + if (!(impl_opts & LYD_IMPLICIT_NO_DEFAULTS) && ((struct lysc_node_leaf *)snode)->dflt.str && lyd_find_sibling_val(*first, snode, NULL, 0, NULL)) { /* create default leaf */ - ret = lyd_create_term2(snode, ((struct lysc_node_leaf *)snode)->dflt, &node); - if (ret == LY_EINCOMPLETE) { - if (node_types) { - /* remember to resolve type */ - LY_CHECK_RET(ly_set_add(node_types, node, 1, NULL)); - } - } else if (ret) { - return ret; + LY_CHECK_RET(lyd_create_term(snode, ((struct lysc_node_leaf *)snode)->dflt.str, + strlen(((struct lysc_node_leaf *)snode)->dflt.str), 1, 1, NULL, LY_VALUE_SCHEMA_RESOLVED, + ((struct lysc_node_leaf *)snode)->dflt.prefixes, LYD_HINT_DATA, &incomplete, &node)); + if (incomplete && node_types) { + /* remember to resolve type */ + LY_CHECK_RET(ly_set_add(node_types, node, 1, NULL)); } node->flags = LYD_DEFAULT | (lysc_has_when(snode) ? LYD_WHEN_TRUE : 0); lyd_insert_node(parent, first, node, LYD_INSERT_NODE_DEFAULT); @@ -2060,14 +2029,11 @@ lyd_new_implicit(struct lyd_node *parent, struct lyd_node **first, const struct /* create all default leaf-lists */ dflts = ((struct lysc_node_leaflist *)snode)->dflts; LY_ARRAY_FOR(dflts, u) { - ret = lyd_create_term2(snode, dflts[u], &node); - if (ret == LY_EINCOMPLETE) { - if (node_types) { - /* remember to resolve type */ - LY_CHECK_RET(ly_set_add(node_types, node, 1, NULL)); - } - } else if (ret) { - return ret; + LY_CHECK_RET(lyd_create_term(snode, dflts[u].str, strlen(dflts[u].str), 1, 1, NULL, + LY_VALUE_SCHEMA_RESOLVED, dflts[u].prefixes, LYD_HINT_DATA, &incomplete, &node)); + if (incomplete && node_types) { + /* remember to resolve type */ + LY_CHECK_RET(ly_set_add(node_types, node, 1, NULL)); } node->flags = LYD_DEFAULT | (lysc_has_when(snode) ? LYD_WHEN_TRUE : 0); lyd_insert_node(parent, first, node, LYD_INSERT_NODE_DEFAULT); diff --git a/src/tree_data_sorted.c b/src/tree_data_sorted.c index ce0820ce7..e27927a87 100644 --- a/src/tree_data_sorted.c +++ b/src/tree_data_sorted.c @@ -196,7 +196,7 @@ static int rb_sort_clb(const struct ly_ctx *ctx, const struct lyd_value *val1, const struct lyd_value *val2) { assert(val1->realtype == val2->realtype); - return val1->realtype->plugin->sort(ctx, val1, val2); + return LYSC_GET_TYPE_PLG(val1->realtype->plugin_ref)->sort(ctx, val1, val2); } /** diff --git a/src/tree_schema.c b/src/tree_schema.c index 916a834e4..24f8a554f 100644 --- a/src/tree_schema.c +++ b/src/tree_schema.c @@ -259,7 +259,7 @@ lys_getnext_(const struct lysc_node *last, const struct lysc_node *parent, const LY_ARRAY_FOR(parent->exts, u) { if (!strcmp(parent->exts[u].def->name, "mount-point") && !strcmp(parent->exts[u].def->module->name, "ietf-yang-schema-mount")) { - lyplg_ext_schema_mount_get_ctx(&parent->exts[u], &sm_ctx); + lyplg_ext_schema_mount_get_ctx(&parent->exts[u], NULL, &sm_ctx); if (sm_ctx) { /* some usable context created */ break; @@ -478,7 +478,7 @@ lys_find_xpath_atoms(const struct ly_ctx *ctx, const struct lysc_node *ctx_node, cleanup: lyxp_set_free_content(&xp_set); - lyxp_expr_free(ctx, exp); + lyxp_expr_free(exp); return ret; } @@ -573,7 +573,7 @@ lys_find_xpath(const struct ly_ctx *ctx, const struct lysc_node *ctx_node, const cleanup: lyxp_set_free_content(&xp_set); - lyxp_expr_free(ctx, exp); + lyxp_expr_free(exp); if (ret) { ly_set_free(*set, NULL); *set = NULL; @@ -642,7 +642,7 @@ lys_find_path_atoms(const struct ly_ctx *ctx, const struct lysc_node *ctx_node, cleanup: ly_path_free(p); - lyxp_expr_free(ctx, expr); + lyxp_expr_free(expr); return ret; } @@ -677,7 +677,7 @@ lys_find_path(const struct ly_ctx *ctx, const struct lysc_node *ctx_node, const cleanup: ly_path_free(p); - lyxp_expr_free(ctx, expr); + lyxp_expr_free(expr); return snode; } @@ -828,7 +828,7 @@ _lys_set_implemented(struct lys_module *mod, const char **features, struct lys_g r = lys_implement(mod, features, unres); LY_CHECK_ERR_GOTO(r && (r != LY_ERECOMPILE), ret = r, cleanup); - if (mod->ctx->flags & LY_CTX_ALL_IMPLEMENTED) { + if (mod->ctx->opts & LY_CTX_ALL_IMPLEMENTED) { /* implement all the imports as well */ for (i = 0; i < unres->creating.count; ++i) { mod = unres->creating.objs[i]; @@ -836,7 +836,7 @@ _lys_set_implemented(struct lys_module *mod, const char **features, struct lys_g continue; } - imp_f = (mod->ctx->flags & LY_CTX_ENABLE_IMP_FEATURES) ? all_f : NULL; + imp_f = (mod->ctx->opts & LY_CTX_ENABLE_IMP_FEATURES) ? all_f : NULL; r = lys_implement(mod, imp_f, unres); LY_CHECK_ERR_GOTO(r && (r != LY_ERECOMPILE), ret = r, cleanup); } @@ -935,8 +935,8 @@ lys_unres_dep_sets_create_mod_r(struct lys_module *mod, struct ly_set *ctx_set, } /* process modules and submodules importing this module */ - for (i = 0; i < mod->ctx->list.count; ++i) { - mod2 = mod->ctx->list.objs[i]; + for (i = 0; i < mod->ctx->modules.count; ++i) { + mod2 = mod->ctx->modules.objs[i]; found = 0; imports = mod2->parsed->imports; @@ -1020,7 +1020,7 @@ lys_unres_dep_sets_create(struct ly_ctx *ctx, struct ly_set *main_set, struct ly assert(!main_set->count); /* start with a duplicate set of modules that we will remove from */ - LY_CHECK_GOTO(ret = ly_set_dup(&ctx->list, NULL, &ctx_set), cleanup); + LY_CHECK_GOTO(ret = ly_set_dup(&ctx->modules, NULL, &ctx_set), cleanup); /* first create all dep sets with single modules */ LY_CHECK_GOTO(ret = lys_unres_dep_sets_create_single(ctx_set, main_set), cleanup); @@ -1099,46 +1099,43 @@ void lys_unres_glob_revert(struct ly_ctx *ctx, struct lys_glob_unres *unres) { uint32_t i, j, idx, *prev_lo, temp_lo = 0; - struct lysf_ctx fctx = {.ctx = ctx}; + struct lys_module *mod; struct ly_set *dep_set; LY_ERR ret; for (i = 0; i < unres->implementing.count; ++i) { - fctx.mod = unres->implementing.objs[i]; - assert(fctx.mod->implemented); + mod = unres->implementing.objs[i]; + assert(mod->implemented); /* make the module correctly non-implemented again */ - fctx.mod->implemented = 0; - lys_precompile_augments_deviations_revert(ctx, fctx.mod); - lysc_module_free(&fctx, fctx.mod->compiled); - fctx.mod->compiled = NULL; + mod->implemented = 0; + lys_precompile_augments_deviations_revert(ctx, mod); + lysc_module_free(ctx, mod->compiled); + mod->compiled = NULL; /* should not be made implemented */ - fctx.mod->to_compile = 0; + mod->to_compile = 0; } for (i = 0; i < unres->creating.count; ++i) { - fctx.mod = unres->creating.objs[i]; + mod = unres->creating.objs[i]; /* remove the module from the context */ - ly_set_rm(&ctx->list, fctx.mod, NULL); + ly_set_rm(&ctx->modules, mod, NULL); /* remove it also from dep sets */ for (j = 0; j < unres->dep_sets.count; ++j) { dep_set = unres->dep_sets.objs[j]; - if (ly_set_contains(dep_set, fctx.mod, &idx)) { + if (ly_set_contains(dep_set, mod, &idx)) { ly_set_rm_index(dep_set, idx, NULL); break; } } /* free the module */ - lys_module_free(&fctx, fctx.mod, 1); + lys_module_free(ctx, mod, 1); } - /* remove the extensions as well */ - lysf_ctx_erase(&fctx); - if (unres->implementing.count) { /* recompile previous context because some implemented modules are no longer implemented, * we can reuse the current to_compile flags */ @@ -1177,13 +1174,13 @@ 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, mod->parsed, LY_EINVAL); + LY_CHECK_ARG_RET(NULL, mod, mod->parsed, !(mod->ctx->opts & LY_CTX_INT_IMMUTABLE), LY_EINVAL); /* implement */ ret = _lys_set_implemented(mod, features, unres); LY_CHECK_GOTO(ret, cleanup); - if (!(mod->ctx->flags & LY_CTX_EXPLICIT_COMPILE)) { + if (!(mod->ctx->opts & LY_CTX_EXPLICIT_COMPILE)) { /* create dep set for the module and mark all the modules that will be (re)compiled */ LY_CHECK_GOTO(ret = lys_unres_dep_sets_create(mod->ctx, &unres->dep_sets, mod), cleanup); @@ -1192,10 +1189,10 @@ lys_set_implemented(struct lys_module *mod, const char **features) /* unres resolved */ lys_unres_glob_erase(unres); - } - /* new context state */ - ly_ctx_new_change(mod->ctx); + /* new context state */ + ly_ctx_new_change(mod->ctx); + } cleanup: if (ret) { @@ -1353,12 +1350,13 @@ static LY_ERR lysp_resolve_ext_instance_records(struct lysp_ctx *pctx) { LY_ERR r; - struct lysf_ctx fctx = {.ctx = PARSER_CTX(pctx)}; struct lysp_ext_instance *exts, *ext; + struct lysp_ext *ext_def; const struct lys_module *mod; uint32_t i; LY_ARRAY_COUNT_TYPE u; char *path = NULL; + struct lyplg_ext *ext_plg; /* first finish parsing all extension instances ... */ for (i = 0; i < pctx->ext_inst.count; ++i) { @@ -1366,14 +1364,12 @@ lysp_resolve_ext_instance_records(struct lysp_ctx *pctx) LY_ARRAY_FOR(exts, u) { ext = &exts[u]; - /* find the extension definition */ - LY_CHECK_RET(lysp_ext_find_definition(PARSER_CTX(pctx), ext, &mod, &ext->def)); + /* find the extension definition, use its plugin */ + LY_CHECK_RET(lysp_ext_find_definition(PARSER_CTX(pctx), ext, &mod, &ext_def)); + ext->plugin_ref = ext_def->plugin_ref; /* resolve the argument, if needed */ - LY_CHECK_RET(lysp_ext_instance_resolve_argument(PARSER_CTX(pctx), ext)); - - /* find the extension record, if any */ - ext->record = lyplg_ext_record_find(mod->ctx, mod->name, mod->revision, ext->def->name); + LY_CHECK_RET(lysp_ext_instance_resolve_argument(PARSER_CTX(pctx), ext_def, ext)); } } @@ -1383,7 +1379,7 @@ lysp_resolve_ext_instance_records(struct lysp_ctx *pctx) u = 0; while (u < LY_ARRAY_COUNT(exts)) { ext = &exts[u]; - if (!ext->record || !ext->record->plugin.parse) { + if (!ext->plugin_ref || !(ext_plg = LYSC_GET_EXT_PLG(ext->plugin_ref))->parse) { goto next_iter; } @@ -1394,14 +1390,14 @@ lysp_resolve_ext_instance_records(struct lysp_ctx *pctx) ly_log_location(NULL, NULL, path, NULL); /* parse */ - r = ext->record->plugin.parse(pctx, ext); + r = ext_plg->parse(pctx, ext); ly_log_location_revert(0, 0, 1, 0); free(path); if (r == LY_ENOT) { /* instance should be ignored, remove it */ - lysp_ext_instance_free(&fctx, ext); + lysp_ext_instance_free(PARSER_CTX(pctx), ext); LY_ARRAY_DECREMENT(exts); if (u < LY_ARRAY_COUNT(exts)) { /* replace by the last item */ @@ -1542,8 +1538,7 @@ lys_parse_submodule(struct ly_ctx *ctx, struct ly_in *in, LYS_INFORMAT format, s struct lysp_submodule *submod = NULL, *latest_sp; struct lysp_yang_ctx *yangctx = NULL; struct lysp_yin_ctx *yinctx = NULL; - struct lysp_ctx *pctx = NULL; - struct lysf_ctx fctx = {.ctx = ctx}; + struct lysp_ctx *pctx; LY_CHECK_ARG_RET(ctx, ctx, in, LY_EINVAL); @@ -1599,7 +1594,7 @@ lys_parse_submodule(struct ly_ctx *ctx, struct ly_in *in, LYS_INFORMAT format, s ly_set_erase(&pctx->tpdfs_nodes, NULL); ly_set_erase(&pctx->grps_nodes, NULL); ly_set_erase(&pctx->ext_inst, NULL); - lysp_module_free(&fctx, (struct lysp_module *)submod); + lysp_module_free(ctx, (struct lysp_module *)submod); submod = NULL; goto cleanup; } else if (r) { @@ -1624,7 +1619,7 @@ lys_parse_submodule(struct ly_ctx *ctx, struct ly_in *in, LYS_INFORMAT format, s ly_set_erase(&pctx->grps_nodes, NULL); ly_set_erase(&pctx->ext_inst, NULL); } - lysp_module_free(&fctx, (struct lysp_module *)submod); + lysp_module_free(ctx, (struct lysp_module *)submod); } else if (submod) { *submodule = submod; @@ -1669,8 +1664,8 @@ lysp_add_internal_ietf_netconf(struct lysp_ctx *pctx, struct lysp_module *mod) */ LY_ARRAY_NEW_RET(mod->mod->ctx, mod->exts, extp, LY_EMEM); LY_CHECK_ERR_RET(!extp, LOGMEM(mod->mod->ctx), LY_EMEM); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "md_:annotation", 0, &extp->name)); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "operation", 0, &extp->argument)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "md_:annotation", 0, &extp->name)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "operation", 0, &extp->argument)); extp->format = LY_VALUE_SCHEMA; extp->prefix_data = mod; extp->parent = mod; @@ -1679,8 +1674,8 @@ lysp_add_internal_ietf_netconf(struct lysp_ctx *pctx, struct lysp_module *mod) extp->child = stmt = calloc(1, sizeof *extp->child); LY_CHECK_ERR_RET(!stmt, LOGMEM(mod->mod->ctx), LY_EMEM); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "type", 0, &stmt->stmt)); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "enumeration", 0, &stmt->arg)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "type", 0, &stmt->stmt)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "enumeration", 0, &stmt->arg)); stmt->format = LY_VALUE_SCHEMA; stmt->prefix_data = mod; stmt->kw = LY_STMT_TYPE; @@ -1688,8 +1683,8 @@ lysp_add_internal_ietf_netconf(struct lysp_ctx *pctx, struct lysp_module *mod) stmt->child = calloc(1, sizeof *stmt->child); stmt = stmt->child; LY_CHECK_ERR_RET(!stmt, LOGMEM(mod->mod->ctx), LY_EMEM); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "enum", 0, &stmt->stmt)); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "merge", 0, &stmt->arg)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "enum", 0, &stmt->stmt)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "merge", 0, &stmt->arg)); stmt->format = LY_VALUE_SCHEMA; stmt->prefix_data = mod; stmt->kw = LY_STMT_ENUM; @@ -1697,8 +1692,8 @@ lysp_add_internal_ietf_netconf(struct lysp_ctx *pctx, struct lysp_module *mod) stmt->next = calloc(1, sizeof *stmt->child); stmt = stmt->next; LY_CHECK_ERR_RET(!stmt, LOGMEM(mod->mod->ctx), LY_EMEM); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "enum", 0, &stmt->stmt)); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "replace", 0, &stmt->arg)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "enum", 0, &stmt->stmt)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "replace", 0, &stmt->arg)); stmt->format = LY_VALUE_SCHEMA; stmt->prefix_data = mod; stmt->kw = LY_STMT_ENUM; @@ -1706,8 +1701,8 @@ lysp_add_internal_ietf_netconf(struct lysp_ctx *pctx, struct lysp_module *mod) stmt->next = calloc(1, sizeof *stmt->child); stmt = stmt->next; LY_CHECK_ERR_RET(!stmt, LOGMEM(mod->mod->ctx), LY_EMEM); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "enum", 0, &stmt->stmt)); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "create", 0, &stmt->arg)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "enum", 0, &stmt->stmt)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "create", 0, &stmt->arg)); stmt->format = LY_VALUE_SCHEMA; stmt->prefix_data = mod; stmt->kw = LY_STMT_ENUM; @@ -1715,8 +1710,8 @@ lysp_add_internal_ietf_netconf(struct lysp_ctx *pctx, struct lysp_module *mod) stmt->next = calloc(1, sizeof *stmt->child); stmt = stmt->next; LY_CHECK_ERR_RET(!stmt, LOGMEM(mod->mod->ctx), LY_EMEM); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "enum", 0, &stmt->stmt)); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "delete", 0, &stmt->arg)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "enum", 0, &stmt->stmt)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "delete", 0, &stmt->arg)); stmt->format = LY_VALUE_SCHEMA; stmt->prefix_data = mod; stmt->kw = LY_STMT_ENUM; @@ -1724,8 +1719,8 @@ lysp_add_internal_ietf_netconf(struct lysp_ctx *pctx, struct lysp_module *mod) stmt->next = calloc(1, sizeof *stmt->child); stmt = stmt->next; LY_CHECK_ERR_RET(!stmt, LOGMEM(mod->mod->ctx), LY_EMEM); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "enum", 0, &stmt->stmt)); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "remove", 0, &stmt->arg)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "enum", 0, &stmt->stmt)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "remove", 0, &stmt->arg)); stmt->format = LY_VALUE_SCHEMA; stmt->prefix_data = mod; stmt->kw = LY_STMT_ENUM; @@ -1735,8 +1730,8 @@ lysp_add_internal_ietf_netconf(struct lysp_ctx *pctx, struct lysp_module *mod) */ LY_ARRAY_NEW_RET(mod->mod->ctx, mod->exts, extp, LY_EMEM); LY_CHECK_ERR_RET(!extp, LOGMEM(mod->mod->ctx), LY_EMEM); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "md_:annotation", 0, &extp->name)); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "type", 0, &extp->argument)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "md_:annotation", 0, &extp->name)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "type", 0, &extp->argument)); extp->format = LY_VALUE_SCHEMA; extp->prefix_data = mod; extp->parent = mod; @@ -1745,8 +1740,8 @@ lysp_add_internal_ietf_netconf(struct lysp_ctx *pctx, struct lysp_module *mod) extp->child = stmt = calloc(1, sizeof *extp->child); LY_CHECK_ERR_RET(!stmt, LOGMEM(mod->mod->ctx), LY_EMEM); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "type", 0, &stmt->stmt)); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "enumeration", 0, &stmt->arg)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "type", 0, &stmt->stmt)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "enumeration", 0, &stmt->arg)); stmt->format = LY_VALUE_SCHEMA; stmt->prefix_data = mod; stmt->kw = LY_STMT_TYPE; @@ -1754,8 +1749,8 @@ lysp_add_internal_ietf_netconf(struct lysp_ctx *pctx, struct lysp_module *mod) stmt->child = calloc(1, sizeof *stmt->child); stmt = stmt->child; LY_CHECK_ERR_RET(!stmt, LOGMEM(mod->mod->ctx), LY_EMEM); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "enum", 0, &stmt->stmt)); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "subtree", 0, &stmt->arg)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "enum", 0, &stmt->stmt)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "subtree", 0, &stmt->arg)); stmt->format = LY_VALUE_SCHEMA; stmt->prefix_data = mod; stmt->kw = LY_STMT_ENUM; @@ -1763,8 +1758,8 @@ lysp_add_internal_ietf_netconf(struct lysp_ctx *pctx, struct lysp_module *mod) stmt->next = calloc(1, sizeof *stmt->child); stmt = stmt->next; LY_CHECK_ERR_RET(!stmt, LOGMEM(mod->mod->ctx), LY_EMEM); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "enum", 0, &stmt->stmt)); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "xpath", 0, &stmt->arg)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "enum", 0, &stmt->stmt)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "xpath", 0, &stmt->arg)); stmt->format = LY_VALUE_SCHEMA; stmt->prefix_data = mod; stmt->kw = LY_STMT_ENUM; @@ -1774,8 +1769,8 @@ lysp_add_internal_ietf_netconf(struct lysp_ctx *pctx, struct lysp_module *mod) stmt->child = calloc(1, sizeof *stmt->child); stmt = stmt->child; LY_CHECK_ERR_RET(!stmt, LOGMEM(mod->mod->ctx), LY_EMEM); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "if-feature", 0, &stmt->stmt)); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "xpath", 0, &stmt->arg)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "if-feature", 0, &stmt->stmt)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "xpath", 0, &stmt->arg)); stmt->format = LY_VALUE_SCHEMA; stmt->prefix_data = mod; stmt->kw = LY_STMT_IF_FEATURE; @@ -1786,8 +1781,8 @@ lysp_add_internal_ietf_netconf(struct lysp_ctx *pctx, struct lysp_module *mod) */ LY_ARRAY_NEW_RET(mod->mod->ctx, mod->exts, extp, LY_EMEM); LY_CHECK_ERR_RET(!extp, LOGMEM(mod->mod->ctx), LY_EMEM); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "md_:annotation", 0, &extp->name)); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "select", 0, &extp->argument)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "md_:annotation", 0, &extp->name)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "select", 0, &extp->argument)); extp->format = LY_VALUE_SCHEMA; extp->prefix_data = mod; extp->parent = mod; @@ -1796,8 +1791,8 @@ lysp_add_internal_ietf_netconf(struct lysp_ctx *pctx, struct lysp_module *mod) extp->child = stmt = calloc(1, sizeof *extp->child); LY_CHECK_ERR_RET(!stmt, LOGMEM(mod->mod->ctx), LY_EMEM); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "type", 0, &stmt->stmt)); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "yang_:xpath1.0", 0, &stmt->arg)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "type", 0, &stmt->stmt)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "yang_:xpath1.0", 0, &stmt->arg)); stmt->format = LY_VALUE_SCHEMA; stmt->prefix_data = mod; stmt->kw = LY_STMT_TYPE; @@ -1819,111 +1814,111 @@ lysp_add_internal_ietf_netconf(struct lysp_ctx *pctx, struct lysp_module *mod) */ LY_LIST_NEW_RET(mod->mod->ctx, &mod->data, cont, next, LY_EMEM); cont->nodetype = LYS_CONTAINER; - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "rpc-error", 0, &cont->name)); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "presence", 0, &cont->presence)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "rpc-error", 0, &cont->name)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "presence", 0, &cont->presence)); cont->flags = LYS_INTERNAL; LY_LIST_NEW_RET(mod->mod->ctx, &cont->child, leaf, next, LY_EMEM); leaf->nodetype = LYS_LEAF; - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "error-type", 0, &leaf->name)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "error-type", 0, &leaf->name)); leaf->flags = LYS_INTERNAL; - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "enumeration", 0, &leaf->type.name)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "enumeration", 0, &leaf->type.name)); leaf->type.pmod = mod; leaf->type.flags = LYS_SET_ENUM; LY_ARRAY_NEW_RET(mod->mod->ctx, leaf->type.enums, enm, LY_EMEM); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "transport", 0, &enm->name)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "transport", 0, &enm->name)); LY_ARRAY_NEW_RET(mod->mod->ctx, leaf->type.enums, enm, LY_EMEM); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "rpc", 0, &enm->name)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "rpc", 0, &enm->name)); LY_ARRAY_NEW_RET(mod->mod->ctx, leaf->type.enums, enm, LY_EMEM); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "protocol", 0, &enm->name)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "protocol", 0, &enm->name)); LY_ARRAY_NEW_RET(mod->mod->ctx, leaf->type.enums, enm, LY_EMEM); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "application", 0, &enm->name)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "application", 0, &enm->name)); LY_LIST_NEW_RET(mod->mod->ctx, &cont->child, leaf, next, LY_EMEM); leaf->nodetype = LYS_LEAF; - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "error-tag", 0, &leaf->name)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "error-tag", 0, &leaf->name)); leaf->flags = LYS_INTERNAL; - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "enumeration", 0, &leaf->type.name)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "enumeration", 0, &leaf->type.name)); leaf->type.pmod = mod; leaf->type.flags = LYS_SET_ENUM; LY_ARRAY_NEW_RET(mod->mod->ctx, leaf->type.enums, enm, LY_EMEM); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "in-use", 0, &enm->name)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "in-use", 0, &enm->name)); LY_ARRAY_NEW_RET(mod->mod->ctx, leaf->type.enums, enm, LY_EMEM); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "invalid-value", 0, &enm->name)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "invalid-value", 0, &enm->name)); LY_ARRAY_NEW_RET(mod->mod->ctx, leaf->type.enums, enm, LY_EMEM); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "too-big", 0, &enm->name)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "too-big", 0, &enm->name)); LY_ARRAY_NEW_RET(mod->mod->ctx, leaf->type.enums, enm, LY_EMEM); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "missing-attribute", 0, &enm->name)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "missing-attribute", 0, &enm->name)); LY_ARRAY_NEW_RET(mod->mod->ctx, leaf->type.enums, enm, LY_EMEM); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "bad-attribute", 0, &enm->name)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "bad-attribute", 0, &enm->name)); LY_ARRAY_NEW_RET(mod->mod->ctx, leaf->type.enums, enm, LY_EMEM); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "unknown-attribute", 0, &enm->name)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "unknown-attribute", 0, &enm->name)); LY_ARRAY_NEW_RET(mod->mod->ctx, leaf->type.enums, enm, LY_EMEM); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "missing-element", 0, &enm->name)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "missing-element", 0, &enm->name)); LY_ARRAY_NEW_RET(mod->mod->ctx, leaf->type.enums, enm, LY_EMEM); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "bad-element", 0, &enm->name)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "bad-element", 0, &enm->name)); LY_ARRAY_NEW_RET(mod->mod->ctx, leaf->type.enums, enm, LY_EMEM); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "unknown-element", 0, &enm->name)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "unknown-element", 0, &enm->name)); LY_ARRAY_NEW_RET(mod->mod->ctx, leaf->type.enums, enm, LY_EMEM); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "unknown-namespace", 0, &enm->name)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "unknown-namespace", 0, &enm->name)); LY_ARRAY_NEW_RET(mod->mod->ctx, leaf->type.enums, enm, LY_EMEM); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "access-denied", 0, &enm->name)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "access-denied", 0, &enm->name)); LY_ARRAY_NEW_RET(mod->mod->ctx, leaf->type.enums, enm, LY_EMEM); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "lock-denied", 0, &enm->name)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "lock-denied", 0, &enm->name)); LY_ARRAY_NEW_RET(mod->mod->ctx, leaf->type.enums, enm, LY_EMEM); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "resource-denied", 0, &enm->name)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "resource-denied", 0, &enm->name)); LY_ARRAY_NEW_RET(mod->mod->ctx, leaf->type.enums, enm, LY_EMEM); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "rollback-failed", 0, &enm->name)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "rollback-failed", 0, &enm->name)); LY_ARRAY_NEW_RET(mod->mod->ctx, leaf->type.enums, enm, LY_EMEM); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "data-exists", 0, &enm->name)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "data-exists", 0, &enm->name)); LY_ARRAY_NEW_RET(mod->mod->ctx, leaf->type.enums, enm, LY_EMEM); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "data-missing", 0, &enm->name)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "data-missing", 0, &enm->name)); LY_ARRAY_NEW_RET(mod->mod->ctx, leaf->type.enums, enm, LY_EMEM); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "operation-not-supported", 0, &enm->name)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "operation-not-supported", 0, &enm->name)); LY_ARRAY_NEW_RET(mod->mod->ctx, leaf->type.enums, enm, LY_EMEM); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "operation-failed", 0, &enm->name)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "operation-failed", 0, &enm->name)); LY_ARRAY_NEW_RET(mod->mod->ctx, leaf->type.enums, enm, LY_EMEM); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "partial-operation", 0, &enm->name)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "partial-operation", 0, &enm->name)); LY_ARRAY_NEW_RET(mod->mod->ctx, leaf->type.enums, enm, LY_EMEM); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "malformed-message", 0, &enm->name)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "malformed-message", 0, &enm->name)); LY_LIST_NEW_RET(mod->mod->ctx, &cont->child, leaf, next, LY_EMEM); leaf->nodetype = LYS_LEAF; - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "error-severity", 0, &leaf->name)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "error-severity", 0, &leaf->name)); leaf->flags = LYS_INTERNAL; - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "enumeration", 0, &leaf->type.name)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "enumeration", 0, &leaf->type.name)); leaf->type.pmod = mod; leaf->type.flags = LYS_SET_ENUM; LY_ARRAY_NEW_RET(mod->mod->ctx, leaf->type.enums, enm, LY_EMEM); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "error", 0, &enm->name)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "error", 0, &enm->name)); LY_ARRAY_NEW_RET(mod->mod->ctx, leaf->type.enums, enm, LY_EMEM); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "warning", 0, &enm->name)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "warning", 0, &enm->name)); LY_LIST_NEW_RET(mod->mod->ctx, &cont->child, leaf, next, LY_EMEM); leaf->nodetype = LYS_LEAF; - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "error-app-tag", 0, &leaf->name)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "error-app-tag", 0, &leaf->name)); leaf->flags = LYS_INTERNAL; - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "string", 0, &leaf->type.name)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "string", 0, &leaf->type.name)); leaf->type.pmod = mod; LY_LIST_NEW_RET(mod->mod->ctx, &cont->child, leaf, next, LY_EMEM); leaf->nodetype = LYS_LEAF; - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "error-path", 0, &leaf->name)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "error-path", 0, &leaf->name)); leaf->flags = LYS_INTERNAL; - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "yang_:xpath1.0", 0, &leaf->type.name)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "yang_:xpath1.0", 0, &leaf->type.name)); leaf->type.pmod = mod; /* the rest are opaque nodes, error-message (because of 'xml:lang' attribute) and error-info (because can be any nodes) */ /* create new imports for the used prefixes */ LY_ARRAY_NEW_RET(mod->mod->ctx, mod->imports, imp, LY_EMEM); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "ietf-yang-metadata", 0, &imp->name)); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "md_", 0, &imp->prefix)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "ietf-yang-metadata", 0, &imp->name)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "md_", 0, &imp->prefix)); imp->flags = LYS_INTERNAL; LY_ARRAY_NEW_RET(mod->mod->ctx, mod->imports, imp, LY_EMEM); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "ietf-yang-types", 0, &imp->name)); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "yang_", 0, &imp->prefix)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "ietf-yang-types", 0, &imp->name)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "yang_", 0, &imp->prefix)); imp->flags = LYS_INTERNAL; return LY_SUCCESS; @@ -1949,8 +1944,8 @@ lysp_add_internal_ietf_netconf_with_defaults(struct lysp_ctx *pctx, struct lysp_ LY_ARRAY_NEW_RET(mod->mod->ctx, mod->exts, extp, LY_EMEM); /* fill in the extension instance fields */ - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "md_:annotation", 0, &extp->name)); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "default", 0, &extp->argument)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "md_:annotation", 0, &extp->name)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "default", 0, &extp->argument)); extp->format = LY_VALUE_SCHEMA; extp->prefix_data = mod; extp->parent = mod; @@ -1959,8 +1954,8 @@ lysp_add_internal_ietf_netconf_with_defaults(struct lysp_ctx *pctx, struct lysp_ extp->child = stmt = calloc(1, sizeof *extp->child); LY_CHECK_ERR_RET(!stmt, LOGMEM(mod->mod->ctx), LY_EMEM); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "type", 0, &stmt->stmt)); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "boolean", 0, &stmt->arg)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "type", 0, &stmt->stmt)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "boolean", 0, &stmt->arg)); stmt->format = LY_VALUE_SCHEMA; stmt->prefix_data = mod; stmt->kw = LY_STMT_TYPE; @@ -1979,8 +1974,8 @@ lysp_add_internal_ietf_netconf_with_defaults(struct lysp_ctx *pctx, struct lysp_ /* create new import for the used prefix */ LY_ARRAY_NEW_RET(mod->mod->ctx, mod->imports, imp, LY_EMEM); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "ietf-yang-metadata", 0, &imp->name)); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "md_", 0, &imp->prefix)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "ietf-yang-metadata", 0, &imp->name)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "md_", 0, &imp->prefix)); imp->flags = LYS_INTERNAL; return LY_SUCCESS; @@ -2007,16 +2002,16 @@ lysp_add_internal_yang(struct lysp_ctx *pctx, struct lysp_module *mod) /* add new typedef */ LY_ARRAY_NEW_RET(PARSER_CTX(pctx), mod->typedefs, tpdf, LY_EMEM); - LY_CHECK_RET(lydict_insert(PARSER_CTX(pctx), "lyds_tree", 0, &tpdf->name)); - LY_CHECK_RET(lydict_insert(PARSER_CTX(pctx), "uint64", 0, &tpdf->type.name)); + LY_CHECK_RET(lysdict_insert(PARSER_CTX(pctx), "lyds_tree", 0, &tpdf->name)); + LY_CHECK_RET(lysdict_insert(PARSER_CTX(pctx), "uint64", 0, &tpdf->type.name)); tpdf->type.pmod = mod; /* add new extension instance */ LY_ARRAY_NEW_RET(PARSER_CTX(pctx), mod->exts, extp, LY_EMEM); /* fill in the extension instance fields */ - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "md:annotation", 0, &extp->name)); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "lyds_tree", 0, &extp->argument)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "md:annotation", 0, &extp->name)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "lyds_tree", 0, &extp->argument)); extp->format = LY_VALUE_SCHEMA; extp->prefix_data = mod; extp->parent = mod; @@ -2026,8 +2021,8 @@ lysp_add_internal_yang(struct lysp_ctx *pctx, struct lysp_module *mod) /* prepare for metadata plugin */ extp->child = stmt = calloc(1, sizeof *extp->child); LY_CHECK_ERR_RET(!stmt, LOGMEM(mod->mod->ctx), LY_EMEM); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "type", 0, &stmt->stmt)); - LY_CHECK_RET(lydict_insert(mod->mod->ctx, "lyds_tree", 0, &stmt->arg)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "type", 0, &stmt->stmt)); + LY_CHECK_RET(lysdict_insert(mod->mod->ctx, "lyds_tree", 0, &stmt->arg)); stmt->format = LY_VALUE_SCHEMA; stmt->prefix_data = mod; stmt->kw = LY_STMT_TYPE; @@ -2047,6 +2042,35 @@ lysp_add_internal_yang(struct lysp_ctx *pctx, struct lysp_module *mod) return LY_SUCCESS; } +/** + * @brief Compile (copy) all submodules of a parsed module. + * + * @param[in] mod Module with the parsed and compiled module. + * @return LY_ERR value. + */ +static LY_ERR +lys_compile_submodules(struct lys_module *mod) +{ + LY_ERR rc = LY_SUCCESS; + LY_ARRAY_COUNT_TYPE u; + const struct lysp_submodule *submodp; + struct lysc_submodule *submod; + + LY_ARRAY_FOR(mod->parsed->includes, u) { + submodp = mod->parsed->includes[u].submodule; + + LY_ARRAY_NEW_GOTO(mod->ctx, mod->submodules, submod, rc, cleanup); + DUP_STRING_GOTO(mod->ctx, submodp->name, submod->name, rc, cleanup); + if (submodp->revs) { + LY_CHECK_GOTO(rc = lysdict_insert(mod->ctx, submodp->revs[0].date, 0, &submod->revision), cleanup); + } + DUP_STRING_GOTO(mod->ctx, submodp->filepath, submod->filepath, rc, cleanup); + } + +cleanup: + return rc; +} + LY_ERR lys_parse_in(struct ly_ctx *ctx, struct ly_in *in, LYS_INFORMAT format, const struct lysp_load_module_data *mod_data, struct ly_set *new_mods, struct lys_module **module) @@ -2056,7 +2080,7 @@ lys_parse_in(struct ly_ctx *ctx, struct ly_in *in, LYS_INFORMAT format, const st struct lysp_yang_ctx *yangctx = NULL; struct lysp_yin_ctx *yinctx = NULL; struct lysp_ctx *pctx = NULL; - struct lysf_ctx fctx = {.ctx = ctx}; + LY_ARRAY_COUNT_TYPE u; ly_bool mod_created = 0, mod_exists = 0; assert(ctx && in && new_mods); @@ -2089,7 +2113,7 @@ lys_parse_in(struct ly_ctx *ctx, struct ly_in *in, LYS_INFORMAT format, const st /* make sure that the newest revision is at position 0 */ lysp_sort_revisions(mod->parsed->revs); if (mod->parsed->revs) { - LY_CHECK_GOTO(rc = lydict_insert(ctx, mod->parsed->revs[0].date, 0, &mod->revision), cleanup); + LY_CHECK_GOTO(rc = lysdict_insert(ctx, mod->parsed->revs[0].date, 0, &mod->revision), cleanup); } /* decide the latest revision */ @@ -2177,13 +2201,17 @@ lys_parse_in(struct ly_ctx *ctx, struct ly_in *in, LYS_INFORMAT format, const st mod_created = 1; /* add into context */ - rc = ly_set_add(&ctx->list, mod, 1, NULL); + rc = ly_set_add(&ctx->modules, mod, 1, NULL); LY_CHECK_GOTO(rc, cleanup); /* resolve includes and all imports */ LY_CHECK_GOTO(rc = lysp_resolve_import_include(pctx, mod->parsed, new_mods), cleanup); - /* resolve extension instance plugin records */ + /* resolve extension plugins and parse extension instances */ + LY_ARRAY_FOR(mod->parsed->extensions, u) { + mod->parsed->extensions[u].plugin_ref = lyplg_ext_plugin_find(mod->ctx, mod->name, + mod->revision, mod->parsed->extensions[u].name); + } LY_CHECK_GOTO(rc = lysp_resolve_ext_instance_records(pctx), cleanup); /* check name collisions */ @@ -2192,11 +2220,11 @@ lys_parse_in(struct ly_ctx *ctx, struct ly_in *in, LYS_INFORMAT format, const st LY_CHECK_GOTO(rc = lysp_check_dup_features(pctx, mod->parsed), cleanup); LY_CHECK_GOTO(rc = lysp_check_dup_identities(pctx, mod->parsed), cleanup); - /* compile features */ + /* compile features, extensions, identities, and submodules */ LY_CHECK_GOTO(rc = lys_compile_feature_iffeatures(mod->parsed), cleanup); - - /* compile identities */ + LY_CHECK_GOTO(rc = lys_compile_extensions(mod), cleanup); LY_CHECK_GOTO(rc = lys_compile_identities(mod), cleanup); + LY_CHECK_GOTO(rc = lys_compile_submodules(mod), cleanup); cleanup: if (rc && mod && mod->name) { @@ -2209,10 +2237,7 @@ lys_parse_in(struct ly_ctx *ctx, struct ly_in *in, LYS_INFORMAT format, const st } } if (!mod_created) { - fctx.mod = mod; - lys_module_free(&fctx, mod, 0); - lysf_ctx_erase(&fctx); - + lys_module_free(ctx, mod, 0); mod = mod_dup; } @@ -2260,7 +2285,7 @@ lys_parse(struct ly_ctx *ctx, struct ly_in *in, LYS_INFORMAT format, const char if (module) { *module = NULL; } - LY_CHECK_ARG_RET(NULL, ctx, in, LY_EINVAL); + LY_CHECK_ARG_RET(NULL, ctx, !(ctx->opts & LY_CTX_INT_IMMUTABLE), in, LY_EINVAL); format = lys_parse_get_format(in, format); LY_CHECK_ARG_RET(ctx, format, LY_EINVAL); @@ -2276,7 +2301,7 @@ lys_parse(struct ly_ctx *ctx, struct ly_in *in, LYS_INFORMAT format, const char ret = _lys_set_implemented(mod, features, &ctx->unres); LY_CHECK_GOTO(ret, cleanup); - if (!(ctx->flags & LY_CTX_EXPLICIT_COMPILE)) { + if (!(ctx->opts & LY_CTX_EXPLICIT_COMPILE)) { /* create dep set for the module and mark all the modules that will be (re)compiled */ LY_CHECK_GOTO(ret = lys_unres_dep_sets_create(ctx, &ctx->unres.dep_sets, mod), cleanup); @@ -2285,10 +2310,10 @@ lys_parse(struct ly_ctx *ctx, struct ly_in *in, LYS_INFORMAT format, const char /* unres resolved */ lys_unres_glob_erase(&ctx->unres); - } - /* new context state */ - ly_ctx_new_change(ctx); + /* new context state */ + ly_ctx_new_change(ctx); + } cleanup: if (ret) { @@ -2306,7 +2331,7 @@ lys_parse_mem(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format, struct LY_ERR ret; struct ly_in *in = NULL; - LY_CHECK_ARG_RET(ctx, data, format != LYS_IN_UNKNOWN, LY_EINVAL); + LY_CHECK_ARG_RET(ctx, ctx, !(ctx->opts & LY_CTX_INT_IMMUTABLE), data, format != LYS_IN_UNKNOWN, LY_EINVAL); LY_CHECK_ERR_RET(ret = ly_in_new_memory(data, &in), LOGERR(ctx, ret, "Unable to create input handler."), ret); @@ -2322,7 +2347,7 @@ lys_parse_fd(struct ly_ctx *ctx, int fd, LYS_INFORMAT format, struct lys_module LY_ERR ret; struct ly_in *in = NULL; - LY_CHECK_ARG_RET(ctx, fd > -1, format != LYS_IN_UNKNOWN, LY_EINVAL); + LY_CHECK_ARG_RET(ctx, ctx, !(ctx->opts & LY_CTX_INT_IMMUTABLE), fd > -1, format != LYS_IN_UNKNOWN, LY_EINVAL); LY_CHECK_ERR_RET(ret = ly_in_new_fd(fd, &in), LOGERR(ctx, ret, "Unable to create input handler."), ret); @@ -2338,7 +2363,7 @@ lys_parse_path(struct ly_ctx *ctx, const char *path, LYS_INFORMAT format, struct LY_ERR ret; struct ly_in *in = NULL; - LY_CHECK_ARG_RET(ctx, path, format != LYS_IN_UNKNOWN, LY_EINVAL); + LY_CHECK_ARG_RET(ctx, ctx, !(ctx->opts & LY_CTX_INT_IMMUTABLE), path, format != LYS_IN_UNKNOWN, LY_EINVAL); LY_CHECK_ERR_RET(ret = ly_in_new_filepath(path, 0, &in), LOGERR(ctx, ret, "Unable to create input handler for filepath %s.", path), ret); diff --git a/src/tree_schema.h b/src/tree_schema.h index 35da1a415..256595336 100644 --- a/src/tree_schema.h +++ b/src/tree_schema.h @@ -299,12 +299,8 @@ struct lysp_ext { const char *dsc; /**< description statement */ const char *ref; /**< reference statement */ struct lysp_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */ + uintptr_t plugin_ref; /**< reference to extension plugin, use ::lysc_get_ext_plugin() to get the plugin */ uint16_t flags; /**< LYS_STATUS_* and LYS_YINELEM_* values (@ref snodeflags) */ - - struct lysc_ext *compiled; /**< pointer to the compiled extension definition. - The extension definition is compiled only if there is compiled extension instance, - otherwise this pointer remains NULL. The compiled extension definition is shared - among all extension instances. */ }; /** @@ -1187,7 +1183,7 @@ struct lysc_ext { const char *name; /**< extension name */ const char *argname; /**< argument name, NULL if not specified */ struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */ - struct lyplg_ext *plugin; /**< Plugin implementing the specific extension */ + uintptr_t plugin_ref; /**< reference to extension plugin, use ::lysc_get_ext_plugin() to get the plugin */ struct lys_module *module; /**< module structure */ uint16_t flags; /**< LYS_STATUS_* value (@ref snodeflags) */ }; @@ -1260,14 +1256,13 @@ struct lysc_range { struct lysc_pattern { const char *expr; /**< original, not compiled, regular expression */ - pcre2_code *code; /**< compiled regular expression */ const char *dsc; /**< description */ const char *ref; /**< reference */ const char *emsg; /**< error-message */ const char *eapptag; /**< error-app-tag value */ struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */ - uint32_t inverted : 1; /**< invert-match flag */ - uint32_t refcount : 31; /**< reference counter */ + uint32_t inverted : 1; /**< invert-match flag */ + uint32_t refcount : 31; /**< reference counter */ }; struct lysc_must { @@ -1283,7 +1278,7 @@ struct lysc_must { struct lysc_type { const char *name; /**< referenced typedef name (without prefix, if any), NULL for built-in types */ struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */ - struct lyplg_type *plugin; /**< type's manipulation callbacks plugin */ + uintptr_t plugin_ref; /**< reference to type plugin, use ::lysc_get_type_plugin() to get the plugin */ LY_DATA_TYPE basetype; /**< base type of the type */ uint32_t refcount; /**< reference counter for type sharing, it may be accessed concurrently when creating/freeing data node values that reference it (instance-identifier) */ @@ -1292,7 +1287,7 @@ struct lysc_type { struct lysc_type_num { const char *name; /**< referenced typedef name (without prefix, if any), NULL for built-in types */ struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */ - struct lyplg_type *plugin; /**< type's manipulation callbacks plugin */ + uintptr_t plugin_ref; /**< reference to type plugin, use ::lysc_get_type_plugin() to get the plugin */ LY_DATA_TYPE basetype; /**< base type of the type */ uint32_t refcount; /**< reference counter for type sharing */ @@ -1302,7 +1297,7 @@ struct lysc_type_num { struct lysc_type_dec { const char *name; /**< referenced typedef name (without prefix, if any), NULL for built-in types */ struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */ - struct lyplg_type *plugin; /**< type's manipulation callbacks plugin */ + uintptr_t plugin_ref; /**< reference to type plugin, use ::lysc_get_type_plugin() to get the plugin */ LY_DATA_TYPE basetype; /**< base type of the type */ uint32_t refcount; /**< reference counter for type sharing */ @@ -1313,7 +1308,7 @@ struct lysc_type_dec { struct lysc_type_str { const char *name; /**< referenced typedef name (without prefix, if any), NULL for built-in types */ struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */ - struct lyplg_type *plugin; /**< type's manipulation callbacks plugin */ + uintptr_t plugin_ref; /**< reference to type plugin, use ::lysc_get_type_plugin() to get the plugin */ LY_DATA_TYPE basetype; /**< base type of the type */ uint32_t refcount; /**< reference counter for type sharing */ @@ -1338,7 +1333,7 @@ struct lysc_type_bitenum_item { struct lysc_type_enum { const char *name; /**< referenced typedef name (without prefix, if any), NULL for built-in types */ struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */ - struct lyplg_type *plugin; /**< type's manipulation callbacks plugin */ + uintptr_t plugin_ref; /**< reference to type plugin, use ::lysc_get_type_plugin() to get the plugin */ LY_DATA_TYPE basetype; /**< base type of the type */ uint32_t refcount; /**< reference counter for type sharing */ @@ -1348,7 +1343,7 @@ struct lysc_type_enum { struct lysc_type_bits { const char *name; /**< referenced typedef name (without prefix, if any), NULL for built-in types */ struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */ - struct lyplg_type *plugin; /**< type's manipulation callbacks plugin */ + uintptr_t plugin_ref; /**< reference to type plugin, use ::lysc_get_type_plugin() to get the plugin */ LY_DATA_TYPE basetype; /**< base type of the type */ uint32_t refcount; /**< reference counter for type sharing */ @@ -1359,7 +1354,7 @@ struct lysc_type_bits { struct lysc_type_leafref { const char *name; /**< referenced typedef name (without prefix, if any), NULL for built-in types */ struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */ - struct lyplg_type *plugin; /**< type's manipulation callbacks plugin */ + uintptr_t plugin_ref; /**< reference to type plugin, use ::lysc_get_type_plugin() to get the plugin */ LY_DATA_TYPE basetype; /**< base type of the type */ uint32_t refcount; /**< reference counter for type sharing */ @@ -1372,7 +1367,7 @@ struct lysc_type_leafref { struct lysc_type_identityref { const char *name; /**< referenced typedef name (without prefix, if any), NULL for built-in types */ struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */ - struct lyplg_type *plugin; /**< type's manipulation callbacks plugin */ + uintptr_t plugin_ref; /**< reference to type plugin, use ::lysc_get_type_plugin() to get the plugin */ LY_DATA_TYPE basetype; /**< base type of the type */ uint32_t refcount; /**< reference counter for type sharing */ @@ -1383,7 +1378,7 @@ struct lysc_type_identityref { struct lysc_type_instanceid { const char *name; /**< referenced typedef name (without prefix, if any), NULL for built-in types */ struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */ - struct lyplg_type *plugin; /**< type's manipulation callbacks plugin */ + uintptr_t plugin_ref; /**< reference to type plugin, use ::lysc_get_type_plugin() to get the plugin */ LY_DATA_TYPE basetype; /**< base type of the type */ uint32_t refcount; /**< reference counter for type sharing */ @@ -1393,7 +1388,7 @@ struct lysc_type_instanceid { struct lysc_type_union { const char *name; /**< referenced typedef name (without prefix, if any), NULL for built-in types */ struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */ - struct lyplg_type *plugin; /**< type's manipulation callbacks plugin */ + uintptr_t plugin_ref; /**< reference to type plugin, use ::lysc_get_type_plugin() to get the plugin */ LY_DATA_TYPE basetype; /**< base type of the type */ uint32_t refcount; /**< reference counter for type sharing */ @@ -1403,7 +1398,7 @@ struct lysc_type_union { struct lysc_type_bin { const char *name; /**< referenced typedef name (without prefix, if any), NULL for built-in types */ struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */ - struct lyplg_type *plugin; /**< type's manipulation callbacks plugin */ + uintptr_t plugin_ref; /**< reference to type plugin, use ::lysc_get_type_plugin() to get the plugin */ LY_DATA_TYPE basetype; /**< base type of the type */ uint32_t refcount; /**< reference counter for type sharing */ @@ -1607,6 +1602,11 @@ struct lysc_node_choice { struct lysc_node_case *dflt; /**< default case of the choice, only a pointer into the cases array. */ }; +struct lysc_value { + const char *str; /**< string value */ + struct lysc_prefix *prefixes; /**< compiled used prefixes in the string value ([sized array](@ref sizedarrays)) */ +}; + struct lysc_node_leaf { union { struct lysc_node node; /**< implicit cast for the members compatible with ::lysc_node */ @@ -1635,7 +1635,7 @@ struct lysc_node_leaf { struct lysc_type *type; /**< type of the leaf node (mandatory) */ const char *units; /**< units of the leaf's type */ - struct lyd_value *dflt; /**< default value, use ::lyd_value_get_canonical() to get the canonical string */ + struct lysc_value dflt; /**< default value */ }; struct lysc_node_leaflist { @@ -1666,8 +1666,7 @@ struct lysc_node_leaflist { struct lysc_type *type; /**< type of the leaf node (mandatory) */ const char *units; /**< units of the leaf's type */ - struct lyd_value **dflts; /**< list ([sized array](@ref sizedarrays)) of default values, use - ::lyd_value_get_canonical() to get the canonical strings */ + struct lysc_value *dflts; /**< list ([sized array](@ref sizedarrays)) of default values */ uint32_t min; /**< min-elements constraint */ uint32_t max; /**< max-elements constraint */ @@ -1735,6 +1734,15 @@ struct lysc_node_anydata { struct lysc_when **when; /**< list of pointers to when statements ([sized array](@ref sizedarrays)) */ }; +/** + * @brief Compiled YANG submodule with only some basic metadata required for generating `ietf-yang-library` data. + */ +struct lysc_submodule { + const char *name; /**< submodule name */ + const char *revision; /**< submodule revision, if any */ + const char *filepath; /**< submodule file path, if any */ +}; + /** * @brief Compiled YANG schema tree structure representing YANG module. * @@ -1742,12 +1750,13 @@ struct lysc_node_anydata { * Contains only the necessary information for the data validation. */ struct lysc_module { - struct lys_module *mod; /**< covering module structure */ + struct lys_module *mod; /**< covering module structure */ - struct lysc_node *data; /**< list of module's top-level data nodes (linked list) */ - struct lysc_node_action *rpcs; /**< first of actions nodes (linked list) */ - struct lysc_node_notif *notifs; /**< first of notifications nodes (linked list) */ - struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */ + const char **features; /**< array of all the enabled features ([sized array](@ref sizedarrays)) */ + struct lysc_node *data; /**< list of module's top-level data nodes (linked list) */ + struct lysc_node_action *rpcs; /**< first of actions nodes (linked list) */ + struct lysc_node_notif *notifs; /**< first of notifications nodes (linked list) */ + struct lysc_ext_instance *exts; /**< list of extension instances ([sized array](@ref sizedarrays)) */ }; /** @@ -1787,6 +1796,24 @@ struct lysc_module { ((lysc_node && (((lysc_node->nodetype == LYS_LIST) && (lysc_node->flags & LYS_KEYLESS)) || \ ((lysc_node->nodetype == LYS_LEAFLIST) && !(lysc_node->flags & LYS_CONFIG_W)))) ? 1 : 0) +/** + * @brief Get a type plugin. + * + * @param[in] plugin_ref Reference to a type plugin. Either an index in the type plugins + * array (e.g. 1 -> binary type) or a pointer to the user defined plugin. Indexes start at 1. + * @return Type plugin or NULL. + */ +LIBYANG_API_DECL struct lyplg_type *lysc_get_type_plugin(uintptr_t plugin_ref); + +/** + * @brief Get an extension plugin. + * + * @param[in] plugin_ref Reference to an extension plugin. Either an index in the extension plugins + * array (e.g. 1 -> metadata extension) or a pointer to the user defined plugin. Indexes start at 1. + * @return Extension plugin or NULL. + */ +LIBYANG_API_DECL struct lyplg_ext *lysc_get_ext_plugin(uintptr_t plugin_ref); + /** * @brief Get nearest @p schema parent (including the node itself) that can be instantiated in data. * @@ -2135,36 +2162,40 @@ LIBYANG_API_DECL char *lysc_path(const struct lysc_node *node, LYSC_PATH_TYPE pa * @brief Available YANG schema tree structures representing YANG module. */ struct lys_module { - struct ly_ctx *ctx; /**< libyang context of the module (mandatory) */ - const char *name; /**< name of the module (mandatory) */ - const char *revision; /**< revision of the module (if present) */ - const char *ns; /**< namespace of the module (module - mandatory) */ - const char *prefix; /**< module prefix or submodule belongsto prefix of main module (mandatory) */ - const char *filepath; /**< path, if the schema was read from a file, NULL in case of reading from memory */ - const char *org; /**< party/company responsible for the module */ - const char *contact; /**< contact information for the module */ - const char *dsc; /**< description of the module */ - const char *ref; /**< cross-reference for the module */ - - struct lysp_module *parsed; /**< Simply parsed (unresolved) YANG schema tree */ - struct lysc_module *compiled; /**< Compiled and fully validated YANG schema tree for data parsing. - Available only for implemented modules. */ - - struct lysc_ident *identities; /**< List of compiled identities of the module ([sized array](@ref sizedarrays)) - also contains the disabled identities when their if-feature(s) are evaluated to \"false\", - and also the list is filled even if the module is not implemented. - The list is located here because it avoids problems when the module became implemented in - future (no matter if implicitly via augment/deviate or explicitly via - ::lys_set_implemented()). Note that if the module is not implemented (compiled), the - identities cannot be instantiated in data (in identityrefs). */ - - struct lys_module **augmented_by;/**< List of modules that augment this module ([sized array](@ref sizedarrays)) */ - struct lys_module **deviated_by; /**< List of modules that deviate this module ([sized array](@ref sizedarrays)) */ - - ly_bool implemented; /**< flag if the module is implemented, not just imported */ - ly_bool to_compile; /**< flag marking a module that was changed but not (re)compiled, see - ::LY_CTX_EXPLICIT_COMPILE. */ - uint8_t latest_revision; /**< Flag to mark the latest available revision, see [latest_revision options](@ref latestrevflags). */ + struct ly_ctx *ctx; /**< libyang context of the module (mandatory) */ + const char *name; /**< name of the module (mandatory) */ + const char *revision; /**< revision of the module (if present) */ + const char *ns; /**< namespace of the module (module - mandatory) */ + const char *prefix; /**< module prefix or submodule belongsto prefix of main module (mandatory) */ + const char *filepath; /**< path, if the schema was read from a file, NULL in case of reading from memory */ + const char *org; /**< party/company responsible for the module */ + const char *contact; /**< contact information for the module */ + const char *dsc; /**< description of the module */ + const char *ref; /**< cross-reference for the module */ + + struct lysp_module *parsed; /**< Simply parsed (unresolved) YANG schema tree */ + struct lysc_module *compiled; /**< Compiled and fully validated YANG schema tree for data parsing. + Available only for implemented modules. */ + + struct lysc_ext *extensions; /**< List of compiled extension statements ([sized array](@ref sizedarrays)), + filled even if module not implemented. */ + struct lysc_ident *identities; /**< List of compiled identities of the module ([sized array](@ref sizedarrays)) + also contains the disabled identities when their if-feature(s) are evaluated to \"false\", + and also the list is filled even if the module is not implemented. + The list is located here because it avoids problems when the module became implemented in + future (no matter if implicitly via augment/deviate or explicitly via + ::lys_set_implemented()). Note that if the module is not implemented (compiled), the + identities cannot be instantiated in data (in identityrefs). */ + + struct lysc_submodule *submodules; /**< List of all the submodules ([sized array](@ref sizedarrays)) */ + struct lys_module **augmented_by; /**< List of modules that augment this module ([sized array](@ref sizedarrays)) */ + struct lys_module **deviated_by; /**< List of modules that deviate this module ([sized array](@ref sizedarrays)) */ + + ly_bool implemented; /**< flag if the module is implemented, not just imported */ + ly_bool to_compile; /**< flag marking a module that was changed but not (re)compiled, see + ::LY_CTX_EXPLICIT_COMPILE. */ + uint8_t latest_revision; /**< Flag to mark the latest available revision, + see [latest_revision options](@ref latestrevflags). */ }; /** diff --git a/src/tree_schema_common.c b/src/tree_schema_common.c index 1b185c305..a4d4b0617 100644 --- a/src/tree_schema_common.c +++ b/src/tree_schema_common.c @@ -37,6 +37,7 @@ #include "schema_features.h" #include "set.h" #include "tree.h" +#include "tree_data_internal.h" #include "tree_edit.h" #include "tree_schema.h" #include "tree_schema_internal.h" @@ -717,7 +718,7 @@ lys_parse_localfile(struct ly_ctx *ctx, const char *name, const char *revision, *found = 0; *result = NULL; - LY_CHECK_RET(lys_search_localfile(ly_ctx_get_searchdirs(ctx), !(ctx->flags & LY_CTX_DISABLE_SEARCHDIR_CWD), name, + LY_CHECK_RET(lys_search_localfile(ly_ctx_get_searchdirs(ctx), !(ctx->opts & LY_CTX_DISABLE_SEARCHDIR_CWD), name, revision, &filepath, &format)); if (!filepath) { LOGVRB("Module \"%s%s%s\" not found in local searchdirs.", name, revision ? "@" : "", revision ? revision : ""); @@ -787,7 +788,7 @@ lys_load_mod_from_clb_or_file(struct ly_ctx *ctx, const char *name, const char * clb_used = 0; } - if (ctx->flags & LY_CTX_DISABLE_SEARCHDIRS) { + if (ctx->opts & LY_CTX_DISABLE_SEARCHDIRS) { /* searchdirs disabled */ searchdirs_used = 1; } else if (mod_latest && (mod_latest->latest_revision & LYS_MOD_LATEST_SEARCHDIRS)) { @@ -798,7 +799,7 @@ lys_load_mod_from_clb_or_file(struct ly_ctx *ctx, const char *name, const char * } while (!found && (!clb_used || !searchdirs_used)) { - if ((!(ctx->flags & LY_CTX_PREFER_SEARCHDIRS) || searchdirs_used) && !clb_used) { + if ((!(ctx->opts & LY_CTX_PREFER_SEARCHDIRS) || searchdirs_used) && !clb_used) { if (!ctx->imp_clb(name, revision, NULL, NULL, ctx->imp_clb_data, &format, &module_data, &module_data_free)) { /* parse the module returned by the callback */ LY_CHECK_RET(ly_in_new_memory(module_data, &in)); @@ -1161,7 +1162,7 @@ lysp_load_submod_from_clb_or_file(struct lysp_ctx *pctx, const char *name, const clb_used = 0; } - if (ctx->flags & LY_CTX_DISABLE_SEARCHDIRS) { + if (ctx->opts & LY_CTX_DISABLE_SEARCHDIRS) { /* searchdirs disabled */ searchdirs_used = 1; } else { @@ -1169,7 +1170,7 @@ lysp_load_submod_from_clb_or_file(struct lysp_ctx *pctx, const char *name, const } while (!found && (!clb_used || !searchdirs_used)) { - if ((!(ctx->flags & LY_CTX_PREFER_SEARCHDIRS) || searchdirs_used) && !clb_used) { + if ((!(ctx->opts & LY_CTX_PREFER_SEARCHDIRS) || searchdirs_used) && !clb_used) { if (!ctx->imp_clb(PARSER_CUR_PMOD(pctx)->mod->name, NULL, name, revision, ctx->imp_clb_data, &format, &submodule_data, &submodule_data_free)) { /* parse the submodule returned by the callback */ @@ -2270,11 +2271,14 @@ lysp_ext_find_definition(const struct ly_ctx *ctx, const struct lysp_ext_instanc ly_parse_nodeid(&tmp, &prefix, &pref_len, &name, &name_len); /* get module where the extension definition should be placed */ - *ext_mod = mod = ly_resolve_prefix(ctx, prefix, pref_len, ext->format, ext->prefix_data); + mod = ly_resolve_prefix(ctx, prefix, pref_len, ext->format, ext->prefix_data); if (!mod) { LOGVAL(ctx, LYVE_REFERENCE, "Invalid prefix \"%.*s\" used for extension instance identifier.", (int)pref_len, prefix); return LY_EVALID; } + if (ext_mod) { + *ext_mod = mod; + } if (!ext_def) { /* we are done */ @@ -2309,11 +2313,46 @@ lysp_ext_find_definition(const struct ly_ctx *ctx, const struct lysp_ext_instanc } LY_ERR -lysp_ext_instance_resolve_argument(struct ly_ctx *ctx, struct lysp_ext_instance *ext_p) +lysc_ext_find_definition(const struct ly_ctx *ctx, const struct lysp_ext_instance *ext, struct lysc_ext **ext_def) { - assert(ext_p->def); + const char *tmp, *name, *prefix; + size_t pref_len, name_len; + LY_ARRAY_COUNT_TYPE u; + const struct lys_module *mod = NULL; + + *ext_def = NULL; + + /* parse the prefix, the nodeid was previously already parsed and checked */ + tmp = ext->name; + ly_parse_nodeid(&tmp, &prefix, &pref_len, &name, &name_len); - if (!ext_p->def->argname || ext_p->argument) { + /* get module where the extension definition should be placed */ + mod = ly_resolve_prefix(ctx, prefix, pref_len, ext->format, ext->prefix_data); + if (!mod) { + LOGVAL(ctx, LYVE_REFERENCE, "Invalid prefix \"%.*s\" used for extension instance identifier.", (int)pref_len, prefix); + return LY_EVALID; + } + + /* find the compiled extension definition there */ + LY_ARRAY_FOR(mod->extensions, u) { + if (!strcmp(name, mod->extensions[u].name)) { + *ext_def = &mod->extensions[u]; + break; + } + } + + if (!*ext_def) { + LOGVAL(ctx, LYVE_REFERENCE, "Extension definition of extension instance \"%s\" not found.", ext->name); + return LY_EVALID; + } + + return LY_SUCCESS; +} + +LY_ERR +lysp_ext_instance_resolve_argument(const struct ly_ctx *ctx, const struct lysp_ext *ext_def, struct lysp_ext_instance *ext_p) +{ + if (!ext_def->argname || ext_p->argument) { /* nothing to do */ return LY_SUCCESS; } @@ -2322,7 +2361,7 @@ lysp_ext_instance_resolve_argument(struct ly_ctx *ctx, struct lysp_ext_instance /* schema was parsed from YIN and an argument is expected, ... */ struct lysp_stmt *stmt = NULL; - if (ext_p->def->flags & LYS_YINELEM_TRUE) { + if (ext_def->flags & LYS_YINELEM_TRUE) { /* ... argument was the first XML child element */ for (stmt = ext_p->child; stmt && (stmt->flags & LYS_YIN_ATTR); stmt = stmt->next) {} if (stmt) { @@ -2333,9 +2372,9 @@ lysp_ext_instance_resolve_argument(struct ly_ctx *ctx, struct lysp_ext_instance arg = stmt->stmt; ly_parse_nodeid(&arg, &prefix_arg, &prefix_arg_len, &name_arg, &name_arg_len); - if (ly_strncmp(ext_p->def->argname, name_arg, name_arg_len)) { + if (ly_strncmp(ext_def->argname, name_arg, name_arg_len)) { LOGVAL(ctx, LYVE_SEMANTICS, "Extension instance \"%s\" expects argument element \"%s\" as its first XML child, " - "but \"%.*s\" element found.", ext_p->name, ext_p->def->argname, (int)name_arg_len, name_arg); + "but \"%.*s\" element found.", ext_p->name, ext_def->argname, (int)name_arg_len, name_arg); return LY_EVALID; } @@ -2347,14 +2386,14 @@ lysp_ext_instance_resolve_argument(struct ly_ctx *ctx, struct lysp_ext_instance if (ly_resolve_prefix(ctx, prefix_ext, prefix_ext_len, ext_p->format, ext_p->prefix_data) != ly_resolve_prefix(ctx, prefix_arg, prefix_arg_len, stmt->format, stmt->prefix_data)) { LOGVAL(ctx, LYVE_SEMANTICS, "Extension instance \"%s\" element and its argument element \"%s\" are " - "expected in the same namespace, but they differ.", ext_p->name, ext_p->def->argname); + "expected in the same namespace, but they differ.", ext_p->name, ext_def->argname); return LY_EVALID; } } } else { /* ... argument was one of the XML attributes which are represented as child stmt with LYS_YIN_ATTR flag */ for (stmt = ext_p->child; stmt && (stmt->flags & LYS_YIN_ATTR); stmt = stmt->next) { - if (!strcmp(stmt->stmt, ext_p->def->argname)) { + if (!strcmp(stmt->stmt, ext_def->argname)) { /* this is the extension's argument */ break; } @@ -2362,7 +2401,7 @@ lysp_ext_instance_resolve_argument(struct ly_ctx *ctx, struct lysp_ext_instance } if (stmt) { - LY_CHECK_RET(lydict_insert(ctx, stmt->arg, 0, &ext_p->argument)); + LY_CHECK_RET(lysdict_insert(ctx, stmt->arg, 0, &ext_p->argument)); stmt->flags |= LYS_YIN_ARGUMENT; } } @@ -2370,7 +2409,7 @@ lysp_ext_instance_resolve_argument(struct ly_ctx *ctx, struct lysp_ext_instance if (!ext_p->argument) { /* missing extension's argument */ LOGVAL(ctx, LYVE_SEMANTICS, "Extension instance \"%s\" missing argument %s\"%s\".", - ext_p->name, (ext_p->def->flags & LYS_YINELEM_TRUE) ? "element " : "", ext_p->def->argname); + ext_p->name, (ext_def->flags & LYS_YINELEM_TRUE) ? "element " : "", ext_def->argname); return LY_EVALID; } @@ -2813,3 +2852,22 @@ lys_stmt_flags(enum ly_stmt stmt) return 0; } + +int +lysc_value_cmp(const struct lysc_node *schema, const struct lyd_node *ctx_node, const struct lysc_value *val, + const char *val2) +{ + LY_ERR r; + int cmp; + const char *canon; + + r = lyd_value_validate2(schema->module->ctx, schema, val->str, strlen(val->str), LY_VALUE_SCHEMA_RESOLVED, + val->prefixes, ctx_node, NULL, &canon); + if (r && (r != LY_EINCOMPLETE)) { + return -1; + } + + cmp = strcmp(canon, val2); + lydict_remove(schema->module->ctx, canon); + return cmp; +} diff --git a/src/tree_schema_free.c b/src/tree_schema_free.c index 21e7ed74c..8f06b145e 100644 --- a/src/tree_schema_free.c +++ b/src/tree_schema_free.c @@ -4,7 +4,7 @@ * @author Michal Vasko * @brief Freeing functions for schema tree structures. * - * 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. @@ -23,6 +23,7 @@ #include "log.h" #include "ly_common.h" #include "plugins_exts.h" +#include "plugins_internal.h" #include "plugins_types.h" #include "tree.h" #include "tree_data.h" @@ -33,29 +34,29 @@ #include "xml.h" #include "xpath.h" -static void lysc_node_free_(struct lysf_ctx *ctx, struct lysc_node *node); +static void lysc_node_free_(const struct ly_ctx *ctx, struct lysc_node *node); void lysp_qname_free(const struct ly_ctx *ctx, struct lysp_qname *qname) { if (qname) { - lydict_remove(ctx, qname->str); + lysdict_remove(ctx, qname->str); } } /** * @brief Free the parsed generic statement structure. * - * @param[in] ctx libyang context. + * @param[in] ctx Context to use. * @param[in] grp Parsed schema statement structure to free. Note that the structure itself is not freed. */ static void -lysp_stmt_free(struct ly_ctx *ctx, struct lysp_stmt *stmt) +lysp_stmt_free(const struct ly_ctx *ctx, struct lysp_stmt *stmt) { struct lysp_stmt *child, *next; - lydict_remove(ctx, stmt->stmt); - lydict_remove(ctx, stmt->arg); + lysdict_remove(ctx, stmt->stmt); + lysdict_remove(ctx, stmt->arg); ly_free_prefix_data(stmt->format, stmt->prefix_data); LY_LIST_FOR_SAFE(stmt->child, next, child) { @@ -66,19 +67,20 @@ lysp_stmt_free(struct ly_ctx *ctx, struct lysp_stmt *stmt) } void -lysp_ext_instance_free(struct lysf_ctx *ctx, struct lysp_ext_instance *ext) +lysp_ext_instance_free(const struct ly_ctx *ctx, struct lysp_ext_instance *ext) { struct lysp_stmt *stmt, *next; + struct lyplg_ext *ext_plg; - lydict_remove(ctx->ctx, ext->name); - lydict_remove(ctx->ctx, ext->argument); + lysdict_remove(ctx, ext->name); + lysdict_remove(ctx, ext->argument); ly_free_prefix_data(ext->format, ext->prefix_data); - if (ext->record && ext->record->plugin.pfree) { - ext->record->plugin.pfree(ctx->ctx, ext); + if (ext->plugin_ref && (ext_plg = LYSC_GET_EXT_PLG(ext->plugin_ref))->pfree) { + ext_plg->pfree(ctx, ext); } LY_LIST_FOR_SAFE(ext->child, next, stmt) { - lysp_stmt_free(ctx->ctx, stmt); + lysp_stmt_free(ctx, stmt); } FREE_ARRAY(ctx, ext->exts, lysp_ext_instance_free); @@ -87,17 +89,17 @@ lysp_ext_instance_free(struct lysf_ctx *ctx, struct lysp_ext_instance *ext) /** * @brief Free the parsed import structure. * - * @param[in] ctx Free context. + * @param[in] ctx Context to use. * @param[in] import Parsed schema import structure to free. Note that the structure itself is not freed. */ static void -lysp_import_free(struct lysf_ctx *ctx, struct lysp_import *import) +lysp_import_free(const struct ly_ctx *ctx, struct lysp_import *import) { /* imported module is freed directly from the context's list */ - lydict_remove(ctx->ctx, import->name); - lydict_remove(ctx->ctx, import->prefix); - lydict_remove(ctx->ctx, import->dsc); - lydict_remove(ctx->ctx, import->ref); + lysdict_remove(ctx, import->name); + lysdict_remove(ctx, import->prefix); + lysdict_remove(ctx, import->dsc); + lysdict_remove(ctx, import->ref); FREE_ARRAY(ctx, import->exts, lysp_ext_instance_free); } @@ -108,31 +110,31 @@ lysp_import_free(struct lysf_ctx *ctx, struct lysp_import *import) * the parsed submodule is shared with any include in a submodule. Therefore, the referenced submodules in the include * record are freed only from main module's records. * - * @param[in] ctx libyang context - * @param[in] include The include record to be erased, the record itself is not freed. - * @param[in] main_module Flag to get know if the include record is placed in main module so also the referenced submodule - * is supposed to be freed. + * @param[in] ctx Context to use. + * @param[in] include Record to be erased, the record itself is not freed. + * @param[in] main_module Flag to distinguish when the include record is placed in main module so also the referenced + * submodule is supposed to be freed. */ static void -lysp_include_free_(struct lysf_ctx *ctx, struct lysp_include *include, ly_bool main_module) +lysp_include_free_(const struct ly_ctx *ctx, struct lysp_include *include, ly_bool main_module) { if (main_module && include->submodule) { lysp_module_free(ctx, (struct lysp_module *)include->submodule); } - lydict_remove(ctx->ctx, include->name); - lydict_remove(ctx->ctx, include->dsc); - lydict_remove(ctx->ctx, include->ref); + lysdict_remove(ctx, include->name); + lysdict_remove(ctx, include->dsc); + lysdict_remove(ctx, include->ref); FREE_ARRAY(ctx, include->exts, lysp_ext_instance_free); } /** * @brief Free the parsed include structure of a submodule. * - * @param[in] ctx Free context. + * @param[in] ctx Context to use. * @param[in] include Parsed schema include structure to free. Note that the structure itself is not freed. */ static void -lysp_include_free_submodule(struct lysf_ctx *ctx, struct lysp_include *include) +lysp_include_free_submodule(const struct ly_ctx *ctx, struct lysp_include *include) { lysp_include_free_(ctx, include, 0); } @@ -140,11 +142,11 @@ lysp_include_free_submodule(struct lysf_ctx *ctx, struct lysp_include *include) /** * @brief Free the parsed include structure of a module. * - * @param[in] ctx Free context. + * @param[in] ctx Context to use. * @param[in] include Parsed schema include structure to free. Note that the structure itself is not freed. */ static void -lysp_include_free(struct lysf_ctx *ctx, struct lysp_include *include) +lysp_include_free(const struct ly_ctx *ctx, struct lysp_include *include) { lysp_include_free_(ctx, include, 1); } @@ -152,136 +154,110 @@ lysp_include_free(struct lysf_ctx *ctx, struct lysp_include *include) /** * @brief Free the parsed revision structure. * - * @param[in] ctx Free context. + * @param[in] ctx Context to use. * @param[in] rev Parsed schema revision structure to free. Note that the structure itself is not freed. */ static void -lysp_revision_free(struct lysf_ctx *ctx, struct lysp_revision *rev) +lysp_revision_free(const struct ly_ctx *ctx, struct lysp_revision *rev) { - lydict_remove(ctx->ctx, rev->dsc); - lydict_remove(ctx->ctx, rev->ref); + lysdict_remove(ctx, rev->dsc); + lysdict_remove(ctx, rev->ref); FREE_ARRAY(ctx, rev->exts, lysp_ext_instance_free); } -/** - * @brief Free the compiled extension definition and NULL the provided pointer. - * - * @param[in] ctx Free context. - * @param[in,out] ext Compiled extension definition to be freed. - */ -static void -lysc_extension_free(struct lysf_ctx *ctx, struct lysc_ext **ext) -{ - if (ly_set_contains(&ctx->ext_set, *ext, NULL)) { - /* already freed and only referenced again in this module */ - return; - } - - /* remember this extension to be freed, nothing to do on error */ - (void)ly_set_add(&ctx->ext_set, *ext, 0, NULL); - - /* recursive exts free */ - FREE_ARRAY(ctx, (*ext)->exts, lysc_ext_instance_free); - - *ext = NULL; -} - /** * @brief Free the parsed ext structure. * - * @param[in] ctx Free context. + * @param[in] ctx Context to use. * @param[in] ext Parsed schema ext structure to free. Note that the structure itself is not freed. */ static void -lysp_ext_free(struct lysf_ctx *ctx, struct lysp_ext *ext) +lysp_ext_free(const struct ly_ctx *ctx, struct lysp_ext *ext) { - lydict_remove(ctx->ctx, ext->name); - lydict_remove(ctx->ctx, ext->argname); - lydict_remove(ctx->ctx, ext->dsc); - lydict_remove(ctx->ctx, ext->ref); + lysdict_remove(ctx, ext->name); + lysdict_remove(ctx, ext->argname); + lysdict_remove(ctx, ext->dsc); + lysdict_remove(ctx, ext->ref); FREE_ARRAY(ctx, ext->exts, lysp_ext_instance_free); - if (ext->compiled) { - lysc_extension_free(ctx, &ext->compiled); - } } /** * @brief Free the parsed feature structure. * - * @param[in] ctx Free context. + * @param[in] ctx Context to use. * @param[in] feat Parsed schema feature structure to free. Note that the structure itself is not freed. */ static void -lysp_feature_free(struct lysf_ctx *ctx, struct lysp_feature *feat) +lysp_feature_free(const struct ly_ctx *ctx, struct lysp_feature *feat) { - lydict_remove(ctx->ctx, feat->name); - FREE_ARRAY(ctx->ctx, feat->iffeatures, lysp_qname_free); + lysdict_remove(ctx, feat->name); + FREE_ARRAY(ctx, feat->iffeatures, lysp_qname_free); FREE_ARRAY(ctx, feat->iffeatures_c, lysc_iffeature_free); LY_ARRAY_FREE(feat->depfeatures); - lydict_remove(ctx->ctx, feat->dsc); - lydict_remove(ctx->ctx, feat->ref); + lysdict_remove(ctx, feat->dsc); + lysdict_remove(ctx, feat->ref); FREE_ARRAY(ctx, feat->exts, lysp_ext_instance_free); } /** * @brief Free the parsed identity structure. * - * @param[in] ctx Free context. + * @param[in] ctx Context to use. * @param[in] ident Parsed schema identity structure to free. Note that the structure itself is not freed. */ static void -lysp_ident_free(struct lysf_ctx *ctx, struct lysp_ident *ident) +lysp_ident_free(const struct ly_ctx *ctx, struct lysp_ident *ident) { - lydict_remove(ctx->ctx, ident->name); - FREE_ARRAY(ctx->ctx, ident->iffeatures, lysp_qname_free); - FREE_STRINGS(ctx->ctx, ident->bases); - lydict_remove(ctx->ctx, ident->dsc); - lydict_remove(ctx->ctx, ident->ref); + lysdict_remove(ctx, ident->name); + FREE_ARRAY(ctx, ident->iffeatures, lysp_qname_free); + FREE_STRINGS(ctx, ident->bases); + lysdict_remove(ctx, ident->dsc); + lysdict_remove(ctx, ident->ref); FREE_ARRAY(ctx, ident->exts, lysp_ext_instance_free); } void -lysp_restr_free(struct lysf_ctx *ctx, struct lysp_restr *restr) +lysp_restr_free(const struct ly_ctx *ctx, struct lysp_restr *restr) { - lydict_remove(ctx->ctx, restr->arg.str); - lydict_remove(ctx->ctx, restr->emsg); - lydict_remove(ctx->ctx, restr->eapptag); - lydict_remove(ctx->ctx, restr->dsc); - lydict_remove(ctx->ctx, restr->ref); + lysdict_remove(ctx, restr->arg.str); + lysdict_remove(ctx, restr->emsg); + lysdict_remove(ctx, restr->eapptag); + lysdict_remove(ctx, restr->dsc); + lysdict_remove(ctx, restr->ref); FREE_ARRAY(ctx, restr->exts, lysp_ext_instance_free); } /** * @brief Free the parsed type enum item. * - * @param[in] ctx Free context. + * @param[in] ctx Context to use. * @param[in] item Parsed schema type enum item to free. Note that the structure itself is not freed. */ static void -lysp_type_enum_free(struct lysf_ctx *ctx, struct lysp_type_enum *item) +lysp_type_enum_free(const struct ly_ctx *ctx, struct lysp_type_enum *item) { - lydict_remove(ctx->ctx, item->name); - lydict_remove(ctx->ctx, item->dsc); - lydict_remove(ctx->ctx, item->ref); - FREE_ARRAY(ctx->ctx, item->iffeatures, lysp_qname_free); + lysdict_remove(ctx, item->name); + lysdict_remove(ctx, item->dsc); + lysdict_remove(ctx, item->ref); + FREE_ARRAY(ctx, item->iffeatures, lysp_qname_free); FREE_ARRAY(ctx, item->exts, lysp_ext_instance_free); } void -lysp_type_free(struct lysf_ctx *ctx, struct lysp_type *type) +lysp_type_free(const struct ly_ctx *ctx, struct lysp_type *type) { if (!type) { return; } - lydict_remove(ctx->ctx, type->name); + lysdict_remove(ctx, type->name); FREE_MEMBER(ctx, type->range, lysp_restr_free); FREE_MEMBER(ctx, type->length, lysp_restr_free); FREE_ARRAY(ctx, type->patterns, lysp_restr_free); FREE_ARRAY(ctx, type->enums, lysp_type_enum_free); FREE_ARRAY(ctx, type->bits, lysp_type_enum_free); - lyxp_expr_free(ctx->ctx, type->path); - FREE_STRINGS(ctx->ctx, type->bases); + lyxp_expr_free(type->path); + FREE_STRINGS(ctx, type->bases); FREE_ARRAY(ctx, type->types, lysp_type_free); FREE_ARRAY(ctx, type->exts, lysp_ext_instance_free); if (type->compiled) { @@ -292,17 +268,17 @@ lysp_type_free(struct lysf_ctx *ctx, struct lysp_type *type) /** * @brief Free the parsed typedef structure. * - * @param[in] ctx Free context. + * @param[in] ctx Context to use. * @param[in] tpdf Parsed schema typedef structure to free. Note that the structure itself is not freed. */ static void -lysp_tpdf_free(struct lysf_ctx *ctx, struct lysp_tpdf *tpdf) +lysp_tpdf_free(const struct ly_ctx *ctx, struct lysp_tpdf *tpdf) { - lydict_remove(ctx->ctx, tpdf->name); - lydict_remove(ctx->ctx, tpdf->units); - lydict_remove(ctx->ctx, tpdf->dflt.str); - lydict_remove(ctx->ctx, tpdf->dsc); - lydict_remove(ctx->ctx, tpdf->ref); + lysdict_remove(ctx, tpdf->name); + lysdict_remove(ctx, tpdf->units); + lysdict_remove(ctx, tpdf->dflt.str); + lysdict_remove(ctx, tpdf->dsc); + lysdict_remove(ctx, tpdf->ref); FREE_ARRAY(ctx, tpdf->exts, lysp_ext_instance_free); lysp_type_free(ctx, &tpdf->type); @@ -312,11 +288,11 @@ lysp_tpdf_free(struct lysf_ctx *ctx, struct lysp_tpdf *tpdf) /** * @brief Free the parsed grouping structure. * - * @param[in] ctx Free context. + * @param[in] ctx Context to use. * @param[in] grp Parsed schema grouping structure to free. Note that the structure itself is not freed. */ static void -lysp_grp_free(struct lysf_ctx *ctx, struct lysp_node_grp *grp) +lysp_grp_free(const struct ly_ctx *ctx, struct lysp_node_grp *grp) { struct lysp_node *node, *next; @@ -336,22 +312,22 @@ lysp_grp_free(struct lysf_ctx *ctx, struct lysp_node_grp *grp) } void -lysp_when_free(struct lysf_ctx *ctx, struct lysp_when *when) +lysp_when_free(const struct ly_ctx *ctx, struct lysp_when *when) { - lydict_remove(ctx->ctx, when->cond); - lydict_remove(ctx->ctx, when->dsc); - lydict_remove(ctx->ctx, when->ref); + lysdict_remove(ctx, when->cond); + lysdict_remove(ctx, when->dsc); + lysdict_remove(ctx, when->ref); FREE_ARRAY(ctx, when->exts, lysp_ext_instance_free); } /** * @brief Free the parsed augment structure. * - * @param[in] ctx Free context. + * @param[in] ctx Context to use. * @param[in] aug Parsed schema augment structure to free. Note that the structure itself is not freed. */ static void -lysp_augment_free(struct lysf_ctx *ctx, struct lysp_node_augment *aug) +lysp_augment_free(const struct ly_ctx *ctx, struct lysp_node_augment *aug) { struct lysp_node *node, *next; @@ -367,7 +343,7 @@ lysp_augment_free(struct lysf_ctx *ctx, struct lysp_node_augment *aug) } void -lysp_deviate_free(struct lysf_ctx *ctx, struct lysp_deviate *d) +lysp_deviate_free(const struct ly_ctx *ctx, struct lysp_deviate *d) { struct lysp_deviate_add *add = (struct lysp_deviate_add *)d; struct lysp_deviate_rpl *rpl = (struct lysp_deviate_rpl *)d; @@ -383,30 +359,30 @@ lysp_deviate_free(struct lysf_ctx *ctx, struct lysp_deviate *d) break; case LYS_DEV_ADD: case LYS_DEV_DELETE: /* compatible for dynamically allocated data */ - lydict_remove(ctx->ctx, add->units); + lysdict_remove(ctx, add->units); FREE_ARRAY(ctx, add->musts, lysp_restr_free); - FREE_ARRAY(ctx->ctx, add->uniques, lysp_qname_free); - FREE_ARRAY(ctx->ctx, add->dflts, lysp_qname_free); + FREE_ARRAY(ctx, add->uniques, lysp_qname_free); + FREE_ARRAY(ctx, add->dflts, lysp_qname_free); break; case LYS_DEV_REPLACE: FREE_MEMBER(ctx, rpl->type, lysp_type_free); - lydict_remove(ctx->ctx, rpl->units); - lysp_qname_free(ctx->ctx, &rpl->dflt); + lysdict_remove(ctx, rpl->units); + lysp_qname_free(ctx, &rpl->dflt); break; default: - LOGINT(ctx->ctx); + LOGINT(ctx); break; } } void -lysp_deviation_free(struct lysf_ctx *ctx, struct lysp_deviation *dev) +lysp_deviation_free(const struct ly_ctx *ctx, struct lysp_deviation *dev) { struct lysp_deviate *next, *iter; - lydict_remove(ctx->ctx, dev->nodeid); - lydict_remove(ctx->ctx, dev->dsc); - lydict_remove(ctx->ctx, dev->ref); + lysdict_remove(ctx, dev->nodeid); + lysdict_remove(ctx, dev->dsc); + lysdict_remove(ctx, dev->ref); LY_LIST_FOR_SAFE(dev->deviates, next, iter) { lysp_deviate_free(ctx, iter); free(iter); @@ -417,24 +393,24 @@ lysp_deviation_free(struct lysf_ctx *ctx, struct lysp_deviation *dev) /** * @brief Free the parsed refine structure. * - * @param[in] ctx Free context. + * @param[in] ctx Context to use. * @param[in] ref Parsed schema refine structure to free. Note that the structure itself is not freed. */ static void -lysp_refine_free(struct lysf_ctx *ctx, struct lysp_refine *ref) +lysp_refine_free(const struct ly_ctx *ctx, struct lysp_refine *ref) { - lydict_remove(ctx->ctx, ref->nodeid); - lydict_remove(ctx->ctx, ref->dsc); - lydict_remove(ctx->ctx, ref->ref); - FREE_ARRAY(ctx->ctx, ref->iffeatures, lysp_qname_free); + lysdict_remove(ctx, ref->nodeid); + lysdict_remove(ctx, ref->dsc); + lysdict_remove(ctx, ref->ref); + FREE_ARRAY(ctx, ref->iffeatures, lysp_qname_free); FREE_ARRAY(ctx, ref->musts, lysp_restr_free); - lydict_remove(ctx->ctx, ref->presence); - FREE_ARRAY(ctx->ctx, ref->dflts, lysp_qname_free); + lysdict_remove(ctx, ref->presence); + FREE_ARRAY(ctx, ref->dflts, lysp_qname_free); FREE_ARRAY(ctx, ref->exts, lysp_ext_instance_free); } void -lysp_node_free(struct lysf_ctx *ctx, struct lysp_node *node) +lysp_node_free(const struct ly_ctx *ctx, struct lysp_node *node) { struct lysp_node *child, *next; struct lysp_node_container *cont; @@ -450,10 +426,10 @@ lysp_node_free(struct lysf_ctx *ctx, struct lysp_node *node) struct lysp_restr *musts = lysp_node_musts(node); struct lysp_when *when = lysp_node_when(node); - lydict_remove(ctx->ctx, node->name); - lydict_remove(ctx->ctx, node->dsc); - lydict_remove(ctx->ctx, node->ref); - FREE_ARRAY(ctx->ctx, node->iffeatures, lysp_qname_free); + lysdict_remove(ctx, node->name); + lysdict_remove(ctx, node->dsc); + lysdict_remove(ctx, node->ref); + FREE_ARRAY(ctx, node->iffeatures, lysp_qname_free); FREE_ARRAY(ctx, node->exts, lysp_ext_instance_free); FREE_MEMBER(ctx, when, lysp_when_free); @@ -463,7 +439,7 @@ lysp_node_free(struct lysf_ctx *ctx, struct lysp_node *node) case LYS_CONTAINER: cont = (struct lysp_node_container *)node; - lydict_remove(ctx->ctx, cont->presence); + lysdict_remove(ctx, cont->presence); FREE_ARRAY(ctx, cont->typedefs, lysp_tpdf_free); if (cont->groupings) { LY_LIST_FOR_SAFE(&cont->groupings->node, next, child) { @@ -488,20 +464,20 @@ lysp_node_free(struct lysf_ctx *ctx, struct lysp_node *node) leaf = (struct lysp_node_leaf *)node; lysp_type_free(ctx, &leaf->type); - lydict_remove(ctx->ctx, leaf->units); - lydict_remove(ctx->ctx, leaf->dflt.str); + lysdict_remove(ctx, leaf->units); + lysdict_remove(ctx, leaf->dflt.str); break; case LYS_LEAFLIST: llist = (struct lysp_node_leaflist *)node; lysp_type_free(ctx, &llist->type); - lydict_remove(ctx->ctx, llist->units); - FREE_ARRAY(ctx->ctx, llist->dflts, lysp_qname_free); + lysdict_remove(ctx, llist->units); + FREE_ARRAY(ctx, llist->dflts, lysp_qname_free); break; case LYS_LIST: list = (struct lysp_node_list *)node; - lydict_remove(ctx->ctx, list->key); + lysdict_remove(ctx, list->key); FREE_ARRAY(ctx, list->typedefs, lysp_tpdf_free); if (list->groupings) { LY_LIST_FOR_SAFE(&list->groupings->node, next, child) { @@ -521,7 +497,7 @@ lysp_node_free(struct lysf_ctx *ctx, struct lysp_node *node) lysp_node_free(ctx, child); } } - FREE_ARRAY(ctx->ctx, list->uniques, lysp_qname_free); + FREE_ARRAY(ctx, list->uniques, lysp_qname_free); break; case LYS_CHOICE: choice = (struct lysp_node_choice *)node; @@ -529,7 +505,7 @@ lysp_node_free(struct lysf_ctx *ctx, struct lysp_node *node) LY_LIST_FOR_SAFE(choice->child, next, child) { lysp_node_free(ctx, child); } - lydict_remove(ctx->ctx, choice->dflt.str); + lysdict_remove(ctx, choice->dflt.str); break; case LYS_CASE: cas = (struct lysp_node_case *)node; @@ -604,14 +580,14 @@ lysp_node_free(struct lysf_ctx *ctx, struct lysp_node *node) lysp_augment_free(ctx, ((struct lysp_node_augment *)node)); break; default: - LOGINT(ctx->ctx); + LOGINT(ctx); } free(node); } void -lysp_module_free(struct lysf_ctx *ctx, struct lysp_module *module) +lysp_module_free(const struct ly_ctx *ctx, struct lysp_module *module) { struct lysp_node *node, *next; @@ -623,7 +599,6 @@ lysp_module_free(struct lysf_ctx *ctx, struct lysp_module *module) FREE_ARRAY(ctx, module->includes, module->is_submod ? lysp_include_free_submodule : lysp_include_free); FREE_ARRAY(ctx, module->revs, lysp_revision_free); - FREE_ARRAY(ctx, module->extensions, lysp_ext_free); FREE_ARRAY(ctx, module->features, lysp_feature_free); FREE_ARRAY(ctx, module->identities, lysp_ident_free); FREE_ARRAY(ctx, module->typedefs, lysp_tpdf_free); @@ -645,33 +620,38 @@ lysp_module_free(struct lysf_ctx *ctx, struct lysp_module *module) FREE_ARRAY(ctx, module->deviations, lysp_deviation_free); FREE_ARRAY(ctx, module->exts, lysp_ext_instance_free); + /* free parsed extensions definitions after parsed extension instances were freed */ + FREE_ARRAY(ctx, module->extensions, lysp_ext_free); + if (module->is_submod) { struct lysp_submodule *submod = (struct lysp_submodule *)module; - lydict_remove(ctx->ctx, submod->name); - lydict_remove(ctx->ctx, submod->filepath); - lydict_remove(ctx->ctx, submod->prefix); - lydict_remove(ctx->ctx, submod->org); - lydict_remove(ctx->ctx, submod->contact); - lydict_remove(ctx->ctx, submod->dsc); - lydict_remove(ctx->ctx, submod->ref); + lysdict_remove(ctx, submod->name); + lysdict_remove(ctx, submod->filepath); + lysdict_remove(ctx, submod->prefix); + lysdict_remove(ctx, submod->org); + lysdict_remove(ctx, submod->contact); + lysdict_remove(ctx, submod->dsc); + lysdict_remove(ctx, submod->ref); } free(module); } void -lysc_ext_instance_free(struct lysf_ctx *ctx, struct lysc_ext_instance *ext) +lysc_ext_instance_free(const struct ly_ctx *ctx, struct lysc_ext_instance *ext) { - if (ext->def && ext->def->plugin && ext->def->plugin->cfree) { - ext->def->plugin->cfree(ctx->ctx, ext); + struct lyplg_ext *ext_plg; + + if (ext->def && ext->def->plugin_ref && (ext_plg = LYSC_GET_EXT_PLG(ext->def->plugin_ref))->cfree) { + ext_plg->cfree(ctx, ext); } - lydict_remove(ctx->ctx, ext->argument); + lysdict_remove(ctx, ext->argument); FREE_ARRAY(ctx, ext->exts, lysc_ext_instance_free); } void -lysc_iffeature_free(struct lysf_ctx *UNUSED(ctx), struct lysc_iffeature *iff) +lysc_iffeature_free(const struct ly_ctx *UNUSED(ctx), struct lysc_iffeature *iff) { LY_ARRAY_FREE(iff->features); free(iff->expr); @@ -680,19 +660,20 @@ lysc_iffeature_free(struct lysf_ctx *UNUSED(ctx), struct lysc_iffeature *iff) /** * @brief Free the compiled when structure (decrease refcount) and NULL the provided pointer. * - * @param[in] ctx Free context. + * @param[in] ctx Context to use. * @param[in] grp Parsed schema grouping structure to free. Note that the structure itself is not freed. */ static void -lysc_when_free(struct lysf_ctx *ctx, struct lysc_when **w) +lysc_when_free(const struct ly_ctx *ctx, struct lysc_when **w) { if (--(*w)->refcount) { return; } - lyxp_expr_free(ctx->ctx, (*w)->cond); + + lyxp_expr_free((*w)->cond); ly_free_prefix_data(LY_VALUE_SCHEMA_RESOLVED, (*w)->prefixes); - lydict_remove(ctx->ctx, (*w)->dsc); - lydict_remove(ctx->ctx, (*w)->ref); + lysdict_remove(ctx, (*w)->dsc); + lysdict_remove(ctx, (*w)->ref); FREE_ARRAY(ctx, (*w)->exts, lysc_ext_instance_free); free(*w); } @@ -700,23 +681,23 @@ lysc_when_free(struct lysf_ctx *ctx, struct lysc_when **w) /** * @brief Free the compiled must structure. * - * @param[in] ctx Free context. + * @param[in] ctx Context to use. * @param[in,out] must Compiled must structure to be freed. * Since the structure is typically part of the sized array, the structure itself is not freed. */ static void -lysc_must_free(struct lysf_ctx *ctx, struct lysc_must *must) +lysc_must_free(const struct ly_ctx *ctx, struct lysc_must *must) { if (!must) { return; } - lyxp_expr_free(ctx->ctx, must->cond); + lyxp_expr_free(must->cond); ly_free_prefix_data(LY_VALUE_SCHEMA_RESOLVED, must->prefixes); - lydict_remove(ctx->ctx, must->emsg); - lydict_remove(ctx->ctx, must->eapptag); - lydict_remove(ctx->ctx, must->dsc); - lydict_remove(ctx->ctx, must->ref); + lysdict_remove(ctx, must->emsg); + lysdict_remove(ctx, must->eapptag); + lysdict_remove(ctx, must->dsc); + lysdict_remove(ctx, must->ref); FREE_ARRAY(ctx, must->exts, lysc_ext_instance_free); } @@ -736,6 +717,8 @@ lysc_ident_derived_unlink(const struct lysc_ident *ident) const char *base_name; uint32_t i; + assert(ident->module->parsed); + /* find the parsed identity */ LY_ARRAY_FOR(ident->module->parsed->identities, u) { if (ident->module->parsed->identities[u].name == ident->name) { @@ -811,71 +794,70 @@ lysc_ident_derived_unlink(const struct lysc_ident *ident) /** * @brief Free the compiled identity structure. * - * @param[in] ctx Free context. + * @param[in] ctx Context to use. * @param[in,out] ident Compiled identity structure to be freed. * Since the structure is typically part of the sized array, the structure itself is not freed. */ static void -lysc_ident_free(struct lysf_ctx *ctx, struct lysc_ident *ident) +lysc_ident_free(const struct ly_ctx *ctx, struct lysc_ident *ident) { - lydict_remove(ctx->ctx, ident->name); - lydict_remove(ctx->ctx, ident->dsc); - lydict_remove(ctx->ctx, ident->ref); + lysdict_remove(ctx, ident->name); + lysdict_remove(ctx, ident->dsc); + lysdict_remove(ctx, ident->ref); LY_ARRAY_FREE(ident->derived); FREE_ARRAY(ctx, ident->exts, lysc_ext_instance_free); } void -lysc_range_free(struct lysf_ctx *ctx, struct lysc_range *range) +lysc_range_free(const struct ly_ctx *ctx, struct lysc_range *range) { LY_ARRAY_FREE(range->parts); - lydict_remove(ctx->ctx, range->eapptag); - lydict_remove(ctx->ctx, range->emsg); - lydict_remove(ctx->ctx, range->dsc); - lydict_remove(ctx->ctx, range->ref); + lysdict_remove(ctx, range->eapptag); + lysdict_remove(ctx, range->emsg); + lysdict_remove(ctx, range->dsc); + lysdict_remove(ctx, range->ref); FREE_ARRAY(ctx, range->exts, lysc_ext_instance_free); } void -lysc_pattern_free(struct lysf_ctx *ctx, struct lysc_pattern **pattern) +lysc_pattern_free(const struct ly_ctx *ctx, struct lysc_pattern **pattern) { if (--(*pattern)->refcount) { return; } - pcre2_code_free((*pattern)->code); - lydict_remove(ctx->ctx, (*pattern)->expr); - lydict_remove(ctx->ctx, (*pattern)->eapptag); - lydict_remove(ctx->ctx, (*pattern)->emsg); - lydict_remove(ctx->ctx, (*pattern)->dsc); - lydict_remove(ctx->ctx, (*pattern)->ref); + lysdict_remove(ctx, (*pattern)->expr); + lysdict_remove(ctx, (*pattern)->eapptag); + lysdict_remove(ctx, (*pattern)->emsg); + lysdict_remove(ctx, (*pattern)->dsc); + lysdict_remove(ctx, (*pattern)->ref); FREE_ARRAY(ctx, (*pattern)->exts, lysc_ext_instance_free); free(*pattern); } void -lysc_enum_item_free(struct lysf_ctx *ctx, struct lysc_type_bitenum_item *item) +lysc_enum_item_free(const struct ly_ctx *ctx, struct lysc_type_bitenum_item *item) { - lydict_remove(ctx->ctx, item->name); - lydict_remove(ctx->ctx, item->dsc); - lydict_remove(ctx->ctx, item->ref); + lysdict_remove(ctx, item->name); + lysdict_remove(ctx, item->dsc); + lysdict_remove(ctx, item->ref); FREE_ARRAY(ctx, item->exts, lysc_ext_instance_free); } /** * @brief Free the compiled type structure. * - * @param[in] ctx Free context. + * @param[in] ctx Context to use. * @param[in,out] type Pointer to compiled type structure to be freed. * Since the structure is typically part of the sized array, the structure itself is not freed. */ static void -lysc_type2_free(struct lysf_ctx *ctx, struct lysc_type **type) +lysc_type2_free(const struct ly_ctx *ctx, struct lysc_type **type) { lysc_type_free(ctx, *type); } void -lysc_type_free(struct lysf_ctx *ctx, struct lysc_type *type) +lysc_type_free(const struct ly_ctx *ctx, struct lysc_type *type) { if (!type || (LY_ATOMIC_DEC_BARRIER(type->refcount) > 1)) { return; @@ -915,7 +897,7 @@ lysc_type_free(struct lysf_ctx *ctx, struct lysc_type *type) FREE_ARRAY(ctx, ((struct lysc_type_union *)type)->types, lysc_type2_free); break; case LY_TYPE_LEAFREF: - lyxp_expr_free(ctx->ctx, ((struct lysc_type_leafref *)type)->path); + lyxp_expr_free(((struct lysc_type_leafref *)type)->path); ly_free_prefix_data(LY_VALUE_SCHEMA_RESOLVED, ((struct lysc_type_leafref *)type)->prefixes); lysc_type_free(ctx, ((struct lysc_type_leafref *)type)->realtype); break; @@ -927,7 +909,7 @@ lysc_type_free(struct lysf_ctx *ctx, struct lysc_type *type) break; } - lydict_remove(ctx->ctx, type->name); + lysdict_remove(ctx, type->name); FREE_ARRAY(ctx, type->exts, lysc_ext_instance_free); free(type); } @@ -935,12 +917,12 @@ lysc_type_free(struct lysf_ctx *ctx, struct lysc_type *type) /** * @brief Free the compiled input/output structure. * - * @param[in] ctx Free context. - * @param[in,out] inout Compiled inout structure to be freed. + * @param[in] ctx Context to use. + * @param[in] inout Compiled inout structure to be freed. * Since the structure is part of the RPC/action structure, it is not freed itself. */ static void -lysc_node_action_inout_free(struct lysf_ctx *ctx, struct lysc_node_action_inout *inout) +lysc_node_action_inout_free(const struct ly_ctx *ctx, struct lysc_node_action_inout *inout) { struct lysc_node *child, *child_next; @@ -953,12 +935,12 @@ lysc_node_action_inout_free(struct lysf_ctx *ctx, struct lysc_node_action_inout /** * @brief Free the compiled RPC/action structure. * - * @param[in] ctx Free context. - * @param[in,out] action Compiled RPC/action structure to be freed. + * @param[in] ctx Context to use. + * @param[in] action Compiled RPC/action structure to be freed. * Since the structure is typically part of the sized array, the structure itself is not freed. */ static void -lysc_node_action_free(struct lysf_ctx *ctx, struct lysc_node_action *action) +lysc_node_action_free(const struct ly_ctx *ctx, struct lysc_node_action *action) { FREE_ARRAY(ctx, action->when, lysc_when_free); if (action->input.nodetype) { @@ -972,12 +954,12 @@ lysc_node_action_free(struct lysf_ctx *ctx, struct lysc_node_action *action) /** * @brief Free the compiled notification structure. * - * @param[in] ctx Free context. - * @param[in,out] notif Compiled notification structure to be freed. + * @param[in] ctx Context to use. + * @param[in] notif Compiled notification structure to be freed. * Since the structure is typically part of the sized array, the structure itself is not freed. */ static void -lysc_node_notif_free(struct lysf_ctx *ctx, struct lysc_node_notif *notif) +lysc_node_notif_free(const struct ly_ctx *ctx, struct lysc_node_notif *notif) { struct lysc_node *child, *child_next; @@ -989,7 +971,7 @@ lysc_node_notif_free(struct lysf_ctx *ctx, struct lysc_node_notif *notif) } void -lysc_node_container_free(struct lysf_ctx *ctx, struct lysc_node_container *node) +lysc_node_container_free(const struct ly_ctx *ctx, struct lysc_node_container *node) { struct lysc_node *child, *child_next; @@ -1006,64 +988,60 @@ lysc_node_container_free(struct lysf_ctx *ctx, struct lysc_node_container *node) FREE_ARRAY(ctx, node->musts, lysc_must_free); } +void +lysc_value_free(const struct ly_ctx *ctx, struct lysc_value *val) +{ + lysdict_remove(ctx, val->str); + ly_free_prefix_data(LY_VALUE_SCHEMA_RESOLVED, val->prefixes); +} + /** * @brief Free the compiled leaf structure. * - * @param[in] ctx Free context. - * @param[in,out] node Compiled leaf structure to be freed. + * @param[in] ctx Context to use. + * @param[in] node Compiled leaf structure to be freed. * Since the structure is typically part of the sized array, the structure itself is not freed. */ static void -lysc_node_leaf_free(struct lysf_ctx *ctx, struct lysc_node_leaf *node) +lysc_node_leaf_free(const struct ly_ctx *ctx, struct lysc_node_leaf *node) { FREE_ARRAY(ctx, node->when, lysc_when_free); FREE_ARRAY(ctx, node->musts, lysc_must_free); if (node->type) { lysc_type_free(ctx, node->type); } - lydict_remove(ctx->ctx, node->units); - if (node->dflt) { - node->dflt->realtype->plugin->free(ctx->ctx, node->dflt); - lysc_type_free(ctx, (struct lysc_type *)node->dflt->realtype); - free(node->dflt); - } + lysdict_remove(ctx, node->units); + lysc_value_free(ctx, &node->dflt); } /** * @brief Free the compiled leaflist structure. * - * @param[in] ctx Free context. - * @param[in,out] node Compiled leaflist structure to be freed. + * @param[in] ctx Context to use. + * @param[in] node Compiled leaflist structure to be freed. * Since the structure is typically part of the sized array, the structure itself is not freed. */ static void -lysc_node_leaflist_free(struct lysf_ctx *ctx, struct lysc_node_leaflist *node) +lysc_node_leaflist_free(const struct ly_ctx *ctx, struct lysc_node_leaflist *node) { - LY_ARRAY_COUNT_TYPE u; - FREE_ARRAY(ctx, node->when, lysc_when_free); FREE_ARRAY(ctx, node->musts, lysc_must_free); if (node->type) { lysc_type_free(ctx, node->type); } - lydict_remove(ctx->ctx, node->units); - LY_ARRAY_FOR(node->dflts, u) { - node->dflts[u]->realtype->plugin->free(ctx->ctx, node->dflts[u]); - lysc_type_free(ctx, (struct lysc_type *)node->dflts[u]->realtype); - free(node->dflts[u]); - } - LY_ARRAY_FREE(node->dflts); + lysdict_remove(ctx, node->units); + FREE_ARRAY(ctx, node->dflts, lysc_value_free); } /** * @brief Free the compiled list structure. * - * @param[in] ctx Free context. - * @param[in,out] node Compiled list structure to be freed. + * @param[in] ctx Context to use. + * @param[in] node Compiled list structure to be freed. * Since the structure is typically part of the sized array, the structure itself is not freed. */ static void -lysc_node_list_free(struct lysf_ctx *ctx, struct lysc_node_list *node) +lysc_node_list_free(const struct ly_ctx *ctx, struct lysc_node_list *node) { LY_ARRAY_COUNT_TYPE u; struct lysc_node *child, *child_next; @@ -1090,12 +1068,12 @@ lysc_node_list_free(struct lysf_ctx *ctx, struct lysc_node_list *node) /** * @brief Free the compiled choice structure. * - * @param[in] ctx Free context. - * @param[in,out] node Compiled choice structure to be freed. + * @param[in] ctx Context to use. + * @param[in] node Compiled choice structure to be freed. * Since the structure is typically part of the sized array, the structure itself is not freed. */ static void -lysc_node_choice_free(struct lysf_ctx *ctx, struct lysc_node_choice *node) +lysc_node_choice_free(const struct ly_ctx *ctx, struct lysc_node_choice *node) { struct lysc_node *child, *child_next; @@ -1108,12 +1086,12 @@ lysc_node_choice_free(struct lysf_ctx *ctx, struct lysc_node_choice *node) /** * @brief Free the compiled case structure. * - * @param[in] ctx Free context. - * @param[in,out] node Compiled case structure to be freed. + * @param[in] ctx Context to use. + * @param[in] node Compiled case structure to be freed. * Since the structure is typically part of the sized array, the structure itself is not freed. */ static void -lysc_node_case_free(struct lysf_ctx *ctx, struct lysc_node_case *node) +lysc_node_case_free(const struct ly_ctx *ctx, struct lysc_node_case *node) { struct lysc_node *child, *child_next; @@ -1126,12 +1104,12 @@ lysc_node_case_free(struct lysf_ctx *ctx, struct lysc_node_case *node) /** * @brief Free the compiled anyxml/anydata structure. * - * @param[in] ctx Free context. - * @param[in,out] node Compiled anyxml/anydata structure to be freed. + * @param[in] ctx Context to use. + * @param[in] node Compiled anyxml/anydata structure to be freed. * Since the structure is typically part of the sized array, the structure itself is not freed. */ static void -lysc_node_anydata_free(struct lysf_ctx *ctx, struct lysc_node_anydata *node) +lysc_node_anydata_free(const struct ly_ctx *ctx, struct lysc_node_anydata *node) { FREE_ARRAY(ctx, node->when, lysc_when_free); FREE_ARRAY(ctx, node->musts, lysc_must_free); @@ -1140,19 +1118,19 @@ lysc_node_anydata_free(struct lysf_ctx *ctx, struct lysc_node_anydata *node) /** * @brief Free the compiled node structure. * - * @param[in] ctx Free context. - * @param[in,out] node Compiled node structure to be freed. + * @param[in] ctx Context to use. + * @param[in] node Compiled node structure to be freed. * Since the structure is typically part of the sized array, the structure itself is not freed. */ static void -lysc_node_free_(struct lysf_ctx *ctx, struct lysc_node *node) +lysc_node_free_(const struct ly_ctx *ctx, struct lysc_node *node) { ly_bool inout = 0; /* common part */ - lydict_remove(ctx->ctx, node->name); - lydict_remove(ctx->ctx, node->dsc); - lydict_remove(ctx->ctx, node->ref); + lysdict_remove(ctx, node->name); + lysdict_remove(ctx, node->dsc); + lysdict_remove(ctx, node->ref); /* nodetype-specific part */ switch (node->nodetype) { @@ -1191,7 +1169,7 @@ lysc_node_free_(struct lysf_ctx *ctx, struct lysc_node *node) lysc_node_notif_free(ctx, (struct lysc_node_notif *)node); break; default: - LOGINT(ctx->ctx); + LOGINT(ctx); } FREE_ARRAY(ctx, node->exts, lysc_ext_instance_free); @@ -1202,7 +1180,7 @@ lysc_node_free_(struct lysf_ctx *ctx, struct lysc_node *node) } void -lysc_node_free(struct lysf_ctx *ctx, struct lysc_node *node, ly_bool unlink) +lysc_node_free(const struct ly_ctx *ctx, struct lysc_node *node, ly_bool unlink) { struct lysc_node *next, *iter, **child_p; @@ -1234,7 +1212,7 @@ lysc_node_free(struct lysf_ctx *ctx, struct lysc_node *node, ly_bool unlink) } else { iter = (struct lysc_node *)lysc_node_child(node->parent); } - LY_CHECK_ERR_RET(!iter, LOGINT(ctx->ctx), ); + LY_CHECK_ERR_RET(!iter, LOGINT(ctx), ); } else if (node->nodetype == LYS_RPC) { iter = (struct lysc_node *)node->module->compiled->rpcs; } else if (node->nodetype == LYS_NOTIF) { @@ -1272,7 +1250,7 @@ lysc_node_free(struct lysf_ctx *ctx, struct lysc_node *node, ly_bool unlink) } void -lysc_module_free(struct lysf_ctx *ctx, struct lysc_module *module) +lysc_module_free(const struct ly_ctx *ctx, struct lysc_module *module) { struct lysc_node *node, *node_next; @@ -1280,6 +1258,7 @@ lysc_module_free(struct lysf_ctx *ctx, struct lysc_module *module) return; } + FREE_STRINGS(ctx, module->features); LY_LIST_FOR_SAFE(module->data, node_next, node) { lysc_node_free_(ctx, node); } @@ -1294,8 +1273,37 @@ lysc_module_free(struct lysf_ctx *ctx, struct lysc_module *module) free(module); } +/** + * @brief Free the compiled submodule metadata. + * + * @param[in] ctx Context to use. + * @param[in] submodule COmpiled submodule to be freed. + */ +static void +lysc_submodule_free(const struct ly_ctx *ctx, struct lysc_submodule *submodule) +{ + lysdict_remove(ctx, submodule->name); + lysdict_remove(ctx, submodule->revision); + lysdict_remove(ctx, submodule->filepath); +} + +/** + * @brief Free the compiled extension definition. + * + * @param[in] ctx Context to use. + * @param[in] ext Compiled extension definition to be freed. + */ +static void +lysc_extension_free(const struct ly_ctx *ctx, struct lysc_ext *ext) +{ + lysdict_remove(ctx, ext->name); + lysdict_remove(ctx, ext->argname); + + FREE_ARRAY(ctx, ext->exts, lysc_ext_instance_free); +} + void -lys_module_free(struct lysf_ctx *ctx, struct lys_module *module, ly_bool remove_links) +lys_module_free(const struct ly_ctx *ctx, struct lys_module *module, ly_bool remove_links) { LY_ARRAY_COUNT_TYPE u; @@ -1306,6 +1314,7 @@ lys_module_free(struct lysf_ctx *ctx, struct lys_module *module, ly_bool remove_ assert(!module->implemented); assert(!module->compiled); + /* free identities */ if (remove_links) { /* remove derived identity links */ LY_ARRAY_FOR(module->identities, u) { @@ -1313,45 +1322,34 @@ lys_module_free(struct lysf_ctx *ctx, struct lys_module *module, ly_bool remove_ } } FREE_ARRAY(ctx, module->identities, lysc_ident_free); + + /* free parsed module, which can reference compiled extension definitions */ lysp_module_free(ctx, module->parsed); + /* free compiled extension definitions */ + FREE_ARRAY(ctx, module->extensions, lysc_extension_free); + + FREE_ARRAY(ctx, module->submodules, lysc_submodule_free); LY_ARRAY_FREE(module->augmented_by); LY_ARRAY_FREE(module->deviated_by); - lydict_remove(ctx->ctx, module->name); - lydict_remove(ctx->ctx, module->revision); - lydict_remove(ctx->ctx, module->ns); - lydict_remove(ctx->ctx, module->prefix); - lydict_remove(ctx->ctx, module->filepath); - lydict_remove(ctx->ctx, module->org); - lydict_remove(ctx->ctx, module->contact); - lydict_remove(ctx->ctx, module->dsc); - lydict_remove(ctx->ctx, module->ref); + lysdict_remove(ctx, module->name); + lysdict_remove(ctx, module->revision); + lysdict_remove(ctx, module->ns); + lysdict_remove(ctx, module->prefix); + lysdict_remove(ctx, module->filepath); + lysdict_remove(ctx, module->org); + lysdict_remove(ctx, module->contact); + lysdict_remove(ctx, module->dsc); + lysdict_remove(ctx, module->ref); free(module); } -void -lysf_ctx_erase(struct lysf_ctx *ctx) -{ - struct lysc_ext *ext; - uint32_t i; - - for (i = 0; i < ctx->ext_set.count; ++i) { - ext = ctx->ext_set.objs[i]; - - lydict_remove(ctx->ctx, ext->name); - lydict_remove(ctx->ctx, ext->argname); - free(ext); - } - ly_set_erase(&ctx->ext_set, NULL); -} - LIBYANG_API_DEF void lyplg_ext_pfree_instance_substatements(const struct ly_ctx *ctx, struct lysp_ext_substmt *substmts) { LY_ARRAY_COUNT_TYPE u; - struct lysf_ctx fctx = {.ctx = (struct ly_ctx *)ctx}; ly_bool node_free; LY_ARRAY_FOR(substmts, u) { @@ -1380,7 +1378,7 @@ lyplg_ext_pfree_instance_substatements(const struct ly_ctx *ctx, struct lysp_ext 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); + lysp_node_free(ctx, child); if (node_free) { free(child); } @@ -1390,63 +1388,63 @@ lyplg_ext_pfree_instance_substatements(const struct ly_ctx *ctx, struct lysp_ext } case LY_STMT_BASE: /* multiple strings */ - FREE_ARRAY(ctx, **(const char ***)substmts[u].storage_p, lydict_remove); + FREE_ARRAY(ctx, **(const char ***)substmts[u].storage_p, lysdict_remove); break; case LY_STMT_BIT: case LY_STMT_ENUM: /* single enum */ - lysp_type_enum_free(&fctx, *substmts[u].storage_p); + lysp_type_enum_free(ctx, *substmts[u].storage_p); break; case LY_STMT_DEVIATE: /* single deviate */ - lysp_deviate_free(&fctx, *substmts[u].storage_p); + lysp_deviate_free(ctx, *substmts[u].storage_p); break; case LY_STMT_DEVIATION: /* single deviation */ - lysp_deviation_free(&fctx, *substmts[u].storage_p); + lysp_deviation_free(ctx, *substmts[u].storage_p); break; case LY_STMT_EXTENSION: /* single extension */ - lysp_ext_free(&fctx, *substmts[u].storage_p); + lysp_ext_free(ctx, *substmts[u].storage_p); break; case LY_STMT_EXTENSION_INSTANCE: /* multiple extension instances */ - FREE_ARRAY(&fctx, *(struct lysp_ext_instance **)substmts[u].storage_p, lysp_ext_instance_free); + FREE_ARRAY(ctx, *(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 **)substmts[u].storage_p, lysp_feature_free); + FREE_ARRAY(ctx, *(struct lysp_feature **)substmts[u].storage_p, lysp_feature_free); break; case LY_STMT_IDENTITY: /* multiple identities */ - FREE_ARRAY(&fctx, *(struct lysp_ident **)substmts[u].storage_p, lysp_ident_free); + FREE_ARRAY(ctx, *(struct lysp_ident **)substmts[u].storage_p, lysp_ident_free); break; case LY_STMT_IMPORT: /* multiple imports */ - FREE_ARRAY(&fctx, *(struct lysp_import **)substmts[u].storage_p, lysp_import_free); + FREE_ARRAY(ctx, *(struct lysp_import **)substmts[u].storage_p, lysp_import_free); break; case LY_STMT_INCLUDE: /* multiple includes */ - FREE_ARRAY(&fctx, *(struct lysp_include **)substmts[u].storage_p, lysp_include_free); + FREE_ARRAY(ctx, *(struct lysp_include **)substmts[u].storage_p, lysp_include_free); break; case LY_STMT_REFINE: /* multiple refines */ - FREE_ARRAY(&fctx, *(struct lysp_refine **)substmts[u].storage_p, lysp_refine_free); + FREE_ARRAY(ctx, *(struct lysp_refine **)substmts[u].storage_p, lysp_refine_free); break; case LY_STMT_REVISION: /* multiple revisions */ - FREE_ARRAY(&fctx, *(struct lysp_revision **)substmts[u].storage_p, lysp_revision_free); + FREE_ARRAY(ctx, *(struct lysp_revision **)substmts[u].storage_p, lysp_revision_free); break; case LY_STMT_CONFIG: @@ -1480,7 +1478,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, *substmts[u].storage_p); + lysdict_remove(ctx, *substmts[u].storage_p); break; case LY_STMT_LENGTH: @@ -1488,17 +1486,17 @@ 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 **)substmts[u].storage_p, lysp_restr_free); + FREE_ARRAY(ctx, *(struct lysp_restr **)substmts[u].storage_p, lysp_restr_free); break; case LY_STMT_WHEN: /* multiple whens */ - FREE_ARRAY(&fctx, *(struct lysp_when **)substmts[u].storage_p, lysp_when_free); + FREE_ARRAY(ctx, *(struct lysp_when **)substmts[u].storage_p, lysp_when_free); break; case LY_STMT_PATH: /* single expression */ - lyxp_expr_free(ctx, *substmts[u].storage_p); + lyxp_expr_free(*substmts[u].storage_p); break; case LY_STMT_DEFAULT: @@ -1510,21 +1508,21 @@ lyplg_ext_pfree_instance_substatements(const struct ly_ctx *ctx, struct lysp_ext case LY_STMT_TYPEDEF: /* multiple typedefs */ - FREE_ARRAY(&fctx, *(struct lysp_tpdf **)substmts[u].storage_p, lysp_tpdf_free); + FREE_ARRAY(ctx, *(struct lysp_tpdf **)substmts[u].storage_p, lysp_tpdf_free); break; case LY_STMT_TYPE: { /* single type */ struct lysp_type **type_p = (struct lysp_type **)substmts[u].storage_p; - lysp_type_free(&fctx, *type_p); + lysp_type_free(ctx, *type_p); free(*type_p); break; } case LY_STMT_MODULE: case LY_STMT_SUBMODULE: /* single (sub)module */ - lysp_module_free(&fctx, *substmts[u].storage_p); + lysp_module_free(ctx, *substmts[u].storage_p); break; default: @@ -1539,7 +1537,6 @@ LIBYANG_API_DEF void lyplg_ext_cfree_instance_substatements(const struct ly_ctx *ctx, struct lysc_ext_substmt *substmts) { LY_ARRAY_COUNT_TYPE u; - struct lysf_ctx fctx = {.ctx = (struct ly_ctx *)ctx}; ly_bool node_free; LY_ARRAY_FOR(substmts, u) { @@ -1565,7 +1562,7 @@ lyplg_ext_cfree_instance_substatements(const struct ly_ctx *ctx, struct lysc_ext 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); + lysc_node_free_(ctx, child); if (node_free) { free(child); } @@ -1602,7 +1599,7 @@ lyplg_ext_cfree_instance_substatements(const struct ly_ctx *ctx, struct lysc_ext /* single item */ const char *str = *substmts[u].storage_p; - lydict_remove(ctx, str); + lysdict_remove(ctx, str); break; } case LY_STMT_BIT: @@ -1610,7 +1607,7 @@ lyplg_ext_cfree_instance_substatements(const struct ly_ctx *ctx, struct lysc_ext /* sized array */ struct lysc_type_bitenum_item *items = *substmts[u].storage_p; - FREE_ARRAY(&fctx, items, lysc_enum_item_free); + FREE_ARRAY(ctx, items, lysc_enum_item_free); break; } case LY_STMT_LENGTH: @@ -1618,47 +1615,47 @@ lyplg_ext_cfree_instance_substatements(const struct ly_ctx *ctx, struct lysc_ext /* single item */ struct lysc_range *range = *substmts[u].storage_p; - lysc_range_free(&fctx, range); + lysc_range_free(ctx, range); break; } case LY_STMT_MUST: { /* sized array */ struct lysc_must *musts = *substmts[u].storage_p; - FREE_ARRAY(&fctx, musts, lysc_must_free); + FREE_ARRAY(ctx, musts, lysc_must_free); break; } case LY_STMT_WHEN: /* single item, expects a pointer */ - lysc_when_free(&fctx, (struct lysc_when **)substmts[u].storage_p); + lysc_when_free(ctx, (struct lysc_when **)substmts[u].storage_p); break; case LY_STMT_PATTERN: { /* sized array of pointers */ struct lysc_pattern **patterns = *substmts[u].storage_p; - FREE_ARRAY(&fctx, patterns, lysc_pattern_free); + FREE_ARRAY(ctx, patterns, lysc_pattern_free); break; } case LY_STMT_TYPE: { /* single item */ struct lysc_type *type = *substmts[u].storage_p; - lysc_type_free(&fctx, type); + lysc_type_free(ctx, type); break; } case LY_STMT_IDENTITY: { /* sized array */ struct lysc_ident *idents = *substmts[u].storage_p; - FREE_ARRAY(&fctx, idents, lysc_ident_free); + FREE_ARRAY(ctx, idents, lysc_ident_free); break; } case LY_STMT_EXTENSION_INSTANCE: { /* sized array */ struct lysc_ext_instance *exts = *substmts[u].storage_p; - FREE_ARRAY(&fctx, exts, lysc_ext_instance_free); + FREE_ARRAY(ctx, exts, lysc_ext_instance_free); break; } case LY_STMT_AUGMENT: diff --git a/src/tree_schema_free.h b/src/tree_schema_free.h index f4141ded1..6b9b4ee9a 100644 --- a/src/tree_schema_free.h +++ b/src/tree_schema_free.h @@ -3,7 +3,7 @@ * @author Michal Vasko * @brief internal freeing functions for YANG schema trees. * - * 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. @@ -18,15 +18,10 @@ #include "set.h" #include "tree_schema.h" +struct lysc_value; struct lysp_yang_ctx; struct lysp_yin_ctx; -struct lysf_ctx { - struct ly_ctx *ctx; - struct lys_module *mod; - struct ly_set ext_set; -}; - /** * @brief Macro to free [sized array](@ref sizedarrays) of items using the provided free function. The ARRAY itself is also freed, * but the memory is not sanitized. @@ -42,12 +37,12 @@ struct lysf_ctx { * @brief Macro to free [sized array](@ref sizedarrays) of strings stored in the context's dictionary. The ARRAY itself is also freed, * but the memory is not sanitized. */ -#define FREE_STRINGS(CTX, ARRAY) {LY_ARRAY_COUNT_TYPE c__; LY_ARRAY_FOR(ARRAY, c__){lydict_remove(CTX, ARRAY[c__]);}LY_ARRAY_FREE(ARRAY);} +#define FREE_STRINGS(CTX, ARRAY) {LY_ARRAY_COUNT_TYPE c__; LY_ARRAY_FOR(ARRAY, c__){lysdict_remove(CTX, ARRAY[c__]);}LY_ARRAY_FREE(ARRAY);} /** * @brief Free a parsed qualified name. * - * @param[in] ctx libyang context. + * @param[in] ctx Context to use. * @param[in] qname Qualified name to free. */ void lysp_qname_free(const struct ly_ctx *ctx, struct lysp_qname *qname); @@ -55,118 +50,126 @@ void lysp_qname_free(const struct ly_ctx *ctx, struct lysp_qname *qname); /** * @brief Free the parsed extension instance structure. * - * @param[in] ctx Free context. + * @param[in] ctx Context to use. * @param[in] ext Parsed extension instance structure to free. Note that the instance itself is not freed. */ -void lysp_ext_instance_free(struct lysf_ctx *ctx, struct lysp_ext_instance *ext); +void lysp_ext_instance_free(const struct ly_ctx *ctx, struct lysp_ext_instance *ext); /** * @brief Free a parsed restriction. * - * @param[in] ctx Free context. + * @param[in] ctx Context to use. * @param[in] restr Restriction to free. */ -void lysp_restr_free(struct lysf_ctx *ctx, struct lysp_restr *restr); +void lysp_restr_free(const struct ly_ctx *ctx, struct lysp_restr *restr); /** * @brief Free the parsed type structure. * - * @param[in] ctx Free context. + * @param[in] ctx Context to use. * @param[in] type Parsed schema type structure to free. Note that the type itself is not freed. */ -void lysp_type_free(struct lysf_ctx *ctx, struct lysp_type *type); +void lysp_type_free(const struct ly_ctx *ctx, struct lysp_type *type); /** * @brief Free the parsed when structure. * - * @param[in] ctx Free context. + * @param[in] ctx Context to use. * @param[in] when Parsed schema when structure to free. Note that the structure itself is not freed. */ -void lysp_when_free(struct lysf_ctx *ctx, struct lysp_when *when); +void lysp_when_free(const struct ly_ctx *ctx, struct lysp_when *when); /** * @brief Free the parsed deviate structure. * - * @param[in] ctx Free context. + * @param[in] ctx Context to use. * @param[in] d Parsed schema deviate structure to free. Note that the structure itself is not freed. */ -void lysp_deviate_free(struct lysf_ctx *ctx, struct lysp_deviate *d); +void lysp_deviate_free(const struct ly_ctx *ctx, struct lysp_deviate *d); /** * @brief Free the parsed deviation structure. * - * @param[in] ctx Free context. + * @param[in] ctx Context to use. * @param[in] dev Parsed schema deviation structure to free. Note that the structure itself is not freed. */ -void lysp_deviation_free(struct lysf_ctx *ctx, struct lysp_deviation *dev); +void lysp_deviation_free(const struct ly_ctx *ctx, struct lysp_deviation *dev); /** * @brief Free a parsed node. * - * @param[in] ctx Free context. + * @param[in] ctx Context to use. * @param[in] node Node to free. */ -void lysp_node_free(struct lysf_ctx *ctx, struct lysp_node *node); +void lysp_node_free(const struct ly_ctx *ctx, struct lysp_node *node); /** * @brief Free the parsed YANG schema tree structure. Works for both modules and submodules. * - * @param[in] ctx Free context. + * @param[in] ctx Context to use. * @param[in] module Parsed YANG schema tree structure to free. */ -void lysp_module_free(struct lysf_ctx *ctx, struct lysp_module *module); +void lysp_module_free(const struct ly_ctx *ctx, struct lysp_module *module); /** * @brief Free the compiled extension instance structure. * - * @param[in] ctx Free context. - * @param[in,out] ext Compiled extension instance structure to be cleaned. + * @param[in] ctx Context to use. + * @param[in] ext Compiled extension instance structure to be cleaned. * Since the structure is typically part of the sized array, the structure itself is not freed. */ -void lysc_ext_instance_free(struct lysf_ctx *ctx, struct lysc_ext_instance *ext); +void lysc_ext_instance_free(const struct ly_ctx *ctx, struct lysc_ext_instance *ext); /** * @brief Free the compiled if-feature structure. * - * @param[in] ctx Free context. - * @param[in,out] iff Compiled if-feature structure to be cleaned. + * @param[in] ctx Context to use. + * @param[in] iff Compiled if-feature structure to be cleaned. * Since the structure is typically part of the sized array, the structure itself is not freed. */ -void lysc_iffeature_free(struct lysf_ctx *ctx, struct lysc_iffeature *iff); +void lysc_iffeature_free(const struct ly_ctx *ctx, struct lysc_iffeature *iff); /** * @brief Free the compiled range structure. * - * @param[in] ctx Free context. + * @param[in] ctx Context to use. * @param[in,out] range Compiled range structure to be freed. * Since the structure is typically part of the sized array, the structure itself is not freed. */ -void lysc_range_free(struct lysf_ctx *ctx, struct lysc_range *range); +void lysc_range_free(const struct ly_ctx *ctx, struct lysc_range *range); /** * @brief Free a compiled pattern. * - * @param[in] ctx Free context. + * @param[in] ctx Context to use. * @param[in] pattern Pointer to the pattern to free. */ -void lysc_pattern_free(struct lysf_ctx *ctx, struct lysc_pattern **pattern); +void lysc_pattern_free(const struct ly_ctx *ctx, struct lysc_pattern **pattern); /** * @brief Free a bit/enum item. * - * @param[in] ctx Free context. + * @param[in] ctx Context to use. * @param[in] item Bit/enum item to free. */ -void lysc_enum_item_free(struct lysf_ctx *ctx, struct lysc_type_bitenum_item *item); +void lysc_enum_item_free(const struct ly_ctx *ctx, struct lysc_type_bitenum_item *item); /** * @brief Free the compiled type structure. * - * @param[in] ctx Free context. - * @param[in,out] type Compiled type structure to be freed. The structure has refcount, so it is freed only in case + * @param[in] ctx Context to use. + * @param[in] type Compiled type structure to be freed. The structure has refcount, so it is freed only in case * the value is decreased to 0. */ -void lysc_type_free(struct lysf_ctx *ctx, struct lysc_type *type); +void lysc_type_free(const struct ly_ctx *ctx, struct lysc_type *type); + +/** + * @brief Free a compiled value. + * + * @param[in] ctx Context to use. + * @param[in] val Compiled value to free. + */ +void lysc_value_free(const struct ly_ctx *ctx, struct lysc_value *val); /** * @brief Free the compiled container node structure. @@ -174,44 +177,37 @@ void lysc_type_free(struct lysf_ctx *ctx, struct lysc_type *type); * Only the container-specific members are freed, for generic node free function, * use ::lysc_node_free(). * - * @param[in] ctx Free context. - * @param[in,out] node Compiled container node structure to be freed. + * @param[in] ctx Context to use. + * @param[in] node Compiled container node structure to be freed. */ -void lysc_node_container_free(struct lysf_ctx *ctx, struct lysc_node_container *node); +void lysc_node_container_free(const struct ly_ctx *ctx, struct lysc_node_container *node); /** * @brief Free the compiled node structure. * - * @param[in] ctx Free context. + * @param[in] ctx Context to use. * @param[in] node Compiled node structure to be freed. * @param[in] unlink Whether to first unlink the node before freeing. */ -void lysc_node_free(struct lysf_ctx *ctx, struct lysc_node *node, ly_bool unlink); +void lysc_node_free(const struct ly_ctx *ctx, struct lysc_node *node, ly_bool unlink); /** * @brief Free the compiled schema structure. * - * @param[in] ctx Free context. - * @param[in,out] module Compiled schema module structure to free. + * @param[in] ctx Context to use. + * @param[in] module Compiled schema module structure to free. */ -void lysc_module_free(struct lysf_ctx *ctx, struct lysc_module *module); +void lysc_module_free(const struct ly_ctx *ctx, struct lysc_module *module); /** * @brief Free the schema structure. It just frees, it does not remove the schema from its context. * - * @param[in] ctx Free context. - * @param[in,out] module Schema module structure to free. + * @param[in] ctx Context to use. + * @param[in] module Schema module structure to free. * @param[in] remove_links Whether to remove links in other modules to structures in this module. Not needed if * the whole context is being freed. */ -void lys_module_free(struct lysf_ctx *ctx, struct lys_module *module, ly_bool remove_links); - -/** - * @brief Erase free context. - * - * @param[in] ctx Free context to erase. - */ -void lysf_ctx_erase(struct lysf_ctx *ctx); +void lys_module_free(const struct ly_ctx *ctx, struct lys_module *module, ly_bool remove_links); /** * @brief Free lys parser context. diff --git a/src/tree_schema_internal.h b/src/tree_schema_internal.h index 974c99664..d4981a59f 100644 --- a/src/tree_schema_internal.h +++ b/src/tree_schema_internal.h @@ -3,7 +3,7 @@ * @author Radek Krejci * @brief internal functions for YANG schema trees. * - * 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. @@ -181,6 +181,14 @@ struct lysp_yin_ctx { struct lyxml_ctx *xmlctx; /**< context for xml parser */ }; +/** + * @brief Internal pattern hash table record. + */ +struct ly_pattern_ht_rec { + const char *pattern; /**< Pattern string, used both as key to hash and value to search for. */ + pcre2_code *pcode; /**< Compiled PCRE2 pattern code. */ +}; + /** * @brief Check that @p c is valid UTF8 code point for YANG string. * @@ -446,6 +454,17 @@ struct lysc_must **lysc_node_musts_p(const struct lysc_node *node); LY_ERR lysp_ext_find_definition(const struct ly_ctx *ctx, const struct lysp_ext_instance *ext, const struct lys_module **ext_mod, struct lysp_ext **ext_def); +/** + * @brief Find compiled extension definition for the given extension instance. + * + * @param[in] ctx libyang context. + * @param[in] ext Extension instance for which the definition will be searched. + * @param[out] ext_def Found compiled extension definition. + * @return LY_SUCCESS when the definition was found. + * @return LY_EVALID when the extension instance is invalid and/or the definition not found. + */ +LY_ERR lysc_ext_find_definition(const struct ly_ctx *ctx, const struct lysp_ext_instance *ext, struct lysc_ext **ext_def); + /** * @brief Get schema node in extension instance according to the given parameters. * @@ -468,10 +487,12 @@ const struct lysc_node *lysc_ext_find_node(const struct lysc_ext_instance *ext, * as substatements and resolving argument is postponed. * * @param[in] ctx libyang context - * @param[in] ext_p Parsed extension to be updated. + * @param[in] ext_def Parsed extension definition. + * @param[in,out] ext_p Parsed extension to be updated. * @return LY_ERR value. */ -LY_ERR lysp_ext_instance_resolve_argument(struct ly_ctx *ctx, struct lysp_ext_instance *ext_p); +LY_ERR lysp_ext_instance_resolve_argument(const struct ly_ctx *ctx, const struct lysp_ext *ext_def, + struct lysp_ext_instance *ext_p); /** * @brief Iterate over the specified type of the extension instances @@ -737,4 +758,89 @@ uint8_t lys_stmt_flags(enum ly_stmt stmt); */ LY_ERR lyplg_ext_get_storage_p(const struct lysc_ext_instance *ext, int stmt, void ***storage_pp); +/** + * @brief Compare compiled value with another canonical value. + * + * @param[in] schema Schema node with the type of @p val. + * @param[in] ctx_node Data context node, if any. + * @param[in] val Compiled value that needs to be canonized. + * @param[in] val2 Canonical value. + * @return strcmp return value. + */ +int lysc_value_cmp(const struct lysc_node *schema, const struct lyd_node *ctx_node, const struct lysc_value *val, + const char *val2); + +/** + * @brief Get the size of the printed context with all the nested structures. + * + * @param[in] ctx Context to print. + * @param[in,out] addr_ht Hash table with printed addresses of all the shared structures, can be added to. + * @param[in,out] size Resulting size of @p ctx, is added to. + */ +void ly_ctx_compiled_size_context(const struct ly_ctx *ctx, struct ly_ht *addr_ht, int *size); + +/** + * @brief Get the size of the compiled substatements storage of a compiled extension instance for serialization. + * + * @param[in] substmts Substatements to examine. + * @param[in,out] addr_ht Hash table with printed addresses of all the shared structures, can be added to. + * @return Total size of compiled substatements storage. + */ +int ly_ctx_compiled_ext_stmts_storage_size(const struct lysc_ext_substmt *substmts, struct ly_ht *addr_ht); + +struct ctxp_ht_addr { + const void *orig_addr; /**< address of the shared structure to be printed */ + const void *addr; /**< address of the printed shared structure */ +}; + +/** + * @brief Print context structure with all nested structures into a memory chunk. + * + * @param[in] orig_ctx Context to print. + * @param[in,out] ctx Printed context, to fill. + * @param[in,out] addr_ht Hash table with pairs of addresses of shared structures to be printed and their printed + * addresses, can be added to. + * @param[in,out] ptr_set Set with pointers to be set to printed addresses. + * @param[in,out] mem Memory chunk to print into, is moved after all the printed data. + */ +void ly_ctx_compiled_print_context(const struct ly_ctx *orig_ctx, struct ly_ctx *ctx, struct ly_ht *addr_ht, + struct ly_set *ptr_set, void **mem); + +/** + * @brief Print the compiled substatements storage of a compiled extension instance. + * + * @param[in] orig_substmts Extension instance substatements to print. + * @param[in,out] substmts Printed extension instance substatements with storage pointers to modify. + * @param[in,out] addr_ht Hash table with pairs of addresses of shared structures to be printed and their printed + * addresses, can be added to. + * @param[in,out] ptr_set Set with pointers to be set to printed addresses. + * @param[in,out] mem Memory chunk to print into, is moved after all the printed data. + * @return LY_SUCCESS on success; + * @return LY_ERR on error. + */ +LY_ERR ly_ctx_compiled_ext_stmts_storage_print(const struct lysc_ext_substmt *orig_substmts, + struct lysc_ext_substmt *substmts, struct ly_ht *addr_ht, struct ly_set *ptr_set, void **mem); + +/** + * @brief Get the printed address of a shared structure. + * + * @param[in] addr_ht Hash table with printed addresses of all the shared structures. + * @param[in] addr Address of the shared structure to be printed. + * @param[in] ignore_not_found Whether it is expected an address may not be found. + * @return Printed address of the shared structure; + * @return NULL if not found. + */ +void *ly_ctx_compiled_addr_ht_get(const struct ly_ht *addr_ht, const void *addr, ly_bool ignore_not_found); + +/** + * @brief Add the printed address of a shared structure. + * + * @param[in,out] addr_ht Hash table with pairs of addresses of shared structures to be printed and their printed + * addresses, is added to. + * @param[in] orig_addr Address fo the shared structure to be printed. + * @param[in] addr Addres of the printed shared structure. + * @return LY_ERR value. + */ +LY_ERR ly_ctx_compiled_addr_ht_add(struct ly_ht *addr_ht, const void *orig_addr, const void *addr); + #endif /* LY_TREE_SCHEMA_INTERNAL_H_ */ diff --git a/src/validation.c b/src/validation.c index 25be0feeb..b0562dc7b 100644 --- a/src/validation.c +++ b/src/validation.c @@ -23,6 +23,7 @@ #include #include "compat.h" +#include "dict.h" #include "diff.h" #include "hash_table.h" #include "log.h" @@ -31,6 +32,7 @@ #include "parser_internal.h" #include "plugins_exts.h" #include "plugins_exts/metadata.h" +#include "plugins_internal.h" #include "plugins_types.h" #include "set.h" #include "tree.h" @@ -347,7 +349,7 @@ lyd_validate_autodel_node_del(struct lyd_node **first, struct lyd_node *del, con /* remove from node_types set */ LYD_TREE_DFS_BEGIN(del, iter) { if ((iter->schema->nodetype & LYD_NODE_TERM) && - ((struct lysc_node_leaf *)iter->schema)->type->plugin->validate && + LYSC_GET_TYPE_PLG(((struct lysc_node_leaf *)iter->schema)->type->plugin_ref)->validate && ly_set_contains(node_types, iter, &idx)) { ly_set_rm_index(node_types, idx, NULL); } @@ -456,7 +458,8 @@ lyd_validate_unres(struct lyd_node **tree, const struct lys_module *mod, enum ly struct lyd_ctx_ext_val *ext_v = ext_val->objs[i]; /* validate extension data */ - r = ext_v->ext->def->plugin->validate(ext_v->ext, ext_v->sibling, *tree, data_type, val_opts, diff); + r = LYSC_GET_EXT_PLG(ext_v->ext->def->plugin_ref)->validate(ext_v->ext, ext_v->sibling, *tree, + data_type, val_opts, diff); LY_VAL_ERR_GOTO(r, rc = r, val_opts, cleanup); /* remove this item from the set */ @@ -473,7 +476,7 @@ lyd_validate_unres(struct lyd_node **tree, const struct lys_module *mod, enum ly struct lyd_ctx_ext_node *ext_n = ext_node->objs[i]; /* validate the node */ - r = ext_n->ext->def->plugin->node(ext_n->ext, ext_n->node, val_opts); + r = LYSC_GET_EXT_PLG(ext_n->ext->def->plugin_ref)->node(ext_n->ext, ext_n->node, val_opts); LY_VAL_ERR_GOTO(r, rc = r, val_opts, cleanup); /* remove this item from the set */ @@ -717,7 +720,7 @@ lyd_val_has_default(const struct lysc_node *schema) { switch (schema->nodetype) { case LYS_LEAF: - if (((struct lysc_node_leaf *)schema)->dflt) { + if (((struct lysc_node_leaf *)schema)->dflt.str) { return 1; } break; @@ -1295,10 +1298,10 @@ struct lyd_val_uniq_arg { static ly_bool lyd_val_uniq_list_equal(void *val1_p, void *val2_p, ly_bool UNUSED(mod), void *cb_data) { - struct ly_ctx *ctx; + const struct ly_ctx *ctx; struct lysc_node_list *slist; struct lyd_node *diter, *first, *second; - struct lyd_value *val1, *val2; + const char *val1, *val2, *canon1, *canon2; char *path1, *path2, *uniq_str, *ptr; LY_ARRAY_COUNT_TYPE u, v; struct lyd_val_uniq_arg *arg = cb_data; @@ -1312,7 +1315,7 @@ lyd_val_uniq_list_equal(void *val1_p, void *val2_p, ly_bool UNUSED(mod), void *c assert(first && (first->schema->nodetype == LYS_LIST)); assert(second && (second->schema == first->schema)); - ctx = first->schema->module->ctx; + ctx = LYD_CTX(first); slist = (struct lysc_node_list *)first->schema; @@ -1327,24 +1330,36 @@ lyd_val_uniq_list_equal(void *val1_p, void *val2_p, ly_bool UNUSED(mod), void *c uniquecheck: LY_ARRAY_FOR(slist->uniques[u], v) { /* first */ + canon1 = NULL; + val1 = NULL; diter = lyd_val_uniq_find_leaf(slist->uniques[u][v], first); if (diter) { - val1 = &((struct lyd_node_term *)diter)->value; - } else { - /* use default value */ - val1 = slist->uniques[u][v]->dflt; + val1 = lyd_get_value(diter); + } else if (slist->uniques[u][v]->dflt.str) { + /* use canonical default value */ + lyd_value_validate2(ctx, first->schema, slist->uniques[u][v]->dflt.str, + strlen(slist->uniques[u][v]->dflt.str), LY_VALUE_SCHEMA_RESOLVED, + slist->uniques[u][v]->dflt.prefixes, NULL, NULL, &canon2); + val1 = canon1; } /* second */ + canon2 = NULL; + val2 = NULL; diter = lyd_val_uniq_find_leaf(slist->uniques[u][v], second); if (diter) { - val2 = &((struct lyd_node_term *)diter)->value; - } else { - /* use default value */ - val2 = slist->uniques[u][v]->dflt; + val2 = lyd_get_value(diter); + } else if (slist->uniques[u][v]->dflt.str) { + /* use canonical default value */ + lyd_value_validate2(ctx, first->schema, slist->uniques[u][v]->dflt.str, + strlen(slist->uniques[u][v]->dflt.str), LY_VALUE_SCHEMA_RESOLVED, + slist->uniques[u][v]->dflt.prefixes, NULL, NULL, &canon2); + val2 = canon2; } - if (!val1 || !val2 || val1->realtype->plugin->compare(ctx, val1, val2)) { + lydict_remove(ctx, canon1); + lydict_remove(ctx, canon2); + if (!val1 || !val2 || (val1 != val2)) { /* values differ or either one is not set */ break; } @@ -1417,12 +1432,9 @@ lyd_validate_unique(const struct lyd_node *first, const struct lysc_node *snode, LY_ARRAY_COUNT_TYPE u, v, x = 0; LY_ERR ret = LY_SUCCESS; uint32_t hash, i; - size_t key_len; - ly_bool dyn; - const void *hash_key; struct lyd_val_uniq_arg arg, *args = NULL; struct ly_ht **uniqtables = NULL; - struct lyd_value *val; + const char *val; struct ly_ctx *ctx = snode->module->ctx; assert(uniques); @@ -1466,10 +1478,12 @@ lyd_validate_unique(const struct lyd_node *first, const struct lysc_node *snode, for (v = hash = 0; v < LY_ARRAY_COUNT(uniques[u]); v++) { diter = lyd_val_uniq_find_leaf(uniques[u][v], set->objs[i]); if (diter) { - val = &((struct lyd_node_term *)diter)->value; - } else { - /* use default value */ - val = uniques[u][v]->dflt; + val = lyd_get_value(diter); + } else if (uniques[u][v]->dflt.str) { + /* use canonical default value */ + ret = lyd_value_validate2(ctx, snode, uniques[u][v]->dflt.str, strlen(uniques[u][v]->dflt.str), + LY_VALUE_SCHEMA_RESOLVED, uniques[u][v]->dflt.prefixes, NULL, NULL, &val); + LY_CHECK_GOTO(ret, cleanup); } if (!val) { /* unique item not present nor has default value */ @@ -1477,11 +1491,7 @@ lyd_validate_unique(const struct lyd_node *first, const struct lysc_node *snode, } /* get hash key */ - hash_key = val->realtype->plugin->print(NULL, val, LY_VALUE_LYB, NULL, &dyn, &key_len); - hash = lyht_hash_multi(hash, hash_key, key_len); - if (dyn) { - free((void *)hash_key); - } + hash = lyht_hash_multi(hash, val, strlen(val)); } if (!val) { /* skip this list instance since its unique set is incomplete */ @@ -1852,7 +1862,7 @@ lyd_validate_nested_ext(struct lyd_node *sibling, struct ly_set *ext_val) /* try to find the extension instance */ nested_exts = sibling->parent->schema->exts; LY_ARRAY_FOR(nested_exts, u) { - if (nested_exts[u].def->plugin->validate) { + if (LYSC_GET_EXT_PLG(nested_exts[u].def->plugin_ref)->validate) { if (ext) { /* more extension instances with validate callback */ LOGINT_RET(LYD_CTX(sibling)); @@ -1885,7 +1895,7 @@ lyd_validate_node_ext(struct lyd_node *node, struct ly_set *ext_node) /* try to find a relevant extension instance with node callback */ exts = node->schema->exts; LY_ARRAY_FOR(exts, u) { - if (exts[u].def->plugin && exts[u].def->plugin->node) { + if (exts[u].def->plugin_ref && LYSC_GET_EXT_PLG(exts[u].def->plugin_ref)->node) { /* store for validation */ ext_n = malloc(sizeof *ext_n); LY_CHECK_ERR_RET(!ext_n, LOGMEM(LYD_CTX(node)), LY_EMEM); @@ -1937,14 +1947,15 @@ lyd_validate_subtree(struct lyd_node *root, struct ly_set *node_when, struct ly_ LY_LIST_FOR(node->meta, meta) { lyplg_ext_get_storage(meta->annotation, LY_STMT_TYPE, sizeof type, (const void **)&type); - if (type->plugin->validate) { + if (LYSC_GET_TYPE_PLG(type->plugin_ref)->validate) { /* metadata type resolution */ r = ly_set_add(meta_types, (void *)meta, 1, NULL); LY_CHECK_ERR_GOTO(r, rc = r, cleanup); } } - if ((node->schema->nodetype & LYD_NODE_TERM) && ((struct lysc_node_leaf *)node->schema)->type->plugin->validate) { + if ((node->schema->nodetype & LYD_NODE_TERM) && + LYSC_GET_TYPE_PLG(((struct lysc_node_leaf *)node->schema)->type->plugin_ref)->validate) { /* node type resolution */ r = ly_set_add(node_types, (void *)node, 1, NULL); LY_CHECK_ERR_GOTO(r, rc = r, cleanup); diff --git a/src/xpath.c b/src/xpath.c index 99a4a2278..0e812a617 100644 --- a/src/xpath.c +++ b/src/xpath.c @@ -34,6 +34,7 @@ #include "parser_data.h" #include "path.h" #include "plugins_exts/metadata.h" +#include "plugins_internal.h" #include "plugins_types.h" #include "printer_data.h" #include "schema_compile_node.h" @@ -52,9 +53,9 @@ static LY_ERR moveto_resolve_module(const char **qname, uint32_t *qname_len, con static LY_ERR moveto_axis_node_next(const struct lyd_node **iter, enum lyxp_node_type *iter_type, const struct lyd_node *node, enum lyxp_node_type node_type, enum lyxp_axis axis, struct lyxp_set *set); static LY_ERR moveto_node(struct lyxp_set *set, const struct lys_module *moveto_mod, const char *ncname, - enum lyxp_axis axis, uint32_t options); + uint32_t ncname_len, enum lyxp_axis axis, uint32_t options); static LY_ERR moveto_scnode(struct lyxp_set *set, const struct lys_module *moveto_mod, const char *ncname, - enum lyxp_axis axis, uint32_t options); + uint32_t ncname_len, enum lyxp_axis axis, uint32_t options); static LY_ERR moveto_op_comp(struct lyxp_set *set1, struct lyxp_set *set2, const char *op, ly_bool *result); /* Functions are divided into the following basic classes: @@ -1696,9 +1697,9 @@ static LY_ERR set_comp_canonize(struct lyxp_set *set, const struct lyxp_set_node *xp_node) { const struct lysc_type *type = NULL; - struct lyd_value val; - struct ly_err_item *err = NULL; + const char *canon; LY_ERR r; + struct lyplg_type *type_plg; /* is there anything to canonize even? */ if (set->type == LYXP_SET_STRING) { @@ -1714,33 +1715,34 @@ set_comp_canonize(struct lyxp_set *set, const struct lyxp_set_node *xp_node) return LY_SUCCESS; } + type_plg = LYSC_GET_TYPE_PLG(type->plugin_ref); + /* check for built-in types without required canonization */ - if ((type->basetype == LY_TYPE_STRING) && (type->plugin->store == lyplg_type_store_string)) { + if ((type->basetype == LY_TYPE_STRING) && (type_plg->store == lyplg_type_store_string)) { /* string */ return LY_SUCCESS; } - if ((type->basetype == LY_TYPE_BOOL) && (type->plugin->store == lyplg_type_store_boolean)) { + if ((type->basetype == LY_TYPE_BOOL) && (type_plg->store == lyplg_type_store_boolean)) { /* boolean */ return LY_SUCCESS; } - if ((type->basetype == LY_TYPE_ENUM) && (type->plugin->store == lyplg_type_store_enum)) { + if ((type->basetype == LY_TYPE_ENUM) && (type_plg->store == lyplg_type_store_enum)) { /* enumeration */ return LY_SUCCESS; } /* print canonized string, ignore errors, the value may not satisfy schema constraints */ - r = type->plugin->store(set->ctx, type, set->val.str, strlen(set->val.str), 0, set->format, set->prefix_data, - LYD_HINT_DATA, xp_node->node->schema, &val, NULL, &err); - ly_err_free(err); + r = lyd_value_validate2(set->ctx, xp_node->node->schema, set->val.str, strlen(set->val.str), + set->format, set->prefix_data, NULL, NULL, &canon); if (r && (r != LY_EINCOMPLETE)) { - /* invalid value, function store automaticaly dealloc value when fail */ + /* invalid value, fine */ return LY_SUCCESS; } /* use the canonized string value */ free(set->val.str); - set->val.str = strdup(lyd_value_get_canonical(set->ctx, &val)); - type->plugin->free(set->ctx, &val); + set->val.str = strdup(canon); + lydict_remove(set->ctx, canon); LY_CHECK_ERR_RET(!set->val.str, LOGMEM(set->ctx), LY_EMEM); return LY_SUCCESS; @@ -2792,7 +2794,7 @@ exp_add_token(const struct ly_ctx *ctx, struct lyxp_expr *exp, enum lyxp_token t } void -lyxp_expr_free(const struct ly_ctx *ctx, struct lyxp_expr *expr) +lyxp_expr_free(struct lyxp_expr *expr) { uint32_t i; @@ -2800,7 +2802,7 @@ lyxp_expr_free(const struct ly_ctx *ctx, struct lyxp_expr *expr) return; } - lydict_remove(ctx, expr->expr); + free(expr->expr); free(expr->tokens); free(expr->tok_pos); free(expr->tok_len); @@ -2913,7 +2915,8 @@ lyxp_expr_parse(const struct ly_ctx *ctx, const char *expr_str, size_t expr_len, /* init lyxp_expr structure */ expr = calloc(1, sizeof *expr); LY_CHECK_ERR_GOTO(!expr, LOGMEM(ctx); ret = LY_EMEM, error); - LY_CHECK_GOTO(ret = lydict_insert(ctx, expr_str, expr_len, &expr->expr), error); + expr->expr = strndup(expr_str, expr_len); + LY_CHECK_ERR_GOTO(!expr->expr, LOGMEM(ctx); ret = LY_EMEM, error); expr->used = 0; expr->size = LYXP_EXPR_SIZE_START; expr->tokens = malloc(expr->size * sizeof *expr->tokens); @@ -3225,7 +3228,7 @@ lyxp_expr_parse(const struct ly_ctx *ctx, const char *expr_str, size_t expr_len, return LY_SUCCESS; error: - lyxp_expr_free(ctx, expr); + lyxp_expr_free(expr); return ret; } @@ -3299,11 +3302,12 @@ lyxp_expr_dup(const struct ly_ctx *ctx, const struct lyxp_expr *exp, uint32_t st dup->size = used; /* copy only subexpression */ - LY_CHECK_GOTO(ret = lydict_insert(ctx, expr_start, expr_len, &dup->expr), cleanup); + dup->expr = strndup(expr_start, expr_len); + LY_CHECK_ERR_GOTO(!dup->expr, LOGMEM(ctx); ret = LY_EMEM, cleanup); cleanup: if (ret) { - lyxp_expr_free(ctx, dup); + lyxp_expr_free(dup); } else { *dup_p = dup; } @@ -3622,6 +3626,7 @@ warn_equality_value(const struct lyxp_expr *exp, struct lyxp_set *set, uint32_t struct lyd_value storage; LY_ERR rc; struct ly_err_item *err = NULL; + struct lyplg_type *type_plg; if ((scnode = warn_get_scnode_in_ctx(set)) && (scnode->nodetype & (LYS_LEAF | LYS_LEAFLIST)) && ((exp->tokens[val_exp] == LYXP_TOKEN_LITERAL) || (exp->tokens[val_exp] == LYXP_TOKEN_NUMBER))) { @@ -3646,7 +3651,8 @@ warn_equality_value(const struct lyxp_expr *exp, struct lyxp_set *set, uint32_t type = ((struct lysc_node_leaf *)scnode)->type; if (type->basetype != LY_TYPE_IDENT) { - rc = type->plugin->store(set->ctx, type, value, strlen(value), 0, set->format, set->prefix_data, + type_plg = LYSC_GET_TYPE_PLG(type->plugin_ref); + rc = type_plg->store(set->ctx, type, value, strlen(value), 0, set->format, set->prefix_data, LYD_HINT_DATA, scnode, &storage, NULL, &err); if (rc == LY_EINCOMPLETE) { rc = LY_SUCCESS; @@ -3663,7 +3669,7 @@ warn_equality_value(const struct lyxp_expr *exp, struct lyxp_set *set, uint32_t (exp->tok_pos[last_equal_exp] - exp->tok_pos[equal_exp]) + exp->tok_len[last_equal_exp], set->cur_scnode); } else { - type->plugin->free(set->ctx, &storage); + type_plg->free(set->ctx, &storage); } } free(value); @@ -4976,18 +4982,11 @@ xpath_re_match(struct lyxp_set **args, uint32_t UNUSED(arg_count), struct lyxp_s if (set->cur_node) { LOG_LOCSET(NULL, set->cur_node); } - rc = lys_compile_type_pattern_check(set->ctx, args[1]->val.str, &(*pattern)->code); - if (set->cur_node) { - LOG_LOCBACK(0, 1); - } - if (rc != LY_SUCCESS) { - free(*pattern); - LY_ARRAY_FREE(patterns); - return rc; - } - rc = lyplg_type_validate_patterns(patterns, args[0]->val.str, strlen(args[0]->val.str), &err); - pcre2_code_free((*pattern)->code); + /* validate the pattern */ + (*pattern)->expr = args[1]->val.str; + rc = lyplg_type_validate_patterns(set->ctx, patterns, args[0]->val.str, strlen(args[0]->val.str), &err); + free(*pattern); LY_ARRAY_FREE(patterns); if (rc && (rc != LY_EVALID)) { @@ -5595,7 +5594,7 @@ static LY_ERR xpath_pi_node(struct lyxp_set *set, enum lyxp_axis axis, uint32_t options) { if (options & LYXP_SCNODE_ALL) { - return moveto_scnode(set, NULL, NULL, axis, options); + return moveto_scnode(set, NULL, NULL, 0, axis, options); } if (set->type != LYXP_SET_NODE_SET) { @@ -5604,7 +5603,7 @@ xpath_pi_node(struct lyxp_set *set, enum lyxp_axis axis, uint32_t options) } /* just like moving to a node with no restrictions */ - return moveto_node(set, NULL, NULL, axis, options); + return moveto_node(set, NULL, NULL, 0, axis, options); } /** @@ -5759,7 +5758,8 @@ moveto_root(struct lyxp_set *set, uint32_t options) * @param[in] node Node to check. * @param[in] node_type Node type of @p node. * @param[in] set Set to read general context from. - * @param[in] node_name Node name in the dictionary to move to, NULL for any node. + * @param[in] node_name Node name to move to, NULL for any node. + * @param[in] node_name_len Length of @p node_name. * @param[in] moveto_mod Expected module of the node, NULL for no prefix. * @param[in] options XPath options. * @return LY_ERR (LY_ENOT if node does not match, LY_EINCOMPLETE on unresolved when, @@ -5767,7 +5767,7 @@ moveto_root(struct lyxp_set *set, uint32_t options) */ static LY_ERR moveto_node_check(const struct lyd_node *node, enum lyxp_node_type node_type, const struct lyxp_set *set, - const char *node_name, const struct lys_module *moveto_mod, uint32_t options) + const char *node_name, uint32_t node_name_len, const struct lys_module *moveto_mod, uint32_t options) { const struct lysc_node *schema; @@ -5808,12 +5808,8 @@ moveto_node_check(const struct lyd_node *node, enum lyxp_node_type node_type, co } /* name check */ - if (node_name) { - if ((set->ctx == LYD_CTX(node)) && (schema->name != node_name)) { - return LY_ENOT; - } else if ((set->ctx != LYD_CTX(node)) && strcmp(schema->name, node_name)) { - return LY_ENOT; - } + if (node_name && ly_strncmp(schema->name, node_name, node_name_len)) { + return LY_ENOT; } /* when check, accept the context node because it should only be the path ".", we have checked the when is valid before */ @@ -6114,14 +6110,15 @@ moveto_axis_node_next(const struct lyd_node **iter, enum lyxp_node_type *iter_ty * * @param[in,out] set Set to use. * @param[in] moveto_mod Matching node module, NULL for no prefix. - * @param[in] ncname Matching node name in the dictionary, NULL for any. + * @param[in] ncname Matching node name, NULL for any. + * @param[in] ncname_len Length of @p ncname. * @param[in] axis Axis to search on. * @param[in] options XPath options. * @return LY_ERR (LY_EINCOMPLETE on unresolved when) */ static LY_ERR -moveto_node(struct lyxp_set *set, const struct lys_module *moveto_mod, const char *ncname, enum lyxp_axis axis, - uint32_t options) +moveto_node(struct lyxp_set *set, const struct lys_module *moveto_mod, const char *ncname, + uint32_t ncname_len, enum lyxp_axis axis, uint32_t options) { LY_ERR r, rc = LY_SUCCESS; const struct lyd_node *iter; @@ -6146,7 +6143,7 @@ moveto_node(struct lyxp_set *set, const struct lys_module *moveto_mod, const cha iter = NULL; iter_type = 0; while (!moveto_axis_node_next(&iter, &iter_type, set->val.nodes[i].node, set->val.nodes[i].type, axis, set)) { - r = moveto_node_check(iter, iter_type, set, ncname, moveto_mod, options); + r = moveto_node_check(iter, iter_type, set, ncname, ncname_len, moveto_mod, options); if (r == LY_EINCOMPLETE) { rc = r; goto cleanup; @@ -6250,7 +6247,7 @@ moveto_node_hash_child(struct lyxp_set *set, const struct lysc_node *scnode, con if (scnode->nodetype == LYS_LIST) { LY_CHECK_GOTO(ret = lyd_create_list(scnode, predicates, NULL, 1, &inst), cleanup); } else if (scnode->nodetype == LYS_LEAFLIST) { - LY_CHECK_GOTO(ret = lyd_create_term2(scnode, &predicates[0].value, &inst), cleanup); + LY_CHECK_GOTO(ret = lyd_create_term_canon(scnode, predicates[0].value, &inst), cleanup); } for (i = 0; i < set->used; ++i) { @@ -6308,13 +6305,14 @@ moveto_node_hash_child(struct lyxp_set *set, const struct lysc_node *scnode, con * @param[in] node Schema node to check. * @param[in] ctx_scnode Context node. * @param[in] set Set to read general context from. - * @param[in] node_name Node name in the dictionary to move to, NULL for any nodes. + * @param[in] node_name Node name to move to, NULL for any nodes. + * @param[in] node_name_len Length of @p node_name. * @param[in] moveto_mod Expected module of the node, NULL for no prefix. * @return LY_ERR (LY_ENOT if node does not match, LY_EINVAL if neither node nor any children match) */ static LY_ERR moveto_scnode_check(const struct lysc_node *node, const struct lysc_node *ctx_scnode, const struct lyxp_set *set, - const char *node_name, const struct lys_module *moveto_mod) + const char *node_name, uint32_t node_name_len, const struct lys_module *moveto_mod) { if (!moveto_mod && node_name) { switch (set->format) { @@ -6360,7 +6358,7 @@ moveto_scnode_check(const struct lysc_node *node, const struct lysc_node *ctx_sc } /* name check */ - if (node_name && (node->name != node_name)) { + if (node_name && ly_strncmp(node->name, node_name, node_name_len)) { return LY_ENOT; } @@ -6752,14 +6750,15 @@ moveto_axis_scnode_next(const struct lysc_node **iter, enum lyxp_node_type *iter * * @param[in,out] set Set to use. * @param[in] moveto_mod Matching node module, NULL for no prefix. - * @param[in] ncname Matching node name in the dictionary, NULL for any. + * @param[in] ncname Matching node name, NULL for any. + * @param[in] ncname_len Length of @p ncname. * @param[in] axis Axis to search on. * @param[in] options XPath options. * @return LY_ERR */ static LY_ERR -moveto_scnode(struct lyxp_set *set, const struct lys_module *moveto_mod, const char *ncname, enum lyxp_axis axis, - uint32_t options) +moveto_scnode(struct lyxp_set *set, const struct lys_module *moveto_mod, const char *ncname, + uint32_t ncname_len, enum lyxp_axis axis, uint32_t options) { ly_bool temp_ctx = 0; uint32_t getnext_opts, orig_used, i, mod_idx, idx; @@ -6797,7 +6796,7 @@ moveto_scnode(struct lyxp_set *set, const struct lys_module *moveto_mod, const c iter_type = 0; while (!moveto_axis_scnode_next(&iter, &iter_type, &mod, &mod_idx, set->val.scnodes[i].scnode, set->val.scnodes[i].type, axis, set, getnext_opts)) { - if (moveto_scnode_check(iter, NULL, set, ncname, moveto_mod)) { + if (moveto_scnode_check(iter, NULL, set, ncname, ncname_len, moveto_mod)) { continue; } @@ -6814,7 +6813,7 @@ moveto_scnode(struct lyxp_set *set, const struct lys_module *moveto_mod, const c /* only consider extension nodes after no local ones were found */ if ((orig_used == set->used) && moveto_mod && ncname && ((axis == LYXP_AXIS_DESCENDANT) || (axis == LYXP_AXIS_CHILD)) && (set->val.scnodes[i].type == LYXP_NODE_ELEM) && !ly_nested_ext_schema(NULL, set->val.scnodes[i].scnode, - moveto_mod->name, strlen(moveto_mod->name), LY_VALUE_JSON, NULL, ncname, strlen(ncname), &iter, NULL)) { + moveto_mod->name, strlen(moveto_mod->name), LY_VALUE_JSON, NULL, ncname, ncname_len, &iter, NULL)) { /* there is a matching node from an extension, use it */ LY_CHECK_RET(lyxp_set_scnode_insert_node(set, iter, LYXP_NODE_ELEM, axis, &idx)); if ((idx < orig_used) && (idx > i)) { @@ -6842,12 +6841,14 @@ moveto_scnode(struct lyxp_set *set, const struct lys_module *moveto_mod, const c * * @param[in] set Set to use. * @param[in] moveto_mod Matching node module, NULL for no prefix. - * @param[in] ncname Matching node name in the dictionary, NULL for any. + * @param[in] ncname Matching node name, NULL for any. + * @param[in] ncname_len Length of @p ncname. * @param[in] options XPath options. * @return LY_ERR (LY_EINCOMPLETE on unresolved when) */ static LY_ERR -moveto_node_alldesc_child(struct lyxp_set *set, const struct lys_module *moveto_mod, const char *ncname, uint32_t options) +moveto_node_alldesc_child(struct lyxp_set *set, const struct lys_module *moveto_mod, + const char *ncname, uint32_t ncname_len, uint32_t options) { uint32_t i; const struct lyd_node *next, *elem, *start; @@ -6874,7 +6875,7 @@ moveto_node_alldesc_child(struct lyxp_set *set, const struct lys_module *moveto_ /* TREE DFS */ start = set->val.nodes[i].node; for (elem = next = start; elem; elem = next) { - rc = moveto_node_check(elem, LYXP_NODE_ELEM, set, ncname, moveto_mod, options); + rc = moveto_node_check(elem, LYXP_NODE_ELEM, set, ncname, ncname_len, moveto_mod, options); if (!rc) { /* add matching node into result set */ set_insert_node(&ret_set, elem, 0, LYXP_NODE_ELEM, ret_set.used); @@ -6932,13 +6933,14 @@ moveto_node_alldesc_child(struct lyxp_set *set, const struct lys_module *moveto_ * @param[in] start Start node whose subtree to add. * @param[in] start_idx Index of @p start in @p set. * @param[in] moveto_mod Matching node module, NULL for no prefix. - * @param[in] ncname Matching node name in the dictionary, NULL for any. + * @param[in] ncname Matching node name, NULL for any. + * @param[in] ncname Length of @p ncname. * @param[in] options XPath options. * @return LY_ERR value. */ static LY_ERR moveto_scnode_dfs(struct lyxp_set *set, const struct lysc_node *start, uint32_t start_idx, - const struct lys_module *moveto_mod, const char *ncname, uint32_t options) + const struct lys_module *moveto_mod, const char *ncname, uint32_t ncname_len, uint32_t options) { const struct lysc_node *next, *elem; uint32_t idx; @@ -6951,7 +6953,7 @@ moveto_scnode_dfs(struct lyxp_set *set, const struct lysc_node *start, uint32_t goto next_iter; } - rc = moveto_scnode_check(elem, start, set, ncname, moveto_mod); + rc = moveto_scnode_check(elem, start, set, ncname, ncname_len, moveto_mod); if (!rc) { if (lyxp_set_scnode_contains(set, elem, LYXP_NODE_ELEM, start_idx, &idx)) { set->val.scnodes[idx].in_ctx = LYXP_SET_SCNODE_ATOM_CTX; @@ -7005,12 +7007,14 @@ moveto_scnode_dfs(struct lyxp_set *set, const struct lysc_node *start, uint32_t * * @param[in] set Set to use. * @param[in] moveto_mod Matching node module, NULL for no prefix. - * @param[in] ncname Matching node name in the dictionary, NULL for any. + * @param[in] ncname Matching node name, NULL for any. + * @param[in] ncname_len Length of @p ncname. * @param[in] options XPath options. * @return LY_ERR value. */ static LY_ERR -moveto_scnode_alldesc_child(struct lyxp_set *set, const struct lys_module *moveto_mod, const char *ncname, uint32_t options) +moveto_scnode_alldesc_child(struct lyxp_set *set, const struct lys_module *moveto_mod, + const char *ncname, uint32_t ncname_len, uint32_t options) { uint32_t i, orig_used, mod_idx; const struct lys_module *mod; @@ -7050,13 +7054,13 @@ moveto_scnode_alldesc_child(struct lyxp_set *set, const struct lys_module *movet root = NULL; /* no getnext opts needed */ while ((root = lys_getnext(root, NULL, mod->compiled, 0))) { - LY_CHECK_RET(moveto_scnode_dfs(set, root, i, moveto_mod, ncname, options)); + LY_CHECK_RET(moveto_scnode_dfs(set, root, i, moveto_mod, ncname, ncname_len, options)); } } } else if (set->val.scnodes[i].type == LYXP_NODE_ELEM) { /* add all the descendants recursively */ - LY_CHECK_RET(moveto_scnode_dfs(set, set->val.scnodes[i].scnode, i, moveto_mod, ncname, options)); + LY_CHECK_RET(moveto_scnode_dfs(set, set->val.scnodes[i].scnode, i, moveto_mod, ncname, ncname_len, options)); } } @@ -7069,12 +7073,13 @@ moveto_scnode_alldesc_child(struct lyxp_set *set, const struct lys_module *movet * * @param[in,out] set Set to use. * @param[in] mod Matching metadata module, NULL for any. - * @param[in] ncname Matching metadata name in the dictionary, NULL for any. + * @param[in] ncname Matching metadata name, NULL for any. + * @param[in] ncname_len Length of @p ncname. * @param[in] options XPath options. * @return LY_ERR */ static LY_ERR -moveto_attr(struct lyxp_set *set, const struct lys_module *mod, const char *ncname, uint32_t options) +moveto_attr(struct lyxp_set *set, const struct lys_module *mod, const char *ncname, uint32_t ncname_len, uint32_t options) { struct lyd_meta *sub; @@ -7100,7 +7105,7 @@ moveto_attr(struct lyxp_set *set, const struct lys_module *mod, const char *ncna continue; } - if (!ncname || (sub->name == ncname)) { + if (!ncname || !ly_strncmp(sub->name, ncname, ncname_len)) { /* match */ if (!replaced) { set->val.meta[i].meta = sub; @@ -7176,12 +7181,14 @@ moveto_union(struct lyxp_set *set1, struct lyxp_set *set2) * * @param[in,out] set Set to use. * @param[in] mod Matching metadata module, NULL for any. - * @param[in] ncname Matching metadata name in the dictionary, NULL for any. + * @param[in] ncname Matching metadata name, NULL for any. + * @param[in] ncname_len Length of @p ncname. * @param[in] options XPath options. * @return LY_ERR (LY_EINCOMPLETE on unresolved when) */ static int -moveto_attr_alldesc(struct lyxp_set *set, const struct lys_module *mod, const char *ncname, uint32_t options) +moveto_attr_alldesc(struct lyxp_set *set, const struct lys_module *mod, const char *ncname, + uint32_t ncname_len, uint32_t options) { struct lyd_meta *sub; struct lyxp_set *set_all_desc = NULL; @@ -7201,7 +7208,7 @@ moveto_attr_alldesc(struct lyxp_set *set, const struct lys_module *mod, const ch /* copy the context */ set_all_desc = set_copy(set); /* get all descendant nodes (the original context nodes are removed) */ - rc = moveto_node_alldesc_child(set_all_desc, NULL, NULL, options); + rc = moveto_node_alldesc_child(set_all_desc, NULL, NULL, 0, options); if (rc != LY_SUCCESS) { lyxp_set_free(set_all_desc); return rc; @@ -7226,7 +7233,7 @@ moveto_attr_alldesc(struct lyxp_set *set, const struct lys_module *mod, const ch continue; } - if (!ncname || (sub->name == ncname)) { + if (!ncname || !ly_strncmp(sub->name, ncname, ncname_len)) { /* match */ if (!replaced) { set->val.meta[i].meta = sub; @@ -7808,7 +7815,7 @@ eval_name_test_try_compile_predicate_append(const struct lyxp_expr *exp, uint32_ *pred_len += sprintf(*pred + *pred_len, "[%s=%c%s%c]", pred_node->name, quot, set2.val.str, quot); cleanup: - lyxp_expr_free(set->ctx, val_exp); + lyxp_expr_free(val_exp); lyxp_set_free_content(&set2); return rc; } @@ -7974,7 +7981,7 @@ eval_name_test_try_compile_predicates(const struct lyxp_expr *exp, uint32_t *tok cleanup: ly_temp_log_options(prev_lo); - lyxp_expr_free(set->ctx, exp2); + lyxp_expr_free(exp2); free(pred); return rc; } @@ -8143,7 +8150,7 @@ eval_name_test_with_predicate(const struct lyxp_expr *exp, uint32_t *tok_idx, en struct lyxp_set *set, uint32_t options) { LY_ERR rc = LY_SUCCESS, r; - const char *ncname, *ncname_dict = NULL; + const char *ncname = NULL; uint32_t i, ncname_len; const struct lys_module *moveto_mod = NULL, *moveto_m; const struct lysc_node *scnode = NULL; @@ -8203,22 +8210,22 @@ eval_name_test_with_predicate(const struct lyxp_expr *exp, uint32_t *tok_idx, en } } - if (!scnode) { - /* we are not able to match based on a schema node and not all the modules match ("*"), - * use dictionary for efficient comparison */ - LY_CHECK_GOTO(rc = lydict_insert(set->ctx, ncname, ncname_len, &ncname_dict), cleanup); +moveto: + if (scnode || (ncname && (ncname[0] == '*') && (ncname_len == 1))) { + /* match based on scnode, not based on ncname */ + ncname = NULL; + ncname_len = 0; } -moveto: /* move to the attribute(s), data node(s), or schema node(s) */ if (axis == LYXP_AXIS_ATTRIBUTE) { if (!(options & LYXP_SKIP_EXPR) && (options & LYXP_SCNODE_ALL)) { set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_NODE); } else { if (all_desc) { - rc = moveto_attr_alldesc(set, moveto_mod, ncname_dict, options); + rc = moveto_attr_alldesc(set, moveto_mod, ncname, ncname_len, options); } else { - rc = moveto_attr(set, moveto_mod, ncname_dict, options); + rc = moveto_attr(set, moveto_mod, ncname, ncname_len, options); } LY_CHECK_GOTO(rc, cleanup); } @@ -8243,14 +8250,14 @@ eval_name_test_with_predicate(const struct lyxp_expr *exp, uint32_t *tok_idx, en if (all_desc && (axis == LYXP_AXIS_CHILD)) { /* efficient evaluation that does not add all the descendants into the set */ - rc = moveto_scnode_alldesc_child(set, moveto_mod, ncname_dict, options); + rc = moveto_scnode_alldesc_child(set, moveto_mod, ncname, ncname_len, options); } else { if (all_desc) { /* "//" == "/descendant-or-self::node()/" */ rc = xpath_pi_node(set, LYXP_AXIS_DESCENDANT_OR_SELF, options); LY_CHECK_GOTO(rc, cleanup); } - rc = moveto_scnode(set, moveto_mod, ncname_dict, axis, options); + rc = moveto_scnode(set, moveto_mod, ncname, ncname_len, axis, options); } LY_CHECK_GOTO(rc, cleanup); @@ -8281,7 +8288,7 @@ eval_name_test_with_predicate(const struct lyxp_expr *exp, uint32_t *tok_idx, en } else { if (all_desc && (axis == LYXP_AXIS_CHILD)) { /* efficient evaluation */ - rc = moveto_node_alldesc_child(set, moveto_mod, ncname_dict, options); + rc = moveto_node_alldesc_child(set, moveto_mod, ncname, ncname_len, options); } else if (scnode && (axis == LYXP_AXIS_CHILD)) { /* we can find the child nodes using hashes */ rc = moveto_node_hash_child(set, scnode, predicates, options); @@ -8291,7 +8298,7 @@ eval_name_test_with_predicate(const struct lyxp_expr *exp, uint32_t *tok_idx, en rc = xpath_pi_node(set, LYXP_AXIS_DESCENDANT_OR_SELF, options); LY_CHECK_GOTO(rc, cleanup); } - rc = moveto_node(set, moveto_mod, ncname_dict, axis, options); + rc = moveto_node(set, moveto_mod, ncname, ncname_len, axis, options); } LY_CHECK_GOTO(rc, cleanup); } @@ -8313,7 +8320,6 @@ eval_name_test_with_predicate(const struct lyxp_expr *exp, uint32_t *tok_idx, en /* restore options */ options &= ~LYXP_SKIP_EXPR; } - lydict_remove(set->ctx, ncname_dict); if (predicates) { ly_path_predicates_free(scnode->module->ctx, predicates); } @@ -8902,7 +8908,7 @@ eval_variable_reference(const struct lyxp_expr *exp, uint32_t *tok_idx, struct l LY_CHECK_GOTO(ret, cleanup); cleanup: - lyxp_expr_free(set->ctx, tokens); + lyxp_expr_free(tokens); return ret; } diff --git a/src/xpath.h b/src/xpath.h index e5c30086d..7a2a029ec 100644 --- a/src/xpath.h +++ b/src/xpath.h @@ -186,7 +186,7 @@ struct lyxp_expr { uint32_t used; /**< Used array items. */ uint32_t size; /**< Allocated array items. */ - const char *expr; /**< The original XPath expression. */ + char *expr; /**< The original XPath expression. */ }; /* @@ -530,9 +530,8 @@ LY_ERR lyxp_vars_find(const struct ly_ctx *ctx, const struct lyxp_var *vars, con /** * @brief Frees a parsed XPath expression. @p expr should not be used afterwards. * - * @param[in] ctx libyang context of the expression. * @param[in] expr Expression to free. */ -void lyxp_expr_free(const struct ly_ctx *ctx, struct lyxp_expr *expr); +void lyxp_expr_free(struct lyxp_expr *expr); #endif /* LY_XPATH_H */ diff --git a/tests/utests/basic/test_context.c b/tests/utests/basic/test_context.c index 116b2ce36..d4f68d133 100644 --- a/tests/utests/basic/test_context.c +++ b/tests/utests/basic/test_context.c @@ -198,81 +198,81 @@ test_options(void **state) /* unset */ /* LY_CTX_ALL_IMPLEMENTED */ - assert_int_not_equal(0, UTEST_LYCTX->flags & LY_CTX_ALL_IMPLEMENTED); + assert_int_not_equal(0, UTEST_LYCTX->opts & LY_CTX_ALL_IMPLEMENTED); assert_int_equal(LY_SUCCESS, ly_ctx_unset_options(UTEST_LYCTX, LY_CTX_ALL_IMPLEMENTED)); - assert_int_equal(0, UTEST_LYCTX->flags & LY_CTX_ALL_IMPLEMENTED); + assert_int_equal(0, UTEST_LYCTX->opts & LY_CTX_ALL_IMPLEMENTED); /* LY_CTX_REF_IMPLEMENTED */ - assert_int_not_equal(0, UTEST_LYCTX->flags & LY_CTX_REF_IMPLEMENTED); + assert_int_not_equal(0, UTEST_LYCTX->opts & LY_CTX_REF_IMPLEMENTED); assert_int_equal(LY_SUCCESS, ly_ctx_unset_options(UTEST_LYCTX, LY_CTX_REF_IMPLEMENTED)); - assert_int_equal(0, UTEST_LYCTX->flags & LY_CTX_REF_IMPLEMENTED); + assert_int_equal(0, UTEST_LYCTX->opts & LY_CTX_REF_IMPLEMENTED); /* LY_CTX_DISABLE_SEARCHDIRS */ - assert_int_not_equal(0, UTEST_LYCTX->flags & LY_CTX_DISABLE_SEARCHDIRS); + assert_int_not_equal(0, UTEST_LYCTX->opts & LY_CTX_DISABLE_SEARCHDIRS); assert_int_equal(LY_SUCCESS, ly_ctx_unset_options(UTEST_LYCTX, LY_CTX_DISABLE_SEARCHDIRS)); - assert_int_equal(0, UTEST_LYCTX->flags & LY_CTX_DISABLE_SEARCHDIRS); + assert_int_equal(0, UTEST_LYCTX->opts & LY_CTX_DISABLE_SEARCHDIRS); /* LY_CTX_DISABLE_SEARCHDIR_CWD */ - assert_int_not_equal(0, UTEST_LYCTX->flags & LY_CTX_DISABLE_SEARCHDIR_CWD); + assert_int_not_equal(0, UTEST_LYCTX->opts & LY_CTX_DISABLE_SEARCHDIR_CWD); assert_int_equal(LY_SUCCESS, ly_ctx_unset_options(UTEST_LYCTX, LY_CTX_DISABLE_SEARCHDIR_CWD)); - assert_int_equal(0, UTEST_LYCTX->flags & LY_CTX_DISABLE_SEARCHDIR_CWD); + assert_int_equal(0, UTEST_LYCTX->opts & LY_CTX_DISABLE_SEARCHDIR_CWD); /* LY_CTX_PREFER_SEARCHDIRS */ - assert_int_not_equal(0, UTEST_LYCTX->flags & LY_CTX_PREFER_SEARCHDIRS); + assert_int_not_equal(0, UTEST_LYCTX->opts & LY_CTX_PREFER_SEARCHDIRS); assert_int_equal(LY_SUCCESS, ly_ctx_unset_options(UTEST_LYCTX, LY_CTX_PREFER_SEARCHDIRS)); - assert_int_equal(0, UTEST_LYCTX->flags & LY_CTX_PREFER_SEARCHDIRS); + assert_int_equal(0, UTEST_LYCTX->opts & LY_CTX_PREFER_SEARCHDIRS); /* LY_CTX_LEAFREF_EXTENDED */ - assert_int_not_equal(0, UTEST_LYCTX->flags & LY_CTX_LEAFREF_EXTENDED); + assert_int_not_equal(0, UTEST_LYCTX->opts & LY_CTX_LEAFREF_EXTENDED); assert_int_equal(LY_SUCCESS, ly_ctx_unset_options(UTEST_LYCTX, LY_CTX_LEAFREF_EXTENDED)); - assert_int_equal(0, UTEST_LYCTX->flags & LY_CTX_LEAFREF_EXTENDED); + assert_int_equal(0, UTEST_LYCTX->opts & LY_CTX_LEAFREF_EXTENDED); /* LY_CTX_LEAFREF_LINKING */ - assert_int_not_equal(0, UTEST_LYCTX->flags & LY_CTX_LEAFREF_LINKING); + assert_int_not_equal(0, UTEST_LYCTX->opts & LY_CTX_LEAFREF_LINKING); assert_int_equal(LY_SUCCESS, ly_ctx_unset_options(UTEST_LYCTX, LY_CTX_LEAFREF_LINKING)); - assert_int_equal(0, UTEST_LYCTX->flags & LY_CTX_LEAFREF_LINKING); + assert_int_equal(0, UTEST_LYCTX->opts & LY_CTX_LEAFREF_LINKING); /* LY_CTX_BUILTIN_PLUGINS_ONLY */ - assert_int_not_equal(0, UTEST_LYCTX->flags & LY_CTX_BUILTIN_PLUGINS_ONLY); + assert_int_not_equal(0, UTEST_LYCTX->opts & LY_CTX_BUILTIN_PLUGINS_ONLY); assert_int_equal(LY_SUCCESS, ly_ctx_unset_options(UTEST_LYCTX, LY_CTX_BUILTIN_PLUGINS_ONLY)); - assert_int_equal(0, UTEST_LYCTX->flags & LY_CTX_BUILTIN_PLUGINS_ONLY); + assert_int_equal(0, UTEST_LYCTX->opts & LY_CTX_BUILTIN_PLUGINS_ONLY); - assert_int_equal(UTEST_LYCTX->flags, ly_ctx_get_options(UTEST_LYCTX)); + assert_int_equal(UTEST_LYCTX->opts, ly_ctx_get_options(UTEST_LYCTX)); /* set back */ /* LY_CTX_ALL_IMPLEMENTED */ assert_int_equal(LY_SUCCESS, ly_ctx_set_options(UTEST_LYCTX, LY_CTX_ALL_IMPLEMENTED)); - assert_int_not_equal(0, UTEST_LYCTX->flags & LY_CTX_ALL_IMPLEMENTED); + assert_int_not_equal(0, UTEST_LYCTX->opts & LY_CTX_ALL_IMPLEMENTED); /* LY_CTX_REF_IMPLEMENTED */ assert_int_equal(LY_SUCCESS, ly_ctx_set_options(UTEST_LYCTX, LY_CTX_REF_IMPLEMENTED)); - assert_int_not_equal(0, UTEST_LYCTX->flags & LY_CTX_REF_IMPLEMENTED); + assert_int_not_equal(0, UTEST_LYCTX->opts & LY_CTX_REF_IMPLEMENTED); /* LY_CTX_DISABLE_SEARCHDIRS */ assert_int_equal(LY_SUCCESS, ly_ctx_set_options(UTEST_LYCTX, LY_CTX_DISABLE_SEARCHDIRS)); - assert_int_not_equal(0, UTEST_LYCTX->flags & LY_CTX_DISABLE_SEARCHDIRS); + assert_int_not_equal(0, UTEST_LYCTX->opts & LY_CTX_DISABLE_SEARCHDIRS); /* LY_CTX_DISABLE_SEARCHDIR_CWD */ assert_int_equal(LY_SUCCESS, ly_ctx_set_options(UTEST_LYCTX, LY_CTX_DISABLE_SEARCHDIR_CWD)); - assert_int_not_equal(0, UTEST_LYCTX->flags & LY_CTX_DISABLE_SEARCHDIR_CWD); + assert_int_not_equal(0, UTEST_LYCTX->opts & LY_CTX_DISABLE_SEARCHDIR_CWD); /* LY_CTX_PREFER_SEARCHDIRS */ assert_int_equal(LY_SUCCESS, ly_ctx_set_options(UTEST_LYCTX, LY_CTX_PREFER_SEARCHDIRS)); - assert_int_not_equal(0, UTEST_LYCTX->flags & LY_CTX_PREFER_SEARCHDIRS); + assert_int_not_equal(0, UTEST_LYCTX->opts & LY_CTX_PREFER_SEARCHDIRS); /* LY_CTX_LEAFREF_EXTENDED */ assert_int_equal(LY_SUCCESS, ly_ctx_set_options(UTEST_LYCTX, LY_CTX_LEAFREF_EXTENDED)); - assert_int_not_equal(0, UTEST_LYCTX->flags & LY_CTX_LEAFREF_EXTENDED); + assert_int_not_equal(0, UTEST_LYCTX->opts & LY_CTX_LEAFREF_EXTENDED); /* LY_CTX_LEAFREF_LINKING */ assert_int_equal(LY_SUCCESS, ly_ctx_set_options(UTEST_LYCTX, LY_CTX_LEAFREF_LINKING)); - assert_int_not_equal(0, UTEST_LYCTX->flags & LY_CTX_LEAFREF_LINKING); + assert_int_not_equal(0, UTEST_LYCTX->opts & LY_CTX_LEAFREF_LINKING); /* LY_CTX_BUILTIN_PLUGINS_ONLY */ assert_int_equal(LY_EINVAL, ly_ctx_set_options(UTEST_LYCTX, LY_CTX_BUILTIN_PLUGINS_ONLY)); CHECK_LOG_CTX("Invalid argument option (LY_CTX_BUILTIN_PLUGINS_ONLY can be set only when creating a new context) (ly_ctx_set_options()).", NULL, 0); - assert_int_equal(UTEST_LYCTX->flags, ly_ctx_get_options(UTEST_LYCTX)); + assert_int_equal(UTEST_LYCTX->opts, ly_ctx_get_options(UTEST_LYCTX)); } static LY_ERR @@ -1004,20 +1004,17 @@ test_set_priv_parsed(void **state) assert_non_null(ly_ctx_load_module(UTEST_LYCTX, "ietf-restconf", "2017-01-26", NULL)); UTEST_ADD_MODULE(schema_a, LYS_IN_YANG, feats, NULL); - print_message("[ ] create context\n"); mod = ly_ctx_get_module(UTEST_LYCTX, "a", NULL); iter = check; assert_int_equal(LY_SUCCESS, lysc_module_dfs_full(mod, check_node_priv_parsed_is_set, &iter)); check_ext_instance_priv_parsed_is_set(mod->compiled->exts); - print_message("[ ] unset option\n"); assert_int_equal(LY_SUCCESS, ly_ctx_unset_options(UTEST_LYCTX, LY_CTX_SET_PRIV_PARSED)); mod = ly_ctx_get_module(UTEST_LYCTX, "a", NULL); iter = check; assert_int_equal(LY_SUCCESS, lysc_module_dfs_full(mod, check_node_priv_parsed_not_set, &iter)); check_ext_instance_priv_parsed_not_set(mod->compiled->exts); - print_message("[ ] set option\n"); assert_int_equal(LY_SUCCESS, ly_ctx_set_options(UTEST_LYCTX, LY_CTX_SET_PRIV_PARSED)); mod = ly_ctx_get_module(UTEST_LYCTX, "a", NULL); iter = check; @@ -1106,6 +1103,14 @@ test_explicit_compile(void **state) assert_non_null(mod); } +static void +test_free_parsed(void **state) +{ + ly_ctx_free_parsed(UTEST_LYCTX); + ly_ctx_destroy(UTEST_LYCTX); + UTEST_LYCTX = NULL; +} + int main(void) { @@ -1118,6 +1123,7 @@ main(void) UTEST(test_ylmem), UTEST(test_set_priv_parsed), UTEST(test_explicit_compile), + UTEST(test_free_parsed), }; return cmocka_run_group_tests(tests, NULL, NULL); diff --git a/tests/utests/basic/test_plugins.c b/tests/utests/basic/test_plugins.c index df7523af5..5c724db9c 100644 --- a/tests/utests/basic/test_plugins.c +++ b/tests/utests/basic/test_plugins.c @@ -44,7 +44,7 @@ test_add_simple(void **state) { struct lys_module *mod; struct lysc_node_leaf *leaf; - struct lyplg_ext_record *record_e; + struct lyplg_ext *plugin_e; struct lyplg_type *plugin_t; assert_int_equal(LY_SUCCESS, lyplg_add(TESTS_BIN "/plugins/plugin_simple" LYPLG_SUFFIX)); @@ -54,14 +54,14 @@ test_add_simple(void **state) leaf = (struct lysc_node_leaf *)mod->compiled->data; assert_int_equal(LYS_LEAF, leaf->nodetype); - assert_non_null(plugin_t = lyplg_type_plugin_find(NULL, "libyang-plugins-simple", NULL, "note")); + assert_non_null(plugin_t = lysc_get_type_plugin(lyplg_type_plugin_find(NULL, "libyang-plugins-simple", NULL, "note"))); assert_string_equal("ly2 simple test v1", plugin_t->id); - assert_ptr_equal(leaf->type->plugin, plugin_t); + assert_ptr_equal(leaf->type->plugin_ref, plugin_t); assert_int_equal(1, LY_ARRAY_COUNT(leaf->exts)); - assert_non_null(record_e = lyplg_ext_record_find(NULL, "libyang-plugins-simple", NULL, "hint")); - assert_string_equal("ly2 simple test v1", record_e->plugin.id); - assert_ptr_equal(leaf->exts[0].def->plugin, &record_e->plugin); + assert_non_null(plugin_e = lysc_get_ext_plugin(lyplg_ext_plugin_find(NULL, "libyang-plugins-simple", NULL, "hint"))); + assert_string_equal("ly2 simple test v1", plugin_e->id); + assert_ptr_equal(leaf->exts[0].def->plugin_ref, plugin_e); /* the second loading of the same plugin - still success */ assert_int_equal(LY_SUCCESS, lyplg_add(TESTS_BIN "/plugins/plugin_simple" LYPLG_SUFFIX)); diff --git a/tests/utests/basic/test_xpath.c b/tests/utests/basic/test_xpath.c index 80ac34a22..f3f8b523e 100644 --- a/tests/utests/basic/test_xpath.c +++ b/tests/utests/basic/test_xpath.c @@ -414,7 +414,8 @@ test_rpc(void **state) struct ly_set *set; assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in)); - assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_XML, LYD_TYPE_REPLY_YANG, &tree, NULL)); + assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_XML, LYD_TYPE_REPLY_YANG, LYD_PARSE_STRICT, + &tree, NULL)); ly_in_free(in, 0); assert_non_null(tree); diff --git a/tests/utests/data/test_lyb.c b/tests/utests/data/test_lyb.c index 26f3e738f..0fc6e4567 100644 --- a/tests/utests/data/test_lyb.c +++ b/tests/utests/data/test_lyb.c @@ -465,14 +465,14 @@ test_opaq(void **state) assert_non_null(ly_ctx_load_module(UTEST_LYCTX, "ietf-netconf", NULL, nc_feats)); ly_in_new_memory(data_xml, &in); - rc = lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_XML, LYD_TYPE_RPC_YANG, &tree_1, NULL); + rc = lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_XML, LYD_TYPE_RPC_YANG, LYD_PARSE_STRICT, &tree_1, NULL); ly_in_free(in, 0); assert_int_equal(rc, LY_SUCCESS); assert_int_equal(lyd_print_mem(&xml_out, tree_1, LYD_LYB, LYD_PRINT_WITHSIBLINGS), 0); ly_in_new_memory(xml_out, &in); - rc = lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_LYB, LYD_TYPE_RPC_YANG, &tree_2, NULL); + rc = lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_LYB, LYD_TYPE_RPC_YANG, LYD_PARSE_STRICT, &tree_2, NULL); ly_in_free(in, 0); assert_int_equal(rc, LY_SUCCESS); diff --git a/tests/utests/data/test_parser_json.c b/tests/utests/data/test_parser_json.c index 1d163d4e3..a3fb746b2 100644 --- a/tests/utests/data/test_parser_json.c +++ b/tests/utests/data/test_parser_json.c @@ -694,7 +694,8 @@ test_rpc(void **state) "\"a:l1\":[{\"@\":{\"ietf-netconf:operation\":\"replace\"},\"a\":\"val_a\",\"b\":\"val_b\",\"c\":\"val_c\"}]}" "}}"; assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in)); - assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_JSON, LYD_TYPE_RPC_YANG, &tree, &op)); + assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_JSON, LYD_TYPE_RPC_YANG, LYD_PARSE_STRICT, + &tree, &op)); ly_in_free(in, 0); assert_non_null(op); @@ -727,7 +728,8 @@ test_rpc(void **state) /* append to parent */ assert_int_equal(LY_SUCCESS, lyd_new_path(NULL, UTEST_LYCTX, "/a:r1", NULL, 0, &op)); assert_int_equal(LY_SUCCESS, ly_in_new_memory("{\"l1\": \"some str\", \"l2\": \"some other str\"}", &in)); - assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, op, in, LYD_JSON, LYD_TYPE_RPC_YANG, &tree, NULL)); + assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, op, in, LYD_JSON, LYD_TYPE_RPC_YANG, LYD_PARSE_STRICT, &tree, + NULL)); ly_in_free(in, 0); assert_int_equal(LY_SUCCESS, lyd_print_mem(&str, op, LYD_JSON, LYD_PRINT_WITHSIBLINGS | LYD_PRINT_SHRINK)); @@ -745,7 +747,8 @@ test_action(void **state) data = "{\"a:c\":{\"act\":{\"al\":\"value\"}}}"; assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in)); - assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_JSON, LYD_TYPE_RPC_YANG, &tree, &op)); + assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_JSON, LYD_TYPE_RPC_YANG, LYD_PARSE_STRICT, + &tree, &op)); ly_in_free(in, 0); assert_non_null(op); @@ -769,7 +772,8 @@ test_notification(void **state) data = "{\"a:c\":{\"n1\":{\"nl\":\"value\"}}}"; assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in)); - assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_JSON, LYD_TYPE_NOTIF_YANG, &tree, &ntf)); + assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_JSON, LYD_TYPE_NOTIF_YANG, LYD_PARSE_STRICT, + &tree, &ntf)); ly_in_free(in, 0); assert_non_null(ntf); @@ -782,7 +786,8 @@ test_notification(void **state) data = "{\"a:n2\":{}}"; assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in)); - assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_JSON, LYD_TYPE_NOTIF_YANG, &tree, &ntf)); + assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_JSON, LYD_TYPE_NOTIF_YANG, LYD_PARSE_STRICT, + &tree, &ntf)); ly_in_free(in, 0); assert_non_null(ntf); @@ -808,7 +813,8 @@ test_reply(void **state) data = "{\"a:c\":{\"act\":{\"al\":25}}}"; assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in)); - assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_JSON, LYD_TYPE_REPLY_YANG, &tree, &op)); + assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_JSON, LYD_TYPE_REPLY_YANG, LYD_PARSE_STRICT, + &tree, &op)); ly_in_free(in, 0); assert_non_null(op); @@ -846,7 +852,8 @@ test_restconf_rpc(void **state) "\"a:l1\":[{\"@\":{\"ietf-netconf:operation\":\"replace\"},\"a\":\"val_a\",\"b\":\"val_b\",\"c\":\"val_c\"}]}" "}}"; assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in)); - assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, tree, in, LYD_JSON, LYD_TYPE_RPC_RESTCONF, &envp, NULL)); + assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, tree, in, LYD_JSON, LYD_TYPE_RPC_RESTCONF, LYD_PARSE_STRICT, + &envp, NULL)); ly_in_free(in, 0); /* the same just connected to the edit-data RPC */ @@ -869,7 +876,8 @@ test_restconf_notification(void **state) data = "{\"ietf-restconf:notification\":{\"eventTime\":\"2013-12-21T00:01:00Z\",\"a:c\":{\"n1\":{\"nl\":\"value\"}}}}"; assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in)); - assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_JSON, LYD_TYPE_NOTIF_RESTCONF, &tree, &ntf)); + assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_JSON, LYD_TYPE_NOTIF_RESTCONF, LYD_PARSE_STRICT, + &tree, &ntf)); ly_in_free(in, 0); /* envelopes separately */ @@ -886,7 +894,8 @@ test_restconf_notification(void **state) /* wrong order */ data = "{\"ietf-restconf:notification\":{\"a:n2\":{},\"eventTime\":\"2013-12-21T00:01:00Z\"}}"; assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in)); - assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_JSON, LYD_TYPE_NOTIF_RESTCONF, &tree, &ntf)); + assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_JSON, LYD_TYPE_NOTIF_RESTCONF, LYD_PARSE_STRICT, + &tree, &ntf)); ly_in_free(in, 0); lyd_free_all(tree); @@ -895,7 +904,8 @@ test_restconf_notification(void **state) /* unknown notification */ data = "{\"ietf-restconf:notification\":{\"eventTime\":\"2013-12-21T00:01:00Z\",\"invalid:n2\":{}}}"; assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in)); - assert_int_equal(LY_EVALID, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_JSON, LYD_TYPE_NOTIF_RESTCONF, &tree, &ntf)); + assert_int_equal(LY_EVALID, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_JSON, LYD_TYPE_NOTIF_RESTCONF, LYD_PARSE_STRICT, + &tree, &ntf)); UTEST_LOG_CTX_CLEAN; ly_in_free(in, 0); lyd_free_all(tree); @@ -912,7 +922,8 @@ test_restconf_reply(void **state) data = "{\"a:output\":{\"al\":25}}"; assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in)); - assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, lyd_child(tree), in, LYD_JSON, LYD_TYPE_REPLY_RESTCONF, &envp, NULL)); + assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, lyd_child(tree), in, LYD_JSON, LYD_TYPE_REPLY_RESTCONF, + LYD_PARSE_STRICT, &envp, NULL)); ly_in_free(in, 0); /* connected to the RPC with the parent */ diff --git a/tests/utests/data/test_parser_xml.c b/tests/utests/data/test_parser_xml.c index 6a0d90eb2..058af7683 100644 --- a/tests/utests/data/test_parser_xml.c +++ b/tests/utests/data/test_parser_xml.c @@ -394,7 +394,8 @@ test_rpc(void **state) " \n" "\n"; assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in)); - assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_XML, LYD_TYPE_RPC_YANG, &tree, &op)); + assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_XML, LYD_TYPE_RPC_YANG, LYD_PARSE_STRICT, + &tree, &op)); ly_in_free(in, 0); assert_non_null(op); @@ -460,7 +461,8 @@ test_action(void **state) " \n" "\n"; assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in)); - assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_XML, LYD_TYPE_RPC_YANG, &tree, &op)); + assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_XML, LYD_TYPE_RPC_YANG, LYD_PARSE_STRICT, + &tree, &op)); ly_in_free(in, 0); assert_non_null(op); @@ -494,7 +496,8 @@ test_notification(void **state) " \n" "\n"; assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in)); - assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_XML, LYD_TYPE_NOTIF_YANG, &tree, &ntf)); + assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_XML, LYD_TYPE_NOTIF_YANG, LYD_PARSE_STRICT, + &tree, &ntf)); ly_in_free(in, 0); assert_non_null(ntf); @@ -508,7 +511,8 @@ test_notification(void **state) /* top-level notif without envelope */ data = "\n"; assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in)); - assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_XML, LYD_TYPE_NOTIF_YANG, &tree, &ntf)); + assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_XML, LYD_TYPE_NOTIF_YANG, LYD_PARSE_STRICT, + &tree, &ntf)); ly_in_free(in, 0); assert_non_null(ntf); @@ -538,7 +542,8 @@ test_reply(void **state) " \n" "\n"; assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in)); - assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_XML, LYD_TYPE_REPLY_YANG, &tree, &op)); + assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_XML, LYD_TYPE_REPLY_YANG, LYD_PARSE_STRICT, + &tree, &op)); ly_in_free(in, 0); assert_non_null(op); @@ -591,7 +596,8 @@ test_netconf_rpc(void **state) "\n" "\n"; assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in)); - assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_XML, LYD_TYPE_RPC_NETCONF, &tree, &op)); + assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_XML, LYD_TYPE_RPC_NETCONF, LYD_PARSE_STRICT, + &tree, &op)); ly_in_free(in, 0); assert_non_null(op); @@ -663,7 +669,8 @@ test_netconf_rpc(void **state) " \n" "\n"; assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in)); - assert_int_equal(LY_EVALID, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_XML, LYD_TYPE_RPC_NETCONF, &tree, &op)); + assert_int_equal(LY_EVALID, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_XML, LYD_TYPE_RPC_NETCONF, LYD_PARSE_STRICT, + &tree, &op)); ly_in_free(in, 0); CHECK_LOG_CTX("Invalid enumeration value \"merge2\".", "/ietf-netconf:copy-config/source/config/a:l1[a='val_a'][b='val_b'][c='5']/cont/e/@ietf-netconf:operation", 13); @@ -688,7 +695,8 @@ test_netconf_action(void **state) "\n" "\n"; assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in)); - assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_XML, LYD_TYPE_RPC_NETCONF, &tree, &op)); + assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_XML, LYD_TYPE_RPC_NETCONF, LYD_PARSE_STRICT, + &tree, &op)); ly_in_free(in, 0); CHECK_LYD_NODE_OPAQ((struct lyd_node_opaq *)tree, 1, 1, LY_VALUE_XML, "rpc", 0, 0, 0, 0, ""); @@ -731,7 +739,8 @@ test_netconf_reply_or_notification(void **state) " \n" "\n"; assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in)); - assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_XML, LYD_TYPE_RPC_YANG, &action, &op)); + assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_XML, LYD_TYPE_RPC_YANG, LYD_PARSE_STRICT, + &action, &op)); ly_in_free(in, 0); /* parse notification first */ @@ -744,7 +753,8 @@ test_netconf_reply_or_notification(void **state) "\n" "\n"; assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in)); - assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_XML, LYD_TYPE_NOTIF_NETCONF, &tree, &op2)); + assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_XML, LYD_TYPE_NOTIF_NETCONF, LYD_PARSE_STRICT, + &tree, &op2)); ly_in_free(in, 0); CHECK_LYD_NODE_OPAQ((struct lyd_node_opaq *)tree, 0, 1, LY_VALUE_XML, "notification", 0, 0, 0, 0, ""); @@ -776,7 +786,8 @@ test_netconf_reply_or_notification(void **state) "2010-12-06T08:00:01Z\n" "\n"; assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in)); - assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_XML, LYD_TYPE_NOTIF_NETCONF, &tree, &op2)); + assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_XML, LYD_TYPE_NOTIF_NETCONF, LYD_PARSE_STRICT, + &tree, &op2)); ly_in_free(in, 0); lyd_free_all(tree); @@ -787,7 +798,8 @@ test_netconf_reply_or_notification(void **state) " 25\n" "\n"; assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in)); - assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, op, in, LYD_XML, LYD_TYPE_REPLY_NETCONF, &tree, NULL)); + assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, op, in, LYD_XML, LYD_TYPE_REPLY_NETCONF, LYD_PARSE_STRICT, + &tree, NULL)); ly_in_free(in, 0); CHECK_LYD_NODE_OPAQ((struct lyd_node_opaq *)tree, 1, 0, LY_VALUE_XML, "rpc-reply", 0, 0, 0, 0, ""); @@ -803,7 +815,8 @@ test_netconf_reply_or_notification(void **state) " \n" "\n"; assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in)); - assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, op, in, LYD_XML, LYD_TYPE_REPLY_NETCONF, &tree, NULL)); + assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, op, in, LYD_XML, LYD_TYPE_REPLY_NETCONF, LYD_PARSE_STRICT, + &tree, NULL)); ly_in_free(in, 0); CHECK_LYD_NODE_OPAQ((struct lyd_node_opaq *)tree, 1, 1, LY_VALUE_XML, "rpc-reply", 0, 0, 0, 0, ""); @@ -827,7 +840,8 @@ test_netconf_reply_or_notification(void **state) " \n" "\n"; assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in)); - assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, op, in, LYD_XML, LYD_TYPE_REPLY_NETCONF, &tree, NULL)); + assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, op, in, LYD_XML, LYD_TYPE_REPLY_NETCONF, LYD_PARSE_STRICT, + &tree, NULL)); ly_in_free(in, 0); CHECK_LYD_NODE_OPAQ((struct lyd_node_opaq *)tree, 1, 1, LY_VALUE_XML, "rpc-reply", 0, 0, 0, 0, ""); @@ -861,7 +875,8 @@ test_restconf_rpc(void **state) "" ""; assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in)); - assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, tree, in, LYD_XML, LYD_TYPE_RPC_RESTCONF, &envp, NULL)); + assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, tree, in, LYD_XML, LYD_TYPE_RPC_RESTCONF, LYD_PARSE_STRICT, + &envp, NULL)); ly_in_free(in, 0); /* the same just connected to the edit-data RPC */ @@ -889,7 +904,8 @@ test_restconf_reply(void **state) data = "25"; assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in)); - assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, lyd_child(tree), in, LYD_XML, LYD_TYPE_REPLY_RESTCONF, &envp, NULL)); + assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, lyd_child(tree), in, LYD_XML, LYD_TYPE_REPLY_RESTCONF, + LYD_PARSE_STRICT, &envp, NULL)); ly_in_free(in, 0); /* connected to the RPC with the parent */ @@ -917,7 +933,8 @@ test_filter_attributes(void **state) " \n" "\n"; assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in)); - assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_XML, LYD_TYPE_RPC_YANG, &tree, NULL)); + assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_XML, LYD_TYPE_RPC_YANG, LYD_PARSE_STRICT, + &tree, NULL)); ly_in_free(in, 0); assert_non_null(tree); @@ -939,7 +956,8 @@ test_filter_attributes(void **state) " \n" "\n"; assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in)); - assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_XML, LYD_TYPE_RPC_YANG, &tree, NULL)); + assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_XML, LYD_TYPE_RPC_YANG, LYD_PARSE_STRICT, + &tree, NULL)); ly_in_free(in, 0); assert_non_null(tree); diff --git a/tests/utests/data/test_printer_xml.c b/tests/utests/data/test_printer_xml.c index 6213a37da..ec2431d81 100644 --- a/tests/utests/data/test_printer_xml.c +++ b/tests/utests/data/test_printer_xml.c @@ -206,26 +206,29 @@ test_defaults(void **state) CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree); CHECK_LYD_STRING(tree, LYD_PRINT_WD_TRIM | LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data); - data = "/d:baa"; + data = "/d:baa"; CHECK_LYD_STRING(tree, LYD_PRINT_WD_ALL | LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data); data = "/d:b" + " ncwd:default=\"true\">/d:b" "aa"; CHECK_LYD_STRING(tree, LYD_PRINT_WD_ALL_TAG | LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data); data = "/d:b" + " ncwd:default=\"true\">/d:b" "aa"; CHECK_LYD_STRING(tree, LYD_PRINT_WD_IMPL_TAG | LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data); lyd_free_all(tree); - /* string value equal to the default but default is an unresolved instance-identifier, so they are not considered equal */ + /* string value equal to the default, intepreted as a string because instance-identifier target does not exist */ data = "/d:baa"; + data_trim = "aa"; + data_all_tag = "/d:baa"; CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree); - CHECK_LYD_STRING(tree, LYD_PRINT_WD_TRIM | LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data); + CHECK_LYD_STRING(tree, LYD_PRINT_WD_TRIM | LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data_trim); CHECK_LYD_STRING(tree, LYD_PRINT_WD_ALL | LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data); - CHECK_LYD_STRING(tree, LYD_PRINT_WD_ALL_TAG | LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data); + CHECK_LYD_STRING(tree, LYD_PRINT_WD_ALL_TAG | LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data_all_tag); CHECK_LYD_STRING(tree, LYD_PRINT_WD_IMPL_TAG | LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data); lyd_free_all(tree); diff --git a/tests/utests/data/test_tree_data.c b/tests/utests/data/test_tree_data.c index b3dde5a6a..fa06489e9 100644 --- a/tests/utests/data/test_tree_data.c +++ b/tests/utests/data/test_tree_data.c @@ -410,7 +410,7 @@ test_target(void **state) lyd_free_all(tree); ly_path_free(path); - lyxp_expr_free(UTEST_LYCTX, exp); + lyxp_expr_free(exp); } static void diff --git a/tests/utests/data/test_validation.c b/tests/utests/data/test_validation.c index 694501604..2fb5f9d73 100644 --- a/tests/utests/data/test_validation.c +++ b/tests/utests/data/test_validation.c @@ -1335,7 +1335,8 @@ test_action(void **state) " \n" " \n" "\n", &in)); - assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_XML, LYD_TYPE_RPC_YANG, &op_tree, NULL)); + assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_XML, LYD_TYPE_RPC_YANG, LYD_PARSE_STRICT, + &op_tree, NULL)); assert_non_null(op_tree); /* missing leafref */ @@ -1403,7 +1404,8 @@ test_rpc(void **state) " 123\n" ""; assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in)); - assert_int_equal(LY_EVALID, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_XML, LYD_TYPE_RPC_YANG, &tree, NULL)); + assert_int_equal(LY_EVALID, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_XML, LYD_TYPE_RPC_YANG, LYD_PARSE_STRICT, + &tree, NULL)); CHECK_LOG_CTX("Unsatisfied length - string \"123\" length is not allowed.", "/val-str:modify-user-password/new-password", 3); ly_in_free(in, 0); @@ -1427,7 +1429,8 @@ test_reply(void **state) " \n" " \n" "\n", &in)); - assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_XML, LYD_TYPE_REPLY_YANG, &op_tree, NULL)); + assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_XML, LYD_TYPE_REPLY_YANG, LYD_PARSE_STRICT, + &op_tree, NULL)); assert_non_null(op_tree); ly_in_free(in, 0); diff --git a/tests/utests/extensions/test_metadata.c b/tests/utests/extensions/test_metadata.c index fcaa9dac6..c3b58b2b1 100644 --- a/tests/utests/extensions/test_metadata.c +++ b/tests/utests/extensions/test_metadata.c @@ -52,7 +52,7 @@ test_yang(void **state) "import ietf-yang-metadata {prefix md;}" "md:annotation aa;}"; assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, NULL)); - CHECK_LOG_CTX("Ext plugin \"ly2 metadata v1\": Missing mandatory keyword \"type\" as a child of \"md:annotation aa\".", + CHECK_LOG_CTX("Ext plugin \"ly2 metadata\": Missing mandatory keyword \"type\" as a child of \"md:annotation aa\".", "/aa:{extension='md:annotation'}/aa", 0); /* not allowed substatement */ @@ -89,7 +89,7 @@ test_yang(void **state) "import ietf-yang-metadata {prefix md;}" "md:annotation aa {type string;} md:annotation aa {type uint8;}}"; assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, NULL)); - CHECK_LOG_CTX("Ext plugin \"ly2 metadata v1\": Extension md:annotation is instantiated multiple times.", + CHECK_LOG_CTX("Ext plugin \"ly2 metadata\": Extension md:annotation is instantiated multiple times.", "/aa:{extension='md:annotation'}/aa", 0); } @@ -130,7 +130,7 @@ test_yin(void **state) "\n" ""; assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YIN, NULL)); - CHECK_LOG_CTX("Ext plugin \"ly2 metadata v1\": Missing mandatory keyword \"type\" as a child of \"md:annotation aa\".", + CHECK_LOG_CTX("Ext plugin \"ly2 metadata\": Missing mandatory keyword \"type\" as a child of \"md:annotation aa\".", "/aa:{extension='md:annotation'}/aa", 0); /* not allowed substatement */ @@ -189,7 +189,7 @@ test_yin(void **state) " \n" ""; assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YIN, NULL)); - CHECK_LOG_CTX("Ext plugin \"ly2 metadata v1\": Extension md:annotation is instantiated multiple times.", + CHECK_LOG_CTX("Ext plugin \"ly2 metadata\": Extension md:annotation is instantiated multiple times.", "/aa:{extension='md:annotation'}/aa", 0); } diff --git a/tests/utests/extensions/test_nacm.c b/tests/utests/extensions/test_nacm.c index 0b1cb8b12..9cbad1e3f 100644 --- a/tests/utests/extensions/test_nacm.c +++ b/tests/utests/extensions/test_nacm.c @@ -48,7 +48,7 @@ test_deny_all(void **state) assert_int_equal(LY_ARRAY_COUNT(cont->exts), 1); assert_int_equal(LY_ARRAY_COUNT(leaf->exts), 1); /* NACM extensions inherit */ assert_ptr_equal(e->def, leaf->exts[0].def); - assert_int_equal(1, *((uint8_t *)e->compiled)); /* plugin's value for default-deny-all */ + assert_int_equal(1, (uintptr_t)e->compiled); /* plugin's value for default-deny-all */ assert_null(cont->next->exts); /* ignored - valid with warning */ @@ -56,7 +56,7 @@ test_deny_all(void **state) "import ietf-netconf-acm {revision-date 2018-02-14; prefix nacm;}" "nacm:default-deny-all;}"; assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, NULL)); - CHECK_LOG_CTX("Ext plugin \"ly2 NACM v1\": " + CHECK_LOG_CTX("Ext plugin \"ly2 NACM\": " "Extension nacm:default-deny-all is allowed only in a data nodes, but it is placed in \"module\" statement.", "/b:{extension='nacm:default-deny-all'}", 0); @@ -65,7 +65,7 @@ test_deny_all(void **state) "import ietf-netconf-acm {revision-date 2018-02-14; prefix nacm;}" "leaf l { type string; nacm:default-deny-all; nacm:default-deny-write;}}"; assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, NULL)); - CHECK_LOG_CTX("Ext plugin \"ly2 NACM v1\": " + CHECK_LOG_CTX("Ext plugin \"ly2 NACM\": " "Extension nacm:default-deny-write is mixed with nacm:default-deny-all.", "/aa:l/{extension='nacm:default-deny-all'}", 0); } @@ -91,14 +91,14 @@ test_deny_write(void **state) assert_int_equal(LY_ARRAY_COUNT(cont->exts), 1); assert_int_equal(LY_ARRAY_COUNT(leaf->exts), 1); /* NACM extensions inherit */ assert_ptr_equal(e->def, leaf->exts[0].def); - assert_int_equal(2, *((uint8_t *)e->compiled)); /* plugin's value for default-deny-write */ + assert_int_equal(2, (uintptr_t)e->compiled); /* plugin's value for default-deny-write */ /* ignored - valid with warning */ data = "module b {yang-version 1.1; namespace urn:tests:extensions:nacm:b; prefix en;" "import ietf-netconf-acm {revision-date 2018-02-14; prefix nacm;}" "notification notif {nacm:default-deny-write;}}"; assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, NULL)); - CHECK_LOG_CTX("Ext plugin \"ly2 NACM v1\": " + CHECK_LOG_CTX("Ext plugin \"ly2 NACM\": " "Extension nacm:default-deny-write is not allowed in notification statement.", "/b:notif/{extension='nacm:default-deny-write'}", 0); @@ -107,7 +107,7 @@ test_deny_write(void **state) "import ietf-netconf-acm {revision-date 2018-02-14; prefix nacm;}" "leaf l { type string; nacm:default-deny-write; nacm:default-deny-write;}}"; assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, NULL)); - CHECK_LOG_CTX("Ext plugin \"ly2 NACM v1\": " + CHECK_LOG_CTX("Ext plugin \"ly2 NACM\": " "Extension nacm:default-deny-write is instantiated multiple times.", "/aa:l/{extension='nacm:default-deny-write'}", 0); } diff --git a/tests/utests/extensions/test_schema_mount.c b/tests/utests/extensions/test_schema_mount.c index 5b57b5684..f521d1bcf 100644 --- a/tests/utests/extensions/test_schema_mount.c +++ b/tests/utests/extensions/test_schema_mount.c @@ -73,7 +73,7 @@ test_schema(void **state) " }\n" "}\n"; assert_int_equal(LY_EINVAL, lys_parse_mem(UTEST_LYCTX, schema, LYS_IN_YANG, NULL)); - CHECK_LOG_CTX("Ext plugin \"ly2 schema mount v1\": " + CHECK_LOG_CTX("Ext plugin \"ly2 schema mount\": " "Extension \"yangmnt:mount-point\" instance not allowed in YANG version 1 module.", "/sm:root/{extension='yangmnt:mount-point'}/root", 0); @@ -90,7 +90,7 @@ test_schema(void **state) " yangmnt:mount-point \"root\";\n" "}\n"; assert_int_equal(LY_EINVAL, lys_parse_mem(UTEST_LYCTX, schema, LYS_IN_YANG, NULL)); - CHECK_LOG_CTX("Ext plugin \"ly2 schema mount v1\": " + CHECK_LOG_CTX("Ext plugin \"ly2 schema mount\": " "Extension \"yangmnt:mount-point\" instance allowed only in container or list statement.", "/sm:{extension='yangmnt:mount-point'}/root", 0); @@ -112,7 +112,7 @@ test_schema(void **state) " }\n" "}\n"; assert_int_equal(LY_EINVAL, lys_parse_mem(UTEST_LYCTX, schema, LYS_IN_YANG, NULL)); - CHECK_LOG_CTX("Ext plugin \"ly2 schema mount v1\": " + CHECK_LOG_CTX("Ext plugin \"ly2 schema mount\": " "Extension \"yangmnt:mount-point\" instance allowed only in container or list statement.", "/sm:root/l/{extension='yangmnt:mount-point'}/root", 0); @@ -136,7 +136,7 @@ test_schema(void **state) " }\n" "}\n"; assert_int_equal(LY_EINVAL, lys_parse_mem(UTEST_LYCTX, schema, LYS_IN_YANG, NULL)); - CHECK_LOG_CTX("Ext plugin \"ly2 schema mount v1\": " + CHECK_LOG_CTX("Ext plugin \"ly2 schema mount\": " "Multiple extension \"yangmnt:mount-point\" instances.", "/sm:l/{extension='yangmnt:mount-point'}/root", 0); @@ -162,7 +162,8 @@ test_schema(void **state) } static LY_ERR -test_ext_data_clb(const struct lysc_ext_instance *ext, void *user_data, void **ext_data, ly_bool *ext_data_free) +test_ext_data_clb(const struct lysc_ext_instance *ext, const struct lyd_node *UNUSED(parent), void *user_data, + void **ext_data, ly_bool *ext_data_free) { void **state = glob_state; struct lyd_node *data = NULL; @@ -195,7 +196,7 @@ test_parse_invalid(void **state) " " ""; CHECK_PARSE_LYD_PARAM(xml, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EINVAL, data); - CHECK_LOG_CTX("Ext plugin \"ly2 schema mount v1\": Failed to get extension data, no callback set.", + CHECK_LOG_CTX("Ext plugin \"ly2 schema mount\": Failed to get extension data, no callback set.", NULL, 0); json = @@ -212,7 +213,7 @@ test_parse_invalid(void **state) " }" "}"; CHECK_PARSE_LYD_PARAM(json, LYD_JSON, 0, LYD_VALIDATE_PRESENT, LY_EINVAL, data); - CHECK_LOG_CTX("Ext plugin \"ly2 schema mount v1\": Failed to get extension data, no callback set.", + CHECK_LOG_CTX("Ext plugin \"ly2 schema mount\": Failed to get extension data, no callback set.", NULL, 0); /* unknown data */ @@ -400,22 +401,22 @@ test_parse_invalid(void **state) " " ""); CHECK_PARSE_LYD_PARAM(xml, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_EVALID, data); - CHECK_LOG_CTX("Ext plugin \"ly2 schema mount v1\": Mandatory node \"type\" instance does not exist.", + CHECK_LOG_CTX("Ext plugin \"ly2 schema mount\": Mandatory node \"type\" instance does not exist.", "/ietf-interfaces:interfaces/interface[name='bu']", 0); CHECK_PARSE_LYD_PARAM(json, LYD_JSON, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_EVALID, data); - CHECK_LOG_CTX("Ext plugin \"ly2 schema mount v1\": Mandatory node \"type\" instance does not exist.", + CHECK_LOG_CTX("Ext plugin \"ly2 schema mount\": Mandatory node \"type\" instance does not exist.", "/ietf-interfaces:interfaces/interface[name='bu']", 0); /* same validation fail in separate validation */ CHECK_PARSE_LYD_PARAM(xml, LYD_XML, LYD_PARSE_STRICT | LYD_PARSE_ONLY, 0, LY_SUCCESS, data); assert_int_equal(LY_EVALID, lyd_validate_all(&data, NULL, LYD_VALIDATE_PRESENT, NULL)); - CHECK_LOG_CTX("Ext plugin \"ly2 schema mount v1\": Mandatory node \"type\" instance does not exist.", + CHECK_LOG_CTX("Ext plugin \"ly2 schema mount\": Mandatory node \"type\" instance does not exist.", "/ietf-interfaces:interfaces/interface[name='bu']", 0); lyd_free_siblings(data); CHECK_PARSE_LYD_PARAM(json, LYD_JSON, LYD_PARSE_STRICT | LYD_PARSE_ONLY, 0, LY_SUCCESS, data); assert_int_equal(LY_EVALID, lyd_validate_all(&data, NULL, LYD_VALIDATE_PRESENT, NULL)); - CHECK_LOG_CTX("Ext plugin \"ly2 schema mount v1\": Mandatory node \"type\" instance does not exist.", + CHECK_LOG_CTX("Ext plugin \"ly2 schema mount\": Mandatory node \"type\" instance does not exist.", "/ietf-interfaces:interfaces/interface[name='bu']", 0); lyd_free_siblings(data); @@ -864,7 +865,7 @@ test_parse_shared(void **state) " \n" "\n"; CHECK_PARSE_LYD_PARAM(xml, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_EVALID, data); - CHECK_LOG_CTX("Ext plugin \"ly2 schema mount v1\": " + CHECK_LOG_CTX("Ext plugin \"ly2 schema mount\": " "Shared-schema yang-library content-id \"2\" differs from \"1\" used previously.", "/ietf-yang-library:yang-library/content-id", 0); @@ -1120,7 +1121,7 @@ test_parse_shared_parent_ref(void **state) "\n" "wrong-target-value\n"; CHECK_PARSE_LYD_PARAM(xml, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_EVALID, data); - CHECK_LOG_CTX("Ext plugin \"ly2 schema mount v1\": " + CHECK_LOG_CTX("Ext plugin \"ly2 schema mount\": " "Invalid leafref value \"target-value\" - no target instance \"/sm:target\" with the same value.", "/ietf-interfaces:interfaces/interface[name='bu']/sm:sm-name", 0); @@ -1145,7 +1146,7 @@ test_parse_shared_parent_ref(void **state) " \"sm:target\": \"wrong-target-value\"\n" "}\n"; CHECK_PARSE_LYD_PARAM(json, LYD_JSON, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_EVALID, data); - CHECK_LOG_CTX("Ext plugin \"ly2 schema mount v1\": " + CHECK_LOG_CTX("Ext plugin \"ly2 schema mount\": " "Invalid leafref value \"target-value\" - no target instance \"/sm:target\" with the same value.", "/ietf-interfaces:interfaces/interface[name='bu']/sm:sm-name", 0); diff --git a/tests/utests/extensions/test_structure.c b/tests/utests/extensions/test_structure.c index cc8ed7184..026f6e7db 100644 --- a/tests/utests/extensions/test_structure.c +++ b/tests/utests/extensions/test_structure.c @@ -154,7 +154,7 @@ test_schema_invalid(void **state) "import ietf-yang-structure-ext {prefix sx;}" "container b { sx:structure struct { container x { leaf x {type string;}}}}}"; UTEST_INVALID_MODULE(data, LYS_IN_YANG, NULL, LY_EVALID); - CHECK_LOG_CTX("Ext plugin \"ly2 structure v1\": " + CHECK_LOG_CTX("Ext plugin \"ly2 structure\": " "Extension sx:structure must not be used as a non top-level statement in \"container\" statement.", "/a:b/{extension='sx:structure'}/struct", 0); @@ -170,7 +170,7 @@ test_schema_invalid(void **state) "sx:structure struct { container x { leaf x {type string;}}}" "sx:structure struct { container y { leaf y {type string;}}}}"; UTEST_INVALID_MODULE(data, LYS_IN_YANG, NULL, LY_EVALID); - CHECK_LOG_CTX("Ext plugin \"ly2 structure v1\": Extension sx:structure is instantiated multiple times.", + CHECK_LOG_CTX("Ext plugin \"ly2 structure\": Extension sx:structure is instantiated multiple times.", "/a:{extension='sx:structure'}/struct", 0); data = "module a {yang-version 1.1; namespace urn:tests:extensions:structure:a; prefix self;" @@ -178,7 +178,7 @@ test_schema_invalid(void **state) "sx:structure struct { container x { leaf x {type string;}}}" "choice struct { container y { leaf y {type string;}}}}"; UTEST_INVALID_MODULE(data, LYS_IN_YANG, NULL, LY_EVALID); - CHECK_LOG_CTX("Ext plugin \"ly2 structure v1\": Extension sx:structure collides with a choice with the same identifier.", + CHECK_LOG_CTX("Ext plugin \"ly2 structure\": Extension sx:structure collides with a choice with the same identifier.", "/a:{extension='sx:structure'}/struct", 0); /* augment-structure */ diff --git a/tests/utests/extensions/test_yangdata.c b/tests/utests/extensions/test_yangdata.c index 4de89804f..3977992da 100644 --- a/tests/utests/extensions/test_yangdata.c +++ b/tests/utests/extensions/test_yangdata.c @@ -117,7 +117,7 @@ test_schema(void **state) "}\n"; assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, &mod)); assert_null(mod->compiled->exts); - CHECK_LOG_CTX("Ext plugin \"ly2 yang-data v1\": " + CHECK_LOG_CTX("Ext plugin \"ly2 yang-data\": " "Extension rc:yang-data is ignored since it appears as a non top-level statement in \"container\" statement.", "/b:b/{extension='rc:yang-data'}/template", 0); assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YANG_COMPILED, 0)); @@ -174,7 +174,7 @@ test_schema_invalid(void **state) "import ietf-restconf {revision-date 2017-01-26; prefix rc;}" "rc:yang-data template { choice x { leaf x {type string;}}}}"; assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, NULL)); - CHECK_LOG_CTX("Ext plugin \"ly2 yang-data v1\": " + CHECK_LOG_CTX("Ext plugin \"ly2 yang-data\": " "Extension rc:yang-data is instantiated with leaf top level data node (inside a choice), " "but only a single container data node is allowed.", "/a:{extension='rc:yang-data'}/template", 0); @@ -182,7 +182,7 @@ test_schema_invalid(void **state) "import ietf-restconf {revision-date 2017-01-26; prefix rc;}" "rc:yang-data template { choice x { case x { container z {presence ppp;} leaf x {type string;}}}}}"; assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, NULL)); - CHECK_LOG_CTX("Ext plugin \"ly2 yang-data v1\": " + CHECK_LOG_CTX("Ext plugin \"ly2 yang-data\": " "Extension rc:yang-data is instantiated with multiple top level data nodes (inside a single choice's case), " "but only a single container data node is allowed.", "/a:{extension='rc:yang-data'}/template", 0); @@ -190,7 +190,7 @@ test_schema_invalid(void **state) "import ietf-restconf {revision-date 2017-01-26; prefix rc;}" "rc:yang-data template { container x { leaf x {type string;}} container y { leaf y {type string;}}}}"; assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, NULL)); - CHECK_LOG_CTX("Ext plugin \"ly2 yang-data v1\": " + CHECK_LOG_CTX("Ext plugin \"ly2 yang-data\": " "Extension rc:yang-data is instantiated with multiple top level data nodes, " "but only a single container data node is allowed.", "/a:{extension='rc:yang-data'}/template", 0); @@ -198,7 +198,7 @@ test_schema_invalid(void **state) "import ietf-restconf {revision-date 2017-01-26; prefix rc;}" "rc:yang-data template;}"; assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, NULL)); - CHECK_LOG_CTX("Ext plugin \"ly2 yang-data v1\": " + CHECK_LOG_CTX("Ext plugin \"ly2 yang-data\": " "Extension rc:yang-data is instantiated without any top level data node, " "but exactly one container data node is expected.", "/a:{extension='rc:yang-data'}/template", 0); @@ -214,7 +214,7 @@ test_schema_invalid(void **state) "rc:yang-data template { container x { leaf x {type string;}}}" "rc:yang-data template { container y { leaf y {type string;}}}}"; assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, NULL)); - CHECK_LOG_CTX("Ext plugin \"ly2 yang-data v1\": " + CHECK_LOG_CTX("Ext plugin \"ly2 yang-data\": " "Extension rc:yang-data is instantiated multiple times.", "/a:{extension='rc:yang-data'}/template", 0); data = "module a {yang-version 1.1; namespace urn:tests:extensions:yangdata:a; prefix self;" @@ -222,7 +222,7 @@ test_schema_invalid(void **state) "grouping t { leaf-list x {type string;}}" "rc:yang-data template { uses t;}}"; assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, NULL)); - CHECK_LOG_CTX("Ext plugin \"ly2 yang-data v1\": " + CHECK_LOG_CTX("Ext plugin \"ly2 yang-data\": " "Extension rc:yang-data is instantiated with leaf-list top level data node, " "but only a single container data node is allowed.", "/a:{extension='rc:yang-data'}/template", 0); } diff --git a/tests/utests/schema/test_printer_tree.c b/tests/utests/schema/test_printer_tree.c index 5438c6114..591ed2081 100644 --- a/tests/utests/schema/test_printer_tree.c +++ b/tests/utests/schema/test_printer_tree.c @@ -1920,7 +1920,8 @@ yang_data(void **state) } static LY_ERR -getter(const struct lysc_ext_instance *ext, void *user_data, void **ext_data, ly_bool *ext_data_free) +getter(const struct lysc_ext_instance *ext, const struct lyd_node *UNUSED(parent), void *user_data, void **ext_data, + ly_bool *ext_data_free) { struct ly_ctx *ctx; struct lyd_node *data = NULL; diff --git a/tests/utests/schema/test_schema.c b/tests/utests/schema/test_schema.c index 42a051e77..c23d8383c 100644 --- a/tests/utests/schema/test_schema.c +++ b/tests/utests/schema/test_schema.c @@ -15,7 +15,10 @@ #define _UTEST_MAIN_ #include "utests.h" +#include #include +#include +#include #include "compat.h" #include "context.h" @@ -1716,7 +1719,7 @@ test_extension_compile(void **state) cctx.path[0] = '/'; /* parsed ext instance */ - lydict_insert(UTEST_LYCTX, "pref:my-ext", 0, &ext_p.name); + lysdict_insert(UTEST_LYCTX, "pref:my-ext", 0, &ext_p.name); ext_p.format = LY_VALUE_JSON; ext_p.parent_stmt = LY_STMT_MODULE; @@ -1725,7 +1728,7 @@ test_extension_compile(void **state) substmtp->stmt = LY_STMT_ERROR_MESSAGE; substmtp->storage_p = &ext_p.parsed; /* fake parse */ - lydict_insert(UTEST_LYCTX, "my error", 0, (const char **)&ext_p.parsed); + lysdict_insert(UTEST_LYCTX, "my error", 0, (const char **)&ext_p.parsed); /* compiled ext instance */ ext_c.parent_stmt = ext_p.parent_stmt; @@ -1738,8 +1741,8 @@ test_extension_compile(void **state) * error-message */ ext_p.child = &child; - lydict_insert(UTEST_LYCTX, "error-message", 0, &child.stmt); - lydict_insert(UTEST_LYCTX, "my error", 0, &child.arg); + lysdict_insert(UTEST_LYCTX, "error-message", 0, &child.stmt); + lysdict_insert(UTEST_LYCTX, "my error", 0, &child.arg); child.format = LY_VALUE_JSON; child.kw = LY_STMT_ERROR_MESSAGE; @@ -1750,13 +1753,13 @@ test_extension_compile(void **state) assert_string_equal(ext_c.compiled, "my error"); cleanup: - lydict_remove(UTEST_LYCTX, ext_p.name); - lydict_remove(UTEST_LYCTX, child.stmt); - lydict_remove(UTEST_LYCTX, child.arg); + lysdict_remove(UTEST_LYCTX, ext_p.name); + lysdict_remove(UTEST_LYCTX, child.stmt); + lysdict_remove(UTEST_LYCTX, child.arg); LY_ARRAY_FREE(ext_p.substmts); - lydict_remove(UTEST_LYCTX, ext_p.parsed); + lysdict_remove(UTEST_LYCTX, ext_p.parsed); LY_ARRAY_FREE(ext_c.substmts); - lydict_remove(UTEST_LYCTX, ext_c.compiled); + lysdict_remove(UTEST_LYCTX, ext_c.compiled); if (rc) { fail(); } @@ -2117,6 +2120,153 @@ test_lysc_backlinks(void **state) } } +static void +test_compiled_print(void **state) +{ + int size; + void *mem, *mem_end; + struct lyd_node *tree = NULL; + struct ly_ctx *printed_ctx = NULL, *printed_ctx2 = NULL; + struct lys_module *mod = NULL; + const char *yang, *xml; + struct lysc_ext_instance *ext; + const char *features[] = {"feat", NULL}; + + /* recreate the context, using builtin/static plugins only */ + ly_ctx_destroy(UTEST_LYCTX); + assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_BUILTIN_PLUGINS_ONLY | LY_CTX_STATIC_PLUGINS_ONLY, &UTEST_LYCTX)); + + /* load the base module */ + yang = "module m1 {yang-version 1.1; namespace urn:m1;prefix m1;" + "import ietf-yang-metadata {prefix md;}" + "identity baseid;" + "identity id1 {base baseid;}" + "feature feat;" + "container root {" + "leaf a {type instance-identifier;}" + "leaf b {type boolean; must \"/m1:root/a\";}" + "leaf c {type binary; when \"/m1:root/b = 'true'\";}" + "leaf d {type decimal64 {fraction-digits 2;}}" + "leaf-list e {type instance-identifier; default \"/m1:root/m1:a\"; default \"/m1:root/m1:b\"; default \"/m1:root/m1:c\";}" + "anydata f;" + "list g {" + " key a;" + " leaf a {type string;}" + " unique \"b c\";" + " unique \"d e\";" + " leaf b {type string;}" + " leaf c {type uint32;}" + " leaf d {type empty;}" + " leaf e {type int8;}" + "}" + "}" + "rpc h {" + " input {leaf a {type string;}}" + "}" + "md:annotation i {" + " description \"test\";" + " if-feature feat;" + " reference \"test\";" + " status \"current\";" + " type uint8;" + " units meters;" + "}" + "}"; + UTEST_ADD_MODULE(yang, LYS_IN_YANG, features, NULL); + + /* load an augment of the base module */ + yang = "module m2 {namespace urn:m2;prefix m2;" + "import m1 {prefix m1;}" + "identity id2 {base m1:baseid;}" + "grouping leaf_group {leaf a {type identityref {base m1:baseid;}}}" + "augment /m1:root {uses leaf_group;}}"; + assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, yang, LYS_IN_YANG, NULL)); + + /* load a structure extension module */ + yang = "module m3 {yang-version 1.1; namespace urn:m3; prefix m3;" + "import ietf-yang-structure-ext {prefix sx;}" + "sx:structure struct { container a { leaf b { type string;}}}}"; + UTEST_ADD_MODULE(yang, LYS_IN_YANG, NULL, &mod); + + /* load a structure augment extension module */ + yang = "module m4 {yang-version 1.1; namespace urn:m4; prefix m4;" + "import ietf-yang-structure-ext {prefix sx;}" + "import m3 {prefix m3;}" + "sx:augment-structure \"/m3:struct/m3:a\" {" + " leaf c {type uint32;}" + "}}"; + UTEST_ADD_MODULE(yang, LYS_IN_YANG, NULL, NULL); + + /* free parsed modules, not needed in a printed context */ + ly_ctx_free_parsed(UTEST_LYCTX); + + /* get the size of the compiled ctx */ + size = ly_ctx_compiled_size(UTEST_LYCTX); + + /* prepare memory chunk for the printed context */ + mem = malloc(size); + assert_non_null(mem); + + /* print the context into the shared memory */ + assert_int_equal(LY_SUCCESS, ly_ctx_compiled_print(UTEST_LYCTX, mem, &mem_end)); + assert_int_equal((char *)mem_end - (char *)mem, size); + + /* create a new printed ctx from this address */ + assert_int_equal(LY_SUCCESS, ly_ctx_new_printed(mem, &printed_ctx)); + + /* try to create another printed ctx from the same address, it should fail */ + assert_int_equal(LY_EEXIST, ly_ctx_new_printed(mem, &printed_ctx2)); + + /* get the structure extension from the printed context */ + mod = ly_ctx_get_module_implemented(printed_ctx, "m3"); + assert_non_null(ext = &mod->compiled->exts[0]); + + /* try to parse data with the printed ctx */ + xml = "\n" + " /m1:root/m1:b\n" + " true\n" + " Zm9vYmFy\n" + " 123.45\n" + " /m1:root/m1:a\n" + " /m1:root/m1:b\n" + " /m1:root/m1:c\n" + " \n" + " \n" + " abc\n" + " \n" + " \n" + " \n" + " key\n" + " unique\n" + " 123\n" + " \n" + " -10\n" + " \n" + " m1:id1\n" + "\n"; + assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(printed_ctx, xml, + LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, &tree)); + + CHECK_LYD_STRING_PARAM(tree, xml, LYD_XML, 0); + lyd_free_all(tree); + + /* parse structure extension data with the printed ctx */ + xml = "\n" + " abc\n" + " 24\n" + "\n"; + assert_int_equal(LY_SUCCESS, ly_in_new_memory(xml, &UTEST_IN)); + assert_int_equal(LY_SUCCESS, lyd_parse_ext_data(ext, NULL, UTEST_IN, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, &tree)); + + CHECK_LYD_STRING_PARAM(tree, xml, LYD_XML, 0); + + lyd_free_all(tree); + + /* cleanup */ + ly_ctx_destroy(printed_ctx); + free(mem); +} + int main(void) { @@ -2140,6 +2290,7 @@ main(void) UTEST(test_ext_recursive), UTEST(test_lysc_path), UTEST(test_lysc_backlinks), + UTEST(test_compiled_print), }; return cmocka_run_group_tests(tests, NULL, NULL); diff --git a/tests/utests/schema/test_tree_schema_compile.c b/tests/utests/schema/test_tree_schema_compile.c index f4e609408..96d88cb93 100644 --- a/tests/utests/schema/test_tree_schema_compile.c +++ b/tests/utests/schema/test_tree_schema_compile.c @@ -235,8 +235,6 @@ test_node_leaflist(void **state) struct lysc_type *type; struct lysc_node_leaflist *ll; struct lysc_node_leaf *l; - const char *dflt; - uint8_t dynamic; assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, "module a {namespace urn:a;prefix a;" "typedef mytype {type union {type leafref {path ../target;} type string;}}" @@ -268,19 +266,14 @@ test_node_leaflist(void **state) assert_non_null(mod->compiled); assert_non_null((ll = (struct lysc_node_leaflist *)mod->compiled->data)); assert_non_null(ll->dflts); - assert_int_equal(6, ll->type->refcount); /* 3x type's reference, 3x default value's reference (typedef's default does not reference own type) */ assert_int_equal(2, LY_ARRAY_COUNT(ll->dflts)); - assert_string_equal("1", dflt = ll->dflts[0]->realtype->plugin->print(UTEST_LYCTX, ll->dflts[0], LY_VALUE_SCHEMA, NULL, &dynamic, NULL)); - assert_int_equal(0, dynamic); - assert_string_equal("1", dflt = ll->dflts[1]->realtype->plugin->print(UTEST_LYCTX, ll->dflts[1], LY_VALUE_SCHEMA, NULL, &dynamic, NULL)); - assert_int_equal(0, dynamic); + assert_string_equal("1", ll->dflts[0].str); + assert_string_equal("1", ll->dflts[1].str); assert_int_equal(LYS_CONFIG_R | LYS_STATUS_CURR | LYS_ORDBY_USER | LYS_SET_DFLT | LYS_SET_CONFIG, ll->flags); assert_non_null((ll = (struct lysc_node_leaflist *)mod->compiled->data->next)); assert_non_null(ll->dflts); - assert_int_equal(6, ll->type->refcount); /* 3x type's reference, 3x default value's reference */ assert_int_equal(1, LY_ARRAY_COUNT(ll->dflts)); - assert_string_equal("10", dflt = ll->dflts[0]->realtype->plugin->print(UTEST_LYCTX, ll->dflts[0], LY_VALUE_SCHEMA, NULL, &dynamic, NULL)); - assert_int_equal(0, dynamic); + assert_string_equal("10", ll->dflts[0].str); assert_int_equal(LYS_CONFIG_W | LYS_STATUS_CURR | LYS_ORDBY_USER, ll->flags); /* ordered-by is ignored (with verbose message) for state data, RPC/action output parameters and notification content */ @@ -302,7 +295,7 @@ test_node_leaflist(void **state) "leaf-list g {type string;}}", LYS_IN_YANG, &mod)); assert_non_null(l = (struct lysc_node_leaf *)mod->compiled->data); assert_string_equal("ref", l->name); - assert_non_null(l->dflt); + assert_non_null(l->dflt.str); /* invalid */ assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module aa {namespace urn:aa;prefix aa;leaf-list ll {type empty;}}", @@ -371,7 +364,7 @@ test_node_list(void **state) assert_string_equal("l", list->name); assert_string_equal("a", list->child->name); assert_true(list->child->flags & LYS_KEY); - assert_null(((struct lysc_node_leaf *)list->child)->dflt); + assert_null(((struct lysc_node_leaf *)list->child)->dflt.str); assert_non_null(list->uniques); assert_int_equal(2, LY_ARRAY_COUNT(list->uniques)); assert_int_equal(2, LY_ARRAY_COUNT(list->uniques[0])); @@ -1734,7 +1727,7 @@ test_type_leafref(void **state) assert_int_equal(LYXP_TOKEN_NAMETEST, expr->tokens[1]); assert_int_equal(LYXP_TOKEN_OPER_PATH, expr->tokens[2]); assert_int_equal(LYXP_TOKEN_NAMETEST, expr->tokens[3]); - lyxp_expr_free(UTEST_LYCTX, expr); + lyxp_expr_free(expr); /* complete leafref paths */ assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, "module a {yang-version 1.1;namespace urn:a;prefix a;" @@ -1903,9 +1896,8 @@ test_type_leafref(void **state) assert_string_equal("../target", ((struct lysc_type_leafref *)type)->path->expr); assert_non_null(((struct lysc_type_leafref *)type)->realtype); assert_int_equal(LY_TYPE_BOOL, ((struct lysc_type_leafref *)type)->realtype->basetype); - assert_non_null(((struct lysc_node_leaf *)mod->compiled->data)->dflt); - assert_int_equal(LY_TYPE_BOOL, ((struct lysc_node_leaf *)mod->compiled->data)->dflt->realtype->basetype); - assert_int_equal(1, ((struct lysc_node_leaf *)mod->compiled->data)->dflt->boolean); + assert_non_null(((struct lysc_node_leaf *)mod->compiled->data)->dflt.str); + assert_string_equal(((struct lysc_node_leaf *)mod->compiled->data)->dflt.str, "true"); /* union reference */ assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, "module m {namespace urn:m;prefix m;" @@ -2183,7 +2175,6 @@ test_type_dflt(void **state) struct lys_module *mod; struct lysc_type *type; struct lysc_node_leaf *leaf; - uint8_t dynamic; /* default is not inherited from union's types */ assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, "module a {namespace urn:a;prefix a; typedef mybasetype {type string;default hello;units xxx;}" @@ -2196,29 +2187,25 @@ test_type_dflt(void **state) assert_int_equal(2, LY_ARRAY_COUNT(((struct lysc_type_union *)type)->types)); assert_int_equal(LY_TYPE_DEC64, ((struct lysc_type_union *)type)->types[0]->basetype); assert_int_equal(LY_TYPE_STRING, ((struct lysc_type_union *)type)->types[1]->basetype); - assert_null(((struct lysc_node_leaf *)mod->compiled->data)->dflt); + assert_null(((struct lysc_node_leaf *)mod->compiled->data)->dflt.str); assert_null(((struct lysc_node_leaf *)mod->compiled->data)->units); assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, "module b {namespace urn:b;prefix b; typedef mybasetype {type string;default hello;units xxx;}" "leaf l {type mybasetype;}}", LYS_IN_YANG, &mod)); type = ((struct lysc_node_leaf *)mod->compiled->data)->type; assert_non_null(type); - assert_int_equal(3, type->refcount); /* 2x type reference, 1x default value's reference (typedf's default does not reference own type)*/ assert_int_equal(LY_TYPE_STRING, type->basetype); assert_non_null(leaf = (struct lysc_node_leaf *)mod->compiled->data); - assert_string_equal("hello", leaf->dflt->realtype->plugin->print(UTEST_LYCTX, leaf->dflt, LY_VALUE_SCHEMA, NULL, &dynamic, NULL)); - assert_int_equal(0, dynamic); + assert_string_equal("hello", leaf->dflt.str); assert_string_equal("xxx", leaf->units); assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, "module c {namespace urn:c;prefix c; typedef mybasetype {type string;default hello;units xxx;}" "leaf l {type mybasetype; default goodbye;units yyy;}}", LYS_IN_YANG, &mod)); type = ((struct lysc_node_leaf *)mod->compiled->data)->type; assert_non_null(type); - assert_int_equal(3, type->refcount); /* 2x type reference, 1x default value's reference */ assert_int_equal(LY_TYPE_STRING, type->basetype); leaf = (struct lysc_node_leaf *)mod->compiled->data; - assert_string_equal("goodbye", leaf->dflt->realtype->plugin->print(UTEST_LYCTX, leaf->dflt, LY_VALUE_SCHEMA, NULL, &dynamic, NULL)); - assert_int_equal(0, dynamic); + assert_string_equal("goodbye", leaf->dflt.str); assert_string_equal("yyy", leaf->units); assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, "module d {namespace urn:d;prefix d; typedef mybasetype {type string;default hello;units xxx;}" @@ -2226,30 +2213,24 @@ test_type_dflt(void **state) "leaf l2 {type mytype;}}", LYS_IN_YANG, &mod)); type = ((struct lysc_node_leaf *)mod->compiled->data)->type; assert_non_null(type); - assert_int_equal(6, type->refcount); /* 4x type reference, 2x default value's reference (1 shared compiled type of typedefs which default does not reference own type) */ assert_int_equal(LY_TYPE_STRING, type->basetype); leaf = (struct lysc_node_leaf *)mod->compiled->data; - assert_string_equal("goodbye", leaf->dflt->realtype->plugin->print(UTEST_LYCTX, leaf->dflt, LY_VALUE_SCHEMA, NULL, &dynamic, NULL)); - assert_int_equal(0, dynamic); + assert_string_equal("goodbye", leaf->dflt.str); assert_string_equal("yyy", leaf->units); type = ((struct lysc_node_leaf *)mod->compiled->data->next)->type; assert_non_null(type); - assert_int_equal(6, type->refcount); /* 4x type reference, 2x default value's reference (1 shared compiled type of typedefs which default does not reference own type) */ assert_int_equal(LY_TYPE_STRING, type->basetype); leaf = (struct lysc_node_leaf *)mod->compiled->data->next; - assert_string_equal("hello", leaf->dflt->realtype->plugin->print(UTEST_LYCTX, leaf->dflt, LY_VALUE_SCHEMA, NULL, &dynamic, NULL)); - assert_int_equal(0, dynamic); + assert_string_equal("hello", leaf->dflt.str); assert_string_equal("xxx", leaf->units); assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, "module e {namespace urn:e;prefix e; typedef mybasetype {type string;}" "typedef mytype {type mybasetype; default hello;units xxx;}leaf l {type mytype;}}", LYS_IN_YANG, &mod)); type = ((struct lysc_node_leaf *)mod->compiled->data)->type; assert_non_null(type); - assert_int_equal(4, type->refcount); /* 3x type reference, 1x default value's reference (typedef's default does not reference own type) */ assert_int_equal(LY_TYPE_STRING, type->basetype); leaf = (struct lysc_node_leaf *)mod->compiled->data; - assert_string_equal("hello", leaf->dflt->realtype->plugin->print(UTEST_LYCTX, leaf->dflt, LY_VALUE_SCHEMA, NULL, &dynamic, NULL)); - assert_int_equal(0, dynamic); + assert_string_equal("hello", leaf->dflt.str); assert_string_equal("xxx", leaf->units); /* mandatory leaf does not takes default value from type */ @@ -2258,7 +2239,7 @@ test_type_dflt(void **state) type = ((struct lysc_node_leaf *)mod->compiled->data)->type; assert_non_null(type); assert_int_equal(LY_TYPE_STRING, type->basetype); - assert_null(((struct lysc_node_leaf *)mod->compiled->data)->dflt); + assert_null(((struct lysc_node_leaf *)mod->compiled->data)->dflt.str); assert_string_equal("xxx", ((struct lysc_node_leaf *)mod->compiled->data)->units); } @@ -2689,7 +2670,6 @@ test_refine(void **state) struct lysc_node *parent, *child; struct lysc_node_leaf *leaf; struct lysc_node_leaflist *llist; - uint8_t dynamic; struct ly_in *in; const char *data, *feats1[] = {"f", NULL}, *feats2[] = {"fa", NULL}; @@ -2721,17 +2701,14 @@ test_refine(void **state) assert_non_null((leaf = (struct lysc_node_leaf *)((struct lysc_node_container *)parent)->child)); assert_int_equal(LYS_LEAF, leaf->nodetype); assert_string_equal("l", leaf->name); - assert_string_equal("hello", leaf->dflt->realtype->plugin->print(UTEST_LYCTX, leaf->dflt, LY_VALUE_SCHEMA, NULL, &dynamic, NULL)); - assert_int_equal(0, dynamic); + assert_string_equal("hello", leaf->dflt.str); assert_int_equal(LYS_CONFIG_R, leaf->flags & LYS_CONFIG_MASK); assert_non_null(llist = (struct lysc_node_leaflist *)leaf->next); assert_int_equal(LYS_LEAFLIST, llist->nodetype); assert_string_equal("ll", llist->name); assert_int_equal(2, LY_ARRAY_COUNT(llist->dflts)); - assert_string_equal("hello", llist->dflts[0]->realtype->plugin->print(UTEST_LYCTX, llist->dflts[0], LY_VALUE_SCHEMA, NULL, &dynamic, NULL)); - assert_int_equal(0, dynamic); - assert_string_equal("world", llist->dflts[1]->realtype->plugin->print(UTEST_LYCTX, llist->dflts[1], LY_VALUE_SCHEMA, NULL, &dynamic, NULL)); - assert_int_equal(0, dynamic); + assert_string_equal("hello", llist->dflts[0].str); + assert_string_equal("world", llist->dflts[1].str); assert_int_equal(5, llist->max); assert_non_null(child = llist->next); assert_int_equal(LYS_CHOICE, child->nodetype); @@ -2743,8 +2720,7 @@ test_refine(void **state) assert_int_equal(LYS_LEAF, leaf->nodetype); assert_string_equal("x", leaf->name); assert_false(LYS_MAND_TRUE & leaf->flags); - assert_string_equal("cheers!", leaf->dflt->realtype->plugin->print(UTEST_LYCTX, leaf->dflt, LY_VALUE_SCHEMA, NULL, &dynamic, NULL)); - assert_int_equal(0, dynamic); + assert_string_equal("cheers!", leaf->dflt.str); assert_non_null(leaf->musts); assert_int_equal(2, LY_ARRAY_COUNT(leaf->musts)); assert_string_equal("refined", leaf->dsc); @@ -2770,8 +2746,7 @@ test_refine(void **state) assert_int_equal(LYS_LEAF, leaf->nodetype); assert_string_equal("x", leaf->name); assert_false(LYS_MAND_TRUE & leaf->flags); - assert_string_equal("hello", leaf->dflt->realtype->plugin->print(UTEST_LYCTX, leaf->dflt, LY_VALUE_SCHEMA, NULL, &dynamic, NULL)); - assert_int_equal(0, dynamic); + assert_string_equal("hello", leaf->dflt.str); assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, "module c {namespace urn:c;prefix c;" "grouping alg {leaf alg2 {type bits {" @@ -3033,8 +3008,6 @@ test_deviation(void **state) const struct lysc_node_list *list; const struct lysc_node_leaflist *llist; const struct lysc_node_leaf *leaf; - const char *str; - uint8_t dynamic; ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, "module a {namespace urn:a;prefix a;" "container top {leaf a {type string;} leaf b {type string;} leaf c {type string;}}" @@ -3119,19 +3092,15 @@ test_deviation(void **state) assert_non_null(node = node->next); assert_null(((struct lysc_node_choice *)node)->dflt); assert_non_null(leaf = (struct lysc_node_leaf *)node->next); - assert_null(leaf->dflt); + assert_null(leaf->dflt.str); assert_non_null(llist = (struct lysc_node_leaflist *)leaf->next); assert_int_equal(1, LY_ARRAY_COUNT(llist->dflts)); - assert_string_equal("hello", llist->dflts[0]->realtype->plugin->print(UTEST_LYCTX, llist->dflts[0], LY_VALUE_SCHEMA, NULL, &dynamic, NULL)); - assert_int_equal(0, dynamic); + assert_string_equal("hello", llist->dflts[0].str); assert_non_null(leaf = (struct lysc_node_leaf *)llist->next); - assert_string_equal("nothing", leaf->dflt->realtype->plugin->print(UTEST_LYCTX, leaf->dflt, LY_VALUE_SCHEMA, NULL, &dynamic, NULL)); - assert_int_equal(0, dynamic); - assert_int_equal(5, leaf->dflt->realtype->refcount); /* 3x type reference, 2x default value reference (typedef's default does not reference own type) */ + assert_string_equal("nothing", leaf->dflt.str); assert_non_null(llist = (struct lysc_node_leaflist *)leaf->next); assert_int_equal(1, LY_ARRAY_COUNT(llist->dflts)); - assert_string_equal("nothing", llist->dflts[0]->realtype->plugin->print(UTEST_LYCTX, llist->dflts[0], LY_VALUE_SCHEMA, NULL, &dynamic, NULL)); - assert_int_equal(0, dynamic); + assert_string_equal("nothing", llist->dflts[0].str); assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, "module g {yang-version 1.1; namespace urn:g;prefix g;import e {prefix x;}" "deviation /x:b {deviate add {default x:ba;}}" @@ -3146,31 +3115,20 @@ test_deviation(void **state) assert_non_null(((struct lysc_node_choice *)node)->dflt); assert_string_equal("ba", ((struct lysc_node_choice *)node)->dflt->name); assert_non_null(leaf = (struct lysc_node_leaf *)node->next); - assert_non_null(leaf->dflt); - assert_string_equal("bye", leaf->dflt->realtype->plugin->print(UTEST_LYCTX, leaf->dflt, LY_VALUE_SCHEMA, NULL, &dynamic, NULL)); - assert_int_equal(0, dynamic); + assert_string_equal("bye", leaf->dflt.str); assert_non_null(llist = (struct lysc_node_leaflist *)leaf->next); assert_int_equal(3, LY_ARRAY_COUNT(llist->dflts)); - assert_string_equal("hello", llist->dflts[0]->realtype->plugin->print(UTEST_LYCTX, llist->dflts[0], LY_VALUE_SCHEMA, NULL, &dynamic, NULL)); - assert_int_equal(0, dynamic); - assert_string_equal("all", llist->dflts[1]->realtype->plugin->print(UTEST_LYCTX, llist->dflts[1], LY_VALUE_SCHEMA, NULL, &dynamic, NULL)); - assert_int_equal(0, dynamic); - assert_string_equal("people", llist->dflts[2]->realtype->plugin->print(UTEST_LYCTX, llist->dflts[2], LY_VALUE_SCHEMA, NULL, &dynamic, NULL)); - assert_int_equal(0, dynamic); + assert_string_equal("hello", llist->dflts[0].str); + assert_string_equal("all", llist->dflts[1].str); + assert_string_equal("people", llist->dflts[2].str); assert_non_null(leaf = (struct lysc_node_leaf *)llist->next); - assert_non_null(leaf->dflt); - assert_string_equal("hi", leaf->dflt->realtype->plugin->print(UTEST_LYCTX, leaf->dflt, LY_VALUE_SCHEMA, NULL, &dynamic, NULL)); - assert_int_equal(0, dynamic); - assert_int_equal(6, leaf->dflt->realtype->refcount); /* 3x type reference, 3x default value reference - - previous type's default values were replaced by node's default values where d2 now has 2 default values */ + assert_string_equal("hi", leaf->dflt.str); assert_int_equal(1, LY_ARRAY_COUNT(leaf->musts)); assert_int_equal(1, LY_ARRAY_COUNT(leaf->musts[0].prefixes)); assert_non_null(llist = (struct lysc_node_leaflist *)leaf->next); assert_int_equal(2, LY_ARRAY_COUNT(llist->dflts)); - assert_string_equal("hi", llist->dflts[0]->realtype->plugin->print(UTEST_LYCTX, llist->dflts[0], LY_VALUE_SCHEMA, NULL, &dynamic, NULL)); - assert_int_equal(0, dynamic); - assert_string_equal("all", llist->dflts[1]->realtype->plugin->print(UTEST_LYCTX, llist->dflts[1], LY_VALUE_SCHEMA, NULL, &dynamic, NULL)); - assert_int_equal(0, dynamic); + assert_string_equal("hi", llist->dflts[0].str); + assert_string_equal("all", llist->dflts[1].str); assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, "module h {yang-version 1.1; namespace urn:h;prefix h;import e {prefix x;}" "deviation /x:b {deviate replace {default x:ba;}}" @@ -3182,9 +3140,7 @@ test_deviation(void **state) assert_non_null(((struct lysc_node_choice *)node)->dflt); assert_string_equal("ba", ((struct lysc_node_choice *)node)->dflt->name); assert_non_null(leaf = (struct lysc_node_leaf *)node->next); - assert_non_null(leaf->dflt); - assert_string_equal("hello", leaf->dflt->realtype->plugin->print(UTEST_LYCTX, leaf->dflt, LY_VALUE_SCHEMA, NULL, &dynamic, NULL)); - assert_int_equal(0, dynamic); + assert_string_equal("hello", leaf->dflt.str); ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, "module i {namespace urn:i;prefix i;" "list l1 {key a; leaf a {type string;} leaf b {type string;} leaf c {type string;}}" @@ -3260,11 +3216,11 @@ test_deviation(void **state) "deviation /b {deviate add {default test;} deviate replace {mandatory false;}}}", LYS_IN_YANG, &mod)); assert_non_null(node = mod->compiled->data); assert_string_equal("a", node->name); - assert_null(((struct lysc_node_leaf *)node)->dflt); + assert_null(((struct lysc_node_leaf *)node)->dflt.str); assert_true((node->flags & LYS_MAND_MASK) == LYS_MAND_TRUE); assert_non_null(node = node->next); assert_string_equal("b", node->name); - assert_non_null(((struct lysc_node_leaf *)node)->dflt); + assert_non_null(((struct lysc_node_leaf *)node)->dflt.str); assert_true((node->flags & LYS_MAND_MASK) == LYS_MAND_FALSE); assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, "module o {namespace urn:o;prefix o;" @@ -3300,16 +3256,12 @@ test_deviation(void **state) assert_non_null(leaf = (struct lysc_node_leaf *)mod->compiled->data); assert_string_equal("a", leaf->name); assert_int_equal(LY_TYPE_INT8, leaf->type->basetype); - assert_string_equal("10", leaf->dflt->realtype->plugin->print(UTEST_LYCTX, leaf->dflt, LY_VALUE_SCHEMA, NULL, &dynamic, NULL)); - assert_int_equal(0, dynamic); - assert_int_equal(10, leaf->dflt->uint8); + assert_string_equal("10", leaf->dflt.str); assert_non_null(llist = (struct lysc_node_leaflist *)leaf->next); assert_string_equal("b", llist->name); assert_int_equal(LY_TYPE_INT8, llist->type->basetype); assert_int_equal(1, LY_ARRAY_COUNT(llist->dflts)); - assert_string_equal("1", llist->dflts[0]->realtype->plugin->print(UTEST_LYCTX, llist->dflts[0], LY_VALUE_SCHEMA, NULL, &dynamic, NULL)); - assert_int_equal(0, dynamic); - assert_int_equal(1, llist->dflts[0]->uint8); + assert_string_equal("1", llist->dflts[0].str); /* instance-identifiers with NULL canonical are changed to string types with a canonical value equal to the original value */ assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, "module q {yang-version 1.1; namespace urn:q;prefix q; import e {prefix e;}" @@ -3319,15 +3271,11 @@ test_deviation(void **state) "deviation /q:q { deviate replace {type string;}}" "deviation /q:ql { deviate replace {type string;}}}", LYS_IN_YANG, NULL)); assert_non_null(leaf = (struct lysc_node_leaf *)mod->compiled->data); - assert_int_equal(LY_TYPE_STRING, leaf->dflt->realtype->basetype); - assert_non_null(leaf->dflt->realtype->plugin->print(UTEST_LYCTX, leaf->dflt, LY_VALUE_CANON, NULL, NULL, NULL)); - assert_string_equal("/e:d2[.='a']", leaf->dflt->_canonical); + assert_string_equal("/e:d2[.='a']", leaf->dflt.str); assert_non_null(llist = (struct lysc_node_leaflist *)leaf->next); assert_int_equal(2, LY_ARRAY_COUNT(llist->dflts)); - assert_int_equal(LY_TYPE_STRING, llist->dflts[0]->realtype->basetype); - assert_string_equal("/e:d[.='b']", llist->dflts[0]->_canonical); - assert_int_equal(LY_TYPE_STRING, llist->dflts[0]->realtype->basetype); - assert_string_equal("/e:d2[.='c']", llist->dflts[1]->_canonical); + assert_string_equal("/e:d[.='b']", llist->dflts[0].str); + assert_string_equal("/e:d2[.='c']", llist->dflts[1].str); assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, "module r {yang-version 1.1; namespace urn:r;prefix r;" "typedef mytype {type uint8; default 200;}" @@ -3336,7 +3284,7 @@ test_deviation(void **state) "deviation /r:lr {deviate replace {type string;}}}", LYS_IN_YANG, &mod)); assert_non_null(leaf = (struct lysc_node_leaf *)mod->compiled->data); assert_string_equal("r", leaf->name); - assert_null(leaf->dflt); + assert_null(leaf->dflt.str); assert_non_null(llist = (struct lysc_node_leaflist *)leaf->next); assert_string_equal("lr", llist->name); assert_null(llist->dflts); @@ -3347,12 +3295,7 @@ test_deviation(void **state) "deviation /s:s {deviate replace {default /s:y;}}}", LYS_IN_YANG, &mod)); assert_non_null(leaf = (struct lysc_node_leaf *)mod->compiled->data); assert_string_equal("s", leaf->name); - assert_non_null(leaf->dflt); - assert_non_null(str = leaf->dflt->realtype->plugin->print(UTEST_LYCTX, leaf->dflt, LY_VALUE_SCHEMA, mod->parsed, &dynamic, NULL)); - assert_string_equal("/s:y", str); - if (dynamic) { - free((char *)str); - } + assert_string_equal("/s:y", leaf->dflt.str); ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, "module t {namespace urn:t;prefix t;" "leaf l {type string;}}"); diff --git a/tests/utests/schema/test_yang.c b/tests/utests/schema/test_yang.c index 384b08cd1..75f89a54e 100644 --- a/tests/utests/schema/test_yang.c +++ b/tests/utests/schema/test_yang.c @@ -57,8 +57,6 @@ LY_ERR parse_when(struct lysp_yang_ctx *ctx, struct lysp_when **when_p); LY_ERR parse_type_enum_value_pos(struct lysp_yang_ctx *ctx, enum ly_stmt val_kw, struct lysp_type_enum *enm); struct lysp_yang_ctx *YCTX; -struct lysf_ctx fctx; - struct ly_in in = {0}; #define YCTX_INIT \ @@ -93,16 +91,13 @@ setup(void **state) YCTX->in = ∈ ly_log_location(NULL, NULL, NULL, &in); - fctx.ctx = PARSER_CTX(YCTX); - fctx.mod = pmod->mod; - return 0; } static int teardown(void **state) { - lys_module_free(&fctx, PARSER_CUR_PMOD(YCTX)->mod, 0); + lys_module_free(PARSER_CTX(YCTX), PARSER_CUR_PMOD(YCTX)->mod, 0); ly_log_location_revert(0, 0, 0, 1); ly_set_free(YCTX->parsed_mods, NULL); @@ -110,8 +105,6 @@ teardown(void **state) free(YCTX); YCTX = NULL; - lysf_ctx_erase(&fctx); - UTEST_TEARDOWN; return 0; @@ -725,7 +718,7 @@ mod_renew(struct lysp_yang_ctx *ctx) struct ly_ctx *ly_ctx = PARSER_CUR_PMOD(ctx)->mod->ctx; struct lysp_module *pmod; - lys_module_free(&fctx, PARSER_CUR_PMOD(ctx)->mod, 0); + lys_module_free(PARSER_CTX(YCTX), PARSER_CUR_PMOD(ctx)->mod, 0); pmod = calloc(1, sizeof *pmod); ctx->parsed_mods->objs[0] = pmod; pmod->mod = calloc(1, sizeof *pmod->mod); @@ -733,7 +726,6 @@ mod_renew(struct lysp_yang_ctx *ctx) pmod->mod->ctx = ly_ctx; ctx->in->line = 1; - fctx.mod = pmod->mod; return pmod; } @@ -744,16 +736,14 @@ submod_renew(struct lysp_yang_ctx *ctx) struct ly_ctx *ly_ctx = PARSER_CUR_PMOD(ctx)->mod->ctx; struct lysp_submodule *submod; - lys_module_free(&fctx, PARSER_CUR_PMOD(ctx)->mod, 0); + lys_module_free(PARSER_CTX(YCTX), PARSER_CUR_PMOD(ctx)->mod, 0); submod = calloc(1, sizeof *submod); ctx->parsed_mods->objs[0] = submod; submod->mod = calloc(1, sizeof *submod->mod); - lydict_insert(ly_ctx, "name", 0, &submod->mod->name); + lysdict_insert(ly_ctx, "name", 0, &submod->mod->name); submod->mod->parsed = (struct lysp_module *)submod; submod->mod->ctx = ly_ctx; - fctx.mod = submod->mod; - return submod; } @@ -952,7 +942,7 @@ test_module(void **state) assert_int_equal(LY_EVALID, yang_parse_module(&ctx_p, &in, m)); CHECK_LOG_CTX("Trailing garbage \"module q {names...\" after module, expected end-of-input.", NULL, 1); lysp_yang_ctx_free(ctx_p); - lys_module_free(&fctx, m, 0); + lys_module_free(PARSER_CTX(YCTX), m, 0); in.current = "prefix " SCHEMA_BEGINNING "}"; m = calloc(1, sizeof *m); @@ -960,7 +950,7 @@ test_module(void **state) assert_int_equal(LY_EVALID, yang_parse_module(&ctx_p, &in, m)); CHECK_LOG_CTX("Invalid keyword \"prefix\", expected \"module\" or \"submodule\".", NULL, 1); lysp_yang_ctx_free(ctx_p); - lys_module_free(&fctx, m, 0); + lys_module_free(PARSER_CTX(YCTX), m, 0); in.current = "module " SCHEMA_BEGINNING "leaf enum {type enumeration {enum seven { position 7;}}}}"; m = calloc(1, sizeof *m); @@ -968,7 +958,7 @@ test_module(void **state) assert_int_equal(LY_EVALID, yang_parse_module(&ctx_p, &in, m)); CHECK_LOG_CTX("Invalid keyword \"position\" as a child of \"enum\".", NULL, 1); lysp_yang_ctx_free(ctx_p); - lys_module_free(&fctx, m, 0); + lys_module_free(PARSER_CTX(YCTX), m, 0); /* extensions */ TEST_GENERIC("prefix:test;}", mod->exts, @@ -1109,7 +1099,7 @@ test_container(void **state) in.current = "cont {" MEMBER" "VALUE1";"MEMBER" "VALUE2";} ..."; \ assert_int_equal(LY_EVALID, parse_container(YCTX, NULL, (struct lysp_node**)&c)); \ CHECK_LOG_CTX("Duplicate keyword \""MEMBER"\".", NULL, 1); \ - lysp_node_free(&fctx, (struct lysp_node*)c); c = NULL; + lysp_node_free(PARSER_CTX(YCTX), (struct lysp_node*)c); c = NULL; TEST_DUP("config", "true", "false"); TEST_DUP("description", "text1", "text2"); @@ -1133,24 +1123,24 @@ test_container(void **state) assert_non_null(c->typedefs); ly_set_erase(&YCTX->tpdfs_nodes, NULL); ly_set_erase(&YCTX->grps_nodes, NULL); - lysp_node_free(&fctx, (struct lysp_node *)c); c = NULL; + lysp_node_free(PARSER_CTX(YCTX), (struct lysp_node *)c); c = NULL; /* invalid */ in.current = " cont {augment /root;} ..."; assert_int_equal(LY_EVALID, parse_container(YCTX, NULL, (struct lysp_node **)&c)); CHECK_LOG_CTX("Invalid keyword \"augment\" as a child of \"container\".", NULL, 1); - lysp_node_free(&fctx, (struct lysp_node *)c); c = NULL; + lysp_node_free(PARSER_CTX(YCTX), (struct lysp_node *)c); c = NULL; in.current = " cont {nonsence true;} ..."; assert_int_equal(LY_EVALID, parse_container(YCTX, NULL, (struct lysp_node **)&c)); CHECK_LOG_CTX("Invalid character sequence \"nonsence\", expected a keyword.", NULL, 1); - lysp_node_free(&fctx, (struct lysp_node *)c); c = NULL; + lysp_node_free(PARSER_CTX(YCTX), (struct lysp_node *)c); c = NULL; PARSER_CUR_PMOD(YCTX)->version = 1; /* simulate YANG 1.0 */ in.current = " cont {action x;} ..."; assert_int_equal(LY_EVALID, parse_container(YCTX, NULL, (struct lysp_node **)&c)); CHECK_LOG_CTX("Invalid keyword \"action\" as a child of \"container\" - " "the statement is allowed only in YANG 1.1 modules.", NULL, 1); - lysp_node_free(&fctx, (struct lysp_node *)c); c = NULL; + lysp_node_free(PARSER_CTX(YCTX), (struct lysp_node *)c); c = NULL; } static void @@ -1163,7 +1153,7 @@ test_leaf(void **state) in.current = "l {" MEMBER" "VALUE1";"MEMBER" "VALUE2";} ..."; \ assert_int_equal(LY_EVALID, parse_leaf(YCTX, NULL, (struct lysp_node**)&l)); \ CHECK_LOG_CTX("Duplicate keyword \""MEMBER"\".", NULL, 1); \ - lysp_node_free(&fctx, (struct lysp_node*)l); l = NULL; + lysp_node_free(PARSER_CTX(YCTX), (struct lysp_node*)l); l = NULL; TEST_DUP("config", "true", "false"); TEST_DUP("default", "x", "y"); @@ -1185,25 +1175,25 @@ test_leaf(void **state) assert_string_equal("yyy", l->units); assert_string_equal("string", l->type.name); assert_non_null(l->musts); - lysp_node_free(&fctx, (struct lysp_node *)l); l = NULL; + lysp_node_free(PARSER_CTX(YCTX), (struct lysp_node *)l); l = NULL; /* full content - now with mandatory */ in.current = "l {mandatory true; type string;} ..."; assert_int_equal(LY_SUCCESS, parse_leaf(YCTX, NULL, (struct lysp_node **)&l)); CHECK_LYSP_NODE(l, NULL, 0, LYS_MAND_TRUE, 0, "l", 0, LYS_LEAF, 0, NULL, 0); assert_string_equal("string", l->type.name); - lysp_node_free(&fctx, (struct lysp_node *)l); l = NULL; + lysp_node_free(PARSER_CTX(YCTX), (struct lysp_node *)l); l = NULL; /* invalid */ in.current = " l {description \"missing type\";} ..."; assert_int_equal(LY_EVALID, parse_leaf(YCTX, NULL, (struct lysp_node **)&l)); CHECK_LOG_CTX("Missing mandatory keyword \"type\" as a child of \"leaf\".", NULL, 1); - lysp_node_free(&fctx, (struct lysp_node *)l); l = NULL; + lysp_node_free(PARSER_CTX(YCTX), (struct lysp_node *)l); l = NULL; in.current = "l { type iid { path qpud wrong {"; assert_int_equal(LY_EVALID, parse_leaf(YCTX, NULL, (struct lysp_node **)&l)); CHECK_LOG_CTX("Invalid character sequence \"wrong\", expected a keyword.", NULL, 1); - lysp_node_free(&fctx, (struct lysp_node *)l); l = NULL; + lysp_node_free(PARSER_CTX(YCTX), (struct lysp_node *)l); l = NULL; } static void @@ -1218,7 +1208,7 @@ test_leaflist(void **state) in.current = "ll {" MEMBER" "VALUE1";"MEMBER" "VALUE2";} ..."; \ assert_int_equal(LY_EVALID, parse_leaflist(YCTX, NULL, (struct lysp_node**)&ll)); \ CHECK_LOG_CTX("Duplicate keyword \""MEMBER"\".", NULL, 1); \ - lysp_node_free(&fctx, (struct lysp_node*)ll); ll = NULL; + lysp_node_free(PARSER_CTX(YCTX), (struct lysp_node*)ll); ll = NULL; TEST_DUP("config", "true", "false"); TEST_DUP("description", "text1", "text2"); @@ -1248,7 +1238,7 @@ test_leaflist(void **state) assert_string_equal("string", ll->type.name); assert_non_null(ll->musts); assert_int_equal(LYS_CONFIG_R | LYS_STATUS_CURR | LYS_ORDBY_USER | LYS_SET_MAX, ll->flags); - lysp_node_free(&fctx, (struct lysp_node *)ll); ll = NULL; + lysp_node_free(PARSER_CTX(YCTX), (struct lysp_node *)ll); ll = NULL; /* full content - now with min-elements */ in.current = "ll {min-elements 10; type string;} ..."; @@ -1258,19 +1248,19 @@ test_leaflist(void **state) assert_int_equal(0, ll->max); assert_int_equal(10, ll->min); assert_int_equal(LYS_SET_MIN, ll->flags); - lysp_node_free(&fctx, (struct lysp_node *)ll); ll = NULL; + lysp_node_free(PARSER_CTX(YCTX), (struct lysp_node *)ll); ll = NULL; /* invalid */ in.current = " ll {description \"missing type\";} ..."; assert_int_equal(LY_EVALID, parse_leaflist(YCTX, NULL, (struct lysp_node **)&ll)); CHECK_LOG_CTX("Missing mandatory keyword \"type\" as a child of \"leaf-list\".", NULL, 1); - lysp_node_free(&fctx, (struct lysp_node *)ll); ll = NULL; + lysp_node_free(PARSER_CTX(YCTX), (struct lysp_node *)ll); ll = NULL; PARSER_CUR_PMOD(YCTX)->version = 1; /* simulate YANG 1.0 - default statement is not allowed */ in.current = " ll {default xx; type string;} ..."; assert_int_equal(LY_EVALID, parse_leaflist(YCTX, NULL, (struct lysp_node **)&ll)); CHECK_LOG_CTX("Invalid keyword \"default\" as a child of \"leaf-list\" - the statement is allowed only in YANG 1.1 modules.", NULL, 1); - lysp_node_free(&fctx, (struct lysp_node *)ll); ll = NULL; + lysp_node_free(PARSER_CTX(YCTX), (struct lysp_node *)ll); ll = NULL; } static void @@ -1286,7 +1276,7 @@ test_list(void **state) in.current = "l {" MEMBER" "VALUE1";"MEMBER" "VALUE2";} ..."; \ assert_int_equal(LY_EVALID, parse_list(YCTX, NULL, (struct lysp_node**)&l)); \ CHECK_LOG_CTX("Duplicate keyword \""MEMBER"\".", NULL, 1); \ - lysp_node_free(&fctx, (struct lysp_node*)l); l = NULL; + lysp_node_free(PARSER_CTX(YCTX), (struct lysp_node*)l); l = NULL; TEST_DUP("config", "true", "false"); TEST_DUP("description", "text1", "text2"); @@ -1316,14 +1306,14 @@ test_list(void **state) assert_non_null(l->musts); ly_set_erase(&YCTX->tpdfs_nodes, NULL); ly_set_erase(&YCTX->grps_nodes, NULL); - lysp_node_free(&fctx, (struct lysp_node *)l); l = NULL; + lysp_node_free(PARSER_CTX(YCTX), (struct lysp_node *)l); l = NULL; /* invalid content */ PARSER_CUR_PMOD(YCTX)->version = 1; /* simulate YANG 1.0 */ in.current = "l {action x;} ..."; assert_int_equal(LY_EVALID, parse_list(YCTX, NULL, (struct lysp_node **)&l)); CHECK_LOG_CTX("Invalid keyword \"action\" as a child of \"list\" - the statement is allowed only in YANG 1.1 modules.", NULL, 1); - lysp_node_free(&fctx, (struct lysp_node *)l); l = NULL; + lysp_node_free(PARSER_CTX(YCTX), (struct lysp_node *)l); l = NULL; } static void @@ -1338,7 +1328,7 @@ test_choice(void **state) in.current = "ch {" MEMBER" "VALUE1";"MEMBER" "VALUE2";} ..."; \ assert_int_equal(LY_EVALID, parse_choice(YCTX, NULL, (struct lysp_node**)&ch)); \ CHECK_LOG_CTX("Duplicate keyword \""MEMBER"\".", NULL, 1); \ - lysp_node_free(&fctx, (struct lysp_node*)ch); ch = NULL; + lysp_node_free(PARSER_CTX(YCTX), (struct lysp_node*)ch); ch = NULL; TEST_DUP("config", "true", "false"); TEST_DUP("default", "a", "b"); @@ -1354,14 +1344,14 @@ test_choice(void **state) "leaf-list ll {type string;} list li;mandatory true;reference test;status current;when true;m:ext;} ..."; assert_int_equal(LY_SUCCESS, parse_choice(YCTX, NULL, (struct lysp_node **)&ch)); CHECK_LYSP_NODE(ch, "test", 1, LYS_CONFIG_R | LYS_STATUS_CURR | LYS_MAND_TRUE, 1, "ch", 0, LYS_CHOICE, 0, "test", 1); - lysp_node_free(&fctx, (struct lysp_node *)ch); ch = NULL; + lysp_node_free(PARSER_CTX(YCTX), (struct lysp_node *)ch); ch = NULL; /* full content - the default missing from the previous node */ in.current = "ch {default c;case c;} ..."; assert_int_equal(LY_SUCCESS, parse_choice(YCTX, NULL, (struct lysp_node **)&ch)); CHECK_LYSP_NODE(ch, NULL, 0, 0, 0, "ch", 0, LYS_CHOICE, 0, NULL, 0); assert_string_equal("c", ch->dflt.str); - lysp_node_free(&fctx, (struct lysp_node *)ch); ch = NULL; + lysp_node_free(PARSER_CTX(YCTX), (struct lysp_node *)ch); ch = NULL; } static void @@ -1376,7 +1366,7 @@ test_case(void **state) in.current = "cs {" MEMBER" "VALUE1";"MEMBER" "VALUE2";} ..."; \ assert_int_equal(LY_EVALID, parse_case(YCTX, NULL, (struct lysp_node**)&cs)); \ CHECK_LOG_CTX("Duplicate keyword \""MEMBER"\".", NULL, 1); \ - lysp_node_free(&fctx, (struct lysp_node*)cs); cs = NULL; + lysp_node_free(PARSER_CTX(YCTX), (struct lysp_node*)cs); cs = NULL; TEST_DUP("description", "text1", "text2"); TEST_DUP("reference", "1", "2"); @@ -1389,13 +1379,13 @@ test_case(void **state) "leaf-list ll {type string;} list li;reference test;status current;uses grp;when true;m:ext;} ..."; assert_int_equal(LY_SUCCESS, parse_case(YCTX, NULL, (struct lysp_node **)&cs)); CHECK_LYSP_NODE(cs, "test", 1, LYS_STATUS_CURR, 1, "cs", 0, LYS_CASE, 0, "test", 1); - lysp_node_free(&fctx, (struct lysp_node *)cs); cs = NULL; + lysp_node_free(PARSER_CTX(YCTX), (struct lysp_node *)cs); cs = NULL; /* invalid content */ in.current = "cs {config true} ..."; assert_int_equal(LY_EVALID, parse_case(YCTX, NULL, (struct lysp_node **)&cs)); CHECK_LOG_CTX("Invalid keyword \"config\" as a child of \"case\".", NULL, 1); - lysp_node_free(&fctx, (struct lysp_node *)cs); cs = NULL; + lysp_node_free(PARSER_CTX(YCTX), (struct lysp_node *)cs); cs = NULL; } static void @@ -1414,7 +1404,7 @@ test_any(void **state, enum ly_stmt kw) in.current = "l {" MEMBER" "VALUE1";"MEMBER" "VALUE2";} ..."; \ assert_int_equal(LY_EVALID, parse_any(YCTX, kw, NULL, (struct lysp_node**)&any)); \ CHECK_LOG_CTX("Duplicate keyword \""MEMBER"\".", NULL, 1); \ - lysp_node_free(&fctx, (struct lysp_node*)any); any = NULL; + lysp_node_free(PARSER_CTX(YCTX), (struct lysp_node*)any); any = NULL; TEST_DUP("config", "true", "false"); TEST_DUP("description", "text1", "text2"); @@ -1432,7 +1422,7 @@ test_any(void **state, enum ly_stmt kw) CHECK_LYSP_NODE(any, "test", 1, LYS_CONFIG_W | LYS_STATUS_CURR | LYS_MAND_TRUE, 1, "any", 0, node_type, 0, "test", 1); assert_non_null(any->musts); - lysp_node_free(&fctx, (struct lysp_node *)any); any = NULL; + lysp_node_free(PARSER_CTX(YCTX), (struct lysp_node *)any); any = NULL; } static void @@ -1460,7 +1450,7 @@ test_grouping(void **state) in.current = "l {" MEMBER" "VALUE1";"MEMBER" "VALUE2";} ..."; \ assert_int_equal(LY_EVALID, parse_grouping(YCTX, NULL, &grp)); \ CHECK_LOG_CTX("Duplicate keyword \""MEMBER"\".", NULL, 1); \ - lysp_node_free(&fctx, &grp->node); grp = NULL; + lysp_node_free(PARSER_CTX(YCTX), &grp->node); grp = NULL; TEST_DUP("description", "text1", "text2"); TEST_DUP("reference", "1", "2"); @@ -1481,20 +1471,20 @@ test_grouping(void **state) assert_int_equal(LYS_STATUS_CURR, grp->flags); ly_set_erase(&YCTX->tpdfs_nodes, NULL); ly_set_erase(&YCTX->grps_nodes, NULL); - lysp_node_free(&fctx, &grp->node); + lysp_node_free(PARSER_CTX(YCTX), &grp->node); grp = NULL; /* invalid content */ in.current = "grp {config true} ..."; assert_int_equal(LY_EVALID, parse_grouping(YCTX, NULL, &grp)); CHECK_LOG_CTX("Invalid keyword \"config\" as a child of \"grouping\".", NULL, 1); - lysp_node_free(&fctx, &grp->node); + lysp_node_free(PARSER_CTX(YCTX), &grp->node); grp = NULL; in.current = "grp {must 'expr'} ..."; assert_int_equal(LY_EVALID, parse_grouping(YCTX, NULL, &grp)); CHECK_LOG_CTX("Invalid keyword \"must\" as a child of \"grouping\".", NULL, 1); - lysp_node_free(&fctx, &grp->node); + lysp_node_free(PARSER_CTX(YCTX), &grp->node); grp = NULL; } @@ -1512,7 +1502,7 @@ test_action(void **state) in.current = "func {" MEMBER" "VALUE1";"MEMBER" "VALUE2";} ..."; \ assert_int_equal(LY_EVALID, parse_action(YCTX, NULL, &rpcs)); \ CHECK_LOG_CTX("Duplicate keyword \""MEMBER"\".", NULL, 1); \ - lysp_node_free(&fctx, (struct lysp_node*)rpcs); rpcs = NULL; + lysp_node_free(PARSER_CTX(YCTX), (struct lysp_node*)rpcs); rpcs = NULL; TEST_DUP("description", "text1", "text2"); TEST_DUP("input", "{leaf l1 {type empty;}} description a", "{leaf l2 {type empty;}} description a"); @@ -1557,15 +1547,15 @@ test_action(void **state) ly_set_erase(&YCTX->tpdfs_nodes, NULL); ly_set_erase(&YCTX->grps_nodes, NULL); - lysp_node_free(&fctx, (struct lysp_node *)rpcs); rpcs = NULL; + lysp_node_free(PARSER_CTX(YCTX), (struct lysp_node *)rpcs); rpcs = NULL; /* invalid content */ in.current = "func {config true} ..."; assert_int_equal(LY_EVALID, parse_action(YCTX, NULL, &rpcs)); CHECK_LOG_CTX("Invalid keyword \"config\" as a child of \"rpc\".", NULL, 1); - lysp_node_free(&fctx, (struct lysp_node *)rpcs); rpcs = NULL; + lysp_node_free(PARSER_CTX(YCTX), (struct lysp_node *)rpcs); rpcs = NULL; - lysp_node_free(&fctx, (struct lysp_node *)c); + lysp_node_free(PARSER_CTX(YCTX), (struct lysp_node *)c); } static void @@ -1582,7 +1572,7 @@ test_notification(void **state) in.current = "func {" MEMBER" "VALUE1";"MEMBER" "VALUE2";} ..."; \ assert_int_equal(LY_EVALID, parse_notif(YCTX, NULL, ¬ifs)); \ CHECK_LOG_CTX("Duplicate keyword \""MEMBER"\".", NULL, 1); \ - lysp_node_free(&fctx, (struct lysp_node*)notifs); notifs = NULL; + lysp_node_free(PARSER_CTX(YCTX), (struct lysp_node*)notifs); notifs = NULL; TEST_DUP("description", "text1", "text2"); TEST_DUP("reference", "1", "2"); @@ -1610,15 +1600,15 @@ test_notification(void **state) ly_set_erase(&YCTX->tpdfs_nodes, NULL); ly_set_erase(&YCTX->grps_nodes, NULL); - lysp_node_free(&fctx, (struct lysp_node *)notifs); notifs = NULL; + lysp_node_free(PARSER_CTX(YCTX), (struct lysp_node *)notifs); notifs = NULL; /* invalid content */ in.current = "ntf {config true} ..."; assert_int_equal(LY_EVALID, parse_notif(YCTX, NULL, ¬ifs)); CHECK_LOG_CTX("Invalid keyword \"config\" as a child of \"notification\".", NULL, 1); - lysp_node_free(&fctx, (struct lysp_node *)notifs); notifs = NULL; + lysp_node_free(PARSER_CTX(YCTX), (struct lysp_node *)notifs); notifs = NULL; - lysp_node_free(&fctx, (struct lysp_node *)c); + lysp_node_free(PARSER_CTX(YCTX), (struct lysp_node *)c); } static void @@ -1633,7 +1623,7 @@ test_uses(void **state) in.current = "l {" MEMBER" "VALUE1";"MEMBER" "VALUE2";} ..."; \ assert_int_equal(LY_EVALID, parse_uses(YCTX, NULL, (struct lysp_node**)&u)); \ CHECK_LOG_CTX("Duplicate keyword \""MEMBER"\".", NULL, 1); \ - lysp_node_free(&fctx, (struct lysp_node*)u); u = NULL; + lysp_node_free(PARSER_CTX(YCTX), (struct lysp_node*)u); u = NULL; TEST_DUP("description", "text1", "text2"); TEST_DUP("reference", "1", "2"); @@ -1647,7 +1637,7 @@ test_uses(void **state) CHECK_LYSP_NODE(u, "test", 1, LYS_STATUS_CURR, 1, "grpref", 0, LYS_USES, 0, "test", 1); assert_non_null(u->augments); assert_non_null(u->refines); - lysp_node_free(&fctx, (struct lysp_node *)u); u = NULL; + lysp_node_free(PARSER_CTX(YCTX), (struct lysp_node *)u); u = NULL; } static void @@ -1662,7 +1652,7 @@ test_augment(void **state) in.current = "l {" MEMBER" "VALUE1";"MEMBER" "VALUE2";} ..."; \ assert_int_equal(LY_EVALID, parse_augment(YCTX, NULL, &a)); \ CHECK_LOG_CTX("Duplicate keyword \""MEMBER"\".", NULL, 1); \ - lysp_node_free(&fctx, (struct lysp_node *)a); a = NULL; + lysp_node_free(PARSER_CTX(YCTX), (struct lysp_node *)a); a = NULL; TEST_DUP("description", "text1", "text2"); TEST_DUP("reference", "1", "2"); @@ -1684,7 +1674,7 @@ test_augment(void **state) assert_non_null(a->when); assert_null(a->parent); assert_int_equal(LYS_STATUS_CURR, a->flags); - lysp_node_free(&fctx, (struct lysp_node *)a); a = NULL; + lysp_node_free(PARSER_CTX(YCTX), (struct lysp_node *)a); a = NULL; } static void diff --git a/tests/utests/schema/test_yin.c b/tests/utests/schema/test_yin.c index 329fcdac9..654b91e85 100644 --- a/tests/utests/schema/test_yin.c +++ b/tests/utests/schema/test_yin.c @@ -112,7 +112,6 @@ LY_ERR yin_parse_submod(struct lysp_yin_ctx *ctx, struct lysp_submodule *submod) CHECK_LYSP_EXT_INSTANCE((NODE), NULL, 1, INSUBSTMT, 0, "myext:c-define", LY_VALUE_XML) struct lysp_yin_ctx *YCTX; -struct lysf_ctx fctx; static int setup_ctx(void **state) @@ -144,16 +143,13 @@ setup(void **state) setup_ctx(state); - fctx.ctx = UTEST_LYCTX; - fctx.mod = PARSER_CUR_PMOD(YCTX)->mod; - return 0; } static int -teardown_ctx(void **UNUSED(state)) +teardown_ctx(void **state) { - lys_module_free(&fctx, PARSER_CUR_PMOD(YCTX)->mod, 0); + lys_module_free(UTEST_LYCTX, PARSER_CUR_PMOD(YCTX)->mod, 0); lysp_yin_ctx_free(YCTX); YCTX = NULL; @@ -165,8 +161,6 @@ teardown(void **state) { teardown_ctx(state); - lysf_ctx_erase(&fctx); - UTEST_TEARDOWN; return 0; @@ -336,8 +330,8 @@ test_yin_parse_content(void **state) ret = yin_parse_content(YCTX, subelems2, 2, NULL, LY_STMT_STATUS, NULL, &exts); assert_int_equal(ret, LY_EVALID); CHECK_LOG_CTX("Redefinition of \"text\" sub-element in \"status\" element.", NULL, 1); - lydict_remove(UTEST_LYCTX, prefix_value); - lydict_remove(UTEST_LYCTX, value); + lysdict_remove(UTEST_LYCTX, prefix_value); + lysdict_remove(UTEST_LYCTX, value); RESET_STATE; /* test first subelem */ @@ -356,7 +350,7 @@ test_yin_parse_content(void **state) ret = yin_parse_content(YCTX, subelems3, 2, NULL, LY_STMT_STATUS, NULL, &exts); assert_int_equal(ret, LY_EVALID); CHECK_LOG_CTX("Sub-element \"text\" of \"status\" element must be defined as it's first sub-element.", NULL, 1); - lydict_remove(UTEST_LYCTX, prefix_value); + lysdict_remove(UTEST_LYCTX, prefix_value); RESET_STATE; /* test mandatory subelem */ @@ -1298,7 +1292,7 @@ test_enum_elem(void **state) CHECK_LYSP_TYPE_ENUM(type.enums, "desc...", 1, flags, 1, "enum-name", "ref...", 55); assert_string_equal(type.enums->iffeatures[0].str, "feature"); TEST_1_CHECK_LYSP_EXT_INSTANCE(type.enums->exts, LY_STMT_ENUM); - lysp_type_free(&fctx, &type); + lysp_type_free(UTEST_LYCTX, &type); memset(&type, 0, sizeof type); data = ELEMENT_WRAPPER_START @@ -1306,7 +1300,7 @@ test_enum_elem(void **state) ELEMENT_WRAPPER_END; assert_int_equal(test_element_helper(state, data, &type, NULL, NULL), LY_SUCCESS); assert_string_equal(type.enums->name, "enum-name"); - lysp_type_free(&fctx, &type); + lysp_type_free(UTEST_LYCTX, &type); memset(&type, 0, sizeof type); } @@ -1332,7 +1326,7 @@ test_bit_elem(void **state) CHECK_LYSP_TYPE_ENUM(type.bits, "desc...", 1, flags, 1, "bit-name", "ref...", 55); assert_string_equal(type.bits->iffeatures[0].str, "feature"); TEST_1_CHECK_LYSP_EXT_INSTANCE(type.bits->exts, LY_STMT_BIT); - lysp_type_free(&fctx, &type); + lysp_type_free(UTEST_LYCTX, &type); memset(&type, 0, sizeof type); data = ELEMENT_WRAPPER_START @@ -1340,7 +1334,7 @@ test_bit_elem(void **state) ELEMENT_WRAPPER_END; assert_int_equal(test_element_helper(state, data, &type, NULL, NULL), LY_SUCCESS); CHECK_LYSP_TYPE_ENUM(type.bits, NULL, 0, 0, 0, "bit-name", NULL, 0); - lysp_type_free(&fctx, &type); + lysp_type_free(UTEST_LYCTX, &type); memset(&type, 0, sizeof type); } @@ -1398,7 +1392,7 @@ test_argument_elem(void **state) assert_int_equal(test_element_helper(state, data, &arg_meta, NULL, NULL), LY_SUCCESS); assert_string_equal(arg, "arg"); assert_true(flags == 0); - lydict_remove(UTEST_LYCTX, arg); + lysdict_remove(UTEST_LYCTX, arg); } static void @@ -1407,7 +1401,7 @@ test_belongsto_elem(void **state) const char *data; struct lysp_submodule submod; - lydict_insert(UTEST_LYCTX, "module-name", 0, &PARSER_CUR_PMOD(YCTX)->mod->name); + lysdict_insert(UTEST_LYCTX, "module-name", 0, &PARSER_CUR_PMOD(YCTX)->mod->name); data = ELEMENT_WRAPPER_START "" ELEMENT_WRAPPER_END; assert_int_equal(test_element_helper(state, data, &submod, NULL, NULL), LY_EVALID); @@ -1530,7 +1524,7 @@ test_length_elem(void **state) "err-app-tag", "err-msg", 1, "ref"); assert_true(type.flags & LYS_SET_LENGTH); TEST_1_CHECK_LYSP_EXT_INSTANCE(&(type.length->exts[0]), LY_STMT_LENGTH); - lysp_type_free(&fctx, &type); + lysp_type_free(UTEST_LYCTX, &type); memset(&type, 0, sizeof(type)); /* min subelems */ @@ -1541,14 +1535,14 @@ test_length_elem(void **state) assert_int_equal(test_element_helper(state, data, &type, NULL, NULL), LY_SUCCESS); CHECK_LYSP_RESTR(type.length, "length-str", NULL, NULL, NULL, 0, NULL); - lysp_type_free(&fctx, &type); + lysp_type_free(UTEST_LYCTX, &type); assert_true(type.flags & LYS_SET_LENGTH); memset(&type, 0, sizeof(type)); data = ELEMENT_WRAPPER_START "" ELEMENT_WRAPPER_END; assert_int_equal(test_element_helper(state, data, &type, NULL, NULL), LY_EVALID); CHECK_LOG_CTX("Missing mandatory attribute value of length element.", NULL, 1); - lysp_type_free(&fctx, &type); + lysp_type_free(UTEST_LYCTX, &type); memset(&type, 0, sizeof(type)); } @@ -1558,12 +1552,12 @@ test_modifier_elem(void **state) const char *data; const char *pat; - assert_int_equal(LY_SUCCESS, lydict_insert(UTEST_LYCTX, "\006pattern", 8, &pat)); + assert_int_equal(LY_SUCCESS, lysdict_insert(UTEST_LYCTX, "\006pattern", 8, &pat)); data = ELEMENT_WRAPPER_START "" ELEMENT_WRAPPER_END; assert_int_equal(test_element_helper(state, data, &pat, NULL, NULL), LY_EVALID); CHECK_LOG_CTX("Invalid value \"invert\" of \"value\" attribute in \"modifier\" element. " "Only valid value is \"invert-match\".", NULL, 1); - lydict_remove(UTEST_LYCTX, pat); + lysdict_remove(UTEST_LYCTX, pat); } static void @@ -1599,14 +1593,14 @@ test_pattern_elem(void **state) CHECK_LYSP_RESTR(type.patterns, "\x015super_pattern", "\"pattern-desc\"", "err-app-tag-value", "err-msg-value", 1, "pattern-ref"); TEST_1_CHECK_LYSP_EXT_INSTANCE(&(type.patterns->exts[0]), LY_STMT_PATTERN); - lysp_type_free(&fctx, &type); + lysp_type_free(UTEST_LYCTX, &type); memset(&type, 0, sizeof(type)); /* min subelems */ data = ELEMENT_WRAPPER_START " " ELEMENT_WRAPPER_END; assert_int_equal(test_element_helper(state, data, &type, NULL, NULL), LY_SUCCESS); CHECK_LYSP_RESTR(type.patterns, "\x006pattern", NULL, NULL, NULL, 0, NULL); - lysp_type_free(&fctx, &type); + lysp_type_free(UTEST_LYCTX, &type); memset(&type, 0, sizeof(type)); } @@ -1678,7 +1672,7 @@ test_prefix_elem(void **state) data = ELEMENT_WRAPPER_START "" ELEMENT_WRAPPER_END; assert_int_equal(test_element_helper(state, data, &value, NULL, NULL), LY_SUCCESS); assert_string_equal(value, "pref"); - lydict_remove(UTEST_LYCTX, value); + lysdict_remove(UTEST_LYCTX, value); } static void @@ -1702,7 +1696,7 @@ test_range_elem(void **state) "err-app-tag", "err-msg", 1, "ref"); assert_true(type.flags & LYS_SET_RANGE); TEST_1_CHECK_LYSP_EXT_INSTANCE(&(type.range->exts[0]), LY_STMT_RANGE); - lysp_type_free(&fctx, &type); + lysp_type_free(UTEST_LYCTX, &type); memset(&type, 0, sizeof(type)); /* min subelems */ @@ -1710,7 +1704,7 @@ test_range_elem(void **state) assert_int_equal(test_element_helper(state, data, &type, NULL, NULL), LY_SUCCESS); CHECK_LYSP_RESTR(type.range, "range-str", NULL, NULL, NULL, 0, NULL); - lysp_type_free(&fctx, &type); + lysp_type_free(UTEST_LYCTX, &type); memset(&type, 0, sizeof(type)); } @@ -1725,7 +1719,7 @@ test_reqinstance_elem(void **state) assert_int_equal(type.require_instance, 1); assert_true(type.flags & LYS_SET_REQINST); TEST_1_CHECK_LYSP_EXT_INSTANCE(&(type.exts[0]), LY_STMT_REQUIRE_INSTANCE); - lysp_type_free(&fctx, &type); + lysp_type_free(UTEST_LYCTX, &type); memset(&type, 0, sizeof(type)); data = ELEMENT_WRAPPER_START "" ELEMENT_WRAPPER_END; @@ -1765,7 +1759,7 @@ test_unique_elem(void **state) data = ELEMENT_WRAPPER_START "" ELEMENT_WRAPPER_END; assert_int_equal(test_element_helper(state, data, &values, NULL, NULL), LY_SUCCESS); assert_string_equal(*values, "tag"); - lydict_remove(UTEST_LYCTX, *values); + lysdict_remove(UTEST_LYCTX, *values); LY_ARRAY_FREE(values); values = NULL; } @@ -1779,7 +1773,7 @@ test_units_elem(void **state) data = ELEMENT_WRAPPER_START "" ELEMENT_WRAPPER_END; assert_int_equal(test_element_helper(state, data, &values, NULL, NULL), LY_SUCCESS); assert_string_equal(values, "name"); - lydict_remove(UTEST_LYCTX, values); + lysdict_remove(UTEST_LYCTX, values); values = NULL; } @@ -1792,17 +1786,17 @@ test_yin_text_value_elem(void **state) data = ELEMENT_WRAPPER_START "text" ELEMENT_WRAPPER_END; assert_int_equal(test_element_helper(state, data, &val, NULL, NULL), LY_SUCCESS); assert_string_equal(val, "text"); - lydict_remove(UTEST_LYCTX, val); + lysdict_remove(UTEST_LYCTX, val); data = " text "; assert_int_equal(test_element_helper(state, data, &val, NULL, NULL), LY_SUCCESS); assert_string_equal(val, "text"); - lydict_remove(UTEST_LYCTX, val); + lysdict_remove(UTEST_LYCTX, val); data = ELEMENT_WRAPPER_START "" ELEMENT_WRAPPER_END; assert_int_equal(test_element_helper(state, data, &val, NULL, NULL), LY_SUCCESS); assert_string_equal("", val); - lydict_remove(UTEST_LYCTX, val); + lysdict_remove(UTEST_LYCTX, val); } static void @@ -1853,13 +1847,13 @@ test_type_elem(void **state) assert_true(type.flags & LYS_SET_RANGE); assert_true(type.flags & LYS_SET_REQINST); assert_true(type.flags & LYS_SET_TYPE); - lysp_type_free(&fctx, &type); + lysp_type_free(UTEST_LYCTX, &type); memset(&type, 0, sizeof(type)); /* min subelems */ data = ELEMENT_WRAPPER_START "" ELEMENT_WRAPPER_END; assert_int_equal(test_element_helper(state, data, &type, NULL, NULL), LY_SUCCESS); - lysp_type_free(&fctx, &type); + lysp_type_free(UTEST_LYCTX, &type); memset(&type, 0, sizeof(type)); } @@ -1962,7 +1956,7 @@ test_any_elem(void **state) CHECK_LYSP_WHEN(parsed->when, "when-cond", NULL, 0, NULL); assert_string_equal(parsed->iffeatures[0].str, "feature"); TEST_1_CHECK_LYSP_EXT_INSTANCE(&(parsed->exts[0]), LY_STMT_ANYXML); - lysp_node_free(&fctx, siblings); + lysp_node_free(UTEST_LYCTX, siblings); siblings = NULL; /* anydata max subelems */ @@ -1987,7 +1981,7 @@ test_any_elem(void **state) CHECK_LYSP_WHEN(parsed->when, "when-cond", NULL, 0, NULL); assert_string_equal(parsed->iffeatures[0].str, "feature"); TEST_1_CHECK_LYSP_EXT_INSTANCE(&(parsed->exts[0]), LY_STMT_ANYDATA); - lysp_node_free(&fctx, siblings); + lysp_node_free(UTEST_LYCTX, siblings); siblings = NULL; /* min subelems */ @@ -1998,7 +1992,7 @@ test_any_elem(void **state) assert_ptr_equal(parsed->parent, node_meta.parent); CHECK_LYSP_NODE(parsed, NULL, 0, 0, 0, "any-name", 0, LYS_ANYDATA, 1, NULL, 0); - lysp_node_free(&fctx, siblings); + lysp_node_free(UTEST_LYCTX, siblings); } static void @@ -2039,7 +2033,7 @@ test_leaf_elem(void **state) assert_string_equal(parsed->type.name, "type"); assert_string_equal(parsed->units, "uni"); assert_string_equal(parsed->dflt.str, "def-val"); - lysp_node_free(&fctx, siblings); + lysp_node_free(UTEST_LYCTX, siblings); siblings = NULL; /* min elements */ @@ -2048,7 +2042,7 @@ test_leaf_elem(void **state) parsed = (struct lysp_node_leaf *)siblings; assert_string_equal(parsed->name, "leaf"); assert_string_equal(parsed->type.name, "type"); - lysp_node_free(&fctx, siblings); + lysp_node_free(UTEST_LYCTX, siblings); siblings = NULL; } @@ -2093,7 +2087,7 @@ test_leaf_list_elem(void **state) assert_string_equal(parsed->units, "uni"); CHECK_LYSP_WHEN(parsed->when, "when-cond", NULL, 0, NULL); TEST_1_CHECK_LYSP_EXT_INSTANCE(&(parsed->exts[0]), LY_STMT_LEAF_LIST); - lysp_node_free(&fctx, siblings); + lysp_node_free(UTEST_LYCTX, siblings); siblings = NULL; data = ELEMENT_WRAPPER_START @@ -2124,7 +2118,7 @@ test_leaf_list_elem(void **state) assert_string_equal(parsed->type.name, "type"); assert_string_equal(parsed->units, "uni"); TEST_1_CHECK_LYSP_EXT_INSTANCE(&(parsed->exts[0]), LY_STMT_LEAF_LIST); - lysp_node_free(&fctx, siblings); + lysp_node_free(UTEST_LYCTX, siblings); siblings = NULL; data = ELEMENT_WRAPPER_START @@ -2155,7 +2149,7 @@ test_leaf_list_elem(void **state) assert_int_equal(parsed->max, 15); assert_string_equal(parsed->type.name, "type"); assert_string_equal(parsed->units, "uni"); - lysp_node_free(&fctx, siblings); + lysp_node_free(UTEST_LYCTX, siblings); siblings = NULL; data = ELEMENT_WRAPPER_START @@ -2167,7 +2161,7 @@ test_leaf_list_elem(void **state) parsed = (struct lysp_node_leaflist *)siblings; assert_string_equal(parsed->name, "llist"); assert_string_equal(parsed->type.name, "type"); - lysp_node_free(&fctx, siblings); + lysp_node_free(UTEST_LYCTX, siblings); siblings = NULL; /* invalid combinations */ @@ -2181,7 +2175,7 @@ test_leaf_list_elem(void **state) assert_int_equal(test_element_helper(state, data, &node_meta, NULL, NULL), LY_EVALID); CHECK_LOG_CTX("Invalid combination of min-elements and max-elements: min value 15 is bigger than the max value 5.", NULL, 4); - lysp_node_free(&fctx, siblings); + lysp_node_free(UTEST_LYCTX, siblings); siblings = NULL; data = ELEMENT_WRAPPER_START @@ -2193,7 +2187,7 @@ test_leaf_list_elem(void **state) ELEMENT_WRAPPER_END; assert_int_equal(test_element_helper(state, data, &node_meta, NULL, NULL), LY_EVALID); CHECK_LOG_CTX("Invalid combination of sub-elemnts \"min-elements\" and \"default\" in \"leaf-list\" element.", NULL, 5); - lysp_node_free(&fctx, siblings); + lysp_node_free(UTEST_LYCTX, siblings); siblings = NULL; data = ELEMENT_WRAPPER_START @@ -2202,7 +2196,7 @@ test_leaf_list_elem(void **state) ELEMENT_WRAPPER_END; assert_int_equal(test_element_helper(state, data, &node_meta, NULL, NULL), LY_EVALID); CHECK_LOG_CTX("Missing mandatory sub-element \"type\" of \"leaf-list\" element.", NULL, 1); - lysp_node_free(&fctx, siblings); + lysp_node_free(UTEST_LYCTX, siblings); siblings = NULL; } @@ -2215,7 +2209,7 @@ test_presence_elem(void **state) data = ELEMENT_WRAPPER_START "" ELEMENT_WRAPPER_END; assert_int_equal(test_element_helper(state, data, &val, NULL, NULL), LY_SUCCESS); assert_string_equal(val, "presence-val"); - lydict_remove(UTEST_LYCTX, val); + lysdict_remove(UTEST_LYCTX, val); data = ELEMENT_WRAPPER_START "" ELEMENT_WRAPPER_END; assert_int_equal(test_element_helper(state, data, &val, NULL, NULL), LY_EVALID); @@ -2231,7 +2225,7 @@ test_key_elem(void **state) data = ELEMENT_WRAPPER_START "" ELEMENT_WRAPPER_END; assert_int_equal(test_element_helper(state, data, &val, NULL, NULL), LY_SUCCESS); assert_string_equal(val, "key-value"); - lydict_remove(UTEST_LYCTX, val); + lysdict_remove(UTEST_LYCTX, val); data = ELEMENT_WRAPPER_START "" ELEMENT_WRAPPER_END; assert_int_equal(test_element_helper(state, data, &val, NULL, NULL), LY_EVALID); @@ -2268,14 +2262,14 @@ test_uses_elem(void **state) assert_string_equal(parsed->refines->nodeid, "target"); assert_string_equal(parsed->augments->nodeid, "target"); TEST_1_CHECK_LYSP_EXT_INSTANCE(&(parsed->exts[0]), LY_STMT_USES); - lysp_node_free(&fctx, siblings); + lysp_node_free(UTEST_LYCTX, siblings); siblings = NULL; /* min subelems */ data = ELEMENT_WRAPPER_START "" ELEMENT_WRAPPER_END; assert_int_equal(test_element_helper(state, data, &node_meta, NULL, NULL), LY_SUCCESS); assert_string_equal(siblings[0].name, "uses-name"); - lysp_node_free(&fctx, siblings); + lysp_node_free(UTEST_LYCTX, siblings); siblings = NULL; } @@ -2351,7 +2345,7 @@ test_list_elem(void **state) assert_string_equal(parsed->typedefs->name, "tpdf"); assert_string_equal(parsed->uniques->str, "utag"); TEST_1_CHECK_LYSP_EXT_INSTANCE(&(parsed->exts[0]), LY_STMT_LIST); - lysp_node_free(&fctx, siblings); + lysp_node_free(UTEST_LYCTX, siblings); ly_set_erase(&YCTX->tpdfs_nodes, NULL); siblings = NULL; @@ -2361,7 +2355,7 @@ test_list_elem(void **state) parsed = (struct lysp_node_list *)&siblings[0]; CHECK_LYSP_NODE(parsed, NULL, 0, 0, 0, "list-name", 0, LYS_LIST, 0, NULL, 0); - lysp_node_free(&fctx, siblings); + lysp_node_free(UTEST_LYCTX, siblings); siblings = NULL; } @@ -2423,14 +2417,14 @@ test_notification_elem(void **state) assert_string_equal(notifs->ref, "ref"); assert_string_equal(notifs->typedefs->name, "tpdf"); TEST_1_CHECK_LYSP_EXT_INSTANCE(&(notifs->exts[0]), LY_STMT_NOTIFICATION); - lysp_node_free(&fctx, (struct lysp_node *)notifs); + lysp_node_free(UTEST_LYCTX, (struct lysp_node *)notifs); notifs = NULL; /* min subelems */ data = ELEMENT_WRAPPER_START "" ELEMENT_WRAPPER_END; assert_int_equal(test_element_helper(state, data, ¬if_meta, NULL, NULL), LY_SUCCESS); assert_string_equal(notifs->name, "notif-name"); - lysp_node_free(&fctx, (struct lysp_node *)notifs); + lysp_node_free(UTEST_LYCTX, (struct lysp_node *)notifs); notifs = NULL; } @@ -2485,14 +2479,14 @@ test_grouping_elem(void **state) assert_string_equal(grps->child->next->next->next->next->next->next->next->name, "choice"); assert_int_equal(grps->child->next->next->next->next->next->next->next->nodetype, LYS_CHOICE); TEST_1_CHECK_LYSP_EXT_INSTANCE(&(grps->exts[0]), LY_STMT_GROUPING); - lysp_node_free(&fctx, &grps->node); + lysp_node_free(UTEST_LYCTX, &grps->node); grps = NULL; /* min subelems */ data = ELEMENT_WRAPPER_START "" ELEMENT_WRAPPER_END; assert_int_equal(test_element_helper(state, data, &grp_meta, NULL, NULL), LY_SUCCESS); assert_string_equal(grps->name, "grp-name"); - lysp_node_free(&fctx, &grps->node); + lysp_node_free(UTEST_LYCTX, &grps->node); grps = NULL; } @@ -2564,7 +2558,7 @@ test_container_elem(void **state) assert_string_equal(parsed->notifs->name, "notf"); assert_string_equal(parsed->actions->name, "act"); TEST_1_CHECK_LYSP_EXT_INSTANCE(&(parsed->exts[0]), LY_STMT_CONTAINER); - lysp_node_free(&fctx, siblings); + lysp_node_free(UTEST_LYCTX, siblings); ly_set_erase(&YCTX->tpdfs_nodes, NULL); siblings = NULL; @@ -2574,7 +2568,7 @@ test_container_elem(void **state) parsed = (struct lysp_node_container *)siblings; CHECK_LYSP_NODE(parsed, NULL, 0, 0, 0, "cont-name", 0, LYS_CONTAINER, 0, NULL, 0); - lysp_node_free(&fctx, siblings); + lysp_node_free(UTEST_LYCTX, siblings); siblings = NULL; } @@ -2632,7 +2626,7 @@ test_case_elem(void **state) assert_int_equal(parsed->child->next->next->next->next->next->next->next->nodetype, LYS_CHOICE); assert_null(parsed->child->next->next->next->next->next->next->next->next); TEST_1_CHECK_LYSP_EXT_INSTANCE(&(parsed->exts[0]), LY_STMT_CASE); - lysp_node_free(&fctx, siblings); + lysp_node_free(UTEST_LYCTX, siblings); siblings = NULL; /* min subelems */ @@ -2641,7 +2635,7 @@ test_case_elem(void **state) parsed = (struct lysp_node_case *)siblings; CHECK_LYSP_NODE(parsed, NULL, 0, 0, 0, "case-name", 0, LYS_CASE, 0, NULL, 0); - lysp_node_free(&fctx, siblings); + lysp_node_free(UTEST_LYCTX, siblings); siblings = NULL; } @@ -2702,7 +2696,7 @@ test_choice_elem(void **state) assert_int_equal(parsed->child->next->next->next->next->next->next->next->nodetype, LYS_LIST); assert_null(parsed->child->next->next->next->next->next->next->next->next); TEST_1_CHECK_LYSP_EXT_INSTANCE(&(parsed->exts[0]), LY_STMT_CHOICE); - lysp_node_free(&fctx, siblings); + lysp_node_free(UTEST_LYCTX, siblings); siblings = NULL; /* min subelems */ @@ -2712,7 +2706,7 @@ test_choice_elem(void **state) assert_string_equal(parsed->name, "choice-name"); CHECK_LYSP_NODE(parsed, NULL, 0, 0, 0, "choice-name", 0, LYS_CHOICE, 0, NULL, 0); - lysp_node_free(&fctx, siblings); + lysp_node_free(UTEST_LYCTX, siblings); siblings = NULL; } @@ -2764,7 +2758,7 @@ test_inout_elem(void **state) assert_int_equal(inout.child->next->next->next->next->next->next->next->nodetype, LYS_USES); assert_null(inout.child->next->next->next->next->next->next->next->next); TEST_1_CHECK_LYSP_EXT_INSTANCE(&(inout.exts[0]), LY_STMT_INPUT); - lysp_node_free(&fctx, (struct lysp_node *)&inout); + lysp_node_free(UTEST_LYCTX, (struct lysp_node *)&inout); memset(&inout, 0, sizeof inout); /* max subelements */ @@ -2808,24 +2802,24 @@ test_inout_elem(void **state) assert_int_equal(inout.child->next->next->next->next->next->next->next->nodetype, LYS_USES); assert_null(inout.child->next->next->next->next->next->next->next->next); TEST_1_CHECK_LYSP_EXT_INSTANCE(&(inout.exts[0]), LY_STMT_OUTPUT); - lysp_node_free(&fctx, (struct lysp_node *)&inout); + lysp_node_free(UTEST_LYCTX, (struct lysp_node *)&inout); memset(&inout, 0, sizeof inout); /* min subelems */ data = ELEMENT_WRAPPER_START "" ELEMENT_WRAPPER_END; assert_int_equal(test_element_helper(state, data, &inout_meta, NULL, NULL), LY_SUCCESS); - lysp_node_free(&fctx, (struct lysp_node *)&inout); + lysp_node_free(UTEST_LYCTX, (struct lysp_node *)&inout); memset(&inout, 0, sizeof inout); data = ELEMENT_WRAPPER_START "" ELEMENT_WRAPPER_END; assert_int_equal(test_element_helper(state, data, &inout_meta, NULL, NULL), LY_SUCCESS); - lysp_node_free(&fctx, (struct lysp_node *)&inout); + lysp_node_free(UTEST_LYCTX, (struct lysp_node *)&inout); memset(&inout, 0, sizeof inout); /* invalid combinations */ data = ELEMENT_WRAPPER_START "" ELEMENT_WRAPPER_END; assert_int_equal(test_element_helper(state, data, &inout_meta, NULL, NULL), LY_EVALID); - lysp_node_free(&fctx, (struct lysp_node *)&inout); + lysp_node_free(UTEST_LYCTX, (struct lysp_node *)&inout); CHECK_LOG_CTX("Unexpected attribute \"name\" of \"input\" element.", NULL, 1); memset(&inout, 0, sizeof inout); } @@ -2872,7 +2866,7 @@ test_action_elem(void **state) assert_string_equal(actions->output.musts->arg.str, "cond"); assert_string_equal(actions->input.child->name, "uses-name"); TEST_1_CHECK_LYSP_EXT_INSTANCE(&(actions->exts[0]), LY_STMT_ACTION); - lysp_node_free(&fctx, (struct lysp_node *)actions); + lysp_node_free(UTEST_LYCTX, (struct lysp_node *)actions); actions = NULL; PARSER_CUR_PMOD(YCTX)->version = LYS_VERSION_1_1; @@ -2905,14 +2899,14 @@ test_action_elem(void **state) assert_string_equal(actions->input.child->name, "uses-name"); assert_string_equal(actions->output.musts->arg.str, "cond"); TEST_1_CHECK_LYSP_EXT_INSTANCE(&(actions->exts[0]), LY_STMT_RPC); - lysp_node_free(&fctx, (struct lysp_node *)actions); + lysp_node_free(UTEST_LYCTX, (struct lysp_node *)actions); actions = NULL; /* min subelems */ data = ELEMENT_WRAPPER_START "" ELEMENT_WRAPPER_END; assert_int_equal(test_element_helper(state, data, &act_meta, NULL, NULL), LY_SUCCESS); assert_string_equal(actions->name, "act"); - lysp_node_free(&fctx, (struct lysp_node *)actions); + lysp_node_free(UTEST_LYCTX, (struct lysp_node *)actions); actions = NULL; } @@ -2976,13 +2970,13 @@ test_augment_elem(void **state) assert_string_equal(augments->actions->name, "action"); assert_string_equal(augments->notifs->name, "notif"); TEST_1_CHECK_LYSP_EXT_INSTANCE(&(augments->exts[0]), LY_STMT_AUGMENT); - lysp_node_free(&fctx, (struct lysp_node *)augments); + lysp_node_free(UTEST_LYCTX, (struct lysp_node *)augments); augments = NULL; data = ELEMENT_WRAPPER_START "" ELEMENT_WRAPPER_END; assert_int_equal(test_element_helper(state, data, &aug_meta, NULL, NULL), LY_SUCCESS); assert_string_equal(augments->nodeid, "target"); - lysp_node_free(&fctx, (struct lysp_node *)augments); + lysp_node_free(UTEST_LYCTX, (struct lysp_node *)augments); augments = NULL; } @@ -3044,15 +3038,13 @@ mod_renew(struct lysp_yin_ctx *ctx) struct ly_ctx *ly_ctx = PARSER_CUR_PMOD(ctx)->mod->ctx; struct lysp_module *pmod; - lys_module_free(&fctx, PARSER_CUR_PMOD(ctx)->mod, 0); + lys_module_free(ly_ctx, PARSER_CUR_PMOD(ctx)->mod, 0); pmod = calloc(1, sizeof *pmod); ctx->parsed_mods->objs[0] = pmod; pmod->mod = calloc(1, sizeof *pmod->mod); pmod->mod->parsed = pmod; pmod->mod->ctx = ly_ctx; - fctx.mod = pmod->mod; - return pmod; } @@ -3176,16 +3168,14 @@ submod_renew(struct lysp_yin_ctx *ctx, const char *belongs_to) struct ly_ctx *ly_ctx = PARSER_CUR_PMOD(ctx)->mod->ctx; struct lysp_submodule *submod; - lys_module_free(&fctx, PARSER_CUR_PMOD(ctx)->mod, 0); + lys_module_free(ly_ctx, PARSER_CUR_PMOD(ctx)->mod, 0); submod = calloc(1, sizeof *submod); ctx->parsed_mods->objs[0] = submod; submod->mod = calloc(1, sizeof *submod->mod); - lydict_insert(ly_ctx, belongs_to, 0, &submod->mod->name); + lysdict_insert(ly_ctx, belongs_to, 0, &submod->mod->name); submod->mod->parsed = (struct lysp_module *)submod; submod->mod->ctx = ly_ctx; - fctx.mod = submod->mod; - return submod; } @@ -3339,7 +3329,7 @@ test_yin_parse_module(void **state) assert_int_equal(yin_parse_module(&yin_ctx, in, mod), LY_SUCCESS); assert_null(mod->parsed->exts->child->next->child); assert_string_equal(mod->parsed->exts->child->next->arg, "test"); - lys_module_free(&fctx, mod, 0); + lys_module_free(UTEST_LYCTX, mod, 0); lysp_yin_ctx_free(yin_ctx); ly_in_free(in, 0); mod = NULL; @@ -3377,7 +3367,7 @@ test_yin_parse_module(void **state) "\n"; assert_int_equal(ly_in_new_memory(data, &in), LY_SUCCESS); assert_int_equal(yin_parse_module(&yin_ctx, in, mod), LY_SUCCESS); - lys_module_free(&fctx, mod, 0); + lys_module_free(UTEST_LYCTX, mod, 0); lysp_yin_ctx_free(yin_ctx); ly_in_free(in, 0); mod = NULL; @@ -3392,7 +3382,7 @@ test_yin_parse_module(void **state) "\n"; assert_int_equal(ly_in_new_memory(data, &in), LY_SUCCESS); assert_int_equal(yin_parse_module(&yin_ctx, in, mod), LY_SUCCESS); - lys_module_free(&fctx, mod, 0); + lys_module_free(UTEST_LYCTX, mod, 0); lysp_yin_ctx_free(yin_ctx); ly_in_free(in, 0); mod = NULL; @@ -3405,7 +3395,7 @@ test_yin_parse_module(void **state) assert_int_equal(ly_in_new_memory(data, &in), LY_SUCCESS); assert_int_equal(yin_parse_module(&yin_ctx, in, mod), LY_EINVAL); CHECK_LOG_CTX("Input data contains submodule which cannot be parsed directly without its main module.", NULL, 0); - lys_module_free(&fctx, mod, 0); + lys_module_free(UTEST_LYCTX, mod, 0); lysp_yin_ctx_free(yin_ctx); ly_in_free(in, 0); @@ -3420,7 +3410,7 @@ test_yin_parse_module(void **state) assert_int_equal(ly_in_new_memory(data, &in), LY_SUCCESS); assert_int_equal(yin_parse_module(&yin_ctx, in, mod), LY_EVALID); CHECK_LOG_CTX("Trailing garbage \"\" after module, expected end-of-input.", NULL, 6); - lys_module_free(&fctx, mod, 0); + lys_module_free(UTEST_LYCTX, mod, 0); lysp_yin_ctx_free(yin_ctx); ly_in_free(in, 0); mod = NULL; @@ -3435,7 +3425,7 @@ test_yin_parse_submodule(void **state) struct lysp_submodule *submod = NULL; struct ly_in *in; - lydict_insert(UTEST_LYCTX, "a", 0, &PARSER_CUR_PMOD(YCTX)->mod->name); + lysdict_insert(UTEST_LYCTX, "a", 0, &PARSER_CUR_PMOD(YCTX)->mod->name); data = "\n" ""; assert_int_equal(ly_in_new_memory(data, &in), LY_SUCCESS); assert_int_equal(yin_parse_submodule(&yin_ctx, UTEST_LYCTX, (struct lysp_ctx *)YCTX, in, &submod), LY_SUCCESS); - lysp_module_free(&fctx, (struct lysp_module *)submod); + lysp_module_free(UTEST_LYCTX, (struct lysp_module *)submod); lysp_yin_ctx_free(yin_ctx); ly_in_free(in, 0); yin_ctx = NULL; @@ -3478,7 +3468,7 @@ test_yin_parse_submodule(void **state) ""; assert_int_equal(ly_in_new_memory(data, &in), LY_SUCCESS); assert_int_equal(yin_parse_submodule(&yin_ctx, UTEST_LYCTX, (struct lysp_ctx *)YCTX, in, &submod), LY_SUCCESS); - lysp_module_free(&fctx, (struct lysp_module *)submod); + lysp_module_free(UTEST_LYCTX, (struct lysp_module *)submod); lysp_yin_ctx_free(yin_ctx); ly_in_free(in, 0); yin_ctx = NULL; @@ -3490,7 +3480,7 @@ test_yin_parse_submodule(void **state) assert_int_equal(ly_in_new_memory(data, &in), LY_SUCCESS); assert_int_equal(yin_parse_submodule(&yin_ctx, UTEST_LYCTX, (struct lysp_ctx *)YCTX, in, &submod), LY_EINVAL); CHECK_LOG_CTX("Input data contains module when a submodule is expected.", NULL, 0); - lysp_module_free(&fctx, (struct lysp_module *)submod); + lysp_module_free(UTEST_LYCTX, (struct lysp_module *)submod); lysp_yin_ctx_free(yin_ctx); ly_in_free(in, 0); yin_ctx = NULL; @@ -3512,7 +3502,7 @@ test_yin_parse_submodule(void **state) assert_int_equal(ly_in_new_memory(data, &in), LY_SUCCESS); assert_int_equal(yin_parse_submodule(&yin_ctx, UTEST_LYCTX, (struct lysp_ctx *)YCTX, in, &submod), LY_EVALID); CHECK_LOG_CTX("Trailing garbage \"compiled->data->next)->type; /* check proper type */ - assert_string_equal("libyang 2 - binary, version 1", type->id); + assert_string_equal("ly2 binary", type->id); /* check store XML double pad */ val = "YWhveQ=="; @@ -250,7 +250,7 @@ test_plugin_print(void **state) struct lyd_value value = {0}; struct lys_module *mod; struct lysc_type *lysc_type; - struct lyplg_type *type = lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_BINARY]); + struct lyplg_type *type = lysc_get_type_plugin(lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_BINARY])); struct ly_err_item *err = NULL; /* create schema. Prepare common used variables */ @@ -262,7 +262,7 @@ test_plugin_print(void **state) val = ""; assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, val, strlen(val), 0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &value, NULL, &err)); - assert_string_equal("", value.realtype->plugin->print(UTEST_LYCTX, &(value), LY_VALUE_CANON, NULL, NULL, NULL)); + assert_string_equal("", lysc_get_type_plugin(value.realtype->plugin_ref)->print(UTEST_LYCTX, &(value), LY_VALUE_CANON, NULL, NULL, NULL)); type->free(UTEST_LYCTX, &value); } @@ -273,7 +273,7 @@ test_plugin_duplicate(void **state) struct lyd_value value = {0}, dup; struct lys_module *mod; struct lysc_type *lysc_type; - struct lyplg_type *type = lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_BINARY]); + struct lyplg_type *type = lysc_get_type_plugin(lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_BINARY])); struct ly_err_item *err = NULL; /* create schema. Prepare common used variables */ @@ -298,7 +298,7 @@ test_plugin_sort(void **state) const char *schema; struct lys_module *mod; struct lyd_value val1 = {0}, val2 = {0}; - struct lyplg_type *type = lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_BINARY]); + struct lyplg_type *type = lysc_get_type_plugin(lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_BINARY])); struct lysc_type *lysc_type; struct ly_err_item *err = NULL; diff --git a/tests/utests/types/bits.c b/tests/utests/types/bits.c index 23614f0c3..1259c1678 100644 --- a/tests/utests/types/bits.c +++ b/tests/utests/types/bits.c @@ -800,7 +800,7 @@ test_plugin_store(void **state) struct ly_err_item *err = NULL; struct lys_module *mod; struct lyd_value value = {0}; - struct lyplg_type *type = lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_BITS]); + struct lyplg_type *type = lysc_get_type_plugin(lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_BITS])); struct lysc_type *lysc_type; struct lysc_type lysc_type_test; LY_ERR ly_ret; @@ -814,7 +814,7 @@ test_plugin_store(void **state) lysc_type = ((struct lysc_node_leaf *)mod->compiled->data)->type; /* check proper type */ - assert_string_equal("libyang 2 - bits, version 1", type->id); + assert_string_equal("ly2 bits", type->id); /* check store */ @@ -894,7 +894,7 @@ test_plugin_compare(void **state) struct ly_err_item *err = NULL; struct lys_module *mod; struct lyd_value values[10]; - struct lyplg_type *type = lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_BITS]); + struct lyplg_type *type = lysc_get_type_plugin(lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_BITS])); struct lysc_type *lysc_type; LY_ERR ly_ret; const char *schema; @@ -938,7 +938,7 @@ test_plugin_compare(void **state) */ diff_type_text = val_init[2]; diff_type = ((struct lysc_node_leaf *)mod->compiled->data->next)->type; - ly_ret = diff_type->plugin->store(UTEST_LYCTX, diff_type, diff_type_text, strlen(diff_type_text), + ly_ret = lysc_get_type_plugin(diff_type->plugin_ref)->store(UTEST_LYCTX, diff_type, diff_type_text, strlen(diff_type_text), 0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &diff_type_val, NULL, &err); assert_int_equal(LY_SUCCESS, ly_ret); assert_int_equal(LY_SUCCESS, type->compare(UTEST_LYCTX, &diff_type_val, &(values[2]))); @@ -956,7 +956,7 @@ test_plugin_sort(void **state) { const char *schema; struct lys_module *mod; - struct lyplg_type *type = lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_BITS]); + struct lyplg_type *type = lysc_get_type_plugin(lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_BITS])); struct lysc_type *lysc_type; struct ly_err_item *err = NULL; struct lyd_value val1 = {0}, val2 = {0}; @@ -993,7 +993,7 @@ test_plugin_print(void **state) struct ly_err_item *err = NULL; struct lys_module *mod; struct lyd_value values[10]; - struct lyplg_type *type = lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_BITS]); + struct lyplg_type *type = lysc_get_type_plugin(lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_BITS])); struct lysc_type *lysc_type; LY_ERR ly_ret; const char *schema; @@ -1035,7 +1035,7 @@ test_plugin_dup(void **state) struct ly_err_item *err = NULL; struct lys_module *mod; struct lyd_value values[10]; - struct lyplg_type *type = lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_BITS]); + struct lyplg_type *type = lysc_get_type_plugin(lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_BITS])); struct lysc_type *lysc_type; const char *schema; LY_ERR ly_ret; diff --git a/tests/utests/types/enumeration.c b/tests/utests/types/enumeration.c index 8ff1c8ca9..ba23765cd 100644 --- a/tests/utests/types/enumeration.c +++ b/tests/utests/types/enumeration.c @@ -94,7 +94,7 @@ test_plugin_sort(void **state) const char *schema; struct lys_module *mod; struct lyd_value val1 = {0}, val2 = {0}; - struct lyplg_type *type = lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_ENUM]); + struct lyplg_type *type = lysc_get_type_plugin(lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_ENUM])); struct lysc_type *lysc_type; struct ly_err_item *err = NULL; diff --git a/tests/utests/types/inet_types.c b/tests/utests/types/inet_types.c index 402cadea1..a97768226 100644 --- a/tests/utests/types/inet_types.c +++ b/tests/utests/types/inet_types.c @@ -196,7 +196,7 @@ test_plugin_sort(void **state) const char *schema; struct lys_module *mod; struct lyd_value val1 = {0}, val2 = {0}; - struct lyplg_type *type = lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_UNION]); + struct lyplg_type *type = lysc_get_type_plugin(lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_UNION])); struct lysc_type *lysc_type; struct ly_err_item *err = NULL; @@ -238,7 +238,7 @@ test_plugin_sort(void **state) /* ipv6-address */ lysc_type = ((struct lysc_node_leaflist *)mod->compiled->data->next)->type; - type = lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_STRING]); + type = lysc_get_type_plugin(lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_STRING])); v1 = "2008:15:0:0:0:0:feAC:1"; assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v1, strlen(v1), @@ -266,7 +266,7 @@ test_plugin_sort(void **state) /* ipv4-address-no-zone */ lysc_type = ((struct lysc_node_leaflist *)mod->compiled->data->next->next)->type; - type = lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_UNION]); + type = lysc_get_type_plugin(lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_UNION])); v1 = "127.0.0.1"; assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v1, strlen(v1), 0, LY_VALUE_JSON, NULL, LYD_VALHINT_STRING, NULL, &val1, NULL, &err)); @@ -281,7 +281,7 @@ test_plugin_sort(void **state) /* ipv6-address-no-zone */ lysc_type = ((struct lysc_node_leaflist *)mod->compiled->data->next->next->next)->type; - type = lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_STRING]); + type = lysc_get_type_plugin(lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_STRING])); v1 = "A:B:c:D:e:f:1:1"; assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v1, strlen(v1), 0, LY_VALUE_JSON, NULL, LYD_VALHINT_STRING, NULL, &val1, NULL, &err)); diff --git a/tests/utests/types/int8.c b/tests/utests/types/int8.c index dff29efbe..48fe8f3a3 100644 --- a/tests/utests/types/int8.c +++ b/tests/utests/types/int8.c @@ -421,7 +421,7 @@ test_schema_yang(void **state) lysc_leaf = (void *)mod->compiled->data; CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x205, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, 1); CHECK_LYSC_TYPE_NUM((struct lysc_type_num *)lysc_leaf->type, LY_TYPE_INT8, 0, 1); - CHECK_LYD_VALUE(*(lysc_leaf->dflt), INT8, "20", 20); + assert_string_equal(lysc_leaf->dflt.str, "20"); range = ((struct lysc_type_num *)lysc_leaf->type)->range; CHECK_LYSC_RANGE(range, NULL, NULL, NULL, 0, 2, NULL); assert_int_equal(range->parts[0].min_64, 0); @@ -441,7 +441,7 @@ test_schema_yang(void **state) lysc_leaf = (void *)mod->compiled->data; CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x205, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, 1); CHECK_LYSC_TYPE_NUM((struct lysc_type_num *)lysc_leaf->type, LY_TYPE_INT8, 0, 1); - CHECK_LYD_VALUE(*(lysc_leaf->dflt), INT8, "127", 127); + assert_string_equal(lysc_leaf->dflt.str, "127"); range = ((struct lysc_type_num *)lysc_leaf->type)->range; CHECK_LYSC_RANGE(range, NULL, NULL, NULL, 0, 2, NULL); assert_int_equal(range->parts[0].min_64, 0); @@ -502,7 +502,7 @@ test_schema_yang(void **state) lysc_leaf = (void *)mod->compiled->data; CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x205, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, 1); CHECK_LYSC_TYPE_NUM((struct lysc_type_num *)lysc_leaf->type, LY_TYPE_INT8, 0, 0); - CHECK_LYD_VALUE(*(lysc_leaf->dflt), INT8, "15", 15); + assert_string_equal(lysc_leaf->dflt.str, "0xf"); lysp_leaf = (void *)mod->parsed->data; CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, "0xf"); CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x0, 0, 0, "int8", 0, 0, 1, 0, 0, 0); @@ -518,7 +518,7 @@ test_schema_yang(void **state) lysc_leaf = (void *)mod->compiled->data; CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x205, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, 1); CHECK_LYSC_TYPE_NUM((struct lysc_type_num *)lysc_leaf->type, LY_TYPE_INT8, 0, 0); - CHECK_LYD_VALUE(*(lysc_leaf->dflt), INT8, "-15", -15); + assert_string_equal(lysc_leaf->dflt.str, "-0xf"); lysp_leaf = (void *)mod->parsed->data; CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, "-0xf"); CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x0, 0, 0, "int8", 0, 0, 1, 0, 0, 0); @@ -534,7 +534,7 @@ test_schema_yang(void **state) lysc_leaf = (void *)mod->compiled->data; CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x205, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, 1); CHECK_LYSC_TYPE_NUM((struct lysc_type_num *)lysc_leaf->type, LY_TYPE_INT8, 0, 1); - CHECK_LYD_VALUE(*(lysc_leaf->dflt), INT8, "127", 127); + assert_string_equal(lysc_leaf->dflt.str, "+0x7F"); range = ((struct lysc_type_num *)lysc_leaf->type)->range; CHECK_LYSC_RANGE(range, NULL, NULL, NULL, 0, 2, NULL); assert_int_equal(range->parts[0].min_64, 0); @@ -587,7 +587,7 @@ test_schema_yang(void **state) lysc_leaf = (void *)mod->compiled->data; CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x205, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, 1); CHECK_LYSC_TYPE_NUM((struct lysc_type_num *)lysc_leaf->type, LY_TYPE_INT8, 0, 0); - CHECK_LYD_VALUE(*(lysc_leaf->dflt), INT8, "15", 15); + assert_string_equal(lysc_leaf->dflt.str, "017"); lysp_leaf = (void *)mod->parsed->data; CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, "017"); CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x0, 0, 0, "int8", 0, 0, 1, 0, 0, 0); @@ -603,7 +603,7 @@ test_schema_yang(void **state) lysc_leaf = (void *)mod->compiled->data; CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x205, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, 1); CHECK_LYSC_TYPE_NUM((struct lysc_type_num *)lysc_leaf->type, LY_TYPE_INT8, 0, 0); - CHECK_LYD_VALUE(*(lysc_leaf->dflt), INT8, "-15", -15); + assert_string_equal(lysc_leaf->dflt.str, "-017"); lysp_leaf = (void *)mod->parsed->data; CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, "-017"); CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x0, 0, 0, "int8", 0, 0, 1, 0, 0, 0); @@ -619,7 +619,7 @@ test_schema_yang(void **state) lysc_leaf = (void *)mod->compiled->data; CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x205, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, 1); CHECK_LYSC_TYPE_NUM((struct lysc_type_num *)lysc_leaf->type, LY_TYPE_INT8, 0, 0); - CHECK_LYD_VALUE(*(lysc_leaf->dflt), INT8, "15", 15); + assert_string_equal(lysc_leaf->dflt.str, "+017"); lysp_leaf = (void *)mod->parsed->data; CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, "+017"); CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x0, 0, 0, "int8", 0, 0, 1, 0, 0, 0); @@ -842,7 +842,7 @@ test_schema_yin(void **state) lysc_leaf = (void *)mod->compiled->data; CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x205, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, 1); CHECK_LYSC_TYPE_NUM((struct lysc_type_num *)lysc_leaf->type, LY_TYPE_INT8, 0, 1); - CHECK_LYD_VALUE(*(lysc_leaf->dflt), INT8, "12", 12); + assert_string_equal(lysc_leaf->dflt.str, "12"); range = ((struct lysc_type_num *)lysc_leaf->type)->range; CHECK_LYSC_RANGE(range, NULL, NULL, NULL, 0, 2, NULL); assert_int_equal(range->parts[0].min_64, -128); @@ -899,7 +899,7 @@ test_schema_yin(void **state) lysc_leaf = (void *)mod->compiled->data; CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x205, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, 1); CHECK_LYSC_TYPE_NUM((struct lysc_type_num *)lysc_leaf->type, LY_TYPE_INT8, 0, 0); - CHECK_LYD_VALUE(*(lysc_leaf->dflt), INT8, "15", 15); + assert_string_equal(lysc_leaf->dflt.str, "+0xf"); lysp_leaf = (void *)mod->parsed->data; CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, "+0xf"); CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x0, 0, 0, "int8", 0, 0, 1, 0, 0, 0); @@ -915,7 +915,7 @@ test_schema_yin(void **state) lysc_leaf = (void *)mod->compiled->data; CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x205, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, 1); CHECK_LYSC_TYPE_NUM((struct lysc_type_num *)lysc_leaf->type, LY_TYPE_INT8, 0, 0); - CHECK_LYD_VALUE(*(lysc_leaf->dflt), INT8, "-15", -15); + assert_string_equal(lysc_leaf->dflt.str, "-0xf"); lysp_leaf = (void *)mod->parsed->data; CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, "-0xf"); CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x0, 0, 0, "int8", 0, 0, 1, 0, 0, 0); @@ -961,7 +961,7 @@ test_schema_yin(void **state) lysc_leaf = (void *)mod->compiled->data; CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x205, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, 1); CHECK_LYSC_TYPE_NUM((struct lysc_type_num *)lysc_leaf->type, LY_TYPE_INT8, 0, 0); - CHECK_LYD_VALUE(*(lysc_leaf->dflt), INT8, "15", 15); + assert_string_equal(lysc_leaf->dflt.str, "+017"); lysp_leaf = (void *)mod->parsed->data; CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, "+017"); CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x0, 0, 0, "int8", 0, 0, 1, 0, 0, 0); @@ -977,7 +977,7 @@ test_schema_yin(void **state) lysc_leaf = (void *)mod->compiled->data; CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x205, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, 1); CHECK_LYSC_TYPE_NUM((struct lysc_type_num *)lysc_leaf->type, LY_TYPE_INT8, 0, 0); - CHECK_LYD_VALUE(*(lysc_leaf->dflt), INT8, "-15", -15); + assert_string_equal(lysc_leaf->dflt.str, "-017"); lysp_leaf = (void *)mod->parsed->data; CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, "-017"); CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x0, 0, 0, "int8", 0, 0, 1, 0, 0, 0); @@ -1399,7 +1399,7 @@ test_plugin_store(void **state) struct ly_err_item *err = NULL; struct lys_module *mod; struct lyd_value value = {0}; - struct lyplg_type *type = lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_INT8]); + struct lyplg_type *type = lysc_get_type_plugin(lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_INT8])); struct lysc_type *lysc_type; LY_ERR ly_ret; char *alloc; @@ -1412,7 +1412,7 @@ test_plugin_store(void **state) lysc_type = ((struct lysc_node_leaf *)mod->compiled->data)->type; /* check proper type */ - assert_string_equal("libyang 2 - integers, version 1", type->id); + assert_string_equal("ly2 integers", type->id); /* check store * options = LY_TYPE_STORE_IMPLEMENT | LY_TYPE_STORE_DYNAMIC @@ -1546,7 +1546,7 @@ test_plugin_compare(void **state) struct ly_err_item *err = NULL; struct lys_module *mod; struct lyd_value values[10]; - struct lyplg_type *type = lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_INT8]); + struct lyplg_type *type = lysc_get_type_plugin(lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_INT8])); struct lysc_type *lysc_type; LY_ERR ly_ret; const char *schema; @@ -1588,7 +1588,7 @@ test_plugin_compare(void **state) */ diff_type_text = "20"; diff_type = ((struct lysc_node_leaf *)mod->compiled->data->next)->type; - ly_ret = diff_type->plugin->store(UTEST_LYCTX, diff_type, diff_type_text, strlen(diff_type_text), + ly_ret = lysc_get_type_plugin(diff_type->plugin_ref)->store(UTEST_LYCTX, diff_type, diff_type_text, strlen(diff_type_text), 0, LY_VALUE_XML, NULL, LYD_VALHINT_DECNUM, NULL, &diff_type_val, NULL, &err); assert_int_equal(LY_SUCCESS, ly_ret); assert_int_equal(LY_SUCCESS, type->compare(UTEST_LYCTX, &diff_type_val, &(values[0]))); @@ -1600,7 +1600,7 @@ test_plugin_compare(void **state) */ diff_type_text = "20"; diff_type = ((struct lysc_node_leaf *)mod->compiled->data->next->next)->type; - ly_ret = diff_type->plugin->store(UTEST_LYCTX, diff_type, diff_type_text, strlen(diff_type_text), + ly_ret = lysc_get_type_plugin(diff_type->plugin_ref)->store(UTEST_LYCTX, diff_type, diff_type_text, strlen(diff_type_text), 0, LY_VALUE_XML, NULL, LYD_VALHINT_DECNUM, NULL, &diff_type_val, NULL, &err); assert_int_equal(LY_SUCCESS, ly_ret); assert_int_equal(LY_ENOT, type->compare(UTEST_LYCTX, &diff_type_val, &(values[0]))); @@ -1612,7 +1612,7 @@ test_plugin_compare(void **state) */ diff_type_text = "20"; diff_type = ((struct lysc_node_leaf *)mod->compiled->data->next->next->next)->type; - ly_ret = diff_type->plugin->store(UTEST_LYCTX, diff_type, diff_type_text, strlen(diff_type_text), + ly_ret = lysc_get_type_plugin(diff_type->plugin_ref)->store(UTEST_LYCTX, diff_type, diff_type_text, strlen(diff_type_text), 0, LY_VALUE_XML, NULL, LYD_VALHINT_DECNUM, NULL, &diff_type_val, NULL, &err); assert_int_equal(LY_SUCCESS, ly_ret); assert_int_equal(LY_ENOT, type->compare(UTEST_LYCTX, &diff_type_val, &(values[0]))); @@ -1631,7 +1631,7 @@ test_plugin_print(void **state) struct ly_err_item *err = NULL; struct lys_module *mod; struct lyd_value values[10]; - struct lyplg_type *type = lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_INT8]); + struct lyplg_type *type = lysc_get_type_plugin(lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_INT8])); struct lysc_type *lysc_type; LY_ERR ly_ret; const char *schema; @@ -1671,7 +1671,7 @@ test_plugin_dup(void **state) struct ly_err_item *err = NULL; struct lys_module *mod; struct lyd_value values[10]; - struct lyplg_type *type = lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_INT8]); + struct lyplg_type *type = lysc_get_type_plugin(lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_INT8])); struct lysc_type *lysc_type[2]; const char *schema; LY_ERR ly_ret; diff --git a/tests/utests/types/leafref.c b/tests/utests/types/leafref.c index 32e29a26a..6e68d36a7 100644 --- a/tests/utests/types/leafref.c +++ b/tests/utests/types/leafref.c @@ -216,7 +216,7 @@ test_plugin_sort(void **state) const char *schema; struct lys_module *mod; struct lyd_value val1 = {0}, val2 = {0}; - struct lyplg_type *type = lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_LEAFREF]); + struct lyplg_type *type = lysc_get_type_plugin(lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_LEAFREF])); struct lysc_type *lysc_type; struct ly_err_item *err = NULL; diff --git a/tests/utests/types/string.c b/tests/utests/types/string.c index 2f002b73a..56ff396ac 100644 --- a/tests/utests/types/string.c +++ b/tests/utests/types/string.c @@ -1060,7 +1060,7 @@ test_plugin_store(void **state) struct ly_err_item *err = NULL; struct lys_module *mod; struct lyd_value value = {0}; - struct lyplg_type *type = lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_STRING]); + struct lyplg_type *type = lysc_get_type_plugin(lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_STRING])); struct lysc_type *lysc_type; char *alloc_text; unsigned int alloc_text_size; @@ -1073,7 +1073,7 @@ test_plugin_store(void **state) lysc_type = ((struct lysc_node_leaf *) mod->compiled->data)->type; /* check proper type */ - assert_string_equal("libyang 2 - string, version 1", type->id); + assert_string_equal("ly2 string", type->id); /* check store */ val_text = "20"; @@ -1201,7 +1201,7 @@ test_plugin_compare(void **state) struct ly_err_item *err = NULL; struct lys_module *mod; struct lyd_value values[10]; - struct lyplg_type *type = lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_STRING]); + struct lyplg_type *type = lysc_get_type_plugin(lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_STRING])); struct lysc_type *lysc_type; LY_ERR ly_ret; const char *schema; @@ -1240,7 +1240,7 @@ test_plugin_compare(void **state) /* SAME TYPE but different node */ diff_type_text = "hi"; diff_type = ((struct lysc_node_leaf *) mod->compiled->data->next)->type; - ly_ret = diff_type->plugin->store(UTEST_LYCTX, diff_type, diff_type_text, strlen(diff_type_text), + ly_ret = lysc_get_type_plugin(diff_type->plugin_ref)->store(UTEST_LYCTX, diff_type, diff_type_text, strlen(diff_type_text), 0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &diff_type_val, NULL, &err); assert_int_equal(LY_SUCCESS, ly_ret); assert_int_equal(LY_SUCCESS, type->compare(UTEST_LYCTX, &diff_type_val, &(values[0]))); @@ -1259,7 +1259,7 @@ test_plugin_print(void **state) struct ly_err_item *err = NULL; struct lys_module *mod; struct lyd_value values[10]; - struct lyplg_type *type = lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_STRING]); + struct lyplg_type *type = lysc_get_type_plugin(lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_STRING])); struct lysc_type *lysc_type; LY_ERR ly_ret; @@ -1298,7 +1298,7 @@ test_plugin_dup(void **state) struct ly_err_item *err = NULL; struct lys_module *mod; struct lyd_value values[10]; - struct lyplg_type *type = lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_STRING]); + struct lyplg_type *type = lysc_get_type_plugin(lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_STRING])); struct lysc_type *lysc_type[2]; const char *schema; LY_ERR ly_ret; diff --git a/tests/utests/types/union.c b/tests/utests/types/union.c index 257776b11..d06774421 100644 --- a/tests/utests/types/union.c +++ b/tests/utests/types/union.c @@ -105,11 +105,11 @@ test_data_xml(void **state) TEST_ERROR_XML2("", "defs", "", "un1", "123456789012345678901", LY_EVALID); CHECK_LOG_CTX("Invalid union value \"123456789012345678901\" - no matching subtype found:\n" - " libyang 2 - leafref, version 1: Invalid leafref value \"123456789012345678901\" - no target instance \"/int8\" with the same value.\n" - " libyang 2 - leafref, version 1: Invalid leafref value \"123456789012345678901\" - no target instance \"/int64\" with the same value.\n" - " libyang 2 - identityref, version 1: Invalid identityref \"123456789012345678901\" value - identity not found in module \"defs\".\n" - " libyang 2 - instance-identifier, version 1: Invalid instance-identifier \"123456789012345678901\" value - syntax error.\n" - " libyang 2 - string, version 1: Unsatisfied length - string \"123456789012345678901\" length is not allowed.\n", + " ly2 leafref: Invalid leafref value \"123456789012345678901\" - no target instance \"/int8\" with the same value.\n" + " ly2 leafref: Invalid leafref value \"123456789012345678901\" - no target instance \"/int64\" with the same value.\n" + " ly2 identityref: Invalid identityref \"123456789012345678901\" value - identity not found in module \"defs\".\n" + " ly2 instance-identifier: Invalid instance-identifier \"123456789012345678901\" value - syntax error.\n" + " ly2 string: Unsatisfied length - string \"123456789012345678901\" length is not allowed.\n", "/defs:un1", 1); } @@ -154,7 +154,7 @@ test_plugin_sort(void **state) const char *schema; struct lys_module *mod; struct lyd_value val1 = {0}, val2 = {0}; - struct lyplg_type *type = lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_UNION]); + struct lyplg_type *type = lysc_get_type_plugin(lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_UNION])); struct lysc_type *lysc_type; struct ly_err_item *err = NULL; @@ -294,8 +294,8 @@ test_validation(void **state) assert_int_equal(LY_SUCCESS, lyd_new_list(tree, NULL, "b", LYD_NEW_VAL_BIN, NULL, &uint_val, sizeof uint_val)); assert_int_equal(LY_EVALID, lyd_validate_all(&tree, NULL, LYD_VALIDATE_PRESENT, NULL)); CHECK_LOG_CTX("Invalid LYB union value - no matching subtype found:\n" - " libyang 2 - leafref, version 1: Invalid leafref value \"one\" - no target instance \"../../a/name\" with the same value.\n" - " libyang 2 - leafref, version 1: Invalid leafref value \"one\" - no target instance \"../../b/name\" with the same value.\n", + " ly2 leafref: Invalid leafref value \"one\" - no target instance \"../../a/name\" with the same value.\n" + " ly2 leafref: Invalid leafref value \"one\" - no target instance \"../../b/name\" with the same value.\n", "/lref:test/community[name='test']/view", 0); lyd_free_all(tree); diff --git a/tests/utests/types/yang_types.c b/tests/utests/types/yang_types.c index 07c5e162b..c5cf8d7c9 100644 --- a/tests/utests/types/yang_types.c +++ b/tests/utests/types/yang_types.c @@ -234,7 +234,7 @@ test_sort(void **state) const char *schema; struct lys_module *mod; struct lyd_value val1 = {0}, val2 = {0}; - struct lyplg_type *type = lyplg_type_plugin_find(NULL, "ietf-yang-types", "2013-07-15", "date-and-time"); + struct lyplg_type *type = lysc_get_type_plugin(lyplg_type_plugin_find(NULL, "ietf-yang-types", "2013-07-15", "date-and-time")); struct lysc_type *lysc_type; struct ly_err_item *err = NULL; diff --git a/tests/utests/utests.h b/tests/utests/utests.h index 3e1844f02..8449b3e07 100644 --- a/tests/utests/utests.h +++ b/tests/utests/utests.h @@ -5,7 +5,7 @@ * @author Michal Vasko * @brief this file contains macros for simplification test writing * - * Copyright (c) 2021 - 2022 CESNET, z.s.p.o. + * Copyright (c) 2021 - 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. @@ -17,7 +17,7 @@ #ifndef _UTESTS_H_ #define _UTESTS_H_ -#define _POSIX_C_SOURCE 200809L /* strdup */ +#define _GNU_SOURCE /* strdup, setenv, tzset */ #include #include @@ -232,7 +232,7 @@ struct utest_context { assert_non_null(NODE); \ assert_int_equal((NODE)->basetype, TYPE); \ CHECK_ARRAY((NODE)->exts, EXTS); \ - assert_ptr_equal((NODE)->plugin, lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[TYPE])) + assert_ptr_equal((NODE)->plugin_ref, lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[TYPE])) /** * @brief check compileted numeric type @@ -315,7 +315,6 @@ struct utest_context { */ #define CHECK_LYSC_PATTERN(NODE, DSC, EAPPTAG, EMSG, EXPR, EXTS, INVERTED, REF) \ assert_non_null(NODE); \ - assert_non_null((NODE)->code); \ CHECK_STRING((NODE)->dsc, DSC); \ CHECK_STRING((NODE)->eapptag, EAPPTAG); \ CHECK_STRING((NODE)->emsg, EMSG); \ @@ -801,7 +800,7 @@ struct utest_context { CHECK_ARRAY((NODE)->musts, MUSTS); \ assert_non_null((NODE)->type); \ CHECK_STRING((NODE)->units, UNITS); \ - CHECK_POINTER((NODE)->dflt, DFLT); + CHECK_POINTER((NODE)->dflt.str, DFLT); /** * @brief assert that lyd_meta structure members are correct @@ -936,7 +935,7 @@ struct utest_context { * @param[in] CANNONICAL_VAL expected cannonical value */ #define CHECK_LYD_VALUE_EMPTY(NODE, CANNONICAL_VAL) \ - assert_non_null((NODE).realtype->plugin->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ + assert_non_null(lyd_value_get_canonical(UTEST_LYCTX, &(NODE))); \ assert_string_equal((NODE)._canonical, CANNONICAL_VAL); \ assert_non_null((NODE).realtype); \ assert_int_equal((NODE).realtype->basetype, LY_TYPE_EMPTY); @@ -954,7 +953,7 @@ struct utest_context { * CHECK_LYD_VALUE_ ## TYPE_VAL. */ #define CHECK_LYD_VALUE_UNION(NODE, CANNONICAL_VAL, TYPE_VAL, ...) \ - assert_non_null((NODE).realtype->plugin->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ + assert_non_null(lyd_value_get_canonical(UTEST_LYCTX, &(NODE))); \ assert_string_equal((NODE)._canonical, CANNONICAL_VAL); \ assert_non_null((NODE).realtype); \ assert_int_equal(LY_TYPE_UNION, (NODE).realtype->basetype); \ @@ -976,7 +975,7 @@ struct utest_context { * @param[in] VALUE expected array of bits names */ #define CHECK_LYD_VALUE_BITS(NODE, ...) \ - assert_non_null((NODE).realtype->plugin->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ + assert_non_null(lyd_value_get_canonical(UTEST_LYCTX, &(NODE))); \ assert_string_equal((NODE)._canonical, _GETARG1(__VA_ARGS__, DUMMY)); \ assert_non_null((NODE).realtype); \ assert_int_equal(LY_TYPE_BITS, (NODE).realtype->basetype); \ @@ -1000,7 +999,7 @@ struct utest_context { * @brief Example enum arr[] = {0x0, 0x1}; CHECK_LYD_VALUE(node->value, INST, "test/d", arr); */ #define CHECK_LYD_VALUE_INST(NODE, CANNONICAL_VAL, VALUE) \ - assert_non_null((NODE).realtype->plugin->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ + assert_non_null(lyd_value_get_canonical(UTEST_LYCTX, &(NODE))); \ assert_string_equal((NODE)._canonical, CANNONICAL_VAL); \ assert_non_null((NODE).realtype); \ assert_int_equal(LY_TYPE_INST, (NODE).realtype->basetype); \ @@ -1023,7 +1022,7 @@ struct utest_context { * @param[in] VALUE expected enum item name */ #define CHECK_LYD_VALUE_ENUM(NODE, CANNONICAL_VAL, VALUE) \ - assert_non_null((NODE).realtype->plugin->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ + assert_non_null(lyd_value_get_canonical(UTEST_LYCTX, &(NODE))); \ assert_string_equal((NODE)._canonical, CANNONICAL_VAL); \ assert_non_null((NODE).realtype); \ assert_int_equal(LY_TYPE_ENUM, (NODE).realtype->basetype); \ @@ -1038,7 +1037,7 @@ struct utest_context { * @param[in] VALUE expected inteager value (-128 to 127). */ #define CHECK_LYD_VALUE_INT8(NODE, CANNONICAL_VAL, VALUE) \ - assert_non_null((NODE).realtype->plugin->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ + assert_non_null(lyd_value_get_canonical(UTEST_LYCTX, &(NODE))); \ assert_string_equal((NODE)._canonical, CANNONICAL_VAL); \ assert_non_null((NODE).realtype); \ assert_int_equal(LY_TYPE_INT8, (NODE).realtype->basetype); \ @@ -1053,7 +1052,7 @@ struct utest_context { * @param[in] VALUE expected inteager value. */ #define CHECK_LYD_VALUE_INT16(NODE, CANNONICAL_VAL, VALUE) \ - assert_non_null((NODE).realtype->plugin->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ + assert_non_null(lyd_value_get_canonical(UTEST_LYCTX, &(NODE))); \ assert_string_equal((NODE)._canonical, CANNONICAL_VAL); \ assert_non_null((NODE).realtype); \ assert_int_equal(LY_TYPE_INT16, (NODE).realtype->basetype); \ @@ -1068,7 +1067,7 @@ struct utest_context { * @param[in] VALUE expected inteager (0 to 255). */ #define CHECK_LYD_VALUE_UINT8(NODE, CANNONICAL_VAL, VALUE) \ - assert_non_null((NODE).realtype->plugin->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ + assert_non_null(lyd_value_get_canonical(UTEST_LYCTX, &(NODE))); \ assert_string_equal((NODE)._canonical, CANNONICAL_VAL); \ assert_non_null((NODE).realtype); \ assert_int_equal(LY_TYPE_UINT8, (NODE).realtype->basetype); \ @@ -1083,7 +1082,7 @@ struct utest_context { * @param[in] VALUE expected inteager (0 to MAX_UINT32). */ #define CHECK_LYD_VALUE_UINT32(NODE, CANNONICAL_VAL, VALUE) \ - assert_non_null((NODE).realtype->plugin->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ + assert_non_null(lyd_value_get_canonical(UTEST_LYCTX, &(NODE))); \ assert_string_equal((NODE)._canonical, CANNONICAL_VAL); \ assert_non_null((NODE).realtype); \ assert_int_equal(LY_TYPE_UINT32, (NODE).realtype->basetype); \ @@ -1097,7 +1096,7 @@ struct utest_context { * @param[in] CANNONICAL_VAL expected cannonical value */ #define CHECK_LYD_VALUE_STRING(NODE, CANNONICAL_VAL) \ - assert_non_null((NODE).realtype->plugin->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ + assert_non_null(lyd_value_get_canonical(UTEST_LYCTX, &(NODE))); \ assert_string_equal((NODE)._canonical, CANNONICAL_VAL); \ assert_non_null((NODE).realtype); \ assert_int_equal(LY_TYPE_STRING, (NODE).realtype->basetype); @@ -1110,7 +1109,7 @@ struct utest_context { * @param[in] CANNONICAL_VAL expected cannonical value */ #define CHECK_LYD_VALUE_LEAFREF(NODE, CANNONICAL_VAL) \ - assert_non_null((NODE).realtype->plugin->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ + assert_non_null(lyd_value_get_canonical(UTEST_LYCTX, &(NODE))); \ assert_string_equal((NODE)._canonical, CANNONICAL_VAL); \ assert_non_null((NODE).realtype); \ assert_int_equal(LY_TYPE_LEAFREF, (NODE).realtype->basetype); \ @@ -1125,7 +1124,7 @@ struct utest_context { * @param[in] VALUE expected value 64bit inteager */ #define CHECK_LYD_VALUE_DEC64(NODE, CANNONICAL_VAL, VALUE) \ - assert_non_null((NODE).realtype->plugin->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ + assert_non_null(lyd_value_get_canonical(UTEST_LYCTX, &(NODE))); \ assert_string_equal((NODE)._canonical, CANNONICAL_VAL); \ assert_non_null((NODE).realtype); \ assert_int_equal(LY_TYPE_DEC64, (NODE).realtype->basetype); \ @@ -1146,7 +1145,7 @@ struct utest_context { LYD_VALUE_GET(&(NODE), _val); \ assert_int_equal(_val->size, SIZE); \ assert_int_equal(0, memcmp(_val->data, VALUE, SIZE)); \ - assert_non_null((NODE).realtype->plugin->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ + assert_non_null(lyd_value_get_canonical(UTEST_LYCTX, &(NODE))); \ assert_string_equal((NODE)._canonical, CANNONICAL_VAL); \ assert_non_null((NODE).realtype); \ assert_int_equal(LY_TYPE_BINARY, (NODE).realtype->basetype); \ @@ -1161,7 +1160,7 @@ struct utest_context { * @param[in] VALUE expected boolean value 0,1 */ #define CHECK_LYD_VALUE_BOOL(NODE, CANNONICAL_VAL, VALUE) \ - assert_non_null((NODE).realtype->plugin->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ + assert_non_null(lyd_value_get_canonical(UTEST_LYCTX, &(NODE))); \ assert_string_equal((NODE)._canonical, CANNONICAL_VAL); \ assert_non_null((NODE).realtype); \ assert_int_equal(LY_TYPE_BOOL, (NODE).realtype->basetype); \ @@ -1176,7 +1175,7 @@ struct utest_context { * @param[in] VALUE expected ident name */ #define CHECK_LYD_VALUE_IDENT(NODE, CANNONICAL_VAL, VALUE) \ - assert_non_null((NODE).realtype->plugin->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ + assert_non_null(lyd_value_get_canonical(UTEST_LYCTX, &(NODE))); \ assert_string_equal((NODE)._canonical, CANNONICAL_VAL); \ assert_non_null((NODE).realtype); \ assert_int_equal(LY_TYPE_IDENT, (NODE).realtype->basetype); \ diff --git a/tools/lint/cmd_data.c b/tools/lint/cmd_data.c index 59cb5dcab..af7b33aa7 100644 --- a/tools/lint/cmd_data.c +++ b/tools/lint/cmd_data.c @@ -594,11 +594,11 @@ parse_input_by_type(struct ly_ctx *ctx, enum lyd_type type, struct cmdline_file case LYD_TYPE_RPC_YANG: case LYD_TYPE_REPLY_YANG: case LYD_TYPE_NOTIF_YANG: - ret = lyd_parse_op(ctx, NULL, input_f->in, input_f->format, type, tree, op); + ret = lyd_parse_op(ctx, NULL, input_f->in, input_f->format, type, LYD_PARSE_STRICT, tree, op); break; case LYD_TYPE_RPC_NETCONF: case LYD_TYPE_NOTIF_NETCONF: - ret = lyd_parse_op(ctx, NULL, input_f->in, input_f->format, type, &envp, op); + ret = lyd_parse_op(ctx, NULL, input_f->in, input_f->format, type, LYD_PARSE_STRICT, &envp, op); /* adjust pointers */ for (*tree = *op; lyd_parent(*tree); *tree = lyd_parent(*tree)) {} @@ -606,7 +606,8 @@ parse_input_by_type(struct ly_ctx *ctx, enum lyd_type type, struct cmdline_file case LYD_TYPE_REPLY_NETCONF: /* parse source RPC operation */ assert(reply_rpc && reply_rpc->in); - ret = lyd_parse_op(ctx, NULL, reply_rpc->in, reply_rpc->format, LYD_TYPE_RPC_NETCONF, &envp, op); + ret = lyd_parse_op(ctx, NULL, reply_rpc->in, reply_rpc->format, LYD_TYPE_RPC_NETCONF, LYD_PARSE_STRICT, + &envp, op); if (ret) { YLMSG_E("Failed to parse source NETCONF RPC operation file \"%s\".", reply_rpc->path); goto cleanup; @@ -622,7 +623,7 @@ parse_input_by_type(struct ly_ctx *ctx, enum lyd_type type, struct cmdline_file lyd_free_all(envp); envp = NULL; - ret = lyd_parse_op(ctx, *op, input_f->in, input_f->format, type, &envp, NULL); + ret = lyd_parse_op(ctx, *op, input_f->in, input_f->format, type, LYD_PARSE_STRICT, &envp, NULL); break; default: YLMSG_E("Internal error (%s:%d).", __FILE__, __LINE__); @@ -639,17 +640,20 @@ parse_input_by_type(struct ly_ctx *ctx, enum lyd_type type, struct cmdline_file * @brief Parses and validates data for a specific YANG extension instance. * * @param[in] ctx libyang context with schema. - * @param[in] yo context for yanglint. + * @param[in] yo Context for yanglint. * @param[in] input_f Data input file. - * @param[out] tree Extension data tree. - * @param[in] oper_tree operational data tree. + * @param[in] oper_tree Operational data tree. + * @param[out] tree Extension instance data tree. * @return LY_ERR value. */ static LY_ERR -parse_extension_instance(struct ly_ctx *ctx, struct yl_opt *yo, struct cmdline_file *input_f, struct lyd_node **tree, - struct lyd_node *oper_tree) +parse_ext_inst_data(struct ly_ctx *ctx, struct yl_opt *yo, struct cmdline_file *input_f, + struct lyd_node *oper_tree, struct lyd_node **tree) { LY_ERR ret = LY_SUCCESS; + struct ly_set tree_nodes = {0}; + struct lyd_node *iter; + uint32_t i; if (find_extension(ctx, yo)) { YLMSG_E("Extension '%s:%s:%s' not found in module.", yo->mod_name, yo->name, yo->argument); @@ -666,21 +670,31 @@ parse_extension_instance(struct ly_ctx *ctx, struct yl_opt *yo, struct cmdline_f return LY_EDENIED; } - if ((*tree)->next) { - YLMSG_E("Yanglint does not support more than one top-level node in extension data."); - return LY_EDENIED; - } - - /* operational data are present */ if (oper_tree) { - lyd_insert_sibling(*tree, oper_tree, &oper_tree); + /* remember data top-level nodes */ + LY_LIST_FOR(*tree, iter) { + ly_set_add(&tree_nodes, iter, 1, NULL); + } + + /* connect data with operational data for validation */ + lyd_insert_sibling(*tree, oper_tree, tree); ret = lyd_validate_all(tree, ctx, yo->data_validate_options, NULL); - lyd_unlink_tree(*tree); + + /* disconnect data and operational data */ + *tree = NULL; + for (i = 0; i < tree_nodes.count; ++i) { + iter = tree_nodes.dnodes[i]; + lyd_unlink_tree(iter); + lyd_insert_sibling(*tree, iter, tree); + } } else { + /* validate extension instance data */ ret = lyd_validate_all(tree, ctx, yo->data_validate_options, NULL); } yo->data_ext = 0; + + ly_set_erase(&tree_nodes, NULL); return ret; } @@ -706,7 +720,7 @@ cmd_data_process(struct ly_ctx *ctx, struct yl_opt *yo) struct cmdline_file *input_f = (struct cmdline_file *)yo->data_inputs.objs[u]; if (yo->data_ext) { - ret = parse_extension_instance(ctx, yo, input_f, &tree, oper_tree); + ret = parse_ext_inst_data(ctx, yo, input_f, oper_tree, &tree); } else { ret = parse_input_by_type(ctx, yo->data_type, input_f, yo->data_parse_options, yo->data_validate_options, &tree, &op, &yo->reply_rpc); diff --git a/tools/lint/common.c b/tools/lint/common.c index e2b2b0a22..b02486488 100644 --- a/tools/lint/common.c +++ b/tools/lint/common.c @@ -274,7 +274,8 @@ find_schema_path(const struct ly_ctx *ctx, const char *schema_path) } LY_ERR -ext_data_clb(const struct lysc_ext_instance *ext, void *user_data, void **ext_data, ly_bool *ext_data_free) +ext_data_clb(const struct lysc_ext_instance *ext, const struct lyd_node *UNUSED(parent), void *user_data, + void **ext_data, ly_bool *ext_data_free) { struct ly_ctx *ctx; struct lyd_node *data = NULL; diff --git a/tools/lint/common.h b/tools/lint/common.h index cd3bd1c28..9e909a3b0 100644 --- a/tools/lint/common.h +++ b/tools/lint/common.h @@ -122,12 +122,14 @@ const struct lysc_node *find_schema_path(const struct ly_ctx *ctx, const char *s * @brief General callback providing run-time extension instance data. * * @param[in] ext Compiled extension instance. + * @param[in] parent Data parent, unused. * @param[in] user_data User-supplied callback data. * @param[out] ext_data Provided extension instance data. * @param[out] ext_data_free Whether the extension instance should free @p ext_data or not. * @return LY_ERR value. */ -LY_ERR ext_data_clb(const struct lysc_ext_instance *ext, void *user_data, void **ext_data, ly_bool *ext_data_free); +LY_ERR ext_data_clb(const struct lysc_ext_instance *ext, const struct lyd_node *parent, void *user_data, + void **ext_data, ly_bool *ext_data_free); /** * @brief Concatenation of paths into one string.