From 271b0cf6714e7a1093e105c62d0274536f51ee19 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Mon, 21 Jul 2025 09:08:51 +0200 Subject: [PATCH 01/99] yanglint UPDATE top-level list of ext-inst data support Refs #2403 --- tools/lint/cmd_data.c | 41 +++++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/tools/lint/cmd_data.c b/tools/lint/cmd_data.c index 59cb5dcab..c935bde35 100644 --- a/tools/lint/cmd_data.c +++ b/tools/lint/cmd_data.c @@ -639,17 +639,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 +669,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 +719,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); From 7783869951e1494d6f4366892baebb32132c360d Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Mon, 21 Jul 2025 09:09:29 +0200 Subject: [PATCH 02/99] VERSION bump to version 3.13.3 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e8f774d46..aa9dc08bd 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 From 737ae716d39ed27c7b40c1862e7f4b1fe2f08c53 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Tue, 10 Sep 2024 15:06:55 +0200 Subject: [PATCH 03/99] tree schema UPDATE allow freeing parsed modules --- src/context.c | 103 +++++++++++++++++++++-------------------- src/context.h | 8 ++++ src/schema_compile.c | 29 ++++++++++++ src/tree_schema.c | 38 +++++++++++++-- src/tree_schema.h | 82 ++++++++++++++++++-------------- src/tree_schema_free.c | 12 ++++- 6 files changed, 181 insertions(+), 91 deletions(-) diff --git a/src/context.c b/src/context.c index 68a8ff21e..43c8f8d5d 100644 --- a/src/context.c +++ b/src/context.c @@ -765,8 +765,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 +782,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])); } } @@ -1120,32 +1120,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 +1153,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 +1161,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 +1214,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."); @@ -1248,16 +1232,12 @@ ly_ctx_get_yanglib_data(const struct ly_ctx *ctx, struct lyd_node **root_p, cons 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; - } /* * 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 +1253,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 +1262,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 +1272,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 +1294,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,6 +1341,29 @@ ly_ctx_get_yanglib_data(const struct ly_ctx *ctx, struct lyd_node **root_p, cons return ret; } +LIBYANG_API_DEF void +ly_ctx_free_parsed(struct ly_ctx *ctx) +{ + struct lysf_ctx fctx = {.ctx = ctx}; + uint32_t i; + struct lys_module *mod; + + if (!ctx) { + return; + } + + for (i = 0; i < ctx->list.count; ++i) { + mod = ctx->list.objs[i]; + + /* free the parsed modules */ + lysp_module_free(&fctx, mod->parsed); + mod->parsed = NULL; + } + + /* free extensions */ + lysf_ctx_erase(&fctx); +} + /** * @brief Callback for freeing context error hash table values. * diff --git a/src/context.h b/src/context.h index 1293dbcaa..6a50c6627 100644 --- a/src/context.h +++ b/src/context.h @@ -647,6 +647,14 @@ 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 Free all internal structures of the specified context. * diff --git a/src/schema_compile.c b/src/schema_compile.c index 904f00dad..3ce961f79 100644 --- a/src/schema_compile.c +++ b/src/schema_compile.c @@ -1712,6 +1712,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 = lydict_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 +1762,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); diff --git a/src/tree_schema.c b/src/tree_schema.c index 916a834e4..2a66df71e 100644 --- a/src/tree_schema.c +++ b/src/tree_schema.c @@ -2047,6 +2047,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 = lydict_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) @@ -2192,11 +2221,10 @@ 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 */ - LY_CHECK_GOTO(rc = lys_compile_feature_iffeatures(mod->parsed), cleanup); - - /* compile identities */ - LY_CHECK_GOTO(rc = lys_compile_identities(mod), cleanup); + /* compile features, identities, and submodules */ + LY_CHECK_GOTO(ret = lys_compile_feature_iffeatures(mod->parsed), cleanup); + LY_CHECK_GOTO(ret = lys_compile_identities(mod), cleanup); + LY_CHECK_GOTO(ret = lys_compile_submodules(mod), cleanup); cleanup: if (rc && mod && mod->name) { diff --git a/src/tree_schema.h b/src/tree_schema.h index 35da1a415..61ac5a492 100644 --- a/src/tree_schema.h +++ b/src/tree_schema.h @@ -1735,6 +1735,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 +1751,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 the extension instances ([sized array](@ref sizedarrays)) */ }; /** @@ -2135,36 +2145,38 @@ 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_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_free.c b/src/tree_schema_free.c index 21e7ed74c..8cc787c11 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. @@ -1280,6 +1280,7 @@ lysc_module_free(struct lysf_ctx *ctx, struct lysc_module *module) return; } + FREE_STRINGS(ctx->ctx, module->features); LY_LIST_FOR_SAFE(module->data, node_next, node) { lysc_node_free_(ctx, node); } @@ -1294,6 +1295,14 @@ lysc_module_free(struct lysf_ctx *ctx, struct lysc_module *module) free(module); } +static void +lysc_submodule_free(struct lysf_ctx *ctx, struct lysc_submodule *submodule) +{ + lydict_remove(ctx->ctx, submodule->name); + lydict_remove(ctx->ctx, submodule->revision); + lydict_remove(ctx->ctx, submodule->filepath); +} + void lys_module_free(struct lysf_ctx *ctx, struct lys_module *module, ly_bool remove_links) { @@ -1315,6 +1324,7 @@ lys_module_free(struct lysf_ctx *ctx, struct lys_module *module, ly_bool remove_ FREE_ARRAY(ctx, module->identities, lysc_ident_free); lysp_module_free(ctx, module->parsed); + FREE_ARRAY(ctx, module->submodules, lysc_submodule_free); LY_ARRAY_FREE(module->augmented_by); LY_ARRAY_FREE(module->deviated_by); From 2e11ff4dbd36b409ace36df6c7110e87a6779fe8 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Thu, 12 Sep 2024 14:41:11 +0200 Subject: [PATCH 04/99] tree schema UPDATE put compiled ext definitions into main module Simplifies freeing compiled ext instances without the need for s dedicated context. --- src/context.c | 39 +- src/log.c | 2 +- src/parser_common.c | 2 +- src/parser_yang.c | 15 +- src/parser_yin.c | 9 +- src/path.c | 3 +- src/plugins.c | 10 +- src/plugins_exts.c | 4 +- src/plugins_exts.h | 3 +- src/plugins_exts/nacm.c | 2 +- src/plugins_internal.h | 10 +- src/printer_tree.c | 10 +- src/printer_yang.c | 2 +- src/printer_yin.c | 14 +- src/schema_compile.c | 121 ++++--- src/schema_compile.h | 17 +- src/schema_compile_amend.c | 15 +- src/schema_compile_node.c | 18 +- src/schema_features.c | 3 +- src/tree_schema.c | 63 ++-- src/tree_schema.h | 12 +- src/tree_schema_common.c | 58 ++- src/tree_schema_free.c | 572 +++++++++++++++--------------- src/tree_schema_free.h | 97 +++-- src/tree_schema_internal.h | 17 +- tests/utests/basic/test_context.c | 12 +- tests/utests/basic/test_plugins.c | 8 +- tests/utests/schema/test_yang.c | 106 +++--- tests/utests/schema/test_yin.c | 136 ++++--- 29 files changed, 697 insertions(+), 683 deletions(-) diff --git a/src/context.c b/src/context.c index 43c8f8d5d..90440e3c8 100644 --- a/src/context.c +++ b/src/context.c @@ -1344,7 +1344,6 @@ ly_ctx_get_yanglib_data(const struct ly_ctx *ctx, struct lyd_node **root_p, cons LIBYANG_API_DEF void ly_ctx_free_parsed(struct ly_ctx *ctx) { - struct lysf_ctx fctx = {.ctx = ctx}; uint32_t i; struct lys_module *mod; @@ -1356,12 +1355,9 @@ ly_ctx_free_parsed(struct ly_ctx *ctx) mod = ctx->list.objs[i]; /* free the parsed modules */ - lysp_module_free(&fctx, mod->parsed); + lysp_module_free(ctx, mod->parsed); mod->parsed = NULL; } - - /* free extensions */ - lysf_ctx_erase(&fctx); } /** @@ -1380,28 +1376,33 @@ ly_ctx_ht_err_rec_free(void *val_p) 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; + /* 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->list.count; ++i) { + mod = ctx->list.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->list.count; ++i) { + mod = ctx->list.objs[i]; + lys_module_free(ctx, mod, 0); + } + free(ctx->list.objs); /* search paths list */ ly_set_erase(&ctx->search_paths, free); diff --git a/src/log.c b/src/log.c index 13da500ef..c0396d887 100644 --- a/src/log.c +++ b/src/log.c @@ -939,7 +939,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), ext->plugin->id, level, err, data_path, schema_path, line, format, ap); va_end(ap); } diff --git a/src/parser_common.c b/src/parser_common.c index 0b221af72..4a8620f3e 100644 --- a/src/parser_common.c +++ b/src/parser_common.c @@ -118,7 +118,7 @@ lyd_parser_notif_eventtime_validate(const struct lyd_node *node) } 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); diff --git a/src/parser_yang.c b/src/parser_yang.c index fcf055dab..c4b7ec843 100644 --- a/src/parser_yang.c +++ b/src/parser_yang.c @@ -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; @@ -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..08fd8fab8 100644 --- a/src/parser_yin.c +++ b/src/parser_yin.c @@ -2933,7 +2933,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 +2956,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; @@ -3893,7 +3892,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 +3947,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 +3960,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 +4010,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..360ca236a 100644 --- a/src/path.c +++ b/src/path.c @@ -1471,7 +1471,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; @@ -1486,7 +1485,7 @@ ly_path_predicates_free(const struct ly_ctx *ctx, struct ly_path_predicate *pred 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); + lysc_type_free(ctx, (struct lysc_type *)predicates[u].value.realtype); } break; case LY_PATH_PREDTYPE_LIST_VAR: diff --git a/src/plugins.c b/src/plugins.c index 22c49476b..ea97eb19e 100644 --- a/src/plugins.c +++ b/src/plugins.c @@ -188,7 +188,7 @@ lyplg_record_find(const struct ly_ctx *ctx, enum LYPLG type, const char *module, struct lyplg_type * lyplg_type_plugin_find(const struct ly_ctx *ctx, const char *module, const char *revision, const char *name) { - struct lyplg_record *record = NULL; + struct lyplg_type_record *record = NULL; if (ctx) { /* try to find context specific plugin */ @@ -200,11 +200,11 @@ lyplg_type_plugin_find(const struct ly_ctx *ctx, const char *module, const char record = lyplg_record_find(NULL, LYPLG_TYPE, module, revision, name); } - return record ? &((struct lyplg_type_record *)record)->plugin : NULL; + return record ? &record->plugin : NULL; } -struct lyplg_ext_record * -lyplg_ext_record_find(const struct ly_ctx *ctx, const char *module, const char *revision, const char *name) +struct lyplg_ext * +lyplg_ext_plugin_find(const struct ly_ctx *ctx, const char *module, const char *revision, const char *name) { struct lyplg_ext_record *record = NULL; @@ -218,7 +218,7 @@ lyplg_ext_record_find(const struct ly_ctx *ctx, const char *module, const char * record = lyplg_record_find(NULL, LYPLG_EXTENSION, module, revision, name); } - return record; + return record ? &record->plugin : NULL; } /** diff --git a/src/plugins_exts.c b/src/plugins_exts.c index af8179211..2168c9456 100644 --- a/src/plugins_exts.c +++ b/src/plugins_exts.c @@ -633,6 +633,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 +642,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; diff --git a/src/plugins_exts.h b/src/plugins_exts.h index 4cf80b2a2..cbfc9d38d 100644 --- a/src/plugins_exts.h +++ b/src/plugins_exts.h @@ -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 */ + struct lyplg_ext *plugin; /**< pointer to the extension plugin, if any */ 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 */ diff --git a/src/plugins_exts/nacm.c b/src/plugins_exts/nacm.c index df49721a6..5eaa60e3a 100644 --- a/src/plugins_exts/nacm.c +++ b/src/plugins_exts/nacm.c @@ -101,7 +101,7 @@ nacm_parse(struct lysp_ctx *pctx, struct lysp_ext_instance *ext) /* 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)) { + if ((&parent->exts[u] != ext) && parent->exts[u].plugin && !strcmp(parent->exts[u].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 */ diff --git a/src/plugins_internal.h b/src/plugins_internal.h index 2ba54f136..ac5484db3 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. @@ -63,7 +63,7 @@ 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 @@ -76,13 +76,13 @@ struct lyplg_type *lyplg_type_plugin_find(const struct ly_ctx *ctx, const char * /** * @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 Found extension plugin, NULL if none found. */ -struct lyplg_ext_record *lyplg_ext_record_find(const struct ly_ctx *ctx, const char *module, const char *revision, const char *name); +struct lyplg_ext *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/printer_tree.c b/src/printer_tree.c index f58ded5f4..7b164821a 100644 --- a/src/printer_tree.c +++ b/src/printer_tree.c @@ -1862,7 +1862,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 || !cn->exts[i].def->plugin->printer_ctree) { continue; } if (!trp_ext_parent_is_valid(1, &cn->exts[i])) { @@ -1874,7 +1874,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 || !pn->exts[i].plugin->printer_ptree) { continue; } if (!trp_ext_parent_is_valid(0, &pn->exts[i])) { @@ -2194,7 +2194,7 @@ tro_set_node_overr(ly_bool lysc_tree, const void *node, ly_bool erase_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); } 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 = pe->plugin->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 +2607,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; } @@ -3923,7 +3923,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 = ext_pars->plugin; if (!plugin->printer_ptree) { *ignore = 1; return LY_SUCCESS; diff --git a/src/printer_yang.c b/src/printer_yang.c index 1ed081ed7..f9055d187 100644 --- a/src/printer_yang.c +++ b/src/printer_yang.c @@ -294,7 +294,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, "\""); 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 3ce961f79..cfb58fc5a 100644 --- a/src/schema_compile.c +++ b/src/schema_compile.c @@ -109,51 +109,6 @@ 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) { @@ -169,8 +124,8 @@ 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); @@ -182,7 +137,7 @@ lys_compile_ext(struct lysc_ctx *ctx, struct lysp_ext_instance *extp, struct lys } ret = ext->def->plugin->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); @@ -766,7 +721,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 +771,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; @@ -1367,7 +1322,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 +1408,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 +1436,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 +1477,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 +1489,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 +1523,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; } @@ -1856,12 +1808,67 @@ lys_compile(struct lys_module *mod, struct lys_depset_unres *unres) 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 = ep->plugin; + + 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..7dce5770e 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 @@ -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..bcccba9f1 100644 --- a/src/schema_compile_amend.c +++ b/src/schema_compile_amend.c @@ -477,19 +477,18 @@ lysp_ext_dup(const struct ly_ctx *ctx, const struct lysp_module *pmod, void *par 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 = orig_ext->plugin; 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 && ext->plugin->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->plugin->parse(&pctx, ext), cleanup); } cleanup: @@ -1355,7 +1354,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 */ @@ -1429,7 +1428,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); } @@ -1814,7 +1813,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 +1821,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 diff --git a/src/schema_compile_node.c b/src/schema_compile_node.c index 5498b208e..d0b5976b4 100644 --- a/src/schema_compile_node.c +++ b/src/schema_compile_node.c @@ -1669,7 +1669,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 +1681,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; @@ -2136,7 +2136,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; @@ -2193,7 +2193,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; } @@ -2785,7 +2785,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) { @@ -3500,7 +3500,7 @@ lys_compile_node_list(struct lysc_ctx *ctx, struct lysp_node *pnode, struct lysc /* 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); + lysc_type_free(ctx->ctx, (struct lysc_type *)key->dflt->realtype); free(key->dflt); key->dflt = NULL; } @@ -3696,7 +3696,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 +4273,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_schema.c b/src/tree_schema.c index 2a66df71e..785f28497 100644 --- a/src/tree_schema.c +++ b/src/tree_schema.c @@ -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->list, 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 */ @@ -1353,8 +1350,8 @@ 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; @@ -1366,14 +1363,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 = ext_def->plugin; /* 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 +1378,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 || !ext->plugin->parse) { goto next_iter; } @@ -1394,14 +1389,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->plugin->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 +1537,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); @@ -2085,7 +2079,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); @@ -2212,7 +2206,10 @@ lys_parse_in(struct ly_ctx *ctx, struct ly_in *in, LYS_INFORMAT format, const st /* 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 = 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 */ @@ -2221,8 +2218,9 @@ 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, identities, and submodules */ + /* compile features, extensions, identities, and submodules */ LY_CHECK_GOTO(ret = lys_compile_feature_iffeatures(mod->parsed), cleanup); + LY_CHECK_GOTO(ret = lys_compile_extensions(mod), cleanup); LY_CHECK_GOTO(ret = lys_compile_identities(mod), cleanup); LY_CHECK_GOTO(ret = lys_compile_submodules(mod), cleanup); @@ -2237,10 +2235,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; } diff --git a/src/tree_schema.h b/src/tree_schema.h index 61ac5a492..5a7cfa99f 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)) */ + struct lyplg_ext *plugin; /**< extension definition plugin, if any */ 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 */ + struct lyplg_ext *plugin; /**< plugin implementing the specific extension, if any */ struct lys_module *module; /**< module structure */ uint16_t flags; /**< LYS_STATUS_* value (@ref snodeflags) */ }; @@ -1757,7 +1753,7 @@ struct lysc_module { 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)) */ + struct lysc_ext_instance *exts; /**< list of extension instances ([sized array](@ref sizedarrays)) */ }; /** @@ -2160,6 +2156,8 @@ struct lys_module { 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. diff --git a/src/tree_schema_common.c b/src/tree_schema_common.c index 1b185c305..bb994de4a 100644 --- a/src/tree_schema_common.c +++ b/src/tree_schema_common.c @@ -2270,11 +2270,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 +2312,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); + + /* 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_p->def->argname || ext_p->argument) { + 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 +2360,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 +2371,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 +2385,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; } @@ -2370,7 +2408,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; } diff --git a/src/tree_schema_free.c b/src/tree_schema_free.c index 8cc787c11..04227aec6 100644 --- a/src/tree_schema_free.c +++ b/src/tree_schema_free.c @@ -33,7 +33,7 @@ #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) @@ -46,11 +46,11 @@ lysp_qname_free(const struct ly_ctx *ctx, struct lysp_qname *qname) /** * @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; @@ -66,19 +66,19 @@ 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; - lydict_remove(ctx->ctx, ext->name); - lydict_remove(ctx->ctx, ext->argument); + lydict_remove(ctx, ext->name); + lydict_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 && ext->plugin->pfree) { + ext->plugin->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 +87,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); + lydict_remove(ctx, import->name); + lydict_remove(ctx, import->prefix); + lydict_remove(ctx, import->dsc); + lydict_remove(ctx, import->ref); FREE_ARRAY(ctx, import->exts, lysp_ext_instance_free); } @@ -108,31 +108,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); + lydict_remove(ctx, include->name); + lydict_remove(ctx, include->dsc); + lydict_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 +140,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 +152,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); + lydict_remove(ctx, rev->dsc); + lydict_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); + lydict_remove(ctx, ext->name); + lydict_remove(ctx, ext->argname); + lydict_remove(ctx, ext->dsc); + lydict_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); + lydict_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); + lydict_remove(ctx, feat->dsc); + lydict_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); + lydict_remove(ctx, ident->name); + FREE_ARRAY(ctx, ident->iffeatures, lysp_qname_free); + FREE_STRINGS(ctx, ident->bases); + lydict_remove(ctx, ident->dsc); + lydict_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); + lydict_remove(ctx, restr->arg.str); + lydict_remove(ctx, restr->emsg); + lydict_remove(ctx, restr->eapptag); + lydict_remove(ctx, restr->dsc); + lydict_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); + lydict_remove(ctx, item->name); + lydict_remove(ctx, item->dsc); + lydict_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); + lydict_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(ctx, 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 +266,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); + lydict_remove(ctx, tpdf->name); + lydict_remove(ctx, tpdf->units); + lydict_remove(ctx, tpdf->dflt.str); + lydict_remove(ctx, tpdf->dsc); + lydict_remove(ctx, tpdf->ref); FREE_ARRAY(ctx, tpdf->exts, lysp_ext_instance_free); lysp_type_free(ctx, &tpdf->type); @@ -312,11 +286,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 +310,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); + lydict_remove(ctx, when->cond); + lydict_remove(ctx, when->dsc); + lydict_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 +341,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 +357,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); + lydict_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); + lydict_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); + lydict_remove(ctx, dev->nodeid); + lydict_remove(ctx, dev->dsc); + lydict_remove(ctx, dev->ref); LY_LIST_FOR_SAFE(dev->deviates, next, iter) { lysp_deviate_free(ctx, iter); free(iter); @@ -417,24 +391,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); + lydict_remove(ctx, ref->nodeid); + lydict_remove(ctx, ref->dsc); + lydict_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); + lydict_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 +424,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); + lydict_remove(ctx, node->name); + lydict_remove(ctx, node->dsc); + lydict_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 +437,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); + lydict_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 +462,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); + lydict_remove(ctx, leaf->units); + lydict_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); + lydict_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); + lydict_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 +495,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 +503,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); + lydict_remove(ctx, choice->dflt.str); break; case LYS_CASE: cas = (struct lysp_node_case *)node; @@ -604,14 +578,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 +597,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 +618,36 @@ 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); + lydict_remove(ctx, submod->name); + lydict_remove(ctx, submod->filepath); + lydict_remove(ctx, submod->prefix); + lydict_remove(ctx, submod->org); + lydict_remove(ctx, submod->contact); + lydict_remove(ctx, submod->dsc); + lydict_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); + ext->def->plugin->cfree(ctx, ext); } - lydict_remove(ctx->ctx, ext->argument); + lydict_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 +656,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(ctx, (*w)->cond); ly_free_prefix_data(LY_VALUE_SCHEMA_RESOLVED, (*w)->prefixes); - lydict_remove(ctx->ctx, (*w)->dsc); - lydict_remove(ctx->ctx, (*w)->ref); + lydict_remove(ctx, (*w)->dsc); + lydict_remove(ctx, (*w)->ref); FREE_ARRAY(ctx, (*w)->exts, lysc_ext_instance_free); free(*w); } @@ -700,23 +677,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(ctx, 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); + lydict_remove(ctx, must->emsg); + lydict_remove(ctx, must->eapptag); + lydict_remove(ctx, must->dsc); + lydict_remove(ctx, must->ref); FREE_ARRAY(ctx, must->exts, lysc_ext_instance_free); } @@ -736,6 +713,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 +790,71 @@ 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); + lydict_remove(ctx, ident->name); + lydict_remove(ctx, ident->dsc); + lydict_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) +static void +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); + lydict_remove(ctx, range->eapptag); + lydict_remove(ctx, range->emsg); + lydict_remove(ctx, range->dsc); + lydict_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); + lydict_remove(ctx, (*pattern)->expr); + lydict_remove(ctx, (*pattern)->eapptag); + lydict_remove(ctx, (*pattern)->emsg); + lydict_remove(ctx, (*pattern)->dsc); + lydict_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); + lydict_remove(ctx, item->name); + lydict_remove(ctx, item->dsc); + lydict_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 +894,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(ctx, ((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 +906,7 @@ lysc_type_free(struct lysf_ctx *ctx, struct lysc_type *type) break; } - lydict_remove(ctx->ctx, type->name); + lydict_remove(ctx, type->name); FREE_ARRAY(ctx, type->exts, lysc_ext_instance_free); free(type); } @@ -935,12 +914,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 +932,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 +951,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 +968,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; @@ -1009,21 +988,21 @@ lysc_node_container_free(struct lysf_ctx *ctx, struct lysc_node_container *node) /** * @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); + lydict_remove(ctx, node->units); if (node->dflt) { - node->dflt->realtype->plugin->free(ctx->ctx, node->dflt); + node->dflt->realtype->plugin->free(ctx, node->dflt); lysc_type_free(ctx, (struct lysc_type *)node->dflt->realtype); free(node->dflt); } @@ -1032,12 +1011,12 @@ lysc_node_leaf_free(struct lysf_ctx *ctx, struct lysc_node_leaf *node) /** * @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; @@ -1046,9 +1025,9 @@ lysc_node_leaflist_free(struct lysf_ctx *ctx, struct lysc_node_leaflist *node) if (node->type) { lysc_type_free(ctx, node->type); } - lydict_remove(ctx->ctx, node->units); + lydict_remove(ctx, node->units); LY_ARRAY_FOR(node->dflts, u) { - node->dflts[u]->realtype->plugin->free(ctx->ctx, node->dflts[u]); + node->dflts[u]->realtype->plugin->free(ctx, node->dflts[u]); lysc_type_free(ctx, (struct lysc_type *)node->dflts[u]->realtype); free(node->dflts[u]); } @@ -1058,12 +1037,12 @@ lysc_node_leaflist_free(struct lysf_ctx *ctx, struct lysc_node_leaflist *node) /** * @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 +1069,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 +1087,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 +1105,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 +1119,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); + lydict_remove(ctx, node->name); + lydict_remove(ctx, node->dsc); + lydict_remove(ctx, node->ref); /* nodetype-specific part */ switch (node->nodetype) { @@ -1191,7 +1170,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 +1181,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 +1213,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 +1251,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,7 +1259,7 @@ lysc_module_free(struct lysf_ctx *ctx, struct lysc_module *module) return; } - FREE_STRINGS(ctx->ctx, module->features); + FREE_STRINGS(ctx, module->features); LY_LIST_FOR_SAFE(module->data, node_next, node) { lysc_node_free_(ctx, node); } @@ -1295,16 +1274,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(struct lysf_ctx *ctx, struct lysc_submodule *submodule) +lysc_submodule_free(const struct ly_ctx *ctx, struct lysc_submodule *submodule) { - lydict_remove(ctx->ctx, submodule->name); - lydict_remove(ctx->ctx, submodule->revision); - lydict_remove(ctx->ctx, submodule->filepath); + lydict_remove(ctx, submodule->name); + lydict_remove(ctx, submodule->revision); + lydict_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) +{ + lydict_remove(ctx, ext->name); + lydict_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; @@ -1315,6 +1315,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) { @@ -1322,46 +1323,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); + lydict_remove(ctx, module->name); + lydict_remove(ctx, module->revision); + lydict_remove(ctx, module->ns); + lydict_remove(ctx, module->prefix); + lydict_remove(ctx, module->filepath); + lydict_remove(ctx, module->org); + lydict_remove(ctx, module->contact); + lydict_remove(ctx, module->dsc); + lydict_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) { @@ -1390,7 +1379,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); } @@ -1406,57 +1395,57 @@ lyplg_ext_pfree_instance_substatements(const struct ly_ctx *ctx, struct lysp_ext 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: @@ -1498,12 +1487,12 @@ 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: @@ -1520,21 +1509,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: @@ -1549,7 +1538,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) { @@ -1575,7 +1563,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); } @@ -1620,7 +1608,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: @@ -1628,47 +1616,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..1403f729b 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. @@ -21,12 +21,6 @@ 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. @@ -47,7 +41,7 @@ struct lysf_ctx { /** * @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,84 +49,84 @@ 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. @@ -146,27 +140,27 @@ void lysc_range_free(struct lysf_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 the compiled container node structure. @@ -174,44 +168,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..a518f1087 100644 --- a/src/tree_schema_internal.h +++ b/src/tree_schema_internal.h @@ -446,6 +446,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 +479,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 diff --git a/tests/utests/basic/test_context.c b/tests/utests/basic/test_context.c index 116b2ce36..921b0d5b8 100644 --- a/tests/utests/basic/test_context.c +++ b/tests/utests/basic/test_context.c @@ -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..b957b52f1 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)); @@ -59,9 +59,9 @@ test_add_simple(void **state) assert_ptr_equal(leaf->type->plugin, 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 = 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, 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/schema/test_yang.c b/tests/utests/schema/test_yang.c index 384b08cd1..8657c2939 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,7 +736,7 @@ 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); @@ -752,8 +744,6 @@ submod_renew(struct lysp_yang_ctx *ctx) 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..775dd74aa 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; @@ -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); } @@ -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)); } @@ -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)); } @@ -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; @@ -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; } @@ -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,7 +3168,7 @@ 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); @@ -3184,8 +3176,6 @@ submod_renew(struct lysp_yin_ctx *ctx, const char *belongs_to) 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; @@ -3463,7 +3453,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; @@ -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 \" Date: Thu, 12 Sep 2024 15:26:47 +0200 Subject: [PATCH 05/99] plugins types REFACTOR remove redundant parameter --- src/plugins_types.c | 2 +- src/plugins_types.h | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/plugins_types.c b/src/plugins_types.c index fb6f75a7e..204dfed07 100644 --- a/src/plugins_types.c +++ b/src/plugins_types.c @@ -888,7 +888,7 @@ 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); } diff --git a/src/plugins_types.h b/src/plugins_types.h index 06acc3802..f55e6bbee 100644 --- a/src/plugins_types.h +++ b/src/plugins_types.h @@ -443,10 +443,9 @@ LIBYANG_API_DECL LY_ERR lyplg_type_lypath_new(const struct ly_ctx *ctx, const ch * * 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. From cb193415b2e4ff5385a829ff7b364b0cddd99811 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Thu, 12 Sep 2024 15:34:12 +0200 Subject: [PATCH 06/99] plugins exts UPDATE data node for ext data cb is provided Refs cesnet/libnetconf2#470 --- src/context.h | 6 ++-- src/plugins_exts.c | 5 +-- src/plugins_exts.h | 13 +++++--- src/plugins_exts/schema_mount.c | 35 ++++++++++++++------- src/tree_schema.c | 2 +- tests/utests/extensions/test_schema_mount.c | 3 +- tests/utests/schema/test_printer_tree.c | 3 +- tools/lint/common.c | 3 +- tools/lint/common.h | 4 ++- 9 files changed, 49 insertions(+), 25 deletions(-) diff --git a/src/context.h b/src/context.h index 6a50c6627..495f0a046 100644 --- a/src/context.h +++ b/src/context.h @@ -449,13 +449,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 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. diff --git a/src/plugins_exts.c b/src/plugins_exts.c index 2168c9456..a45fc5567 100644 --- a/src/plugins_exts.c +++ b/src/plugins_exts.c @@ -675,7 +675,8 @@ 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; @@ -684,7 +685,7 @@ lyplg_ext_get_data(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext return LY_EINVAL; } - if ((rc = ctx->ext_clb(ext, ctx->ext_clb_data, ext_data, ext_data_free))) { + if ((rc = ctx->ext_clb(ext, parent, ctx->ext_clb_data, ext_data, ext_data_free))) { lyplg_ext_compile_log(NULL, ext, LY_LLERR, rc, "Callback for getting ext data failed."); } return rc; diff --git a/src/plugins_exts.h b/src/plugins_exts.h index cbfc9d38d..21db6e8e5 100644 --- a/src/plugins_exts.h +++ b/src/plugins_exts.h @@ -1012,13 +1012,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. @@ -1034,20 +1035,24 @@ 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); /** @} pluginsExtensions */ diff --git a/src/plugins_exts/schema_mount.c b/src/plugins_exts/schema_mount.c index be9153020..eb71ee4ee 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. @@ -624,8 +625,16 @@ schema_mount_get_ctx_inline(struct lysc_ext_instance *ext, const struct lyd_node return rc; } -LY_ERR -lyplg_ext_schema_mount_get_ctx(struct lysc_ext_instance *ext, const struct ly_ctx **ext_ctx) +/** + * @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. + */ +static LY_ERR +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 +643,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 +695,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 = schema_mount_get_ctx(ext, parent, &ext_ctx))) { return r; } @@ -834,7 +843,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 +854,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 +919,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; } @@ -1055,7 +1065,8 @@ 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; @@ -1070,7 +1081,7 @@ 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; } @@ -1199,12 +1210,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 diff --git a/src/tree_schema.c b/src/tree_schema.c index 785f28497..f08f6fcc6 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_create_context(&parent->exts[u], NULL, &sm_ctx); if (sm_ctx) { /* some usable context created */ break; diff --git a/tests/utests/extensions/test_schema_mount.c b/tests/utests/extensions/test_schema_mount.c index 5b57b5684..005f35583 100644 --- a/tests/utests/extensions/test_schema_mount.c +++ b/tests/utests/extensions/test_schema_mount.c @@ -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; 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/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..f342cc208 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 aprent, 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. From 53a297bc879c4a0b185e3479181391e7f6537639 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Wed, 18 Sep 2024 11:11:24 +0200 Subject: [PATCH 07/99] tree schema UPDATE do not store lyd_value default values Because it causes issues and they cannot be serialized. --- src/diff.c | 3 +- src/path.c | 36 ++--- src/path.h | 2 +- src/plugins_types.c | 38 +++++ src/plugins_types.h | 16 +- src/plugins_types/instanceid.c | 66 ++------- src/plugins_types/node_instanceid.c | 18 +-- src/printer_yang.c | 20 +-- src/schema_compile.c | 74 ++++------ src/schema_compile_node.c | 8 +- src/tree_data_common.c | 41 +++--- src/tree_data_internal.h | 33 ++++- src/tree_data_new.c | 104 ++++--------- src/tree_schema.h | 10 +- src/tree_schema_common.c | 20 +++ src/tree_schema_free.c | 22 ++- src/tree_schema_free.h | 9 ++ src/tree_schema_internal.h | 12 ++ src/validation.c | 60 ++++---- src/xpath.c | 15 +- tests/utests/data/test_printer_xml.c | 15 +- .../utests/schema/test_tree_schema_compile.c | 137 +++++------------- tests/utests/types/int8.c | 26 ++-- tests/utests/utests.h | 2 +- 24 files changed, 370 insertions(+), 417 deletions(-) diff --git a/src/diff.c b/src/diff.c index 6ae5dc63d..37ffbade4 100644 --- a/src/diff.c +++ b/src/diff.c @@ -2210,8 +2210,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/path.c b/src/path.c index 360ca236a..68c886977 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" @@ -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; @@ -1483,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(ctx, (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_types.c b/src/plugins_types.c index 204dfed07..a360b6653 100644 --- a/src/plugins_types.c +++ b/src/plugins_types.c @@ -893,6 +893,44 @@ 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; + + type = ((struct lysc_node_leaf *)node)->type; + + /* store the value */ + r = type->plugin->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->plugin->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->plugin->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) { diff --git a/src/plugins_types.h b/src/plugins_types.h index f55e6bbee..e3c116499 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,6 +439,19 @@ 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. * diff --git a/src/plugins_types/instanceid.c b/src/plugins_types/instanceid.c index 46bb4baef..fb0ac21a9 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; diff --git a/src/plugins_types/node_instanceid.c b/src/plugins_types/node_instanceid.c index ab141d5f3..f5d074990 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 */ diff --git a/src/printer_yang.c b/src/printer_yang.c index f9055d187..64c9ee934 100644 --- a/src/printer_yang.c +++ b/src/printer_yang.c @@ -952,20 +952,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 +1599,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 +1666,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/schema_compile.c b/src/schema_compile.c index cfb58fc5a..647402464 100644 --- a/src/schema_compile.c +++ b/src/schema_compile.c @@ -881,32 +881,38 @@ 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; + LY_VALUE_FORMAT format; 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) { + rc = type->plugin->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 = lydict_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); @@ -915,14 +921,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 @@ -930,6 +935,7 @@ lys_compile_unres_dflt(struct lysc_ctx *ctx, struct lysc_node *node, struct lysc ly_path_free(val->target); val->target = NULL; } + type->plugin->free(ctx->ctx, &storage); return LY_SUCCESS; } @@ -946,27 +952,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); } /** @@ -983,7 +977,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); @@ -997,17 +990,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); } @@ -1016,10 +1005,11 @@ 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) { + lysc_update_path(ctx, llist->parent ? llist->parent->module : NULL, llist->name); 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); + lysc_update_path(ctx, NULL, NULL); return LY_EVALID; } } diff --git a/src/schema_compile_node.c b/src/schema_compile_node.c index d0b5976b4..0a83120c6 100644 --- a/src/schema_compile_node.c +++ b/src/schema_compile_node.c @@ -3498,11 +3498,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->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; diff --git a/src/tree_data_common.c b/src/tree_data_common.c index 96a6e68ad..26e163283 100644 --- a/src/tree_data_common.c +++ b/src/tree_data_common.c @@ -510,7 +510,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 +532,23 @@ 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 = type->plugin->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; @@ -598,8 +598,7 @@ ly_value_validate(const struct ly_ctx *ctx, const struct lysc_node *node, const rc = type->plugin->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) { @@ -618,6 +617,16 @@ 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; @@ -625,8 +634,6 @@ lyd_value_validate(const struct ly_ctx *ctx, const struct lysc_node *schema, con struct lyd_value val = {0}; ly_bool stored = 0, log = 1; - LY_CHECK_ARG_RET(ctx, schema, !value_len || value, LY_EINVAL); - if (!ctx) { ctx = schema->module->ctx; log = 0; @@ -637,8 +644,7 @@ lyd_value_validate(const struct ly_ctx *ctx, const struct lysc_node *schema, con type = ((struct lysc_node_leaf *)schema)->type; /* store */ - rc = type->plugin->store(ctx, type, value, value_len, 0, LY_VALUE_JSON, NULL, - LYD_HINT_DATA, schema, &val, NULL, &err); + rc = type->plugin->store(ctx, type, value, value_len, 0, format, prefix_data, LYD_HINT_DATA, schema, &val, NULL, &err); if (!rc || (rc == LY_EINCOMPLETE)) { stored = 1; } @@ -668,13 +674,13 @@ 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, val.realtype->plugin->print(ctx, &val, LY_VALUE_CANON, NULL, NULL, NULL), canonical); } } if (stored) { /* free value */ - type->plugin->free(ctx ? ctx : schema->module->ctx, &val); + type->plugin->free(ctx, &val); } return rc; } @@ -710,23 +716,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 +740,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; } } diff --git a/src/tree_data_internal.h b/src/tree_data_internal.h index 03f82bca3..f35253a6a 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 diff --git a/src/tree_data_new.c b/src/tree_data_new.c index d8341175a..180da8c4b 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); } @@ -1568,9 +1533,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 +1573,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 +1633,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 +1777,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); @@ -1949,12 +1914,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; + const struct lysc_node *snode, **choices, **snodes, *iter = NULL; 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 +1990,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 && - lyd_find_sibling_val(*first, snode, NULL, 0, NULL)) { + if (!(impl_opts & LYD_IMPLICIT_NO_DEFAULTS) && ((struct lysc_node_leaf *)iter)->dflt.str && + lyd_find_sibling_val(*first, iter, 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(iter, ((struct lysc_node_leaf *)iter)->dflt.str, + strlen(((struct lysc_node_leaf *)iter)->dflt.str), 1, 1, NULL, LY_VALUE_SCHEMA_RESOLVED, + ((struct lysc_node_leaf *)iter)->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 +2023,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(iter, 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_schema.h b/src/tree_schema.h index 5a7cfa99f..e0267f3da 100644 --- a/src/tree_schema.h +++ b/src/tree_schema.h @@ -1603,6 +1603,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 */ +}; + struct lysc_node_leaf { union { struct lysc_node node; /**< implicit cast for the members compatible with ::lysc_node */ @@ -1631,7 +1636,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 { @@ -1662,8 +1667,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 */ diff --git a/src/tree_schema_common.c b/src/tree_schema_common.c index bb994de4a..786e6b883 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" @@ -2851,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 04227aec6..4ae87b31a 100644 --- a/src/tree_schema_free.c +++ b/src/tree_schema_free.c @@ -985,6 +985,13 @@ lysc_node_container_free(const struct ly_ctx *ctx, struct lysc_node_container *n FREE_ARRAY(ctx, node->musts, lysc_must_free); } +void +lysc_value_free(const struct ly_ctx *ctx, struct lysc_value *val) +{ + lydict_remove(ctx, val->str); + ly_free_prefix_data(LY_VALUE_SCHEMA_RESOLVED, val->prefixes); +} + /** * @brief Free the compiled leaf structure. * @@ -1001,11 +1008,7 @@ lysc_node_leaf_free(const struct ly_ctx *ctx, struct lysc_node_leaf *node) lysc_type_free(ctx, node->type); } lydict_remove(ctx, node->units); - if (node->dflt) { - node->dflt->realtype->plugin->free(ctx, node->dflt); - lysc_type_free(ctx, (struct lysc_type *)node->dflt->realtype); - free(node->dflt); - } + lysc_value_free(ctx, &node->dflt); } /** @@ -1018,20 +1021,13 @@ lysc_node_leaf_free(const struct ly_ctx *ctx, struct lysc_node_leaf *node) static void 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, node->units); - LY_ARRAY_FOR(node->dflts, u) { - node->dflts[u]->realtype->plugin->free(ctx, node->dflts[u]); - lysc_type_free(ctx, (struct lysc_type *)node->dflts[u]->realtype); - free(node->dflts[u]); - } - LY_ARRAY_FREE(node->dflts); + FREE_ARRAY(ctx, node->dflts, lysc_value_free); } /** diff --git a/src/tree_schema_free.h b/src/tree_schema_free.h index 1403f729b..2fffe50a5 100644 --- a/src/tree_schema_free.h +++ b/src/tree_schema_free.h @@ -18,6 +18,7 @@ #include "set.h" #include "tree_schema.h" +struct lysc_value; struct lysp_yang_ctx; struct lysp_yin_ctx; @@ -162,6 +163,14 @@ void lysc_enum_item_free(const struct ly_ctx *ctx, struct lysc_type_bitenum_item */ 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. * diff --git a/src/tree_schema_internal.h b/src/tree_schema_internal.h index a518f1087..810d3fdfe 100644 --- a/src/tree_schema_internal.h +++ b/src/tree_schema_internal.h @@ -750,4 +750,16 @@ 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); + #endif /* LY_TREE_SCHEMA_INTERNAL_H_ */ diff --git a/src/validation.c b/src/validation.c index 25be0feeb..38eb4d7cd 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" @@ -717,7 +718,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 +1296,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 +1313,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 +1328,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 +1430,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 +1476,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 +1489,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 */ diff --git a/src/xpath.c b/src/xpath.c index 99a4a2278..61a1f7d25 100644 --- a/src/xpath.c +++ b/src/xpath.c @@ -1696,8 +1696,7 @@ 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; /* is there anything to canonize even? */ @@ -1729,18 +1728,16 @@ set_comp_canonize(struct lyxp_set *set, const struct lyxp_set_node *xp_node) } /* 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_validate(set->ctx, xp_node->node->schema, set->val.str, strlen(set->val.str), 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; @@ -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) { 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/schema/test_tree_schema_compile.c b/tests/utests/schema/test_tree_schema_compile.c index f4e609408..b57a65334 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])); @@ -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/types/int8.c b/tests/utests/types/int8.c index dff29efbe..f40c1ddc2 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); diff --git a/tests/utests/utests.h b/tests/utests/utests.h index 3e1844f02..8c11bd038 100644 --- a/tests/utests/utests.h +++ b/tests/utests/utests.h @@ -801,7 +801,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 From 9b77f91398e09de52fd80db2038c13d616de3cf5 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Wed, 2 Oct 2024 08:54:39 +0200 Subject: [PATCH 08/99] build UPDATE define global macros --- CMakeLists.txt | 4 ++-- compat/compat.c | 4 +++- src/in.c | 1 - tests/utests/utests.h | 2 -- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index aa9dc08bd..b0146a1f7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -75,8 +75,8 @@ 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 - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wpedantic -std=c11") + # global C flags (POSIX source because of pthread_rwlock_t) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wpedantic -std=c11 -D_POSIX_C_SOURCE=200809L") endif() include_directories(${PROJECT_BINARY_DIR}/libyang ${PROJECT_SOURCE_DIR}/src ${PROJECT_SOURCE_DIR}/src/plugins_exts) 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/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/tests/utests/utests.h b/tests/utests/utests.h index 8c11bd038..8fc6a8c9a 100644 --- a/tests/utests/utests.h +++ b/tests/utests/utests.h @@ -17,8 +17,6 @@ #ifndef _UTESTS_H_ #define _UTESTS_H_ -#define _POSIX_C_SOURCE 200809L /* strdup */ - #include #include #include From 64eff49ade09b9e138f91fca24ffca10bcf1e87a Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Wed, 2 Oct 2024 09:00:07 +0200 Subject: [PATCH 09/99] context UPDATE move writable members outside context So that it can be mapped and shared between processes. --- src/context.c | 96 +++++++--------------- src/context.h | 2 +- src/log.c | 140 ++++++++++++-------------------- src/log.h | 2 +- src/ly_common.c | 98 ++++++++++++++++++++++ src/ly_common.h | 57 +++++++++++-- src/plugins_exts.c | 7 +- src/plugins_exts/schema_mount.c | 5 +- src/tree_data.c | 8 +- src/tree_data_free.c | 6 +- 10 files changed, 250 insertions(+), 171 deletions(-) diff --git a/src/context.c b/src/context.c index 90440e3c8..a9ca6b527 100644 --- a/src/context.c +++ b/src/context.c @@ -258,17 +258,6 @@ 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. */ @@ -280,25 +269,12 @@ ly_ctx_ht_leafref_links_equal_cb(void *val1_p, void *val2_p, ly_bool UNUSED(mod) 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) { struct ly_ctx *ctx = NULL; struct lys_module *module; + struct ly_ctx_data *ctx_data; char *search_dir_list, *sep, *dir; const char **imp_f, *all_f[] = {"*", NULL}; uint32_t i; @@ -319,23 +295,19 @@ ly_ctx_new(const char *search_dir, uint16_t options, struct ly_ctx **new_ctx) 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); + /* ctx data */ + ctx_data = ly_ctx_data_add(ctx); + 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); + 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_GOTO(!ctx_data->leafref_links_ht, rc = LY_EMEM, 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); - - /* init LYB hash lock */ - pthread_mutex_init(&ctx->lyb_hash_lock, NULL); - /* modules list */ ctx->flags = options; if (search_dir) { @@ -648,6 +620,7 @@ LIBYANG_API_DEF LY_ERR ly_ctx_set_options(struct ly_ctx *ctx, uint16_t option) { LY_ERR lyrc = LY_SUCCESS; + struct ly_ctx_data *ctx_data; struct lys_module *mod; uint32_t i; @@ -663,8 +636,9 @@ ly_ctx_set_options(struct ly_ctx *ctx, uint16_t option) } 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); + ctx_data = ly_ctx_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->flags & LY_CTX_SET_PRIV_PARSED) && (option & LY_CTX_SET_PRIV_PARSED)) { @@ -697,19 +671,30 @@ lysc_node_clear_priv_dfs_cb(struct lysc_node *node, void *UNUSED(data), ly_bool return LY_SUCCESS; } +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_unset_options(struct ly_ctx *ctx, uint16_t option) { LY_ARRAY_COUNT_TYPE u, v; const struct lysc_ext_instance *ext; struct lysc_node *root; + struct ly_ctx_data *ctx_data; LY_CHECK_ARG_RET(ctx, ctx, 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; + ctx_data = ly_ctx_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)) { @@ -828,15 +813,17 @@ 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_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_data_get(ctx); + prev = ctx_data->ext_clb; + ctx_data->ext_clb = clb; + ctx_data->ext_clb_data = user_data; return prev; } @@ -1360,19 +1347,6 @@ ly_ctx_free_parsed(struct ly_ctx *ctx) } } -/** - * @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) -{ - struct ly_ctx_err_rec *err = val_p; - - ly_err_free(err->err); -} - LIBYANG_API_DEF void ly_ctx_destroy(struct ly_ctx *ctx) { @@ -1410,20 +1384,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 495f0a046..10543c833 100644 --- a/src/context.h +++ b/src/context.h @@ -472,7 +472,7 @@ typedef LY_ERR (*ly_ext_data_clb)(const struct lysc_ext_instance *ext, const str * @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. diff --git a/src/log.c b/src/log.c index c0396d887..84243b55d 100644 --- a/src/log.c +++ b/src/log.c @@ -175,112 +175,84 @@ 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) +static struct ly_ctx_data_err * +ly_err_data_get(const struct ly_ctx *ctx) { - struct ly_ctx_err_rec rec, *match; + struct ly_ctx_data *ctx_data; + pthread_t tid = pthread_self(); + uint32_t i; - /* prepare record */ - rec.tid = pthread_self(); + /* get context data */ + ctx_data = ly_ctx_data_get(ctx); - /* reuse lock */ - /* LOCK */ - pthread_mutex_lock((pthread_mutex_t *)&ctx->lyb_hash_lock); + pthread_rwlock_rdlock(&ctx_data->err_rwlock); - /* get the pointer to the matching record */ - lyht_find(ctx->err_ht, &rec, lyht_hash((void *)&rec.tid, sizeof rec.tid), (void **)&match); + /* find the thread-specific err */ + for (i = 0; i < ctx_data->err_count; ++i) { + if (!memcmp(&ctx_data->errs[i]->tid, &tid, sizeof tid)) { + return ctx_data->errs[i]; + } + } - /* UNLOCK */ - pthread_mutex_unlock((pthread_mutex_t *)&ctx->lyb_hash_lock); + pthread_rwlock_unlock(&ctx_data->err_rwlock); - return match; -} + pthread_rwlock_wrlock(&ctx_data->err_rwlock); -/** - * @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; + /* no need to retry the search, this thread is executing this function */ - /* insert a new record */ - new.err = NULL; - new.tid = pthread_self(); + /* not found, so create it */ + ctx_data->errs = ly_realloc(ctx_data->errs, (ctx_data->err_count + 1) * sizeof *ctx_data->errs); + ctx_data->errs[ctx_data->err_count] = calloc(1, sizeof **ctx_data->errs); + memcpy(&ctx_data->errs[ctx_data->err_count]->tid, &tid, sizeof tid); - /* reuse lock */ - /* LOCK */ - pthread_mutex_lock((pthread_mutex_t *)&ctx->lyb_hash_lock); + ++ctx_data->err_count; - 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; + return ctx_data->errs[ctx_data->err_count - 1]; } 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_data_err *err_data; LY_CHECK_ARG_RET(NULL, ctx, NULL); - /* get the pointer to the matching record */ - rec = ly_err_get_rec(ctx); + /* get context err data */ + err_data = ly_err_data_get(ctx); - return rec ? rec->err : NULL; + return err_data ? err_data->err : NULL; } 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_data_err *err_data; - LY_CHECK_ARG_RET(NULL, ctx, NULL); + /* get context err data */ + err_data = ly_err_data_get(ctx); - /* get the pointer to the matching record */ - if (!(rec = ly_err_get_rec(ctx))) { + if (!err_data) { return NULL; } - return rec->err ? rec->err->prev : NULL; + return err_data->err ? err_data->err->prev : NULL; } void ly_err_move(struct ly_ctx *src_ctx, struct ly_ctx *trg_ctx) { - struct ly_ctx_err_rec *rec; + struct ly_ctx_data_err *err_data; 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; - } + /* get src context err data */ + err_data = ly_err_data_get(src_ctx); + err = err_data->err; + err_data->err = NULL; /* 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; + err_data = ly_err_data_get(trg_ctx); + ly_err_free(err_data->err); + err_data->err = err; } LIBYANG_API_DEF void @@ -299,28 +271,27 @@ 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_data_err *err_data; struct ly_err_item *e; - if (!(rec = ly_err_get_rec(ctx))) { - return; - } - if (rec->err == eitem) { + err_data = ly_err_data_get(ctx); + if (err_data->err == eitem) { eitem = NULL; } if (!eitem) { /* free all err */ - ly_err_free(rec->err); - rec->err = NULL; + ly_err_free(err_data->err); + err_data->err = NULL; } else { /* disconnect the error */ - for (e = rec->err; e && (e->next != eitem); e = e->next) {} + for (e = err_data->err; e && (e->next != eitem); e = e->next) {} assert(e); e->next = NULL; - rec->err->prev = e; + err_data->err->prev = e; + /* free this err and newer */ ly_err_free(eitem); } @@ -468,18 +439,15 @@ 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_data_err *err_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 err data */ + err_data = ly_err_data_get(ctx); - e = rec->err; + e = err_data->err; if (!e) { /* if we are only to fill in path, there must have been an error stored */ assert(msg); @@ -488,7 +456,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; + err_data->err = e; } else if (!msg) { /* only filling the path */ assert(data_path || schema_path); 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..eb37e2e27 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,15 @@ #include #include "compat.h" +#include "tree_data_internal.h" #include "tree_schema_internal.h" #include "version.h" #include "xml.h" +pthread_rwlock_t ly_ctx_data_rwlock = PTHREAD_RWLOCK_INITIALIZER; +struct ly_ctx_data **ly_ctx_data; +uint32_t ly_ctx_data_count; + LIBYANG_API_DEF uint32_t ly_version_so_major(void) { @@ -88,6 +94,98 @@ ly_version_proj_str(void) return LY_PROJ_VERSION; } +struct ly_ctx_data * +ly_ctx_data_get(const struct ly_ctx *ctx) +{ + struct ly_ctx_data *ctx_data = NULL; + uint32_t i; + + pthread_rwlock_rdlock(&ly_ctx_data_rwlock); + + for (i = 0; i < ly_ctx_data_count; ++i) { + if (ly_ctx_data[i]->ctx == ctx) { + ctx_data = ly_ctx_data[i]; + break; + } + } + + pthread_rwlock_unlock(&ly_ctx_data_rwlock); + + if (!ctx_data) { + LOGINT(ctx); + } + + /* pointer to the structure, cannot be changed so lock is not required */ + return ctx_data; +} + +struct ly_ctx_data * +ly_ctx_data_add(const struct ly_ctx *ctx) +{ + struct ly_ctx_data *ctx_data; + + pthread_rwlock_wrlock(&ly_ctx_data_rwlock); + + /* realloc */ + ly_ctx_data = ly_realloc(ly_ctx_data, (ly_ctx_data_count + 1) * sizeof *ly_ctx_data); + + /* alloc */ + ctx_data = ly_ctx_data[ly_ctx_data_count] = calloc(1, sizeof **ly_ctx_data); + + /* fill */ + ly_ctx_data[ly_ctx_data_count]->ctx = ctx; + + ++ly_ctx_data_count; + + pthread_rwlock_unlock(&ly_ctx_data_rwlock); + + return ctx_data; +} + +void +ly_ctx_data_del(const struct ly_ctx *ctx) +{ + uint32_t i; + struct ly_ctx_data *ctx_data = NULL; + + pthread_rwlock_wrlock(&ly_ctx_data_rwlock); + + /* find the ctx data */ + for (i = 0; i < ly_ctx_data_count; ++i) { + if (ly_ctx_data[i]->ctx == ctx) { + ctx_data = ly_ctx_data[i]; + break; + } + } + if (!ctx_data) { + pthread_rwlock_unlock(&ly_ctx_data_rwlock); + LOGINT(NULL); + return; + } + + /* remove the ctx data, replace by the last */ + --ly_ctx_data_count; + if (ly_ctx_data_count) { + if (i < ly_ctx_data_count) { + ly_ctx_data[i] = ly_ctx_data[ly_ctx_data_count]; + } + } else { + free(ly_ctx_data); + ly_ctx_data = NULL; + } + + pthread_rwlock_unlock(&ly_ctx_data_rwlock); + + /* clear */ + for (i = 0; i < ctx_data->err_count; ++i) { + ly_err_free(ctx_data->errs[i]->err); + free(ctx_data->errs[i]); + } + free(ctx_data->errs); + lyht_free(ctx_data->leafref_links_ht, ly_ctx_ht_leafref_links_rec_free); + free(ctx_data); +} + void * ly_realloc(void *ptr, size_t size) { diff --git a/src/ly_common.h b/src/ly_common.h index 95c904654..5457a7253 100644 --- a/src/ly_common.h +++ b/src/ly_common.h @@ -337,11 +337,27 @@ int LY_VCODE_INSTREXP_len(const char *str); /** * @brief Context error hash table record. */ -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_data_err { + pthread_t tid; /** pthread thread ID */ + struct ly_err_item *err; /** pointer to the error items, if any */ }; +struct ly_ctx_data { + const struct ly_ctx *ctx; + 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 */ + + pthread_rwlock_t err_rwlock; /**< lock protecting errs */ + struct ly_ctx_data_err **errs; /**< array of thread-specific errors related to the context */ + uint32_t err_count; /**< count of items in the errs array */ + + struct ly_ht *leafref_links_ht; /**< hash table of leafref links between term data nodes */ +}; + +extern pthread_rwlock_t ly_ctx_data_rwlock; /**< lock for accessing ly_ctx_data */ +extern struct ly_ctx_data **ly_ctx_data; /**< array of pointers to context-specific data */ +extern uint32_t ly_ctx_data_count; /**< count of ly_ctx_data items */ + /** * @brief Context of the YANG schemas */ @@ -359,11 +375,6 @@ struct ly_ctx { of every loaded module */ uint16_t flags; /**< context settings, 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 +386,36 @@ struct ly_ctx { */ void ly_ctx_new_change(struct ly_ctx *ctx); +/** + * @brief Add a ctx data for a new context. + * + * @param[in] ctx Newly created context. + * @return Newly created data. + */ +struct ly_ctx_data *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 context-specific data of the process. + * + * @param[in] ctx Context whose data to get. + * @return Context data of @p ctx. + */ +struct ly_ctx_data *ly_ctx_data_get(const struct ly_ctx *ctx); + +/** + * @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. * diff --git a/src/plugins_exts.c b/src/plugins_exts.c index a45fc5567..5555fb1cc 100644 --- a/src/plugins_exts.c +++ b/src/plugins_exts.c @@ -679,13 +679,16 @@ lyplg_ext_get_data(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext void **ext_data, ly_bool *ext_data_free) { LY_ERR rc; + struct ly_ctx_data *ctx_data; - if (!ctx->ext_clb) { + ctx_data = ly_ctx_data_get(ctx); + + 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; } - if ((rc = ctx->ext_clb(ext, parent, 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."); } return rc; diff --git a/src/plugins_exts/schema_mount.c b/src/plugins_exts/schema_mount.c index eb71ee4ee..a1db47e8d 100644 --- a/src/plugins_exts/schema_mount.c +++ b/src/plugins_exts/schema_mount.c @@ -1069,10 +1069,13 @@ lyplg_ext_schema_mount_create_context(const struct lysc_ext_instance *ext, const struct ly_ctx **ctx) { struct lyd_node *ext_data = NULL; + struct ly_ctx_data *ctx_data; ly_bool ext_data_free = 0, config; LY_ERR rc = LY_SUCCESS; - if (!ext->module->ctx->ext_clb) { + + ctx_data = ly_ctx_data_get(ext->def->module->ctx); + if (!ctx_data->ext_clb) { return LY_EINVAL; } diff --git a/src/tree_data.c b/src/tree_data.c index 517b1694c..ce9d40110 100644 --- a/src/tree_data.c +++ b/src/tree_data.c @@ -3739,7 +3739,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_data *ctx_data; LY_ERR ret = LY_SUCCESS; uint32_t hash; struct lyd_leafref_links_rec rec = {0}; @@ -3755,16 +3755,16 @@ lyd_get_or_create_leafref_links_record(const struct lyd_node_term *node, struct return LY_EDENIED; } + ctx_data = ly_ctx_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 (lyht_find(ctx_data->leafref_links_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); + 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); } else { return LY_ENOTFOUND; diff --git a/src/tree_data_free.c b/src/tree_data_free.c index 893dfec46..fba97bc17 100644 --- a/src/tree_data_free.c +++ b/src/tree_data_free.c @@ -175,7 +175,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_data *ctx_data; uint32_t hash; struct lyd_leafref_links_rec *rec; @@ -189,9 +189,9 @@ 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_data_get(LYD_CTX(node)); hash = lyht_hash((const char *)&node, sizeof node); - lyht_remove(ht, &rec, hash); + lyht_remove(ctx_data->leafref_links_ht, &rec, hash); free(rec); } From e33258b0dc19964693fec14d8298c53551940526 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Wed, 2 Oct 2024 09:02:26 +0200 Subject: [PATCH 10/99] libyang REFACTOR minor improvements and fixes --- src/dict.c | 5 ----- src/hash_table.c | 4 +--- src/ly_common.h | 18 ------------------ src/parser_yin.c | 18 ++++++++++++++++++ src/plugins_exts.c | 10 +++++----- src/plugins_exts/structure.c | 4 ++-- src/tree_schema.h | 6 +++--- 7 files changed, 29 insertions(+), 36 deletions(-) diff --git a/src/dict.c b/src/dict.c index ba574c8ca..a8ef19b1b 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; } 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/ly_common.h b/src/ly_common.h index 5457a7253..27dab4e31 100644 --- a/src/ly_common.h +++ b/src/ly_common.h @@ -431,24 +431,6 @@ struct lys_module *ly_ctx_get_module_implemented2(const struct ly_ctx *ctx, cons * Generic useful functions. *****************************************************************************/ -/** - * @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 lydict_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(lydict_insert_zc(CTX, (char *)(STRING), &(TARGET))); \ - } else { \ - LY_CHECK_RET(lydict_insert(CTX, LEN ? (STRING) : "", LEN, &(TARGET))); \ - } \ - DYNAMIC = 0 - /** * @brief Wrapper for realloc() call. The only difference is that if it fails to * allocate the requested memory, the original memory is freed as well. diff --git a/src/parser_yin.c b/src/parser_yin.c index 08fd8fab8..f962227c3 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 lydict_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(lydict_insert_zc(CTX, (char *)(STRING), &(TARGET))); \ + } else { \ + LY_CHECK_RET(lydict_insert(CTX, LEN ? (STRING) : "", LEN, &(TARGET))); \ + } \ + DYNAMIC = 0 + /** * @brief check if given string is URI of yin namespace. * diff --git a/src/plugins_exts.c b/src/plugins_exts.c index 5555fb1cc..26aa29e23 100644 --- a/src/plugins_exts.c +++ b/src/plugins_exts.c @@ -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); diff --git a/src/plugins_exts/structure.c b/src/plugins_exts/structure.c index f05e63540..f1ec02c2d 100644 --- a/src/plugins_exts/structure.c +++ b/src/plugins_exts/structure.c @@ -206,11 +206,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); diff --git a/src/tree_schema.h b/src/tree_schema.h index e0267f3da..123e4a830 100644 --- a/src/tree_schema.h +++ b/src/tree_schema.h @@ -1262,8 +1262,8 @@ struct lysc_pattern { 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 { @@ -1605,7 +1605,7 @@ struct lysc_node_choice { struct lysc_value { const char *str; /**< string value */ - struct lysc_prefix *prefixes; /**< compiled used prefixes in the string value */ + struct lysc_prefix *prefixes; /**< compiled used prefixes in the string value ([sized array](@ref sizedarrays)) */ }; struct lysc_node_leaf { From 29eb033a41ba8856f946e3d8f79072988eeeae9e Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Wed, 2 Oct 2024 09:15:36 +0200 Subject: [PATCH 11/99] lyb UPDATE generating schema hashes manually --- src/context.c | 13 +++++++++++++ src/context.h | 4 +++- src/lyb.c | 18 +----------------- src/lyb.h | 6 ++---- src/parser_lyb.c | 14 +++++++++----- src/printer_lyb.c | 13 ++++++++++--- src/schema_compile.c | 6 ++++++ 7 files changed, 44 insertions(+), 30 deletions(-) diff --git a/src/context.c b/src/context.c index a9ca6b527..f0fb008e4 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" @@ -641,6 +642,18 @@ ly_ctx_set_options(struct ly_ctx *ctx, uint16_t option) LY_CHECK_ERR_RET(!ctx_data->leafref_links_ht, LOGARG(ctx, option), LY_EMEM); } + if (!(ctx->flags & LY_CTX_LYB_HASHES) && (option & LY_CTX_LYB_HASHES)) { + for (i = 0; i < ctx->list.count; ++i) { + mod = ctx->list.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; /* recompile the whole context to set the priv pointers */ diff --git a/src/context.h b/src/context.h index 10543c833..30fefa317 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. @@ -207,6 +207,8 @@ struct ly_ctx; 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_LYB_HASHES 0x1000 /**< Generate hashes for all the schema nodes. Required when using LYB data parse + or print. */ /** @} contextoptions */ 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_lyb.c b/src/parser_lyb.c index 66ac68663..523c0e724 100644 --- a/src/parser_lyb.c +++ b/src/parser_lyb.c @@ -413,9 +413,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 +819,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->flags & LY_CTX_LYB_HASHES)) { + /* generate LYB hashes */ + ly_ctx_set_options((*snode)->module->ctx, LY_CTX_LYB_HASHES); + } cleanup: free(name); @@ -1610,6 +1609,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->flags & LY_CTX_LYB_HASHES)) { + /* generate LYB hashes */ + ly_ctx_set_options((struct ly_ctx *)ctx, LY_CTX_LYB_HASHES); + } + if (subtree_sibling) { *subtree_sibling = 0; } diff --git a/src/printer_lyb.c b/src/printer_lyb.c index f13ef1593..267626cc5 100644 --- a/src/printer_lyb.c +++ b/src/printer_lyb.c @@ -496,9 +496,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; } @@ -1165,6 +1162,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)->flags & LY_CTX_LYB_HASHES)) { + 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 +1252,11 @@ lyb_print_data(struct ly_out *out, const struct lyd_node *root, uint32_t options ret = LY_EINVAL; goto cleanup; } + + if (!(ctx->flags & LY_CTX_LYB_HASHES)) { + /* generate LYB hashes */ + ly_ctx_set_options((struct ly_ctx *)ctx, LY_CTX_LYB_HASHES); + } } /* LYB magic number */ diff --git a/src/schema_compile.c b/src/schema_compile.c index 647402464..444834ab0 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" @@ -1792,6 +1793,11 @@ 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); + if (mod->ctx->flags & LY_CTX_LYB_HASHES) { + /* generate schema hashes for all the schema nodes */ + lysc_module_dfs_full(mod, lyb_cache_node_hash_cb, NULL); + } + ly_ctx_new_change(mod->ctx); cleanup: From b265e533def90037474380acd57b25da53570cba Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Wed, 2 Oct 2024 09:17:24 +0200 Subject: [PATCH 12/99] context FEATURE printing compiled context --- CMakeLists.txt | 1 + src/context.h | 19 + src/log.c | 8 +- src/plugins_exts.c | 33 + src/plugins_exts.h | 88 +- src/plugins_exts/metadata.c | 34 +- src/plugins_exts/nacm.c | 52 +- src/plugins_exts/schema_mount.c | 142 +- src/plugins_exts/structure.c | 51 +- src/plugins_exts/yangdata.c | 25 +- src/printer_context.c | 2048 +++++++++++++++++++ src/tree_schema_internal.h | 48 +- tests/utests/extensions/test_metadata.c | 8 +- tests/utests/extensions/test_nacm.c | 12 +- tests/utests/extensions/test_schema_mount.c | 26 +- tests/utests/extensions/test_structure.c | 6 +- tests/utests/extensions/test_yangdata.c | 14 +- tests/utests/schema/test_schema.c | 46 + tests/utests/utests.h | 2 +- 19 files changed, 2580 insertions(+), 83 deletions(-) create mode 100644 src/printer_context.c diff --git a/CMakeLists.txt b/CMakeLists.txt index b0146a1f7..e83200936 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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/src/context.h b/src/context.h index 30fefa317..c7755eb5c 100644 --- a/src/context.h +++ b/src/context.h @@ -659,6 +659,25 @@ LIBYANG_API_DECL LY_ERR ly_ctx_get_yanglib_data(const struct ly_ctx *ctx, struct */ 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. + * + * @param[in] orig_ctx Compiled context to print. + * @param[out] ctx Printed context. + * @param[in,out] mem Memory to print to, is moved after all the printed data. + * @return LY_ERR value. + */ +LIBYANG_API_DECL LY_ERR ly_ctx_compiled_print(const struct ly_ctx *orig_ctx, struct ly_ctx **ctx, void **mem); + /** * @brief Free all internal structures of the specified context. * diff --git a/src/log.c b/src/log.c index 84243b55d..6a9254974 100644 --- a/src/log.c +++ b/src/log.c @@ -215,7 +215,9 @@ ly_err_first(const struct ly_ctx *ctx) { struct ly_ctx_data_err *err_data; - LY_CHECK_ARG_RET(NULL, ctx, NULL); + if (!ctx) { + return NULL; + } /* get context err data */ err_data = ly_err_data_get(ctx); @@ -228,6 +230,10 @@ ly_err_last(const struct ly_ctx *ctx) { struct ly_ctx_data_err *err_data; + if (!ctx) { + return NULL; + } + /* get context err data */ err_data = ly_err_data_get(ctx); diff --git a/src/plugins_exts.c b/src/plugins_exts.c index 26aa29e23..f7bb45c4b 100644 --- a/src/plugins_exts.c +++ b/src/plugins_exts.c @@ -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) { diff --git a/src/plugins_exts.h b/src/plugins_exts.h index 21db6e8e5..477834be7 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. @@ -922,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. * @@ -947,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 { 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 5eaa60e3a..85f1722d9 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. @@ -59,7 +59,8 @@ nacm_inherit_clb(struct lysc_node *node, void *data, ly_bool *dfs_continue) return ret; } } - /* copy the pointer to the static variables */ + + /* copy the NACM value */ inherited->compiled = arg->ext->compiled; } @@ -128,14 +129,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 +144,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 +173,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 +183,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 +201,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 +219,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 +237,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 a1db47e8d..33688df62 100644 --- a/src/plugins_exts/schema_mount.c +++ b/src/plugins_exts/schema_mount.c @@ -22,6 +22,7 @@ #include #include "compat.h" +#include "context.h" #include "dict.h" #include "libyang.h" #include "log.h" @@ -36,26 +37,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 { @@ -417,7 +418,7 @@ schema_mount_get_ctx_shared(struct lysc_ext_instance *ext, const struct lyd_node /* 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; } } @@ -449,8 +450,14 @@ 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 */ @@ -1037,7 +1044,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; @@ -1049,7 +1056,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); @@ -1073,7 +1081,6 @@ lyplg_ext_schema_mount_create_context(const struct lysc_ext_instance *ext, const ly_bool ext_data_free = 0, config; LY_ERR rc = LY_SUCCESS; - ctx_data = ly_ctx_data_get(ext->def->module->ctx); if (!ctx_data->ext_clb) { return LY_EINVAL; @@ -1310,6 +1317,95 @@ 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; + + /* 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 */ + 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 */ + LY_CHECK_RET(ly_ctx_compiled_print(orig_sm_data->shared->schemas[i].ctx, &sm_data->shared->schemas[i].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. * @@ -1323,7 +1419,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, @@ -1333,7 +1429,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 f1ec02c2d..618221368 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. @@ -295,6 +295,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. * @@ -526,7 +563,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 +573,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 +592,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/printer_context.c b/src/printer_context.c new file mode 100644 index 000000000..323161b97 --- /dev/null +++ b/src/printer_context.c @@ -0,0 +1,2048 @@ +/** + * @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 "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; + + /* sized array */ + *size += CTXS_SIZED_ARRAY(exts); + + LY_ARRAY_FOR(exts, u) { + ctxs_exts(exts[u].exts, ht, size); + + /* substmts */ + *size += sizeof(LY_ARRAY_COUNT_TYPE) + LY_ARRAY_COUNT(exts[u].substmts) * sizeof *exts[u].substmts; + + /* compiled, substmts storage */ + if (exts[u].def->plugin && exts[u].def->plugin->compiled_size) { + *size += exts[u].def->plugin->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 += 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[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; + size_t code_size; + 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); + if (lyht_insert(ht, (void *)patterns[u], hash, NULL) == LY_EEXIST) { + continue; + } + + *size += sizeof *patterns[u]; + + pcre2_pattern_info(patterns[u]->code, PCRE2_INFO_SIZE, &code_size); + *size += CTXP_MEM_SIZE(code_size); + 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); +} + +static void +ctxs_context(const struct ly_ctx *ctx, struct ly_ht *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->list.count * sizeof ctx->list.objs; + for (i = 0; i < ctx->list.count; ++i) { + mod = ctx->list.objs[i]; + + /* modules */ + ctxs_module(mod, ht, size); + } + + /* plugins sets */ + *size += ctx->plugins_types.count * sizeof ctx->plugins_types.objs; + *size += ctx->plugins_extensions.count * sizeof ctx->plugins_extensions.objs; +} + +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); + + ctxs_context(ctx, ht, &size); + + /* cleanup */ + lyht_free(ht, NULL); + return 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) { + 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); + +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 */ +}; + +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 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; +} + +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 = NULL; + 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; + + 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 && ext->def->plugin->compiled_print) { + ext->def->plugin->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, struct ly_ht *addr_ht, void **mem) +{ + uint32_t i, len; + + 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; + exp->expr = ly_ctx_compiled_addr_ht_get(addr_ht, orig_exp->expr, 0); +} + +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, addr_ht, 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, addr_ht, 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; + size_t code_size; + + /* 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); + + /* TODO code->tables - seems to be static, probably in the PCRE2 lib */ + pcre2_pattern_info(orig_pattern->code, PCRE2_INFO_SIZE, &code_size); + p->code = *mem; + *mem = (char *)*mem + CTXP_MEM_SIZE(code_size); + memcpy(p->code, orig_pattern->code, code_size); + + 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, addr_ht, 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 = orig_type->plugin; + + 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); + } + 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); + } + 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); + } + } + 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 children, input is the parent */ + ly_ctx_compiled_addr_ht_add(addr_ht, &orig_act->input, &act->input); + 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 children, output is the parent */ + ly_ctx_compiled_addr_ht_add(addr_ht, &orig_act->output, &act->output); + 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; + 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 = orig_extension->plugin; + + 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; +} + +static void +ctxp_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 */ + ctxp_set(&orig_ctx->list, &ctx->list, mem); + for (i = 0; i < ctx->list.count; ++i) { + ctx->list.objs[i] = *mem; + *mem = (char *)*mem + sizeof(struct lys_module); + + ly_ctx_compiled_addr_ht_add(addr_ht, orig_ctx->list.objs[i], ctx->list.objs[i]); + ctxp_module(orig_ctx->list.objs[i], ctx->list.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->flags = orig_ctx->flags; + + /* plugins */ + ctxp_set(&orig_ctx->plugins_types, &ctx->plugins_types, mem); + memcpy(ctx->plugins_types.objs, orig_ctx->plugins_types.objs, + orig_ctx->plugins_types.count * sizeof orig_ctx->plugins_types.objs); + ctxp_set(&orig_ctx->plugins_extensions, &ctx->plugins_extensions, mem); + memcpy(ctx->plugins_extensions.objs, orig_ctx->plugins_extensions.objs, + orig_ctx->plugins_extensions.count * sizeof orig_ctx->plugins_extensions.objs); +} + +LIBYANG_API_DEF LY_ERR +ly_ctx_compiled_print(const struct ly_ctx *orig_ctx, struct ly_ctx **ctx, void **mem) +{ + struct ly_ht *addr_ht; + struct ly_set ptr_set = {0}; + void **ptr_p; + uint32_t i; + + LY_CHECK_ARG_RET(orig_ctx, orig_ctx, ctx, mem, 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 */ + *ctx = *mem; + *mem = (char *)*mem + sizeof **ctx; + ly_ctx_compiled_addr_ht_add(addr_ht, orig_ctx, *ctx); + ctxp_context(orig_ctx, *ctx, addr_ht, &ptr_set, mem); + + /* 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); + return LY_SUCCESS; +} + +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; + + LY_ARRAY_FOR(orig_substmts, u) { + assert(orig_substmts[u].stmt == substmts[u].stmt); + + 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: + ctxp_children(*orig_substmts[u].storage_p, (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/tree_schema_internal.h b/src/tree_schema_internal.h index 810d3fdfe..80d1d0b05 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. @@ -762,4 +762,50 @@ LY_ERR lyplg_ext_get_storage_p(const struct lysc_ext_instance *ext, int stmt, vo 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 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); + +/** + * @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/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 005f35583..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); @@ -196,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 = @@ -213,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 */ @@ -401,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); @@ -865,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); @@ -1121,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); @@ -1146,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_schema.c b/tests/utests/schema/test_schema.c index 42a051e77..4919f25ae 100644 --- a/tests/utests/schema/test_schema.c +++ b/tests/utests/schema/test_schema.c @@ -2117,6 +2117,51 @@ test_lysc_backlinks(void **state) } } +static void +test_compiled_print(void **state) +{ + struct ly_ctx *ctx_mem; + int size; + void *mem, *mem_end; + + /* load another module */ + assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, "module c {yang-version 1.1; namespace urn:c;prefix c;" + "feature feat;" + "feature feat2;" + "leaf a {type instance-identifier;}" + "leaf b {type boolean; must \"/a\";}" + "leaf c {type binary; when \"/c:b = 'true'\";}" + "leaf d {type decimal64 {fraction-digits 2;}}" + "leaf-list e {type instance-identifier; default \"/c:a\"; default \"/c:b\"; default \"/c: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;}}" + "}" + "}", LYS_IN_YANG, NULL)); + + /* get the size */ + size = ly_ctx_compiled_size(UTEST_LYCTX); + mem = malloc(size); + assert_non_null(mem); + + /* print the context */ + mem_end = mem; + assert_int_equal(LY_SUCCESS, ly_ctx_compiled_print(UTEST_LYCTX, &ctx_mem, &mem_end)); + assert_int_equal((char *)mem_end - (char *)mem, size); + + free(mem); +} + int main(void) { @@ -2140,6 +2185,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/utests.h b/tests/utests/utests.h index 8fc6a8c9a..ddfa95b2b 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. From 3590968b9f361a57524660c8ec1583a1e50e1305 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Thu, 3 Oct 2024 10:09:55 +0200 Subject: [PATCH 13/99] cmake BUGFIX gcov/gcc version check --- CMakeModules/GenCoverage.cmake | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) 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.") From adcc4aa123d51c77d054fcf1bb2d35300d741571 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Thu, 3 Oct 2024 11:39:13 +0200 Subject: [PATCH 14/99] context REFACTOR member renaming --- src/context.c | 86 +++++++++++++++---------------- src/ly_common.h | 6 +-- src/parser_lyb.c | 4 +- src/plugins_exts/schema_mount.c | 2 +- src/printer_context.c | 18 +++---- src/printer_lyb.c | 4 +- src/printer_tree.c | 4 +- src/schema_compile.c | 10 ++-- src/schema_compile_amend.c | 6 +-- src/schema_compile_node.c | 4 +- src/tree_schema.c | 18 +++---- src/tree_schema_common.c | 61 +++++++++------------- tests/utests/basic/test_context.c | 50 +++++++++--------- 13 files changed, 130 insertions(+), 143 deletions(-) diff --git a/src/context.c b/src/context.c index f0fb008e4..5522efaad 100644 --- a/src/context.c +++ b/src/context.c @@ -135,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) { @@ -236,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); @@ -310,7 +310,7 @@ ly_ctx_new(const char *search_dir, uint16_t options, struct ly_ctx **new_ctx) } /* modules list */ - ctx->flags = options; + ctx->opts = options; if (search_dir) { search_dir_list = strdup(search_dir); LY_CHECK_ERR_GOTO(!search_dir_list, LOGMEM(NULL); rc = LY_EMEM, cleanup); @@ -339,7 +339,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 */ @@ -350,8 +350,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); } } @@ -359,7 +359,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: @@ -516,7 +516,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; } @@ -571,7 +571,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: @@ -614,7 +614,7 @@ 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 @@ -626,25 +626,25 @@ ly_ctx_set_options(struct ly_ctx *ctx, uint16_t option) 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_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)) { + if (!(ctx->opts & LY_CTX_LEAFREF_LINKING) && (option & LY_CTX_LEAFREF_LINKING)) { ctx_data = ly_ctx_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->flags & LY_CTX_LYB_HASHES) && (option & LY_CTX_LYB_HASHES)) { - for (i = 0; i < ctx->list.count; ++i) { - mod = ctx->list.objs[i]; + 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; } @@ -654,11 +654,11 @@ ly_ctx_set_options(struct ly_ctx *ctx, uint16_t option) } } - 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; } @@ -671,7 +671,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; @@ -704,13 +704,13 @@ ly_ctx_unset_options(struct ly_ctx *ctx, uint16_t option) LY_CHECK_ARG_RET(ctx, ctx, 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)) { + if ((ctx->opts & LY_CTX_LEAFREF_LINKING) && (option & LY_CTX_LEAFREF_LINKING)) { ctx_data = ly_ctx_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; @@ -738,7 +738,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; } @@ -813,8 +813,8 @@ ly_ctx_set_module_imp_clb(struct ly_ctx *ctx, ly_module_imp_clb clb, void *user_ 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) { @@ -846,8 +846,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 +872,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 +1066,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 +1112,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; @@ -1230,8 +1230,8 @@ 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]; + for (i = 0; i < ctx->modules.count; ++i) { + mod = ctx->modules.objs[i]; /* * deprecated legacy @@ -1351,8 +1351,8 @@ ly_ctx_free_parsed(struct ly_ctx *ctx) return; } - 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]; /* free the parsed modules */ lysp_module_free(ctx, mod->parsed); @@ -1372,8 +1372,8 @@ ly_ctx_destroy(struct ly_ctx *ctx) /* 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->list.count; ++i) { - mod = ctx->list.objs[i]; + for (i = 0; i < ctx->modules.count; ++i) { + mod = ctx->modules.objs[i]; lysp_module_free(ctx, mod->parsed); mod->parsed = NULL; @@ -1385,11 +1385,11 @@ ly_ctx_destroy(struct ly_ctx *ctx) } /* free the modules (with compiled extension definitions) */ - 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]; lys_module_free(ctx, mod, 0); } - free(ctx->list.objs); + free(ctx->modules.objs); /* search paths list */ ly_set_erase(&ctx->search_paths, free); diff --git a/src/ly_common.h b/src/ly_common.h index 27dab4e31..36912724c 100644 --- a/src/ly_common.h +++ b/src/ly_common.h @@ -364,8 +364,8 @@ extern uint32_t ly_ctx_data_count; /**< count of ly_ctx_data items */ 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 */ @@ -373,7 +373,7 @@ struct ly_ctx { 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 */ + uint16_t opts; /**< context options, see @ref contextoptions */ struct ly_set plugins_types; /**< context specific set of type plugins */ struct ly_set plugins_extensions; /**< contets specific set of extension plugins */ diff --git a/src/parser_lyb.c b/src/parser_lyb.c index 523c0e724..3bccb76dd 100644 --- a/src/parser_lyb.c +++ b/src/parser_lyb.c @@ -819,7 +819,7 @@ lyb_parse_schema_nested_ext(struct lyd_lyb_ctx *lybctx, const struct lyd_node *p goto cleanup; } - if (!((*snode)->module->ctx->flags & LY_CTX_LYB_HASHES)) { + if (!((*snode)->module->ctx->opts & LY_CTX_LYB_HASHES)) { /* generate LYB hashes */ ly_ctx_set_options((*snode)->module->ctx, LY_CTX_LYB_HASHES); } @@ -1609,7 +1609,7 @@ 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->flags & LY_CTX_LYB_HASHES)) { + if (!(ctx->opts & LY_CTX_LYB_HASHES)) { /* generate LYB hashes */ ly_ctx_set_options((struct ly_ctx *)ctx, LY_CTX_LYB_HASHES); } diff --git a/src/plugins_exts/schema_mount.c b/src/plugins_exts/schema_mount.c index 33688df62..45a523968 100644 --- a/src/plugins_exts/schema_mount.c +++ b/src/plugins_exts/schema_mount.c @@ -1248,7 +1248,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); diff --git a/src/printer_context.c b/src/printer_context.c index 323161b97..92a251f0e 100644 --- a/src/printer_context.c +++ b/src/printer_context.c @@ -571,9 +571,9 @@ ctxs_context(const struct ly_ctx *ctx, struct ly_ht *ht, int *size) ctxs_dict_ht(ctx->dict.hash_tab, size); /* module set */ - *size += ctx->list.count * sizeof ctx->list.objs; - for (i = 0; i < ctx->list.count; ++i) { - mod = ctx->list.objs[i]; + *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, ht, size); @@ -1782,13 +1782,13 @@ ctxp_context(const struct ly_ctx *orig_ctx, struct ly_ctx *ctx, struct ly_ht *ad memset(&ctx->search_paths, 0, sizeof ctx->search_paths); /* modules, referenced */ - ctxp_set(&orig_ctx->list, &ctx->list, mem); - for (i = 0; i < ctx->list.count; ++i) { - ctx->list.objs[i] = *mem; + ctxp_set(&orig_ctx->modules, &ctx->modules, mem); + for (i = 0; i < ctx->modules.count; ++i) { + ctx->modules.objs[i] = *mem; *mem = (char *)*mem + sizeof(struct lys_module); - ly_ctx_compiled_addr_ht_add(addr_ht, orig_ctx->list.objs[i], ctx->list.objs[i]); - ctxp_module(orig_ctx->list.objs[i], ctx->list.objs[i], addr_ht, ptr_set, mem); + ly_ctx_compiled_addr_ht_add(addr_ht, orig_ctx->modules.objs[i], ctx->modules.objs[i]); + ctxp_module(orig_ctx->modules.objs[i], ctx->modules.objs[i], addr_ht, ptr_set, mem); } /* no imp cb */ @@ -1800,7 +1800,7 @@ ctxp_context(const struct ly_ctx *orig_ctx, struct ly_ctx *ctx, struct ly_ht *ad /* change_count and options */ ctx->change_count = orig_ctx->change_count; - ctx->flags = orig_ctx->flags; + ctx->opts = orig_ctx->opts; /* plugins */ ctxp_set(&orig_ctx->plugins_types, &ctx->plugins_types, mem); diff --git a/src/printer_lyb.c b/src/printer_lyb.c index 267626cc5..30f34c051 100644 --- a/src/printer_lyb.c +++ b/src/printer_lyb.c @@ -1163,7 +1163,7 @@ 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)->flags & LY_CTX_LYB_HASHES)) { + if (!(LYD_CTX(node)->opts & LY_CTX_LYB_HASHES)) { ly_ctx_set_options((struct ly_ctx *)LYD_CTX(node), LY_CTX_LYB_HASHES); } @@ -1253,7 +1253,7 @@ lyb_print_data(struct ly_out *out, const struct lyd_node *root, uint32_t options goto cleanup; } - if (!(ctx->flags & LY_CTX_LYB_HASHES)) { + if (!(ctx->opts & LY_CTX_LYB_HASHES)) { /* generate LYB hashes */ ly_ctx_set_options((struct ly_ctx *)ctx, LY_CTX_LYB_HASHES); } diff --git a/src/printer_tree.c b/src/printer_tree.c index 7b164821a..8ba4c819c 100644 --- a/src/printer_tree.c +++ b/src/printer_tree.c @@ -4664,7 +4664,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 +4690,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/schema_compile.c b/src/schema_compile.c index 444834ab0..8354ec975 100644 --- a/src/schema_compile.c +++ b/src/schema_compile.c @@ -427,7 +427,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) { @@ -897,7 +897,7 @@ lys_compile_unres_dflt(struct lysc_ctx *ctx, struct lysc_node *node, struct lysc struct ly_err_item *err = NULL; LY_VALUE_FORMAT format; - options = (ctx->ctx->flags & LY_CTX_REF_IMPLEMENTED) ? LYPLG_TYPE_STORE_IMPLEMENT : 0; + options = (ctx->ctx->opts & LY_CTX_REF_IMPLEMENTED) ? LYPLG_TYPE_STORE_IMPLEMENT : 0; rc = type->plugin->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) { @@ -1118,7 +1118,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); @@ -1139,7 +1139,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); @@ -1793,7 +1793,7 @@ 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); - if (mod->ctx->flags & LY_CTX_LYB_HASHES) { + 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); } diff --git a/src/schema_compile_amend.c b/src/schema_compile_amend.c index bcccba9f1..62ebab1b1 100644 --- a/src/schema_compile_amend.c +++ b/src/schema_compile_amend.c @@ -2549,7 +2549,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 */ @@ -2580,8 +2580,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 0a83120c6..65f81ab45 100644 --- a/src/schema_compile_node.c +++ b/src/schema_compile_node.c @@ -2714,7 +2714,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); @@ -3676,7 +3676,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 */ diff --git a/src/tree_schema.c b/src/tree_schema.c index f08f6fcc6..f7bbda016 100644 --- a/src/tree_schema.c +++ b/src/tree_schema.c @@ -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); @@ -1121,7 +1121,7 @@ lys_unres_glob_revert(struct ly_ctx *ctx, struct lys_glob_unres *unres) mod = unres->creating.objs[i]; /* remove the module from the context */ - ly_set_rm(&ctx->list, mod, NULL); + ly_set_rm(&ctx->modules, mod, NULL); /* remove it also from dep sets */ for (j = 0; j < unres->dep_sets.count; ++j) { @@ -1180,7 +1180,7 @@ lys_set_implemented(struct lys_module *mod, const char **features) 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); @@ -2200,7 +2200,7 @@ 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 */ @@ -2299,7 +2299,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); diff --git a/src/tree_schema_common.c b/src/tree_schema_common.c index 786e6b883..ca8a7f5c1 100644 --- a/src/tree_schema_common.c +++ b/src/tree_schema_common.c @@ -718,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 : ""); @@ -788,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)) { @@ -799,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)); @@ -1151,41 +1151,28 @@ lysp_load_submod_from_clb_or_file(struct lysp_ctx *pctx, const char *name, const struct lysp_load_module_data mod_data = {0}; struct ly_in *in; - assert(!submod_latest || (submod_latest->latest_revision != 2)); - - *submod = NULL; - - if (!ctx->imp_clb) { - /* no callback to call */ - clb_used = 1; - } else { - clb_used = 0; - } - - if (ctx->flags & LY_CTX_DISABLE_SEARCHDIRS) { - /* searchdirs disabled */ - searchdirs_used = 1; - } else { - searchdirs_used = 0; - } - - while (!found && (!clb_used || !searchdirs_used)) { - if ((!(ctx->flags & 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 */ - LY_CHECK_RET(ly_in_new_memory(submodule_data, &in)); - mod_data.name = name; - mod_data.revision = revision; - mod_data.submoduleof = PARSER_CUR_PMOD(pctx)->mod->name; - r = lys_parse_submodule(ctx, in, format, pctx->main_ctx, &mod_data, 0, new_mods, submod); - ly_in_free(in, 0); - if (submodule_data_free) { - submodule_data_free((void *)submodule_data, ctx->imp_clb_data); + if (ctx->imp_clb(PARSER_CUR_PMOD(pctx)->mod->name, NULL, inc->name, + inc->rev[0] ? inc->rev : NULL, ctx->imp_clb_data, + &format, &submodule_data, &submodule_data_free) == LY_SUCCESS) { + LY_CHECK_RET(ly_in_new_memory(submodule_data, &in)); + check_data.name = inc->name; + check_data.revision = inc->rev[0] ? inc->rev : NULL; + check_data.submoduleof = PARSER_CUR_PMOD(pctx)->mod->name; + lys_parse_submodule(ctx, in, format, pctx->main_ctx, lysp_load_module_check, &check_data, new_mods, + &submod); + + /* update inc pointer - parsing another (YANG 1.0) submodule can cause injecting + * submodule's include into main module, where it is missing */ + inc = &pmod->includes[u]; + + ly_in_free(in, 0); + if (submodule_data_free) { + submodule_data_free((void *)submodule_data, ctx->imp_clb_data); + } } - LY_CHECK_RET(r); - - found = 1; + } + if (!submod && !(ctx->opts & LY_CTX_PREFER_SEARCHDIRS)) { + goto search_file; } clb_used = 1; } else if (!searchdirs_used) { diff --git a/tests/utests/basic/test_context.c b/tests/utests/basic/test_context.c index 921b0d5b8..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 From 1bd9890a92107c776774f8d989155d991bfc2c93 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Thu, 3 Oct 2024 12:26:47 +0200 Subject: [PATCH 15/99] context UPDATE prevent printed context from being modified --- src/context.c | 22 +++++++++++----------- src/context.h | 2 ++ src/ly_common.h | 7 +++++-- src/printer_context.c | 1 + src/tree_schema.c | 10 +++++----- 5 files changed, 24 insertions(+), 18 deletions(-) diff --git a/src/context.c b/src/context.c index 5522efaad..a654e6fe7 100644 --- a/src/context.c +++ b/src/context.c @@ -89,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 */ @@ -178,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; @@ -211,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)) @@ -226,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); @@ -592,7 +592,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); @@ -625,7 +625,7 @@ ly_ctx_set_options(struct ly_ctx *ctx, uint16_t option) struct lys_module *mod; uint32_t i; - 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) && !(ctx->opts & LY_CTX_NO_YANGLIBRARY), LOGARG(ctx, option), LY_EINVAL); @@ -701,7 +701,7 @@ ly_ctx_unset_options(struct ly_ctx *ctx, uint16_t option) struct lysc_node *root; struct ly_ctx_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->opts & LY_CTX_LEAFREF_LINKING) && (option & LY_CTX_LEAFREF_LINKING)) { @@ -807,7 +807,7 @@ 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; @@ -1347,9 +1347,7 @@ ly_ctx_free_parsed(struct ly_ctx *ctx) uint32_t i; struct lys_module *mod; - if (!ctx) { - return; - } + 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]; @@ -1370,6 +1368,8 @@ ly_ctx_destroy(struct ly_ctx *ctx) return; } + LY_CHECK_ARG_RET(ctx, !(ctx->opts & LY_CTX_INT_IMMUTABLE), ); + /* 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) { diff --git a/src/context.h b/src/context.h index c7755eb5c..fee63f29f 100644 --- a/src/context.h +++ b/src/context.h @@ -210,6 +210,8 @@ struct ly_ctx; #define LY_CTX_LYB_HASHES 0x1000 /**< Generate hashes for all the schema nodes. Required when using LYB data parse or print. */ +/* 0x80000000 reserved for internal use */ + /** @} contextoptions */ /** diff --git a/src/ly_common.h b/src/ly_common.h index 36912724c..42877473d 100644 --- a/src/ly_common.h +++ b/src/ly_common.h @@ -358,6 +358,9 @@ extern pthread_rwlock_t ly_ctx_data_rwlock; /**< lock for accessing ly_ctx_data extern struct ly_ctx_data **ly_ctx_data; /**< array of pointers to context-specific data */ extern uint32_t ly_ctx_data_count; /**< count of ly_ctx_data items */ +#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 */ @@ -369,11 +372,11 @@ struct ly_ctx { 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 opts; /**< context options, see @ref contextoptions */ + uint32_t opts; /**< context options, see @ref contextoptions */ struct ly_set plugins_types; /**< context specific set of type plugins */ struct ly_set plugins_extensions; /**< contets specific set of extension plugins */ diff --git a/src/printer_context.c b/src/printer_context.c index 92a251f0e..fa61374cf 100644 --- a/src/printer_context.c +++ b/src/printer_context.c @@ -1830,6 +1830,7 @@ ly_ctx_compiled_print(const struct ly_ctx *orig_ctx, struct ly_ctx **ctx, void * *mem = (char *)*mem + sizeof **ctx; ly_ctx_compiled_addr_ht_add(addr_ht, orig_ctx, *ctx); ctxp_context(orig_ctx, *ctx, addr_ht, &ptr_set, mem); + (*ctx)->opts |= LY_CTX_INT_IMMUTABLE; /* set all the pointers to the printed structures */ for (i = 0; i < ptr_set.count; ++i) { diff --git a/src/tree_schema.c b/src/tree_schema.c index f7bbda016..f7d904215 100644 --- a/src/tree_schema.c +++ b/src/tree_schema.c @@ -1174,7 +1174,7 @@ lys_set_implemented(struct lys_module *mod, const char **features) LY_ERR ret = LY_SUCCESS; struct lys_glob_unres *unres = &mod->ctx->unres; - LY_CHECK_ARG_RET(NULL, mod, 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); @@ -2283,7 +2283,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); @@ -2329,7 +2329,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); @@ -2345,7 +2345,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); @@ -2361,7 +2361,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); From d4f63dd352f168ce6890cf05dbd8ff04d283ecb3 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Fri, 4 Oct 2024 15:40:32 +0200 Subject: [PATCH 16/99] context UPDATE parsing data using printed context --- src/context.c | 118 +++++++++++++++++++++++++++++- src/context.h | 17 ++++- src/dict.c | 102 ++++++++++++++++++-------- src/ly_common.c | 4 +- src/ly_common.h | 1 + src/plugins_exts/schema_mount.c | 5 +- src/printer_context.c | 99 ++++--------------------- src/tree_schema_internal.h | 27 +++++++ tests/utests/schema/test_schema.c | 37 ++++++++-- 9 files changed, 279 insertions(+), 131 deletions(-) diff --git a/src/context.c b/src/context.c index a654e6fe7..f9a0bb301 100644 --- a/src/context.c +++ b/src/context.c @@ -1358,6 +1358,118 @@ ly_ctx_free_parsed(struct ly_ctx *ctx) } } +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); + + /* 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; + struct ly_ctx_data *ctx_data = NULL; + + LY_CHECK_ARG_RET(NULL, mem, ctx, LY_EINVAL); + + *ctx = (void *)mem; + + /* ctx data */ + ctx_data = ly_ctx_data_add(*ctx); + + /* data dictionary */ + ctx_data->data_dict = malloc(sizeof *ctx_data->data_dict); + LY_CHECK_ERR_GOTO(!ctx_data->data_dict, rc = LY_EMEM, cleanup); + lydict_init(ctx_data->data_dict); + + /* leafref set */ + if ((*ctx)->opts & LY_CTX_LEAFREF_LINKING) { + 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_GOTO(!ctx_data->leafref_links_ht, rc = LY_EMEM, cleanup); + } + +cleanup: + if (rc && ctx_data) { + ly_ctx_data_del(*ctx); + *ctx = NULL; + } + return rc; +} + LIBYANG_API_DEF void ly_ctx_destroy(struct ly_ctx *ctx) { @@ -1368,7 +1480,11 @@ ly_ctx_destroy(struct ly_ctx *ctx) return; } - LY_CHECK_ARG_RET(ctx, !(ctx->opts & LY_CTX_INT_IMMUTABLE), ); + if (ctx->opts & LY_CTX_INT_IMMUTABLE) { + /* ctx data */ + ly_ctx_data_del(ctx); + return; + } /* free the parsed and compiled modules (both can reference ext instances, which need to be freed, so their * definitions can be freed) */ diff --git a/src/context.h b/src/context.h index fee63f29f..bb789402a 100644 --- a/src/context.h +++ b/src/context.h @@ -673,12 +673,21 @@ 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. * - * @param[in] orig_ctx Compiled context to print. - * @param[out] ctx Printed context. - * @param[in,out] mem Memory to print to, is moved after all the printed data. + * @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 *orig_ctx, struct ly_ctx **ctx, void **mem); +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. + * + * @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 Free all internal structures of the specified context. diff --git a/src/dict.c b/src/dict.c index a8ef19b1b..8188aec97 100644 --- a/src/dict.c +++ b/src/dict.c @@ -68,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) { /* @@ -122,11 +124,20 @@ lydict_remove(const struct ly_ctx *ctx, const char *value) uint32_t hash; struct ly_dict_rec rec, *match = NULL; char *val_p; + struct ly_ctx_data *ctx_data; + struct ly_dict *dict; if (!ctx || !value) { return LY_SUCCESS; } + if (ctx->opts & LY_CTX_INT_IMMUTABLE) { + ctx_data = ly_ctx_data_get(ctx); + dict = ctx_data->data_dict; + } else { + dict = (struct ly_dict *)&ctx->dict; + } + LOGDBG(LY_LDGDICT, "removing \"%s\"", value); len = strlen(value); @@ -136,14 +147,14 @@ 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); + pthread_mutex_lock(&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--; @@ -154,9 +165,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); @@ -164,13 +175,13 @@ lydict_remove(const struct ly_ctx *ctx, const char *value) LOGINT(ctx); } -finish: - pthread_mutex_unlock((pthread_mutex_t *)&ctx->dict.lock); +cleanup: + pthread_mutex_unlock(&dict->lock); return ret; } 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; @@ -180,12 +191,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) { @@ -199,7 +210,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); } @@ -221,7 +232,9 @@ dict_insert(const struct ly_ctx *ctx, char *value, size_t len, ly_bool zerocopy, 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_ctx_data *ctx_data; + struct ly_dict *dict; LY_CHECK_ARG_RET(ctx, ctx, str_p, LY_EINVAL); @@ -234,17 +247,26 @@ 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); + if (ctx->opts & LY_CTX_INT_IMMUTABLE) { + ctx_data = ly_ctx_data_get(ctx); + dict = ctx_data->data_dict; + } else { + dict = (struct ly_dict *)&ctx->dict; + } + + pthread_mutex_lock(&dict->lock); + rc = dict_insert(dict, (char *)value, len, 0, str_p); + pthread_mutex_unlock(&dict->lock); - return result; + return rc; } 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_ctx_data *ctx_data; + struct ly_dict *dict; LY_CHECK_ARG_RET(ctx, ctx, str_p, LY_EINVAL); @@ -253,28 +275,35 @@ 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); + if (ctx->opts & LY_CTX_INT_IMMUTABLE) { + ctx_data = ly_ctx_data_get(ctx); + dict = ctx_data->data_dict; + } else { + dict = (struct ly_dict *)&ctx->dict; + } + + pthread_mutex_lock(&dict->lock); + rc = dict_insert(dict, value, strlen(value), 1, str_p); + pthread_mutex_unlock(&dict->lock); - return result; + 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++; @@ -282,7 +311,7 @@ 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; } @@ -290,7 +319,9 @@ dict_dup(const struct ly_ctx *ctx, char *value, const char **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_ctx_data *ctx_data; + struct ly_dict *dict; LY_CHECK_ARG_RET(ctx, ctx, str_p, LY_EINVAL); @@ -299,9 +330,16 @@ 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); + if (ctx->opts & LY_CTX_INT_IMMUTABLE) { + ctx_data = ly_ctx_data_get(ctx); + dict = ctx_data->data_dict; + } else { + dict = (struct ly_dict *)&ctx->dict; + } + + 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/ly_common.c b/src/ly_common.c index eb37e2e27..89918d86e 100644 --- a/src/ly_common.c +++ b/src/ly_common.c @@ -112,7 +112,7 @@ ly_ctx_data_get(const struct ly_ctx *ctx) pthread_rwlock_unlock(&ly_ctx_data_rwlock); if (!ctx_data) { - LOGINT(ctx); + LOGINT(NULL); } /* pointer to the structure, cannot be changed so lock is not required */ @@ -183,6 +183,8 @@ ly_ctx_data_del(const struct ly_ctx *ctx) } free(ctx_data->errs); lyht_free(ctx_data->leafref_links_ht, ly_ctx_ht_leafref_links_rec_free); + lydict_clean(ctx_data->data_dict); + free(ctx_data->data_dict); free(ctx_data); } diff --git a/src/ly_common.h b/src/ly_common.h index 42877473d..52351c029 100644 --- a/src/ly_common.h +++ b/src/ly_common.h @@ -352,6 +352,7 @@ struct ly_ctx_data { uint32_t err_count; /**< count of items in the errs array */ struct ly_ht *leafref_links_ht; /**< hash table of leafref links between term data nodes */ + struct ly_dict *data_dict; /**< dictionary for data trees, for immutable contexts */ }; extern pthread_rwlock_t ly_ctx_data_rwlock; /**< lock for accessing ly_ctx_data */ diff --git a/src/plugins_exts/schema_mount.c b/src/plugins_exts/schema_mount.c index 45a523968..325f8427b 100644 --- a/src/plugins_exts/schema_mount.c +++ b/src/plugins_exts/schema_mount.c @@ -1357,6 +1357,7 @@ schema_mount_compiled_print(const struct lysc_ext_instance *orig_ext, struct lys struct lyplg_ext_sm *sm_data; pthread_mutexattr_t attr; uint32_t i; + void *ctx_mem; /* sm_data */ ext->compiled = sm_data = *mem; @@ -1387,7 +1388,9 @@ schema_mount_compiled_print(const struct lysc_ext_instance *orig_ext, struct lys for (i = 0; i < sm_data->shared->schema_count; ++i) { /* ctx */ - LY_CHECK_RET(ly_ctx_compiled_print(orig_sm_data->shared->schemas[i].ctx, &sm_data->shared->schemas[i].ctx, mem)); + 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)); /* mount_point */ strcpy(*mem, orig_sm_data->shared->schemas[i].mount_point); diff --git a/src/printer_context.c b/src/printer_context.c index fa61374cf..8e7961e39 100644 --- a/src/printer_context.c +++ b/src/printer_context.c @@ -558,8 +558,8 @@ ctxs_module(const struct lys_module *mod, struct ly_ht *ht, int *size) *size += CTXS_SIZED_ARRAY(mod->deviated_by); } -static void -ctxs_context(const struct ly_ctx *ctx, struct ly_ht *ht, int *size) +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; @@ -576,7 +576,7 @@ ctxs_context(const struct ly_ctx *ctx, struct ly_ht *ht, int *size) mod = ctx->modules.objs[i]; /* modules */ - ctxs_module(mod, ht, size); + ctxs_module(mod, addr_ht, size); } /* plugins sets */ @@ -584,36 +584,6 @@ ctxs_context(const struct ly_ctx *ctx, struct ly_ht *ht, int *size) *size += ctx->plugins_extensions.count * sizeof ctx->plugins_extensions.objs; } -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); - - ctxs_context(ctx, ht, &size); - - /* cleanup */ - lyht_free(ht, NULL); - return size; -} - int ly_ctx_compiled_ext_stmts_storage_size(const struct lysc_ext_substmt *substmts, struct ly_ht *addr_ht) { @@ -747,11 +717,6 @@ ly_ctx_compiled_ext_stmts_storage_size(const struct lysc_ext_substmt *substmts, 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); -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 */ -}; - static void ctxp_mutex(pthread_mutex_t *mutex) { @@ -772,17 +737,6 @@ ctxp_set(const struct ly_set *orig_set, struct ly_set *set, void **mem) *mem = (char *)*mem + (set->count * sizeof set->objs); } -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; -} - static void ctxp_dict_ht(const struct ly_ht *orig_ht, struct ly_ht *ht, struct ly_ht *addr_ht, void **mem) { @@ -1487,6 +1441,10 @@ ctxp_node(const struct lysc_node *orig_node, struct lysc_node *node, struct ly_h 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; @@ -1521,6 +1479,10 @@ ctxp_node(const struct lysc_node *orig_node, struct lysc_node *node, struct ly_h 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: @@ -1765,9 +1727,9 @@ ctxp_module(const struct lys_module *orig_mod, struct lys_module *mod, struct ly mod->latest_revision = orig_mod->latest_revision; } -static void -ctxp_context(const struct ly_ctx *orig_ctx, struct ly_ctx *ctx, struct ly_ht *addr_ht, struct ly_set *ptr_set, - void **mem) +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; @@ -1811,39 +1773,6 @@ ctxp_context(const struct ly_ctx *orig_ctx, struct ly_ctx *ctx, struct ly_ht *ad orig_ctx->plugins_extensions.count * sizeof orig_ctx->plugins_extensions.objs); } -LIBYANG_API_DEF LY_ERR -ly_ctx_compiled_print(const struct ly_ctx *orig_ctx, struct ly_ctx **ctx, void **mem) -{ - struct ly_ht *addr_ht; - struct ly_set ptr_set = {0}; - void **ptr_p; - uint32_t i; - - LY_CHECK_ARG_RET(orig_ctx, orig_ctx, ctx, mem, 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 */ - *ctx = *mem; - *mem = (char *)*mem + sizeof **ctx; - ly_ctx_compiled_addr_ht_add(addr_ht, orig_ctx, *ctx); - ctxp_context(orig_ctx, *ctx, addr_ht, &ptr_set, mem); - (*ctx)->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); - return LY_SUCCESS; -} - 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) diff --git a/src/tree_schema_internal.h b/src/tree_schema_internal.h index 80d1d0b05..ff8d63bf3 100644 --- a/src/tree_schema_internal.h +++ b/src/tree_schema_internal.h @@ -762,6 +762,15 @@ LY_ERR lyplg_ext_get_storage_p(const struct lysc_ext_instance *ext, int stmt, vo 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. * @@ -771,6 +780,24 @@ int lysc_value_cmp(const struct lysc_node *schema, const struct lyd_node *ctx_no */ 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. * diff --git a/tests/utests/schema/test_schema.c b/tests/utests/schema/test_schema.c index 4919f25ae..a1f749d34 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" @@ -2120,8 +2123,9 @@ test_lysc_backlinks(void **state) static void test_compiled_print(void **state) { - struct ly_ctx *ctx_mem; - int size; + struct ly_ctx *pctx; + struct lyd_node *tree; + int size, fd; void *mem, *mem_end; /* load another module */ @@ -2151,15 +2155,34 @@ test_compiled_print(void **state) /* get the size */ size = ly_ctx_compiled_size(UTEST_LYCTX); - mem = malloc(size); - assert_non_null(mem); + + /* prepare the shared memory segment */ + fd = shm_open("/ly_test_schema_ctx", O_RDWR | O_CREAT, 00600); + assert_int_not_equal(fd, -1); + ftruncate(fd, size); + mem = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + assert_ptr_not_equal(mem, MAP_FAILED); /* print the context */ - mem_end = mem; - assert_int_equal(LY_SUCCESS, ly_ctx_compiled_print(UTEST_LYCTX, &ctx_mem, &mem_end)); + assert_int_equal(LY_SUCCESS, ly_ctx_compiled_print(UTEST_LYCTX, mem, &mem_end)); assert_int_equal((char *)mem_end - (char *)mem, size); - free(mem); + /* use the printed context */ + assert_int_equal(LY_SUCCESS, ly_ctx_new_printed(mem, &pctx)); + + /* use it to parse some data */ + assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(pctx, + "/c:b" + "true" + "ahoi", + LYD_XML, 0, LYD_VALIDATE_PRESENT, &tree)); + + /* cleanup */ + lyd_free_siblings(tree); + ly_ctx_destroy(pctx); + munmap(mem, size); + close(fd); + shm_unlink("/ly_test_schema_ctx"); } int From dcb0c2110a477c3dc0ad3183d38d11cf26d5c300 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Fri, 11 Oct 2024 14:12:06 +0200 Subject: [PATCH 17/99] printer context UPDATE dynamic plugins not supported --- src/context.c | 5 +++++ src/printer_context.c | 14 +++----------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/src/context.c b/src/context.c index f9a0bb301..560367523 100644 --- a/src/context.c +++ b/src/context.c @@ -1410,6 +1410,11 @@ ly_ctx_compiled_print(const struct ly_ctx *ctx, void *mem, void **mem_end) LY_CHECK_ARG_RET(ctx, ctx, mem, LY_EINVAL); + if (ctx->plugins_types.count || ctx->plugins_extensions.count) { + 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); diff --git a/src/printer_context.c b/src/printer_context.c index 8e7961e39..0f56dcb2c 100644 --- a/src/printer_context.c +++ b/src/printer_context.c @@ -578,10 +578,6 @@ ly_ctx_compiled_size_context(const struct ly_ctx *ctx, struct ly_ht *addr_ht, in /* modules */ ctxs_module(mod, addr_ht, size); } - - /* plugins sets */ - *size += ctx->plugins_types.count * sizeof ctx->plugins_types.objs; - *size += ctx->plugins_extensions.count * sizeof ctx->plugins_extensions.objs; } int @@ -1764,13 +1760,9 @@ ly_ctx_compiled_print_context(const struct ly_ctx *orig_ctx, struct ly_ctx *ctx, ctx->change_count = orig_ctx->change_count; ctx->opts = orig_ctx->opts; - /* plugins */ - ctxp_set(&orig_ctx->plugins_types, &ctx->plugins_types, mem); - memcpy(ctx->plugins_types.objs, orig_ctx->plugins_types.objs, - orig_ctx->plugins_types.count * sizeof orig_ctx->plugins_types.objs); - ctxp_set(&orig_ctx->plugins_extensions, &ctx->plugins_extensions, mem); - memcpy(ctx->plugins_extensions.objs, orig_ctx->plugins_extensions.objs, - orig_ctx->plugins_extensions.count * sizeof orig_ctx->plugins_extensions.objs); + /* no dynamic plugin support */ + memset(&ctx->plugins_types, 0, sizeof ctx->plugins_types); + memset(&ctx->plugins_extensions, 0, sizeof ctx->plugins_extensions); } LY_ERR From 1bd46275cdba9c406995e64c8477f621d7a091b8 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Fri, 18 Oct 2024 14:55:14 +0200 Subject: [PATCH 18/99] parser data UPDATE support some parsing flags for ops --- src/parser_data.h | 8 +++-- src/tree_data.c | 26 ++++++++------ tests/utests/basic/test_xpath.c | 3 +- tests/utests/data/test_lyb.c | 4 +-- tests/utests/data/test_parser_json.c | 33 +++++++++++------ tests/utests/data/test_parser_xml.c | 54 ++++++++++++++++++---------- tests/utests/data/test_validation.c | 9 +++-- tools/lint/cmd_data.c | 9 ++--- 8 files changed, 95 insertions(+), 51 deletions(-) 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/tree_data.c b/src/tree_data.c index ce9d40110..b7a79c220 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 * 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_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/tools/lint/cmd_data.c b/tools/lint/cmd_data.c index c935bde35..856b46f1c 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__); From 8db49d770b15c5c5cb41bca8758bf6ebb3acf619 Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Fri, 20 Dec 2024 15:43:42 +0100 Subject: [PATCH 19/99] libyang BUGFIX wrong rebase conflict resolution --- src/schema_compile.c | 2 -- src/tree_data_new.c | 14 +++++++------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/schema_compile.c b/src/schema_compile.c index 8354ec975..73b419ca2 100644 --- a/src/schema_compile.c +++ b/src/schema_compile.c @@ -1007,10 +1007,8 @@ lys_compile_unres_llist_dflts(struct lysc_ctx *ctx, struct lysc_node_leaflist *l for (u = orig_count; u < LY_ARRAY_COUNT(llist->dflts); ++u) { for (v = 0; v < u; ++v) { if (llist->dflts[u].str == llist->dflts[v].str) { - lysc_update_path(ctx, llist->parent ? llist->parent->module : NULL, llist->name); LOGVAL(ctx->ctx, LYVE_SEMANTICS, "Configuration leaf-list has multiple defaults of the same value \"%s\".", llist->dflts[u].str); - lysc_update_path(ctx, NULL, NULL); return LY_EVALID; } } diff --git a/src/tree_data_new.c b/src/tree_data_new.c index 180da8c4b..3a6965428 100644 --- a/src/tree_data_new.c +++ b/src/tree_data_new.c @@ -1914,7 +1914,7 @@ 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) { - const struct lysc_node *snode, **choices, **snodes, *iter = NULL; + const struct lysc_node *snode, **choices, **snodes; struct lyd_node *node = NULL; struct lysc_value *dflts; LY_ARRAY_COUNT_TYPE u; @@ -1990,12 +1990,12 @@ 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 *)iter)->dflt.str && - lyd_find_sibling_val(*first, iter, NULL, 0, NULL)) { + 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 */ - LY_CHECK_RET(lyd_create_term(iter, ((struct lysc_node_leaf *)iter)->dflt.str, - strlen(((struct lysc_node_leaf *)iter)->dflt.str), 1, 1, NULL, LY_VALUE_SCHEMA_RESOLVED, - ((struct lysc_node_leaf *)iter)->dflt.prefixes, LYD_HINT_DATA, &incomplete, &node)); + 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)); @@ -2023,7 +2023,7 @@ 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) { - LY_CHECK_RET(lyd_create_term(iter, dflts[u].str, strlen(dflts[u].str), 1, 1, NULL, + 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 */ From 1381d4ae28681db02635a49ee4aa3c6624a37c3d Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Thu, 2 Jan 2025 10:27:06 +0100 Subject: [PATCH 20/99] xpath BUGFIX properly distinguish same dictionaries --- src/xpath.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/xpath.c b/src/xpath.c index 61a1f7d25..beb1c7f50 100644 --- a/src/xpath.c +++ b/src/xpath.c @@ -5767,6 +5767,7 @@ moveto_node_check(const struct lyd_node *node, enum lyxp_node_type node_type, co const char *node_name, const struct lys_module *moveto_mod, uint32_t options) { const struct lysc_node *schema; + ly_bool same_dict = 0; if ((node_type == LYXP_NODE_ROOT_CONFIG) || (node_type == LYXP_NODE_ROOT)) { assert(node_type == set->root_type); @@ -5806,9 +5807,13 @@ 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)) { + if ((set->ctx == LYD_CTX(node)) && !(set->ctx->opts & LY_CTX_INT_IMMUTABLE)) { + same_dict = 1; + } + + if (same_dict && (schema->name != node_name)) { return LY_ENOT; - } else if ((set->ctx != LYD_CTX(node)) && strcmp(schema->name, node_name)) { + } else if (!same_dict && strcmp(schema->name, node_name)) { return LY_ENOT; } } From 0ca2f16d68f1ea4a4fc1ae45eb996f09129424d1 Mon Sep 17 00:00:00 2001 From: roman Date: Thu, 16 Jan 2025 16:13:14 +0100 Subject: [PATCH 21/99] plugins types REFACTOR shorter ids --- src/plugins_types/binary.c | 2 +- src/plugins_types/bits.c | 2 +- src/plugins_types/boolean.c | 2 +- src/plugins_types/date_and_time.c | 2 +- src/plugins_types/decimal64.c | 2 +- src/plugins_types/empty.c | 2 +- src/plugins_types/enumeration.c | 2 +- src/plugins_types/hex_string.c | 8 ++++---- src/plugins_types/identityref.c | 2 +- src/plugins_types/instanceid.c | 2 +- src/plugins_types/instanceid_keys.c | 2 +- src/plugins_types/integer.c | 16 ++++++++-------- src/plugins_types/ipv4_address.c | 2 +- src/plugins_types/ipv4_address_no_zone.c | 2 +- src/plugins_types/ipv4_prefix.c | 2 +- src/plugins_types/ipv6_address.c | 2 +- src/plugins_types/ipv6_address_no_zone.c | 2 +- src/plugins_types/ipv6_prefix.c | 2 +- src/plugins_types/leafref.c | 2 +- src/plugins_types/lyds_tree.c | 2 +- src/plugins_types/node_instanceid.c | 4 ++-- src/plugins_types/string.c | 2 +- src/plugins_types/time_period.c | 2 +- src/plugins_types/union.c | 2 +- src/plugins_types/xpath1.0.c | 2 +- tests/utests/types/binary.c | 2 +- tests/utests/types/bits.c | 2 +- tests/utests/types/int8.c | 2 +- tests/utests/types/string.c | 2 +- tests/utests/types/union.c | 15 +++++++-------- 30 files changed, 47 insertions(+), 48 deletions(-) diff --git a/src/plugins_types/binary.c b/src/plugins_types/binary.c index a0204385d..24f2c2960 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..cdeb84d34 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..42b7918d4 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..c2aaf794e 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..5a9b7ab2d 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..8b88e6154 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..d3159a6e3 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..285967b67 100644 --- a/src/plugins_types/hex_string.c +++ b/src/plugins_types/hex_string.c @@ -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..63cd3c176 100644 --- a/src/plugins_types/identityref.c +++ b/src/plugins_types/identityref.c @@ -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 fb0ac21a9..78f221b87 100644 --- a/src/plugins_types/instanceid.c +++ b/src/plugins_types/instanceid.c @@ -321,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..6d7423cad 100644 --- a/src/plugins_types/instanceid_keys.c +++ b/src/plugins_types/instanceid_keys.c @@ -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..5a52ad7fb 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..98d88c6f3 100644 --- a/src/plugins_types/ipv4_address.c +++ b/src/plugins_types/ipv4_address.c @@ -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..ffe1cbac4 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..7f422cce0 100644 --- a/src/plugins_types/ipv4_prefix.c +++ b/src/plugins_types/ipv4_prefix.c @@ -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..8b0057de4 100644 --- a/src/plugins_types/ipv6_address.c +++ b/src/plugins_types/ipv6_address.c @@ -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..b4422cd33 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..6730172a2 100644 --- a/src/plugins_types/ipv6_prefix.c +++ b/src/plugins_types/ipv6_prefix.c @@ -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..78c3280bc 100644 --- a/src/plugins_types/leafref.c +++ b/src/plugins_types/leafref.c @@ -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..9dbe28e7b 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 f5d074990..34f5ff7fa 100644 --- a/src/plugins_types/node_instanceid.c +++ b/src/plugins_types/node_instanceid.c @@ -334,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, @@ -349,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..c998aeec8 100644 --- a/src/plugins_types/string.c +++ b/src/plugins_types/string.c @@ -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..4e76cf42a 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..944ca61ff 100644 --- a/src/plugins_types/union.c +++ b/src/plugins_types/union.c @@ -766,7 +766,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..8af4ede6a 100644 --- a/src/plugins_types/xpath1.0.c +++ b/src/plugins_types/xpath1.0.c @@ -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/tests/utests/types/binary.c b/tests/utests/types/binary.c index efdc8f112..6abf26fb8 100644 --- a/tests/utests/types/binary.c +++ b/tests/utests/types/binary.c @@ -63,7 +63,7 @@ test_plugin_store(void **state) lysc_type2 = ((struct lysc_node_leaf *)mod->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=="; diff --git a/tests/utests/types/bits.c b/tests/utests/types/bits.c index 23614f0c3..15304a242 100644 --- a/tests/utests/types/bits.c +++ b/tests/utests/types/bits.c @@ -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 */ diff --git a/tests/utests/types/int8.c b/tests/utests/types/int8.c index f40c1ddc2..0be4ad83d 100644 --- a/tests/utests/types/int8.c +++ b/tests/utests/types/int8.c @@ -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 diff --git a/tests/utests/types/string.c b/tests/utests/types/string.c index 2f002b73a..a3d590e50 100644 --- a/tests/utests/types/string.c +++ b/tests/utests/types/string.c @@ -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"; diff --git a/tests/utests/types/union.c b/tests/utests/types/union.c index 257776b11..573abc7bf 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 type int8 value \"123456789012345678901\".\n" + " ly2 - leafref: Invalid type int64 value \"123456789012345678901\".\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); } @@ -294,9 +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", - "/lref:test/community[name='test']/view", 0); + " ly2 - leafref: Invalid leafref value \"one\" - no target instance \"../../a/name\" with the same value.\n" + " ly2 - leafref: Invalid type uint32 value \"one\".\n", "/lref:test/community[name='test']/view", 0); lyd_free_all(tree); } From 1648ec9526975878210ef2002ee7aff7d728217d Mon Sep 17 00:00:00 2001 From: roman Date: Thu, 16 Jan 2025 16:18:48 +0100 Subject: [PATCH 22/99] plugins types UPDATE index/ptr plugin retrieval --- src/parser_lyb.c | 4 +-- src/plugins.c | 56 +++++++++++++++++++++++++++++++++---- src/plugins_internal.h | 2 ++ src/plugins_types.c | 10 +++---- src/plugins_types/leafref.c | 14 +++++----- src/plugins_types/union.c | 46 +++++++++++++++--------------- src/printer_json.c | 2 +- src/printer_lyb.c | 7 ++--- src/printer_xml.c | 4 +-- src/schema_compile.c | 4 +-- src/schema_compile_node.c | 39 ++++++++++++++++---------- src/tree_data.c | 6 ++-- src/tree_data_common.c | 26 ++++++++--------- src/tree_data_free.c | 4 +-- src/tree_data_hash.c | 4 +-- src/tree_data_new.c | 16 +++++------ src/tree_data_sorted.c | 2 +- src/tree_schema.h | 31 ++++++++++++-------- src/validation.c | 4 +-- src/xpath.c | 10 +++---- tests/utests/types/binary.c | 2 +- tests/utests/types/bits.c | 2 +- tests/utests/types/int8.c | 6 ++-- tests/utests/types/string.c | 2 +- tests/utests/utests.h | 36 +++++++++++++----------- 25 files changed, 206 insertions(+), 133 deletions(-) diff --git a/src/parser_lyb.c b/src/parser_lyb.c index 3bccb76dd..c9276da13 100644 --- a/src/parser_lyb.c +++ b/src/parser_lyb.c @@ -266,9 +266,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_plugin(type_lf->realtype->plugin)->lyb_data_len; } else { - lyb_data_len = term->type->plugin->lyb_data_len; + lyb_data_len = lysc_get_type_plugin(term->type->plugin)->lyb_data_len; } if (lyb_data_len < 0) { diff --git a/src/plugins.c b/src/plugins.c index ea97eb19e..221a98c8e 100644 --- a/src/plugins.c +++ b/src/plugins.c @@ -132,6 +132,16 @@ static struct ly_set plugins_handlers = {0}; static struct ly_set plugins_types = {0}; static struct ly_set plugins_extensions = {0}; +LIBYANG_API_DEF struct lyplg_type * +lysc_get_type_plugin(uintptr_t plugin_id) +{ + if (plugin_id < plugins_types.count) { + return &((struct lyplg_type_record *)plugins_types.objs[plugin_id])->plugin; + } else { + return (struct lyplg_type *)plugin_id; + } +} + /** * @brief Iterate over list of loaded plugins of the given @p type. * @@ -162,7 +172,7 @@ plugins_iter(const struct ly_ctx *ctx, enum LYPLG type, uint32_t *index) } 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; @@ -178,6 +188,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,6 +200,37 @@ lyplg_record_find(const struct ly_ctx *ctx, enum LYPLG type, const char *module, return NULL; } +LY_ERR +_lyplg_type_plugin_find(const struct ly_ctx *ctx, const char *module, const char *revision, const char *name, uintptr_t *out) +{ + struct lyplg_type_record *record = NULL; + uint32_t record_idx; + + if (ctx) { + /* try to find context specific plugin */ + record = lyplg_record_find(ctx, LYPLG_TYPE, module, revision, name, &record_idx); + } + + if (!record) { + /* try to find shared plugin */ + record = lyplg_record_find(NULL, LYPLG_TYPE, module, revision, name, &record_idx); + } + + if (!record) { + return LY_ENOTFOUND; + } + + if (!strncmp(record->plugin.id, "ly2 - ", 6)) { + /* internal plugin, return an index */ + *out = record_idx; + } else { + /* external plugin, return the pointer */ + *out = (uintptr_t)&record->plugin; + } + + return LY_SUCCESS; +} + struct lyplg_type * lyplg_type_plugin_find(const struct ly_ctx *ctx, const char *module, const char *revision, const char *name) { @@ -192,12 +238,12 @@ lyplg_type_plugin_find(const struct ly_ctx *ctx, const char *module, const char if (ctx) { /* try to find context specific plugin */ - record = lyplg_record_find(ctx, LYPLG_TYPE, module, revision, name); + record = lyplg_record_find(ctx, LYPLG_TYPE, module, revision, name, NULL); } if (!record) { /* try to find shared plugin */ - record = lyplg_record_find(NULL, LYPLG_TYPE, module, revision, name); + record = lyplg_record_find(NULL, LYPLG_TYPE, module, revision, name, NULL); } return record ? &record->plugin : NULL; @@ -210,12 +256,12 @@ lyplg_ext_plugin_find(const struct ly_ctx *ctx, const char *module, const char * if (ctx) { /* try to find context specific plugin */ - record = lyplg_record_find(ctx, LYPLG_EXTENSION, module, revision, name); + record = lyplg_record_find(ctx, LYPLG_EXTENSION, module, revision, name, NULL); } if (!record) { /* try to find shared plugin */ - record = lyplg_record_find(NULL, LYPLG_EXTENSION, module, revision, name); + record = lyplg_record_find(NULL, LYPLG_EXTENSION, module, revision, name, NULL); } return record ? &record->plugin : NULL; diff --git a/src/plugins_internal.h b/src/plugins_internal.h index ac5484db3..d59a81214 100644 --- a/src/plugins_internal.h +++ b/src/plugins_internal.h @@ -60,6 +60,8 @@ LY_ERR lyplg_init(ly_bool builtin_type_plugins_only); */ void lyplg_clean(void); +LY_ERR _lyplg_type_plugin_find(const struct ly_ctx *ctx, const char *module, const char *revision, const char *name, uintptr_t *out); + /** * @brief Find a type plugin. * diff --git a/src/plugins_types.c b/src/plugins_types.c index a360b6653..ba8677132 100644 --- a/src/plugins_types.c +++ b/src/plugins_types.c @@ -907,7 +907,7 @@ lyplg_type_print_val(const struct lysc_node *node, const char *canon, LY_VALUE_F type = ((struct lysc_node_leaf *)node)->type; /* store the value */ - r = type->plugin->store(node->module->ctx, type, canon, strlen(canon), LYPLG_TYPE_STORE_ONLY, LY_VALUE_CANON, + r = lysc_get_type_plugin(type->plugin)->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) { @@ -918,7 +918,7 @@ lyplg_type_print_val(const struct lysc_node *node, const char *canon, LY_VALUE_F } /* print it in the specific format */ - v = type->plugin->print(node->module->ctx, &storage, format, prefix_data, &dyn, NULL); + v = lysc_get_type_plugin(type->plugin)->print(node->module->ctx, &storage, format, prefix_data, &dyn, NULL); /* store it in the dictionary, storage will be freed */ if (dyn) { @@ -927,7 +927,7 @@ lyplg_type_print_val(const struct lysc_node *node, const char *canon, LY_VALUE_F lydict_dup(node->module->ctx, v, value); } - type->plugin->free(node->module->ctx, &storage); + lysc_get_type_plugin(type->plugin)->free(node->module->ctx, &storage); return LY_SUCCESS; } @@ -1113,7 +1113,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 (!lysc_get_type_plugin(lref->plugin)->compare(LYD_CTX(node), &((struct lyd_node_term *)set.val.nodes[i].node)->value, value)) { break; } } @@ -1138,7 +1138,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 (!lysc_get_type_plugin(lref->plugin)->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); } diff --git a/src/plugins_types/leafref.c b/src/plugins_types/leafref.c index 78c3280bc..8de07dbdd 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_plugin(type_lr->realtype->plugin)->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_plugin(val1->realtype->plugin)->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_plugin(val1->realtype->plugin)->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_plugin(value->realtype->plugin)->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_plugin(original->realtype->plugin)->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_plugin(value->realtype->plugin)->free(ctx, value); } /** diff --git a/src/plugins_types/union.c b/src/plugins_types/union.c index 944ca61ff..230eda975 100644 --- a/src/plugins_types/union.c +++ b/src/plugins_types/union.c @@ -227,9 +227,10 @@ 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)) { + rc = lysc_get_type_plugin(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 != LY_SUCCESS) && (rc != LY_EINCOMPLETE)) { /* clear any leftover/freed garbage */ memset(&subvalue->value, 0, sizeof subvalue->value); @@ -239,14 +240,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_plugin(subvalue->value.realtype->plugin)->print(ctx, &subvalue->value, + LY_VALUE_JSON, NULL, &dynamic, &value_len); /* to avoid leaks, free subvalue->value, but we need the value, which may be stored there */ if (!dynamic) { value = strndup(value, value_len); dynamic = 1; } - type_u->types[ti]->plugin->free(ctx, &subvalue->value); + lysc_get_type_plugin(type_u->types[ti]->plugin)->free(ctx, &subvalue->value); format = LY_VALUE_JSON; prefix_data = NULL; @@ -265,9 +267,9 @@ 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)) { + rc = lysc_get_type_plugin(type->plugin)->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 +280,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 = lysc_get_type_plugin(type->plugin)->validate(ctx, type, ctx_node, tree, &subvalue->value, err); if (rc) { /* validate failed, we need to free the stored value */ - type->plugin->free(ctx, &subvalue->value); + lysc_get_type_plugin(type->plugin)->free(ctx, &subvalue->value); goto cleanup; } } @@ -370,9 +372,9 @@ 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); + msg = ly_realloc(msg, msg_len + 4 + strlen(lysc_get_type_plugin(type_u->types[u]->plugin)->id) + 2 + strlen(errs[u]->msg) + 2); LY_CHECK_ERR_GOTO(!msg, ret = LY_EMEM, cleanup); - msg_len += sprintf(msg + msg_len, " %s: %s\n", type_u->types[u]->plugin->id, errs[u]->msg); + msg_len += sprintf(msg + msg_len, " %s: %s\n", lysc_get_type_plugin(type_u->types[u]->plugin)->id, errs[u]->msg); } if (!use_err_app_tag) { @@ -517,8 +519,8 @@ lyplg_type_validate_union(const struct ly_ctx *ctx, const struct lysc_type *type /* 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); + LY_CHECK_RET(lysc_get_type_plugin(subvalue->value.realtype->plugin)->duplicate(ctx, &subvalue->value, &orig)); + lysc_get_type_plugin(subvalue->value.realtype->plugin)->free(ctx, &subvalue->value); if (subvalue->format == LY_VALUE_LYB) { /* use the specific type to store and validate the value */ @@ -548,7 +550,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_plugin(orig.realtype->plugin)->free(ctx, &orig); return LY_SUCCESS; } @@ -558,7 +560,7 @@ 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_plugin(val1->subvalue->value.realtype->plugin)->compare(ctx, &val1->subvalue->value, &val2->subvalue->value); } LIBYANG_API_DEF int @@ -569,7 +571,7 @@ 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_plugin(val1->subvalue->value.realtype->plugin)->sort(ctx, &val1->subvalue->value, &val2->subvalue->value); } /* compare according to the order of types */ @@ -628,13 +630,13 @@ 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_plugin(subvalue->value.realtype->plugin)->free(ctx, &subvalue->value); r = union_find_type(ctx, type_u, subvalue, 0, 0, NULL, NULL, &type_idx, NULL, &err); ly_err_free(err); LY_CHECK_RET((r != LY_SUCCESS) && (r != LY_EINCOMPLETE), NULL); /* Print subvalue in LYB format. */ - pval = (void *)subvalue->value.realtype->plugin->print(NULL, &subvalue->value, LY_VALUE_LYB, prefix_data, &dynamic, + pval = (void *)lysc_get_type_plugin(subvalue->value.realtype->plugin)->print(NULL, &subvalue->value, LY_VALUE_LYB, prefix_data, &dynamic, &pval_len); LY_CHECK_RET(!pval, NULL); @@ -682,7 +684,7 @@ 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_plugin(subvalue->value.realtype->plugin)->print(ctx, &subvalue->value, format, prefix_data, dynamic, value_len); if (!value->_canonical && (format == LY_VALUE_CANON)) { /* the canonical value is supposed to be stored now */ lydict_insert(ctx, subvalue->value._canonical, 0, (const char **)&value->_canonical); @@ -708,7 +710,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_plugin(orig_val->value.realtype->plugin)->duplicate(ctx, &orig_val->value, &dup_val->value); LY_CHECK_GOTO(ret, cleanup); if (orig_val->orig_len) { @@ -744,7 +746,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_plugin(val->value.realtype->plugin)->free(ctx, &val->value); } lyplg_type_prefix_data_free(val->format, val->prefix_data); free(val->original); diff --git a/src/printer_json.c b/src/printer_json.c index 233bc0254..d7f6e909f 100644 --- a/src/printer_json.c +++ b/src/printer_json.c @@ -354,7 +354,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_plugin(val->realtype->plugin)->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 30f34c051..773c11c23 100644 --- a/src/printer_lyb.c +++ b/src/printer_lyb.c @@ -619,14 +619,13 @@ lyb_print_term_value(struct lyd_node_term *term, struct ly_out *out, struct lyly int32_t lyb_data_len; lyplg_type_print_clb print; - assert(term->value.realtype && term->value.realtype->plugin && term->value.realtype->plugin->print && - term->schema); + assert(term->value.realtype && lysc_get_type_plugin(term->value.realtype->plugin)->print && term->schema); /* Get length of LYB data to print. */ - lyb_data_len = term->value.realtype->plugin->lyb_data_len; + lyb_data_len = lysc_get_type_plugin(term->value.realtype->plugin)->lyb_data_len; /* Get value and also print its length only if size is not fixed. */ - print = term->value.realtype->plugin->print; + print = lysc_get_type_plugin(term->value.realtype->plugin)->print; if (lyb_data_len < 0) { /* Variable-length data. */ diff --git a/src/printer_xml.c b/src/printer_xml.c index 3e11fe14b..f5c785b6f 100644 --- a/src/printer_xml.c +++ b/src/printer_xml.c @@ -233,7 +233,7 @@ 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_plugin(meta->value.realtype->plugin)->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,7 +358,7 @@ 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, + value = lysc_get_type_plugin(((struct lysc_node_leaf *)node->schema)->type->plugin)->print(LYD_CTX(node), &node->value, LY_VALUE_XML, &ns_list, &dynamic, NULL); LY_CHECK_ERR_GOTO(!value, rc = LY_EINVAL, cleanup); diff --git a/src/schema_compile.c b/src/schema_compile.c index 73b419ca2..6eabb6964 100644 --- a/src/schema_compile.c +++ b/src/schema_compile.c @@ -898,7 +898,7 @@ lys_compile_unres_dflt(struct lysc_ctx *ctx, struct lysc_node *node, struct lysc LY_VALUE_FORMAT format; options = (ctx->ctx->opts & LY_CTX_REF_IMPLEMENTED) ? LYPLG_TYPE_STORE_IMPLEMENT : 0; - rc = type->plugin->store(ctx->ctx, type, dflt, strlen(dflt), options, LY_VALUE_SCHEMA, (void *)dflt_pmod, + rc = lysc_get_type_plugin(type->plugin)->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 */ @@ -936,7 +936,7 @@ lys_compile_unres_dflt(struct lysc_ctx *ctx, struct lysc_node *node, struct lysc ly_path_free(val->target); val->target = NULL; } - type->plugin->free(ctx->ctx, &storage); + lysc_get_type_plugin(type->plugin)->free(ctx->ctx, &storage); return LY_SUCCESS; } diff --git a/src/schema_compile_node.c b/src/schema_compile_node.c index 65f81ab45..ff65258ff 100644 --- a/src/schema_compile_node.c +++ b/src/schema_compile_node.c @@ -1786,7 +1786,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, struct ly_set *tpdf_chain, uint32_t tpdf_chain_last, struct lysc_type **type) { LY_ERR rc = LY_SUCCESS; struct lysc_type_bin *bin; @@ -2146,7 +2146,7 @@ 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, struct lysc_type **type, const char **units, struct lysp_qname **dflt) { - LY_ERR ret = LY_SUCCESS; + LY_ERR ret = LY_SUCCESS, r; ly_bool dummyloops = 0, has_leafref; struct lys_type_item *tctx, *tctx_prev = NULL, *tctx_iter; LY_DATA_TYPE basetype = LY_TYPE_UNKNOWN; @@ -2154,7 +2154,8 @@ 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_id = -1; + ly_bool plugin_found = 0; *type = NULL; if (dflt) { @@ -2277,20 +2278,26 @@ 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, - tctx->tpdf->name); - if (!plugin && base) { + r = _lyplg_type_plugin_find(ctx->ctx, tctx->tpdf->type.pmod->mod->name, tctx->tpdf->type.pmod->mod->revision, + tctx->tpdf->name, &plugin_id); + if (r == LY_SUCCESS) { + plugin_found = 1; + } else if ((r == LY_ENOTFOUND) && base) { /* use the base type implementation if available */ - plugin = base->plugin; + plugin_id = base->plugin; + plugin_found = 1; } - if (!plugin) { + if (!plugin_found) { /* use the internal built-in type implementation */ - plugin = lyplg_type_plugin_find(ctx->ctx, "", NULL, ly_data_type2str[basetype]); + r = _lyplg_type_plugin_find(ctx->ctx, "", NULL, ly_data_type2str[basetype], &plugin_id); + if (r == LY_SUCCESS) { + plugin_found = 1; + } } - assert(plugin); + assert(plugin_found); 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_id == base->plugin)) { /* no change, reuse the compiled base */ ((struct lysp_tpdf *)tctx->tpdf)->type.compiled = base; LY_ATOMIC_INC_BARRIER(base->refcount); @@ -2311,7 +2318,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_id, &tpdf_chain, u + 1, &base); LY_CHECK_GOTO(ret, cleanup); /* store separately compiled typedef type to be reused */ @@ -2342,9 +2349,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_id = base->plugin; + } else { + _lyplg_type_plugin_find(ctx->ctx, "", NULL, ly_data_type2str[basetype], &plugin_id); + } 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_id, &tpdf_chain, 0, type); LY_CHECK_GOTO(ret, cleanup); } else { /* no changes of the type in the leaf, just use the base compiled type */ diff --git a/src/tree_data.c b/src/tree_data.c index b7a79c220..556f1f580 100644 --- a/src/tree_data.c +++ b/src/tree_data.c @@ -1883,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_plugin(meta1->value.realtype->plugin)->compare(ctx, &meta1->value, &meta2->value); } /** @@ -2259,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_plugin(orig->value.realtype->plugin)->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 */ @@ -2562,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_plugin(meta->value.realtype->plugin)->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); diff --git a/src/tree_data_common.c b/src/tree_data_common.c index 26e163283..dc3d45670 100644 --- a/src/tree_data_common.c +++ b/src/tree_data_common.c @@ -532,7 +532,7 @@ lyd_value_store(const struct ly_ctx *ctx, struct lyd_value *val, const struct ly options |= LYPLG_TYPE_STORE_ONLY; } - r = type->plugin->store(ctx, type, value, value_len, options, format, prefix_data, hints, ctx_node, val, NULL, &err); + r = lysc_get_type_plugin(type->plugin)->store(ctx, type, value, value_len, options, format, prefix_data, hints, ctx_node, val, NULL, &err); if (dynamic) { *dynamic = 0; } @@ -561,16 +561,16 @@ lyd_value_validate_incomplete(const struct ly_ctx *ctx, const struct lysc_type * LY_ERR ret; struct ly_err_item *err = NULL; - assert(type->plugin->validate); + assert(lysc_get_type_plugin(type->plugin)->validate); - ret = type->plugin->validate(ctx, type, ctx_node, tree, val, &err); + ret = lysc_get_type_plugin(type->plugin)->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 *)lysc_get_type_plugin(type->plugin)->print(ctx, val, LY_VALUE_CANON, NULL, NULL, NULL)); } return ret; } @@ -595,7 +595,7 @@ 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, + rc = lysc_get_type_plugin(type->plugin)->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 */ @@ -609,7 +609,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_plugin(type->plugin)->free(ctx ? ctx : node->module->ctx, &storage); } return rc; } @@ -644,14 +644,14 @@ lyd_value_validate2(const struct ly_ctx *ctx, const struct lysc_node *schema, co type = ((struct lysc_node_leaf *)schema)->type; /* store */ - rc = type->plugin->store(ctx, type, value, value_len, 0, format, prefix_data, LYD_HINT_DATA, schema, &val, NULL, &err); + rc = lysc_get_type_plugin(type->plugin)->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 = lysc_get_type_plugin(type->plugin)->validate(ctx, type, ctx_node, ctx_node, &val, &err); } if (rc && (rc != LY_EINCOMPLETE) && err) { @@ -674,13 +674,13 @@ lyd_value_validate2(const struct ly_ctx *ctx, const struct lysc_node *schema, co if (canonical) { /* return canonical value */ - lydict_dup(ctx, val.realtype->plugin->print(ctx, &val, LY_VALUE_CANON, NULL, NULL, NULL), canonical); + lydict_dup(ctx, lysc_get_type_plugin(val.realtype->plugin)->print(ctx, &val, LY_VALUE_CANON, NULL, NULL, NULL), canonical); } } if (stored) { /* free value */ - type->plugin->free(ctx, &val); + lysc_get_type_plugin(type->plugin)->free(ctx, &val); } return rc; } @@ -705,9 +705,9 @@ 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); + ret = lysc_get_type_plugin(type->plugin)->compare(ctx, &node->value, &val); - type->plugin->free(ctx, &val); + lysc_get_type_plugin(type->plugin)->free(ctx, &val); return ret; } @@ -983,7 +983,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_plugin(value->realtype->plugin)->print(ctx, value, LY_VALUE_CANON, NULL, NULL, NULL); } LIBYANG_API_DEF LY_ERR diff --git a/src/tree_data_free.c b/src/tree_data_free.c index fba97bc17..11211b979 100644 --- a/src/tree_data_free.c +++ b/src/tree_data_free.c @@ -64,7 +64,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_plugin(meta->value.realtype->plugin)->free(meta->annotation->module->ctx, &meta->value); free(meta); } } @@ -235,7 +235,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_plugin(((struct lysc_node_leaf *)node->schema)->type->plugin)->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..66ba634e4 100644 --- a/src/tree_data_hash.c +++ b/src/tree_data_hash.c @@ -55,7 +55,7 @@ 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_plugin(key->value.realtype->plugin)->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 +66,7 @@ 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_plugin(llist->value.realtype->plugin)->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_new.c b/src/tree_data_new.c index 3a6965428..54671e1ae 100644 --- a/src/tree_data_new.c +++ b/src/tree_data_new.c @@ -1225,11 +1225,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); + lysc_get_type_plugin(term->value.realtype->plugin)->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 = lysc_get_type_plugin(((struct lysc_node_leaf *)term->schema)->type->plugin)->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 */ @@ -1245,11 +1245,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); + lysc_get_type_plugin(term->value.realtype->plugin)->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 = lysc_get_type_plugin(((struct lysc_node_leaf *)term->schema)->type->plugin)->duplicate(LYD_CTX(term), val, &term->value); } /* update hash */ @@ -1262,11 +1262,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); + lysc_get_type_plugin(term->value.realtype->plugin)->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(lysc_get_type_plugin(((struct lysc_node_leaf *)term->schema)->type->plugin)->duplicate(LYD_CTX(term), val, &term->value)); } /* update hash */ @@ -1291,7 +1291,7 @@ lyd_change_term_val(struct lyd_node *term, struct lyd_value *val, ly_bool use_va type = ((struct lysc_node_leaf *)term->schema)->type; /* compare original and new value */ - if (type->plugin->compare(LYD_CTX(term), &t->value, val)) { + if (lysc_get_type_plugin(type->plugin)->compare(LYD_CTX(term), &t->value, val)) { /* since they are different, they cannot both be default */ assert(!(term->flags & LYD_DEFAULT) || !is_dflt); @@ -1301,7 +1301,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); + lysc_get_type_plugin(type->plugin)->free(LYD_CTX(term), val); } val_change = 0; } diff --git a/src/tree_data_sorted.c b/src/tree_data_sorted.c index ce0820ce7..473bc077f 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_plugin(val1->realtype->plugin)->sort(ctx, val1, val2); } /** diff --git a/src/tree_schema.h b/src/tree_schema.h index 123e4a830..c4bbd5835 100644 --- a/src/tree_schema.h +++ b/src/tree_schema.h @@ -1279,7 +1279,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; /**< type's manipulation callbacks plugin use lysc_get_type_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) */ @@ -1288,7 +1288,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; /**< type's manipulation callbacks plugin */ LY_DATA_TYPE basetype; /**< base type of the type */ uint32_t refcount; /**< reference counter for type sharing */ @@ -1298,7 +1298,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; /**< type's manipulation callbacks plugin */ LY_DATA_TYPE basetype; /**< base type of the type */ uint32_t refcount; /**< reference counter for type sharing */ @@ -1309,7 +1309,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; /**< type's manipulation callbacks plugin */ LY_DATA_TYPE basetype; /**< base type of the type */ uint32_t refcount; /**< reference counter for type sharing */ @@ -1334,7 +1334,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; /**< type's manipulation callbacks plugin */ LY_DATA_TYPE basetype; /**< base type of the type */ uint32_t refcount; /**< reference counter for type sharing */ @@ -1344,7 +1344,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; /**< type's manipulation callbacks plugin */ LY_DATA_TYPE basetype; /**< base type of the type */ uint32_t refcount; /**< reference counter for type sharing */ @@ -1355,7 +1355,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; /**< type's manipulation callbacks plugin */ LY_DATA_TYPE basetype; /**< base type of the type */ uint32_t refcount; /**< reference counter for type sharing */ @@ -1368,7 +1368,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; /**< type's manipulation callbacks plugin */ LY_DATA_TYPE basetype; /**< base type of the type */ uint32_t refcount; /**< reference counter for type sharing */ @@ -1379,7 +1379,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; /**< type's manipulation callbacks plugin */ LY_DATA_TYPE basetype; /**< base type of the type */ uint32_t refcount; /**< reference counter for type sharing */ @@ -1389,7 +1389,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; /**< type's manipulation callbacks plugin */ LY_DATA_TYPE basetype; /**< base type of the type */ uint32_t refcount; /**< reference counter for type sharing */ @@ -1399,7 +1399,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; /**< type's manipulation callbacks plugin */ LY_DATA_TYPE basetype; /**< base type of the type */ uint32_t refcount; /**< reference counter for type sharing */ @@ -1797,6 +1797,15 @@ 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 + * + * @param[in] plugin_id The plugin identifier + * + * @return { description_of_the_return_value } + */ +LIBYANG_API_DECL struct lyplg_type *lysc_get_type_plugin(uintptr_t plugin_id); + /** * @brief Get nearest @p schema parent (including the node itself) that can be instantiated in data. * diff --git a/src/validation.c b/src/validation.c index 38eb4d7cd..a2f768c24 100644 --- a/src/validation.c +++ b/src/validation.c @@ -1945,14 +1945,14 @@ 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_plugin(type->plugin)->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_plugin(((struct lysc_node_leaf *)node->schema)->type->plugin)->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 beb1c7f50..7695b9986 100644 --- a/src/xpath.c +++ b/src/xpath.c @@ -1714,15 +1714,15 @@ set_comp_canonize(struct lyxp_set *set, const struct lyxp_set_node *xp_node) } /* 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) && (lysc_get_type_plugin(type->plugin)->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) && (lysc_get_type_plugin(type->plugin)->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) && (lysc_get_type_plugin(type->plugin)->store == lyplg_type_store_enum)) { /* enumeration */ return LY_SUCCESS; } @@ -3643,7 +3643,7 @@ 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, + rc = lysc_get_type_plugin(type->plugin)->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; @@ -3660,7 +3660,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); + lysc_get_type_plugin(type->plugin)->free(set->ctx, &storage); } } free(value); diff --git a/tests/utests/types/binary.c b/tests/utests/types/binary.c index 6abf26fb8..0fc2db3bf 100644 --- a/tests/utests/types/binary.c +++ b/tests/utests/types/binary.c @@ -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)->print(UTEST_LYCTX, &(value), LY_VALUE_CANON, NULL, NULL, NULL)); type->free(UTEST_LYCTX, &value); } diff --git a/tests/utests/types/bits.c b/tests/utests/types/bits.c index 15304a242..311bd3a1d 100644 --- a/tests/utests/types/bits.c +++ b/tests/utests/types/bits.c @@ -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)->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]))); diff --git a/tests/utests/types/int8.c b/tests/utests/types/int8.c index 0be4ad83d..7125e9beb 100644 --- a/tests/utests/types/int8.c +++ b/tests/utests/types/int8.c @@ -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)->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)->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)->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]))); diff --git a/tests/utests/types/string.c b/tests/utests/types/string.c index a3d590e50..94bc8ea42 100644 --- a/tests/utests/types/string.c +++ b/tests/utests/types/string.c @@ -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)->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]))); diff --git a/tests/utests/utests.h b/tests/utests/utests.h index ddfa95b2b..19502dfab 100644 --- a/tests/utests/utests.h +++ b/tests/utests/utests.h @@ -230,7 +230,11 @@ 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])) + do { \ + uintptr_t plugin_id; \ + _lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[TYPE], &plugin_id); \ + assert_ptr_equal((NODE)->plugin, plugin_id); \ + } while (0) /** * @brief check compileted numeric type @@ -934,7 +938,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(lysc_get_type_plugin((NODE).realtype->plugin)->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ assert_string_equal((NODE)._canonical, CANNONICAL_VAL); \ assert_non_null((NODE).realtype); \ assert_int_equal((NODE).realtype->basetype, LY_TYPE_EMPTY); @@ -952,7 +956,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(lysc_get_type_plugin((NODE).realtype->plugin)->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ assert_string_equal((NODE)._canonical, CANNONICAL_VAL); \ assert_non_null((NODE).realtype); \ assert_int_equal(LY_TYPE_UNION, (NODE).realtype->basetype); \ @@ -974,7 +978,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(lysc_get_type_plugin((NODE).realtype->plugin)->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ assert_string_equal((NODE)._canonical, _GETARG1(__VA_ARGS__, DUMMY)); \ assert_non_null((NODE).realtype); \ assert_int_equal(LY_TYPE_BITS, (NODE).realtype->basetype); \ @@ -998,7 +1002,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(lysc_get_type_plugin((NODE).realtype->plugin)->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ assert_string_equal((NODE)._canonical, CANNONICAL_VAL); \ assert_non_null((NODE).realtype); \ assert_int_equal(LY_TYPE_INST, (NODE).realtype->basetype); \ @@ -1021,7 +1025,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(lysc_get_type_plugin((NODE).realtype->plugin)->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ assert_string_equal((NODE)._canonical, CANNONICAL_VAL); \ assert_non_null((NODE).realtype); \ assert_int_equal(LY_TYPE_ENUM, (NODE).realtype->basetype); \ @@ -1036,7 +1040,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(lysc_get_type_plugin((NODE).realtype->plugin)->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ assert_string_equal((NODE)._canonical, CANNONICAL_VAL); \ assert_non_null((NODE).realtype); \ assert_int_equal(LY_TYPE_INT8, (NODE).realtype->basetype); \ @@ -1051,7 +1055,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(lysc_get_type_plugin((NODE).realtype->plugin)->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ assert_string_equal((NODE)._canonical, CANNONICAL_VAL); \ assert_non_null((NODE).realtype); \ assert_int_equal(LY_TYPE_INT16, (NODE).realtype->basetype); \ @@ -1066,7 +1070,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(lysc_get_type_plugin((NODE).realtype->plugin)->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ assert_string_equal((NODE)._canonical, CANNONICAL_VAL); \ assert_non_null((NODE).realtype); \ assert_int_equal(LY_TYPE_UINT8, (NODE).realtype->basetype); \ @@ -1081,7 +1085,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(lysc_get_type_plugin((NODE).realtype->plugin)->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ assert_string_equal((NODE)._canonical, CANNONICAL_VAL); \ assert_non_null((NODE).realtype); \ assert_int_equal(LY_TYPE_UINT32, (NODE).realtype->basetype); \ @@ -1095,7 +1099,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(lysc_get_type_plugin((NODE).realtype->plugin)->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ assert_string_equal((NODE)._canonical, CANNONICAL_VAL); \ assert_non_null((NODE).realtype); \ assert_int_equal(LY_TYPE_STRING, (NODE).realtype->basetype); @@ -1108,7 +1112,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(lysc_get_type_plugin((NODE).realtype->plugin)->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ assert_string_equal((NODE)._canonical, CANNONICAL_VAL); \ assert_non_null((NODE).realtype); \ assert_int_equal(LY_TYPE_LEAFREF, (NODE).realtype->basetype); \ @@ -1123,7 +1127,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(lysc_get_type_plugin((NODE).realtype->plugin)->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ assert_string_equal((NODE)._canonical, CANNONICAL_VAL); \ assert_non_null((NODE).realtype); \ assert_int_equal(LY_TYPE_DEC64, (NODE).realtype->basetype); \ @@ -1144,7 +1148,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(lysc_get_type_plugin((NODE).realtype->plugin)->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ assert_string_equal((NODE)._canonical, CANNONICAL_VAL); \ assert_non_null((NODE).realtype); \ assert_int_equal(LY_TYPE_BINARY, (NODE).realtype->basetype); \ @@ -1159,7 +1163,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(lysc_get_type_plugin((NODE).realtype->plugin)->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ assert_string_equal((NODE)._canonical, CANNONICAL_VAL); \ assert_non_null((NODE).realtype); \ assert_int_equal(LY_TYPE_BOOL, (NODE).realtype->basetype); \ @@ -1174,7 +1178,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(lysc_get_type_plugin((NODE).realtype->plugin)->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ assert_string_equal((NODE)._canonical, CANNONICAL_VAL); \ assert_non_null((NODE).realtype); \ assert_int_equal(LY_TYPE_IDENT, (NODE).realtype->basetype); \ From e3eb39a31116e80fe40204e3341085110c224005 Mon Sep 17 00:00:00 2001 From: roman Date: Fri, 17 Jan 2025 14:41:04 +0100 Subject: [PATCH 23/99] context UPDATE widen options from 16 to 32-bit --- src/context.c | 8 ++++---- src/context.h | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/context.c b/src/context.c index 560367523..80d1f6658 100644 --- a/src/context.c +++ b/src/context.c @@ -271,7 +271,7 @@ ly_ctx_ht_leafref_links_equal_cb(void *val1_p, void *val2_p, ly_bool UNUSED(mod) } 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; @@ -609,7 +609,7 @@ 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); @@ -618,7 +618,7 @@ ly_ctx_get_options(const struct ly_ctx *ctx) } 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_data *ctx_data; @@ -694,7 +694,7 @@ ly_ctx_ht_leafref_links_rec_free(void *val_p) } 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; diff --git a/src/context.h b/src/context.h index bb789402a..74fd326cc 100644 --- a/src/context.h +++ b/src/context.h @@ -236,7 +236,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. @@ -356,7 +356,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. @@ -366,7 +366,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. @@ -374,7 +374,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. From 2ac4dbd9298c58c80b2247d34b59d47b131690b8 Mon Sep 17 00:00:00 2001 From: roman Date: Fri, 17 Jan 2025 15:04:40 +0100 Subject: [PATCH 24/99] context UPDATE add static plugins only flag --- src/context.c | 20 +++++++++++++++++--- src/context.h | 4 ++++ src/plugins.c | 12 +++++++----- src/plugins_internal.h | 3 ++- 4 files changed, 30 insertions(+), 9 deletions(-) diff --git a/src/context.c b/src/context.c index 80d1f6658..690f31f34 100644 --- a/src/context.c +++ b/src/context.c @@ -282,7 +282,7 @@ ly_ctx_new(const char *search_dir, uint32_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); @@ -294,7 +294,8 @@ ly_ctx_new(const char *search_dir, uint32_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); + 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); /* ctx data */ ctx_data = ly_ctx_data_add(ctx); @@ -636,6 +637,13 @@ ly_ctx_set_options(struct ly_ctx *ctx, uint32_t option) return LY_EINVAL; } + 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)) { ctx_data = ly_ctx_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); @@ -1410,7 +1418,7 @@ ly_ctx_compiled_print(const struct ly_ctx *ctx, void *mem, void **mem_end) LY_CHECK_ARG_RET(ctx, ctx, mem, LY_EINVAL); - if (ctx->plugins_types.count || ctx->plugins_extensions.count) { + 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; } @@ -1448,6 +1456,7 @@ ly_ctx_new_printed(const void *mem, struct ly_ctx **ctx) { LY_ERR rc = LY_SUCCESS; struct ly_ctx_data *ctx_data = NULL; + ly_bool builtin_plugins_only, static_plugins_only; LY_CHECK_ARG_RET(NULL, mem, ctx, LY_EINVAL); @@ -1456,6 +1465,11 @@ ly_ctx_new_printed(const void *mem, struct ly_ctx **ctx) /* ctx data */ ctx_data = ly_ctx_data_add(*ctx); + /* 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); + /* data dictionary */ ctx_data->data_dict = malloc(sizeof *ctx_data->data_dict); LY_CHECK_ERR_GOTO(!ctx_data->data_dict, rc = LY_EMEM, cleanup); diff --git a/src/context.h b/src/context.h index 74fd326cc..e96f0b402 100644 --- a/src/context.h +++ b/src/context.h @@ -209,6 +209,10 @@ struct ly_ctx; invalid data needs to be stored in YANG node values. */ #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 /**< By default, external plugins from directories the path to which is obtained + from the `LIBYANG_TYPES_PLUGINS_DIR` and `LIBYANG_EXTENSIONS_PLUGINS_DIR` environmental variables + are loaded. This option prevents loading of all external plugins and only + the static (built-in) plugins are loaded. /* 0x80000000 reserved for internal use */ diff --git a/src/plugins.c b/src/plugins.c index 221a98c8e..4ff61ef78 100644 --- a/src/plugins.c +++ b/src/plugins.c @@ -526,7 +526,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; @@ -587,11 +587,13 @@ lyplg_init(ly_bool builtin_type_plugins_only) } #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_internal.h b/src/plugins_internal.h index d59a81214..0f561869f 100644 --- a/src/plugins_internal.h +++ b/src/plugins_internal.h @@ -49,11 +49,12 @@ * 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 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. From c9e640603375c654befa828a727ab95993ddcae2 Mon Sep 17 00:00:00 2001 From: roman Date: Fri, 17 Jan 2025 15:33:35 +0100 Subject: [PATCH 25/99] plugins extension REFACTOR add a dash to ext IDs --- src/plugins_exts/metadata.c | 2 +- src/plugins_exts/nacm.c | 8 +++---- src/plugins_exts/schema_mount.c | 2 +- src/plugins_exts/structure.c | 4 ++-- src/plugins_exts/yangdata.c | 2 +- src/tree_data.c | 2 +- tests/utests/extensions/test_metadata.c | 8 +++---- tests/utests/extensions/test_nacm.c | 8 +++---- tests/utests/extensions/test_schema_mount.c | 26 ++++++++++----------- tests/utests/extensions/test_structure.c | 6 ++--- tests/utests/extensions/test_yangdata.c | 14 +++++------ 11 files changed, 41 insertions(+), 41 deletions(-) diff --git a/src/plugins_exts/metadata.c b/src/plugins_exts/metadata.c index e699e120e..f6f37b45b 100644 --- a/src/plugins_exts/metadata.c +++ b/src/plugins_exts/metadata.c @@ -257,7 +257,7 @@ const struct lyplg_ext_record plugins_metadata[] = { .revision = "2016-08-05", .name = "annotation", - .plugin.id = "ly2 metadata", + .plugin.id = "ly2 - metadata", .plugin.parse = annotation_parse, .plugin.compile = annotation_compile, .plugin.printer_info = annotation_printer_info, diff --git a/src/plugins_exts/nacm.c b/src/plugins_exts/nacm.c index 85f1722d9..8bd77a6ce 100644 --- a/src/plugins_exts/nacm.c +++ b/src/plugins_exts/nacm.c @@ -173,7 +173,7 @@ const struct lyplg_ext_record plugins_nacm[] = { .revision = "2012-02-22", .name = "default-deny-write", - .plugin.id = "ly2 NACM", + .plugin.id = "ly2 - NACM", .plugin.parse = nacm_parse, .plugin.compile = nacm_compile, .plugin.printer_info = NULL, @@ -191,7 +191,7 @@ const struct lyplg_ext_record plugins_nacm[] = { .revision = "2018-02-14", .name = "default-deny-write", - .plugin.id = "ly2 NACM", + .plugin.id = "ly2 - NACM", .plugin.parse = nacm_parse, .plugin.compile = nacm_compile, .plugin.printer_info = NULL, @@ -209,7 +209,7 @@ const struct lyplg_ext_record plugins_nacm[] = { .revision = "2012-02-22", .name = "default-deny-all", - .plugin.id = "ly2 NACM", + .plugin.id = "ly2 - NACM", .plugin.parse = nacm_parse, .plugin.compile = nacm_compile, .plugin.printer_info = NULL, @@ -227,7 +227,7 @@ const struct lyplg_ext_record plugins_nacm[] = { .revision = "2018-02-14", .name = "default-deny-all", - .plugin.id = "ly2 NACM", + .plugin.id = "ly2 - NACM", .plugin.parse = nacm_parse, .plugin.compile = nacm_compile, .plugin.printer_info = NULL, diff --git a/src/plugins_exts/schema_mount.c b/src/plugins_exts/schema_mount.c index 325f8427b..bc23d62a8 100644 --- a/src/plugins_exts/schema_mount.c +++ b/src/plugins_exts/schema_mount.c @@ -1422,7 +1422,7 @@ const struct lyplg_ext_record plugins_schema_mount[] = { .revision = "2019-01-14", .name = "mount-point", - .plugin.id = "ly2 schema mount", + .plugin.id = "ly2 - schema mount", .plugin.parse = schema_mount_parse, .plugin.compile = schema_mount_compile, .plugin.printer_info = NULL, diff --git a/src/plugins_exts/structure.c b/src/plugins_exts/structure.c index 618221368..b1463f912 100644 --- a/src/plugins_exts/structure.c +++ b/src/plugins_exts/structure.c @@ -563,7 +563,7 @@ const struct lyplg_ext_record plugins_structure[] = { .revision = "2020-06-17", .name = "structure", - .plugin.id = "ly2 structure", + .plugin.id = "ly2 - structure", .plugin.parse = structure_parse, .plugin.compile = structure_compile, .plugin.printer_info = structure_printer_info, @@ -582,7 +582,7 @@ const struct lyplg_ext_record plugins_structure[] = { .revision = "2020-06-17", .name = "augment-structure", - .plugin.id = "ly2 structure", + .plugin.id = "ly2 - structure", .plugin.parse = structure_aug_parse, .plugin.compile = NULL, .plugin.printer_info = NULL, diff --git a/src/plugins_exts/yangdata.c b/src/plugins_exts/yangdata.c index 917ce19dd..ea3bc9b10 100644 --- a/src/plugins_exts/yangdata.c +++ b/src/plugins_exts/yangdata.c @@ -278,7 +278,7 @@ const struct lyplg_ext_record plugins_yangdata[] = { .revision = "2017-01-26", .name = "yang-data", - .plugin.id = "ly2 yang-data", + .plugin.id = "ly2 - yang-data", .plugin.parse = yangdata_parse, .plugin.compile = yangdata_compile, .plugin.printer_info = yangdata_printer_info, diff --git a/src/tree_data.c b/src/tree_data.c index 556f1f580..ccbee7710 100644 --- a/src/tree_data.c +++ b/src/tree_data.c @@ -1340,7 +1340,7 @@ 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) && + if (plugin && !strncmp(plugin->id, "ly2 - metadata", 12) && !ly_strncmp(mod->compiled->exts[u].argument, name, name_len)) { return &mod->compiled->exts[u]; } diff --git a/tests/utests/extensions/test_metadata.c b/tests/utests/extensions/test_metadata.c index c3b58b2b1..f526323ad 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\": 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\": 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\": 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\": 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 9cbad1e3f..44daf3bf0 100644 --- a/tests/utests/extensions/test_nacm.c +++ b/tests/utests/extensions/test_nacm.c @@ -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\": " + 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\": " + 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); } @@ -98,7 +98,7 @@ test_deny_write(void **state) "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\": " + 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\": " + 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 f521d1bcf..4b0486895 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\": " + 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\": " + 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\": " + 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\": " + CHECK_LOG_CTX("Ext plugin \"ly2 - schema mount\": " "Multiple extension \"yangmnt:mount-point\" instances.", "/sm:l/{extension='yangmnt:mount-point'}/root", 0); @@ -196,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\": 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 = @@ -213,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\": 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 */ @@ -401,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\": 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\": 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\": 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\": 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); @@ -865,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\": " + 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); @@ -1121,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\": " + 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); @@ -1146,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\": " + 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 026f6e7db..d67c001dd 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\": " + 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\": 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\": 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 3977992da..424789369 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\": " + 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\": " + 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\": " + 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\": " + 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\": " + 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\": " + 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\": " + 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); } From 3c0a0776e8685aae54dcb3748c02eadee168ed91 Mon Sep 17 00:00:00 2001 From: roman Date: Mon, 20 Jan 2025 11:11:37 +0100 Subject: [PATCH 26/99] plugins types UPDATE simplify type plugin getter --- src/context.h | 2 +- src/plugins.c | 52 ++++++++++++++++++++++--------- src/plugins_internal.h | 7 ++--- src/plugins_types.c | 15 ++++++--- src/plugins_types/union.c | 38 ++++++++++++++-------- src/printer_lyb.c | 8 +++-- src/printer_xml.c | 7 +++-- src/schema_compile.c | 6 ++-- src/schema_compile_node.c | 26 ++++++---------- src/tree_data_common.c | 28 +++++++++++------ src/tree_data_hash.c | 7 +++-- src/tree_data_new.c | 16 ++++++---- src/tree_schema.h | 30 +++++++++--------- src/validation.c | 3 +- src/xpath.c | 6 ++-- tests/utests/basic/test_plugins.c | 4 +-- tests/utests/types/binary.c | 8 ++--- tests/utests/types/bits.c | 10 +++--- tests/utests/types/enumeration.c | 2 +- tests/utests/types/inet_types.c | 8 ++--- tests/utests/types/int8.c | 8 ++--- tests/utests/types/leafref.c | 2 +- tests/utests/types/string.c | 8 ++--- tests/utests/types/union.c | 2 +- tests/utests/types/yang_types.c | 2 +- tests/utests/utests.h | 6 +--- 26 files changed, 181 insertions(+), 130 deletions(-) diff --git a/src/context.h b/src/context.h index e96f0b402..2154b393b 100644 --- a/src/context.h +++ b/src/context.h @@ -212,7 +212,7 @@ struct ly_ctx; #define LY_CTX_STATIC_PLUGINS_ONLY 0x2000 /**< By default, external plugins from directories the path to which is obtained from the `LIBYANG_TYPES_PLUGINS_DIR` and `LIBYANG_EXTENSIONS_PLUGINS_DIR` environmental variables are loaded. This option prevents loading of all external plugins and only - the static (built-in) plugins are loaded. + the static (built-in) plugins are loaded. */ /* 0x80000000 reserved for internal use */ diff --git a/src/plugins.c b/src/plugins.c index 4ff61ef78..b84199901 100644 --- a/src/plugins.c +++ b/src/plugins.c @@ -132,16 +132,41 @@ static struct ly_set plugins_handlers = {0}; static struct ly_set plugins_types = {0}; static struct ly_set plugins_extensions = {0}; -LIBYANG_API_DEF struct lyplg_type * -lysc_get_type_plugin(uintptr_t plugin_id) +/** + * @brief Get the plugin of the given @p type. + * + * @param[in] plugin_id Either an index of the built-in plugin (offset by +1) or a pointer to the external plugin. + * @param[in] type Type of the plugin to get. + * @param[in] plugins Array of the built-in plugins used in case @p plugin_id is an index of a built-in plugin. + * @return Plugin of the given @p type or NULL if not found. + */ +static void * +lysc_get_plugin(uintptr_t plugin_id, enum LYPLG type, const struct ly_set *plugins) { - if (plugin_id < plugins_types.count) { - return &((struct lyplg_type_record *)plugins_types.objs[plugin_id])->plugin; + /* plugin_id is offset by +1, so 0 is invalid (NULL ptr equivalent) */ + if (!plugin_id) { + return NULL; + } + + if (plugin_id <= plugins->count) { + /* plugin is built-in, fetch it from the global list */ + if (type == LYPLG_EXTENSION) { + return &((struct lyplg_ext_record *)plugins->objs[plugin_id - 1])->plugin; + } else { + return &((struct lyplg_type_record *)plugins->objs[plugin_id - 1])->plugin; + } } else { - return (struct lyplg_type *)plugin_id; + /* plugin is external, return the pointer */ + return (void *)plugin_id; } } +LIBYANG_API_DEF struct lyplg_type * +lysc_get_type_plugin(uintptr_t plugin_id) +{ + return lysc_get_plugin(plugin_id, LYPLG_TYPE, &plugins_types); +} + /** * @brief Iterate over list of loaded plugins of the given @p type. * @@ -200,11 +225,11 @@ lyplg_record_find(const struct ly_ctx *ctx, enum LYPLG type, const char *module, return NULL; } -LY_ERR -_lyplg_type_plugin_find(const struct ly_ctx *ctx, const char *module, const char *revision, const char *name, uintptr_t *out) +uintptr_t +lyplg_type_plugin_find(const struct ly_ctx *ctx, const char *module, const char *revision, const char *name) { struct lyplg_type_record *record = NULL; - uint32_t record_idx; + uint32_t record_idx = 0; if (ctx) { /* try to find context specific plugin */ @@ -217,18 +242,17 @@ _lyplg_type_plugin_find(const struct ly_ctx *ctx, const char *module, const char } if (!record) { - return LY_ENOTFOUND; + /* not found */ + return 0; } if (!strncmp(record->plugin.id, "ly2 - ", 6)) { - /* internal plugin, return an index */ - *out = record_idx; + /* internal 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 { /* external plugin, return the pointer */ - *out = (uintptr_t)&record->plugin; + return (uintptr_t)&record->plugin; } - - return LY_SUCCESS; } struct lyplg_type * diff --git a/src/plugins_internal.h b/src/plugins_internal.h index 0f561869f..983a08027 100644 --- a/src/plugins_internal.h +++ b/src/plugins_internal.h @@ -61,8 +61,6 @@ LY_ERR lyplg_init(ly_bool builtin_type_plugins_only, ly_bool static_plugins_only */ void lyplg_clean(void); -LY_ERR _lyplg_type_plugin_find(const struct ly_ctx *ctx, const char *module, const char *revision, const char *name, uintptr_t *out); - /** * @brief Find a type plugin. * @@ -72,9 +70,10 @@ LY_ERR _lyplg_type_plugin_find(const struct ly_ctx *ctx, const char *module, con * @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(). */ -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. diff --git a/src/plugins_types.c b/src/plugins_types.c index ba8677132..72f6c40ad 100644 --- a/src/plugins_types.c +++ b/src/plugins_types.c @@ -903,11 +903,13 @@ lyplg_type_print_val(const struct lysc_node *node, const char *canon, LY_VALUE_F struct ly_err_item *err = NULL; const char *v; ly_bool dyn; + struct lyplg_type *type_plugin; type = ((struct lysc_node_leaf *)node)->type; + type_plugin = lysc_get_type_plugin(type->plugin); /* store the value */ - r = lysc_get_type_plugin(type->plugin)->store(node->module->ctx, type, canon, strlen(canon), LYPLG_TYPE_STORE_ONLY, LY_VALUE_CANON, + r = type_plugin->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) { @@ -918,7 +920,7 @@ lyplg_type_print_val(const struct lysc_node *node, const char *canon, LY_VALUE_F } /* print it in the specific format */ - v = lysc_get_type_plugin(type->plugin)->print(node->module->ctx, &storage, format, prefix_data, &dyn, NULL); + v = type_plugin->print(node->module->ctx, &storage, format, prefix_data, &dyn, NULL); /* store it in the dictionary, storage will be freed */ if (dyn) { @@ -927,7 +929,7 @@ lyplg_type_print_val(const struct lysc_node *node, const char *canon, LY_VALUE_F lydict_dup(node->module->ctx, v, value); } - lysc_get_type_plugin(type->plugin)->free(node->module->ctx, &storage); + type_plugin->free(node->module->ctx, &storage); return LY_SUCCESS; } @@ -1053,6 +1055,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; LY_CHECK_ARG_RET(NULL, lref, node, value, errmsg, LY_EINVAL); @@ -1099,6 +1102,8 @@ lyplg_type_resolve_leafref(const struct lysc_type_leafref *lref, const struct ly goto cleanup; } + type = lysc_get_type_plugin(lref->plugin); + /* check the result */ if (target_path) { /* no or exact match(es) */ @@ -1113,7 +1118,7 @@ lyplg_type_resolve_leafref(const struct lysc_type_leafref *lref, const struct ly continue; } - if (!lysc_get_type_plugin(lref->plugin)->compare(LYD_CTX(node), &((struct lyd_node_term *)set.val.nodes[i].node)->value, value)) { + if (!type->compare(LYD_CTX(node), &((struct lyd_node_term *)set.val.nodes[i].node)->value, value)) { break; } } @@ -1138,7 +1143,7 @@ lyplg_type_resolve_leafref(const struct lysc_type_leafref *lref, const struct ly continue; } - if (!lysc_get_type_plugin(lref->plugin)->compare(LYD_CTX(node), &((struct lyd_node_term *)set.val.nodes[i].node)->value, value)) { + if (!type->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); } diff --git a/src/plugins_types/union.c b/src/plugins_types/union.c index 230eda975..a10b7e72e 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_plugin; *err = NULL; @@ -241,7 +242,7 @@ union_store_type(const struct ly_ctx *ctx, struct lysc_type_union *type_u, uint3 assert(subvalue->value.realtype); value = lysc_get_type_plugin(subvalue->value.realtype->plugin)->print(ctx, &subvalue->value, - LY_VALUE_JSON, NULL, &dynamic, &value_len); + 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) { @@ -267,7 +268,9 @@ union_store_type(const struct ly_ctx *ctx, struct lysc_type_union *type_u, uint3 opts |= LYPLG_TYPE_STORE_ONLY; } - rc = lysc_get_type_plugin(type->plugin)->store(ctx, type, value, value_len, opts, format, prefix_data, + type_plugin = lysc_get_type_plugin(type->plugin); + + rc = type_plugin->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 */ @@ -280,10 +283,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 = lysc_get_type_plugin(type->plugin)->validate(ctx, type, ctx_node, tree, &subvalue->value, err); + rc = type_plugin->validate(ctx, type, ctx_node, tree, &subvalue->value, err); if (rc) { /* validate failed, we need to free the stored value */ - lysc_get_type_plugin(type->plugin)->free(ctx, &subvalue->value); + type_plugin->free(ctx, &subvalue->value); goto cleanup; } } @@ -322,6 +325,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; *err = NULL; @@ -372,9 +376,11 @@ union_find_type(const struct ly_ctx *ctx, struct lysc_type_union *type_u, struct } } - msg = ly_realloc(msg, msg_len + 4 + strlen(lysc_get_type_plugin(type_u->types[u]->plugin)->id) + 2 + strlen(errs[u]->msg) + 2); + type = lysc_get_type_plugin(type_u->types[u]->plugin); + + msg = ly_realloc(msg, msg_len + 4 + strlen(type->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", lysc_get_type_plugin(type_u->types[u]->plugin)->id, errs[u]->msg); + msg_len += sprintf(msg + msg_len, " %s: %s\n", type->id, errs[u]->msg); } if (!use_err_app_tag) { @@ -513,14 +519,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; *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(lysc_get_type_plugin(subvalue->value.realtype->plugin)->duplicate(ctx, &subvalue->value, &orig)); - lysc_get_type_plugin(subvalue->value.realtype->plugin)->free(ctx, &subvalue->value); + subvalue_type = lysc_get_type_plugin(subvalue->value.realtype->plugin); + LY_CHECK_RET(subvalue_type->duplicate(ctx, &subvalue->value, &orig)); + subvalue_type->free(ctx, &subvalue->value); if (subvalue->format == LY_VALUE_LYB) { /* use the specific type to store and validate the value */ @@ -560,7 +568,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 lysc_get_type_plugin(val1->subvalue->value.realtype->plugin)->compare(ctx, &val1->subvalue->value, &val2->subvalue->value); + return lysc_get_type_plugin(val1->subvalue->value.realtype->plugin)->compare(ctx, + &val1->subvalue->value, &val2->subvalue->value); } LIBYANG_API_DEF int @@ -571,7 +580,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 lysc_get_type_plugin(val1->subvalue->value.realtype->plugin)->sort(ctx, &val1->subvalue->value, &val2->subvalue->value); + return lysc_get_type_plugin(val1->subvalue->value.realtype->plugin)->sort(ctx, + &val1->subvalue->value, &val2->subvalue->value); } /* compare according to the order of types */ @@ -636,8 +646,8 @@ lyb_union_print(const struct ly_ctx *ctx, struct lysc_type_union *type_u, struct LY_CHECK_RET((r != LY_SUCCESS) && (r != LY_EINCOMPLETE), NULL); /* Print subvalue in LYB format. */ - pval = (void *)lysc_get_type_plugin(subvalue->value.realtype->plugin)->print(NULL, &subvalue->value, LY_VALUE_LYB, prefix_data, &dynamic, - &pval_len); + pval = (void *)lysc_get_type_plugin(subvalue->value.realtype->plugin)->print(NULL, &subvalue->value, LY_VALUE_LYB, + prefix_data, &dynamic, &pval_len); LY_CHECK_RET(!pval, NULL); /* Create LYB data. */ @@ -665,6 +675,7 @@ lyplg_type_print_union(const struct ly_ctx *ctx, const struct lyd_value *value, struct lyd_value_union *subvalue = value->subvalue; struct lysc_type_union *type_u = (struct lysc_type_union *)value->realtype; size_t lyb_data_len = 0; + struct lyplg_type *type; if ((format == LY_VALUE_LYB) && (subvalue->format == LY_VALUE_LYB)) { /* The return value is already ready. */ @@ -684,7 +695,8 @@ lyplg_type_print_union(const struct ly_ctx *ctx, const struct lyd_value *value, } assert(format != LY_VALUE_LYB); - ret = (void *)lysc_get_type_plugin(subvalue->value.realtype->plugin)->print(ctx, &subvalue->value, format, prefix_data, dynamic, value_len); + type = lysc_get_type_plugin(subvalue->value.realtype->plugin); + ret = (void *)type->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); diff --git a/src/printer_lyb.c b/src/printer_lyb.c index 773c11c23..bb8cc4b8f 100644 --- a/src/printer_lyb.c +++ b/src/printer_lyb.c @@ -618,14 +618,16 @@ 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; - assert(term->value.realtype && lysc_get_type_plugin(term->value.realtype->plugin)->print && term->schema); + assert(term->value.realtype && (type = lysc_get_type_plugin(term->value.realtype->plugin)) && + type->print && term->schema); /* Get length of LYB data to print. */ - lyb_data_len = lysc_get_type_plugin(term->value.realtype->plugin)->lyb_data_len; + lyb_data_len = type->lyb_data_len; /* Get value and also print its length only if size is not fixed. */ - print = lysc_get_type_plugin(term->value.realtype->plugin)->print; + print = type->print; if (lyb_data_len < 0) { /* Variable-length data. */ diff --git a/src/printer_xml.c b/src/printer_xml.c index f5c785b6f..75542749e 100644 --- a/src/printer_xml.c +++ b/src/printer_xml.c @@ -233,7 +233,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 = lysc_get_type_plugin(meta->value.realtype->plugin)->print(LYD_CTX(node), &meta->value, LY_VALUE_XML, &ns_list, &dynamic, NULL); + value = lysc_get_type_plugin(meta->value.realtype->plugin)->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 +359,8 @@ xml_print_term(struct xmlpr_ctx *pctx, const struct lyd_node_term *node) } /* print the value */ - value = lysc_get_type_plugin(((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_plugin(((struct lysc_node_leaf *)node->schema)->type->plugin)->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/schema_compile.c b/src/schema_compile.c index 6eabb6964..dd6ed272a 100644 --- a/src/schema_compile.c +++ b/src/schema_compile.c @@ -896,9 +896,11 @@ lys_compile_unres_dflt(struct lysc_ctx *ctx, struct lysc_node *node, struct lysc struct lyd_value storage = {0}, *val; struct ly_err_item *err = NULL; LY_VALUE_FORMAT format; + struct lyplg_type *type_plugin; options = (ctx->ctx->opts & LY_CTX_REF_IMPLEMENTED) ? LYPLG_TYPE_STORE_IMPLEMENT : 0; - rc = lysc_get_type_plugin(type->plugin)->store(ctx->ctx, type, dflt, strlen(dflt), options, LY_VALUE_SCHEMA, (void *)dflt_pmod, + type_plugin = lysc_get_type_plugin(type->plugin); + rc = type_plugin->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 */ @@ -936,7 +938,7 @@ lys_compile_unres_dflt(struct lysc_ctx *ctx, struct lysc_node *node, struct lysc ly_path_free(val->target); val->target = NULL; } - lysc_get_type_plugin(type->plugin)->free(ctx->ctx, &storage); + type_plugin->free(ctx->ctx, &storage); return LY_SUCCESS; } diff --git a/src/schema_compile_node.c b/src/schema_compile_node.c index ff65258ff..561035b96 100644 --- a/src/schema_compile_node.c +++ b/src/schema_compile_node.c @@ -2146,7 +2146,7 @@ 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, struct lysc_type **type, const char **units, struct lysp_qname **dflt) { - LY_ERR ret = LY_SUCCESS, r; + LY_ERR ret = LY_SUCCESS; ly_bool dummyloops = 0, has_leafref; struct lys_type_item *tctx, *tctx_prev = NULL, *tctx_iter; LY_DATA_TYPE basetype = LY_TYPE_UNKNOWN; @@ -2154,8 +2154,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}; - uintptr_t plugin_id = -1; - ly_bool plugin_found = 0; + uintptr_t plugin_id = 0; *type = NULL; if (dflt) { @@ -2278,23 +2277,16 @@ lys_compile_type(struct lysc_ctx *ctx, struct lysp_node *context_pnode, uint16_t } /* try to find loaded user type plugins */ - r = _lyplg_type_plugin_find(ctx->ctx, tctx->tpdf->type.pmod->mod->name, tctx->tpdf->type.pmod->mod->revision, - tctx->tpdf->name, &plugin_id); - if (r == LY_SUCCESS) { - plugin_found = 1; - } else if ((r == LY_ENOTFOUND) && base) { - /* use the base type implementation if available */ + plugin_id = lyplg_type_plugin_find(ctx->ctx, tctx->tpdf->type.pmod->mod->name, tctx->tpdf->type.pmod->mod->revision, + tctx->tpdf->name); + if (!plugin_id && base) { plugin_id = base->plugin; - plugin_found = 1; } - if (!plugin_found) { + if (!plugin_id) { /* use the internal built-in type implementation */ - r = _lyplg_type_plugin_find(ctx->ctx, "", NULL, ly_data_type2str[basetype], &plugin_id); - if (r == LY_SUCCESS) { - plugin_found = 1; - } + plugin_id = lyplg_type_plugin_find(ctx->ctx, "", NULL, ly_data_type2str[basetype]); } - assert(plugin_found); + assert(plugin_id); if ((basetype != LY_TYPE_LEAFREF) && (u != tpdf_chain.count - 1) && !tctx->tpdf->type.flags && !tctx->tpdf->type.exts && (plugin_id == base->plugin)) { @@ -2352,7 +2344,7 @@ lys_compile_type(struct lysc_ctx *ctx, struct lysp_node *context_pnode, uint16_t if (base) { plugin_id = base->plugin; } else { - _lyplg_type_plugin_find(ctx->ctx, "", NULL, ly_data_type2str[basetype], &plugin_id); + plugin_id = 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_id, &tpdf_chain, 0, type); diff --git a/src/tree_data_common.c b/src/tree_data_common.c index dc3d45670..855d4d8c7 100644 --- a/src/tree_data_common.c +++ b/src/tree_data_common.c @@ -532,7 +532,8 @@ lyd_value_store(const struct ly_ctx *ctx, struct lyd_value *val, const struct ly options |= LYPLG_TYPE_STORE_ONLY; } - r = lysc_get_type_plugin(type->plugin)->store(ctx, type, value, value_len, options, format, prefix_data, hints, ctx_node, val, NULL, &err); + r = lysc_get_type_plugin(type->plugin)->store(ctx, type, value, value_len, options, + format, prefix_data, hints, ctx_node, val, NULL, &err); if (dynamic) { *dynamic = 0; } @@ -560,17 +561,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_plugin; - assert(lysc_get_type_plugin(type->plugin)->validate); + type_plugin = lysc_get_type_plugin(type->plugin); + assert(type_plugin && type_plugin->validate); - ret = lysc_get_type_plugin(type->plugin)->validate(ctx, type, ctx_node, tree, val, &err); + ret = type_plugin->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 *)lysc_get_type_plugin(type->plugin)->print(ctx, val, LY_VALUE_CANON, NULL, NULL, NULL)); + (char *)type_plugin->print(ctx, val, LY_VALUE_CANON, NULL, NULL, NULL)); } return ret; } @@ -595,8 +598,8 @@ ly_value_validate(const struct ly_ctx *ctx, const struct lysc_node *node, const } type = ((struct lysc_node_leaf *)node)->type; - rc = lysc_get_type_plugin(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_plugin(type->plugin)->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 */ rc = LY_SUCCESS; @@ -633,6 +636,7 @@ lyd_value_validate2(const struct ly_ctx *ctx, const struct lysc_node *schema, co struct lysc_type *type; struct lyd_value val = {0}; ly_bool stored = 0, log = 1; + struct lyplg_type *type_plugin, *realtype_plugin; if (!ctx) { ctx = schema->module->ctx; @@ -643,15 +647,18 @@ lyd_value_validate2(const struct ly_ctx *ctx, const struct lysc_node *schema, co } type = ((struct lysc_node_leaf *)schema)->type; + type_plugin = lysc_get_type_plugin(type->plugin); + /* store */ - rc = lysc_get_type_plugin(type->plugin)->store(ctx, type, value, value_len, 0, format, prefix_data, LYD_HINT_DATA, schema, &val, NULL, &err); + rc = type_plugin->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 = lysc_get_type_plugin(type->plugin)->validate(ctx, type, ctx_node, ctx_node, &val, &err); + rc = type_plugin->validate(ctx, type, ctx_node, ctx_node, &val, &err); } if (rc && (rc != LY_EINCOMPLETE) && err) { @@ -674,13 +681,14 @@ lyd_value_validate2(const struct ly_ctx *ctx, const struct lysc_node *schema, co if (canonical) { /* return canonical value */ - lydict_dup(ctx, lysc_get_type_plugin(val.realtype->plugin)->print(ctx, &val, LY_VALUE_CANON, NULL, NULL, NULL), canonical); + realtype_plugin = lysc_get_type_plugin(val.realtype->plugin); + lydict_dup(ctx, realtype_plugin->print(ctx, &val, LY_VALUE_CANON, NULL, NULL, NULL), canonical); } } if (stored) { /* free value */ - lysc_get_type_plugin(type->plugin)->free(ctx, &val); + type_plugin->free(ctx, &val); } return rc; } diff --git a/src/tree_data_hash.c b/src/tree_data_hash.c index 66ba634e4..32a6b2d3d 100644 --- a/src/tree_data_hash.c +++ b/src/tree_data_hash.c @@ -33,6 +33,7 @@ lyd_hash(struct lyd_node *node) const void *hash_key; ly_bool dyn; size_t key_len; + struct lyplg_type *type; if (!node->schema) { return LY_SUCCESS; @@ -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 = lysc_get_type_plugin(key->value.realtype->plugin)->print(NULL, &key->value, LY_VALUE_LYB, NULL, &dyn, &key_len); + type = lysc_get_type_plugin(key->value.realtype->plugin); + hash_key = type->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 = lysc_get_type_plugin(llist->value.realtype->plugin)->print(NULL, &llist->value, LY_VALUE_LYB, NULL, &dyn, &key_len); + type = lysc_get_type_plugin(llist->value.realtype->plugin); + hash_key = type->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_new.c b/src/tree_data_new.c index 54671e1ae..ceca209d9 100644 --- a/src/tree_data_new.c +++ b/src/tree_data_new.c @@ -1218,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 *real_type, *schema_type; + + real_type = lysc_get_type_plugin(term->value.realtype->plugin); + schema_type = lysc_get_type_plugin(((struct lysc_node_leaf *)term->schema)->type->plugin); if (term->schema->nodetype == LYS_LEAFLIST) { target = (struct lyd_node *)term; @@ -1225,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 */ - lysc_get_type_plugin(term->value.realtype->plugin)->free(LYD_CTX(term), &term->value); + real_type->free(LYD_CTX(term), &term->value); if (use_val) { term->value = *val; } else { - rc = lysc_get_type_plugin(((struct lysc_node_leaf *)term->schema)->type->plugin)->duplicate(LYD_CTX(term), val, &term->value); + rc = schema_type->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 */ @@ -1245,11 +1249,11 @@ lyd_change_node_value(struct lyd_node_term *term, struct lyd_value *val, ly_bool lyd_unlink_tree(target); /* change value */ - lysc_get_type_plugin(term->value.realtype->plugin)->free(LYD_CTX(term), &term->value); + real_type->free(LYD_CTX(term), &term->value); if (use_val) { term->value = *val; } else { - rc = lysc_get_type_plugin(((struct lysc_node_leaf *)term->schema)->type->plugin)->duplicate(LYD_CTX(term), val, &term->value); + rc = schema_type->duplicate(LYD_CTX(term), val, &term->value); } /* update hash */ @@ -1262,11 +1266,11 @@ lyd_change_node_value(struct lyd_node_term *term, struct lyd_value *val, ly_bool lyd_unlink_hash(target); /* change value */ - lysc_get_type_plugin(term->value.realtype->plugin)->free(LYD_CTX(term), &term->value); + real_type->free(LYD_CTX(term), &term->value); if (use_val) { term->value = *val; } else { - LY_CHECK_RET(lysc_get_type_plugin(((struct lysc_node_leaf *)term->schema)->type->plugin)->duplicate(LYD_CTX(term), val, &term->value)); + LY_CHECK_RET(schema_type->duplicate(LYD_CTX(term), val, &term->value)); } /* update hash */ diff --git a/src/tree_schema.h b/src/tree_schema.h index c4bbd5835..55a18df2e 100644 --- a/src/tree_schema.h +++ b/src/tree_schema.h @@ -1279,7 +1279,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)) */ - uintptr_t plugin; /**< type's manipulation callbacks plugin use lysc_get_type_plugin*/ + uintptr_t plugin; /**< type's manipulation callbacks plugin, use ::lysc_get_type_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) */ @@ -1288,7 +1288,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)) */ - uintptr_t plugin; /**< type's manipulation callbacks plugin */ + uintptr_t plugin; /**< type's manipulation callbacks plugin, use ::lysc_get_type_plugin() */ LY_DATA_TYPE basetype; /**< base type of the type */ uint32_t refcount; /**< reference counter for type sharing */ @@ -1298,7 +1298,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)) */ - uintptr_t plugin; /**< type's manipulation callbacks plugin */ + uintptr_t plugin; /**< type's manipulation callbacks plugin, use ::lysc_get_type_plugin() */ LY_DATA_TYPE basetype; /**< base type of the type */ uint32_t refcount; /**< reference counter for type sharing */ @@ -1309,7 +1309,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)) */ - uintptr_t plugin; /**< type's manipulation callbacks plugin */ + uintptr_t plugin; /**< type's manipulation callbacks plugin, use ::lysc_get_type_plugin() */ LY_DATA_TYPE basetype; /**< base type of the type */ uint32_t refcount; /**< reference counter for type sharing */ @@ -1334,7 +1334,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)) */ - uintptr_t plugin; /**< type's manipulation callbacks plugin */ + uintptr_t plugin; /**< type's manipulation callbacks plugin, use ::lysc_get_type_plugin() */ LY_DATA_TYPE basetype; /**< base type of the type */ uint32_t refcount; /**< reference counter for type sharing */ @@ -1344,7 +1344,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)) */ - uintptr_t plugin; /**< type's manipulation callbacks plugin */ + uintptr_t plugin; /**< type's manipulation callbacks plugin, use ::lysc_get_type_plugin() */ LY_DATA_TYPE basetype; /**< base type of the type */ uint32_t refcount; /**< reference counter for type sharing */ @@ -1355,7 +1355,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)) */ - uintptr_t plugin; /**< type's manipulation callbacks plugin */ + uintptr_t plugin; /**< type's manipulation callbacks plugin, use ::lysc_get_type_plugin() */ LY_DATA_TYPE basetype; /**< base type of the type */ uint32_t refcount; /**< reference counter for type sharing */ @@ -1368,7 +1368,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)) */ - uintptr_t plugin; /**< type's manipulation callbacks plugin */ + uintptr_t plugin; /**< type's manipulation callbacks plugin, use ::lysc_get_type_plugin() */ LY_DATA_TYPE basetype; /**< base type of the type */ uint32_t refcount; /**< reference counter for type sharing */ @@ -1379,7 +1379,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)) */ - uintptr_t plugin; /**< type's manipulation callbacks plugin */ + uintptr_t plugin; /**< type's manipulation callbacks plugin, use ::lysc_get_type_plugin() */ LY_DATA_TYPE basetype; /**< base type of the type */ uint32_t refcount; /**< reference counter for type sharing */ @@ -1389,7 +1389,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)) */ - uintptr_t plugin; /**< type's manipulation callbacks plugin */ + uintptr_t plugin; /**< type's manipulation callbacks plugin, use ::lysc_get_type_plugin() */ LY_DATA_TYPE basetype; /**< base type of the type */ uint32_t refcount; /**< reference counter for type sharing */ @@ -1399,7 +1399,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)) */ - uintptr_t plugin; /**< type's manipulation callbacks plugin */ + uintptr_t plugin; /**< type's manipulation callbacks plugin, use ::lysc_get_type_plugin() */ LY_DATA_TYPE basetype; /**< base type of the type */ uint32_t refcount; /**< reference counter for type sharing */ @@ -1798,11 +1798,11 @@ struct lysc_module { ((lysc_node->nodetype == LYS_LEAFLIST) && !(lysc_node->flags & LYS_CONFIG_W)))) ? 1 : 0) /** - * @brief + * @brief Get a type plugin. * - * @param[in] plugin_id The plugin identifier - * - * @return { description_of_the_return_value } + * @param[in] plugin_id 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_id); diff --git a/src/validation.c b/src/validation.c index a2f768c24..7b380bd07 100644 --- a/src/validation.c +++ b/src/validation.c @@ -1952,7 +1952,8 @@ lyd_validate_subtree(struct lyd_node *root, struct ly_set *node_when, struct ly_ } } - if ((node->schema->nodetype & LYD_NODE_TERM) && lysc_get_type_plugin(((struct lysc_node_leaf *)node->schema)->type->plugin)->validate) { + if ((node->schema->nodetype & LYD_NODE_TERM) && + lysc_get_type_plugin(((struct lysc_node_leaf *)node->schema)->type->plugin)->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 7695b9986..2ae3ce215 100644 --- a/src/xpath.c +++ b/src/xpath.c @@ -3619,6 +3619,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_plugin; 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))) { @@ -3643,7 +3644,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 = lysc_get_type_plugin(type->plugin)->store(set->ctx, type, value, strlen(value), 0, set->format, set->prefix_data, + type_plugin = lysc_get_type_plugin(type->plugin); + rc = type_plugin->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; @@ -3660,7 +3662,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 { - lysc_get_type_plugin(type->plugin)->free(set->ctx, &storage); + type_plugin->free(set->ctx, &storage); } } free(value); diff --git a/tests/utests/basic/test_plugins.c b/tests/utests/basic/test_plugins.c index b957b52f1..54c85f1c2 100644 --- a/tests/utests/basic/test_plugins.c +++ b/tests/utests/basic/test_plugins.c @@ -54,12 +54,12 @@ 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_int_equal(1, LY_ARRAY_COUNT(leaf->exts)); - assert_non_null(plugin_e = lyplg_ext_plugin_find(NULL, "libyang-plugins-simple", NULL, "hint")); + 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, plugin_e); diff --git a/tests/utests/types/binary.c b/tests/utests/types/binary.c index 0fc2db3bf..484ac4102 100644 --- a/tests/utests/types/binary.c +++ b/tests/utests/types/binary.c @@ -51,7 +51,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_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, *lysc_type2; LY_ERR ly_ret; const char *schema; @@ -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 */ @@ -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 311bd3a1d..65e7a0266 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; @@ -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; @@ -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 7125e9beb..8c5ce6bc1 100644 --- a/tests/utests/types/int8.c +++ b/tests/utests/types/int8.c @@ -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; @@ -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; @@ -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 94bc8ea42..c07f372f5 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; @@ -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; @@ -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 573abc7bf..6131c1581 100644 --- a/tests/utests/types/union.c +++ b/tests/utests/types/union.c @@ -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; 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 19502dfab..19546f373 100644 --- a/tests/utests/utests.h +++ b/tests/utests/utests.h @@ -230,11 +230,7 @@ struct utest_context { assert_non_null(NODE); \ assert_int_equal((NODE)->basetype, TYPE); \ CHECK_ARRAY((NODE)->exts, EXTS); \ - do { \ - uintptr_t plugin_id; \ - _lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[TYPE], &plugin_id); \ - assert_ptr_equal((NODE)->plugin, plugin_id); \ - } while (0) + assert_ptr_equal((NODE)->plugin, lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[TYPE])) /** * @brief check compileted numeric type From aa9dce58e21d7a0dfcbf0eecda5f4eaaef472225 Mon Sep 17 00:00:00 2001 From: roman Date: Mon, 20 Jan 2025 11:14:17 +0100 Subject: [PATCH 27/99] plugins exts UPDATE simplify ext plugin getter --- src/log.c | 9 ++++---- src/plugins.c | 42 +++++++++++++++++++------------------- src/plugins_exts.h | 2 +- src/plugins_exts/nacm.c | 6 +++++- src/plugins_internal.h | 5 +++-- src/printer_context.c | 10 +++++---- src/printer_tree.c | 12 +++++------ src/printer_yang.c | 6 ++++-- src/schema_compile.c | 4 ++-- src/schema_compile_amend.c | 4 ++-- src/tree_data.c | 2 +- src/tree_data_common.c | 2 +- src/tree_schema.c | 7 ++++--- src/tree_schema.h | 13 ++++++++++-- src/tree_schema_free.c | 8 ++++---- src/validation.c | 9 ++++---- 16 files changed, 81 insertions(+), 60 deletions(-) diff --git a/src/log.c b/src/log.c index 6a9254974..829707ece 100644 --- a/src/log.c +++ b/src/log.c @@ -913,7 +913,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->plugin->id, level, err, data_path, schema_path, line, format, ap); + ly_ext_log(PARSER_CTX(pctx), lysc_get_ext_plugin(ext->plugin)->id, level, err, data_path, schema_path, line, format, ap); va_end(ap); } @@ -930,7 +930,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_plugin(ext->def->plugin)->id, level, err, NULL, schema_path, 0, format, ap); va_end(ap); } @@ -947,7 +947,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_plugin(ext->def->plugin)->id, level, err, NULL, schema_path, 0, format, ap); va_end(ap); } @@ -968,7 +968,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_plugin(ext->def->plugin)->id, eitem->level, eitem->err, + data_path, schema_path, eitem->line, "%s", ap); va_end(ap); } diff --git a/src/plugins.c b/src/plugins.c index b84199901..e9920081b 100644 --- a/src/plugins.c +++ b/src/plugins.c @@ -167,6 +167,12 @@ lysc_get_type_plugin(uintptr_t plugin_id) return lysc_get_plugin(plugin_id, LYPLG_TYPE, &plugins_types); } +LIBYANG_API_DEF struct lyplg_ext * +lysc_get_ext_plugin(uintptr_t plugin_id) +{ + return lysc_get_plugin(plugin_id, LYPLG_EXTENSION, &plugins_extensions); +} + /** * @brief Iterate over list of loaded plugins of the given @p type. * @@ -255,40 +261,34 @@ lyplg_type_plugin_find(const struct ly_ctx *ctx, const char *module, const char } } -struct lyplg_type * -lyplg_type_plugin_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) { - struct lyplg_type_record *record = NULL; + struct lyplg_ext_record *record = NULL; + uint32_t record_idx = 0; if (ctx) { /* try to find context specific plugin */ - record = lyplg_record_find(ctx, LYPLG_TYPE, module, revision, name, NULL); + record = lyplg_record_find(ctx, LYPLG_EXTENSION, module, revision, name, &record_idx); } if (!record) { /* try to find shared plugin */ - record = lyplg_record_find(NULL, LYPLG_TYPE, module, revision, name, NULL); - } - - return record ? &record->plugin : NULL; -} - -struct lyplg_ext * -lyplg_ext_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, NULL); + record = lyplg_record_find(NULL, LYPLG_EXTENSION, module, revision, name, &record_idx); } if (!record) { - /* try to find shared plugin */ - record = lyplg_record_find(NULL, LYPLG_EXTENSION, module, revision, name, NULL); + /* not found */ + return 0; } - return record ? &record->plugin : NULL; + if (!strncmp(record->plugin.id, "ly2 - ", 6)) { + /* internal 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 { + /* external plugin, return the pointer */ + return (uintptr_t)&record->plugin; + } } /** diff --git a/src/plugins_exts.h b/src/plugins_exts.h index 477834be7..71fdee7a2 100644 --- a/src/plugins_exts.h +++ b/src/plugins_exts.h @@ -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 lyplg_ext *plugin; /**< pointer to the extension plugin, if any */ + uintptr_t plugin; /**< extension plugin, use ::lysc_get_ext_plugin() */ void *parent; /**< pointer to the parent statement holding the extension instance(s), use ::lysp_ext_instance#parent_stmt to access the value/structure */ diff --git a/src/plugins_exts/nacm.c b/src/plugins_exts/nacm.c index 8bd77a6ce..adda9d28a 100644 --- a/src/plugins_exts/nacm.c +++ b/src/plugins_exts/nacm.c @@ -81,6 +81,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)) { @@ -100,9 +101,12 @@ nacm_parse(struct lysp_ctx *pctx, struct lysp_ext_instance *ext) return LY_ENOT; } + ext_plugin = lysc_get_ext_plugin(ext->plugin); + /* check for duplication */ LY_ARRAY_FOR(parent->exts, u) { - if ((&parent->exts[u] != ext) && parent->exts[u].plugin && !strcmp(parent->exts[u].plugin->id, ext->plugin->id)) { + parent_ext_plugin = lysc_get_ext_plugin(parent->exts[u].plugin); + 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 */ diff --git a/src/plugins_internal.h b/src/plugins_internal.h index 983a08027..0526bdef5 100644 --- a/src/plugins_internal.h +++ b/src/plugins_internal.h @@ -83,8 +83,9 @@ uintptr_t lyplg_type_plugin_find(const struct ly_ctx *ctx, const char *module, c * @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 plugin, 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(). */ -struct lyplg_ext *lyplg_ext_plugin_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/printer_context.c b/src/printer_context.c index 0f56dcb2c..6ff911d80 100644 --- a/src/printer_context.c +++ b/src/printer_context.c @@ -112,6 +112,7 @@ 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; /* sized array */ *size += CTXS_SIZED_ARRAY(exts); @@ -123,8 +124,9 @@ ctxs_exts(const struct lysc_ext_instance *exts, struct ly_ht *ht, int *size) *size += sizeof(LY_ARRAY_COUNT_TYPE) + LY_ARRAY_COUNT(exts[u].substmts) * sizeof *exts[u].substmts; /* compiled, substmts storage */ - if (exts[u].def->plugin && exts[u].def->plugin->compiled_size) { - *size += exts[u].def->plugin->compiled_size(&exts[u], ht); + ext = lysc_get_ext_plugin(exts[u].def->plugin); + if (ext && ext->compiled_size) { + *size += ext->compiled_size(&exts[u], ht); } } } @@ -814,8 +816,8 @@ ctxp_ext(const struct lysc_ext_instance *orig_ext, struct lysc_ext_instance *ext } /* compiled, substmts storage, use the plugin */ - if (ext->def->plugin && ext->def->plugin->compiled_print) { - ext->def->plugin->compiled_print(orig_ext, ext, addr_ht, ptr_set, mem); + if (ext->def->plugin && lysc_get_ext_plugin(ext->def->plugin)->compiled_print) { + lysc_get_ext_plugin(ext->def->plugin)->compiled_print(orig_ext, ext, addr_ht, ptr_set, mem); } else { ext->compiled = NULL; } diff --git a/src/printer_tree.c b/src/printer_tree.c index 8ba4c819c..645fde7d0 100644 --- a/src/printer_tree.c +++ b/src/printer_tree.c @@ -1862,7 +1862,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[i].def->plugin || !cn->exts[i].def->plugin->printer_ctree) { + if (!cn->exts[i].def->plugin || !lysc_get_ext_plugin(cn->exts[i].def->plugin)->printer_ctree) { continue; } if (!trp_ext_parent_is_valid(1, &cn->exts[i])) { @@ -1874,7 +1874,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[i].plugin || !pn->exts[i].plugin->printer_ptree) { + if (!pn->exts[i].plugin || !lysc_get_ext_plugin(pn->exts[i].plugin)->printer_ptree) { continue; } if (!trp_ext_parent_is_valid(0, &pn->exts[i])) { @@ -2192,9 +2192,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_plugin(ce->def->plugin)->printer_ctree(ce, NULL, &no->flags, &no->add_opts); } else if (!plc->ctx && (pe = trp_ext_is_present(lysc_tree, node))) { - rc = pe->plugin->printer_ptree(pe, NULL, &no->flags, &no->add_opts); + rc = lysc_get_ext_plugin(pe->plugin)->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); @@ -3915,7 +3915,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_plugin(ext_comp->def->plugin); if (!plugin->printer_ctree) { *ignore = 1; return LY_SUCCESS; @@ -3923,7 +3923,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->plugin; + plugin = lysc_get_ext_plugin(ext_pars->plugin); if (!plugin->printer_ptree) { *ignore = 1; return LY_SUCCESS; diff --git a/src/printer_yang.c b/src/printer_yang.c index 64c9ee934..f6ac698b8 100644 --- a/src/printer_yang.c +++ b/src/printer_yang.c @@ -356,6 +356,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; LY_ARRAY_FOR(exts, u) { if ((exts[u].parent_stmt != substmt) || (exts[u].parent_stmt_index != substmt_index)) { @@ -375,8 +376,9 @@ 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); + ext = lysc_get_ext_plugin(exts[u].def->plugin); + if (ext && ext->printer_info) { + ext->printer_info(&pctx->printer_ctx, &exts[u], &inner_flag); } LEVEL--; diff --git a/src/schema_compile.c b/src/schema_compile.c index dd6ed272a..1845948f1 100644 --- a/src/schema_compile.c +++ b/src/schema_compile.c @@ -132,11 +132,11 @@ lys_compile_ext(struct lysc_ctx *ctx, struct lysp_ext_instance *extp, struct lys 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 && lysc_get_ext_plugin(ext->def->plugin)->compile) { if (ext->argument) { lysc_update_path(ctx, ext->module, ext->argument); } - ret = ext->def->plugin->compile(ctx, extp, ext); + ret = lysc_get_ext_plugin(ext->def->plugin)->compile(ctx, extp, ext); if (ret == LY_ENOT) { lysc_ext_instance_free(ctx->ctx, ext); } diff --git a/src/schema_compile_amend.c b/src/schema_compile_amend.c index 62ebab1b1..81257ea3c 100644 --- a/src/schema_compile_amend.c +++ b/src/schema_compile_amend.c @@ -485,10 +485,10 @@ lysp_ext_dup(const struct ly_ctx *ctx, const struct lysp_module *pmod, void *par ext->flags = orig_ext->flags; LY_CHECK_GOTO(ret = lysp_ext_children_dup(ctx, orig_ext->child, &ext->child), cleanup); - if (ext->plugin && ext->plugin->parse) { + if (ext->plugin && lysc_get_ext_plugin(ext->plugin)->parse) { /* parse again */ LY_CHECK_GOTO(ret = ly_set_add(&pmods, pmod, 1, NULL), cleanup); - LY_CHECK_GOTO(ret = ext->plugin->parse(&pctx, ext), cleanup); + LY_CHECK_GOTO(ret = lysc_get_ext_plugin(ext->plugin)->parse(&pctx, ext), cleanup); } cleanup: diff --git a/src/tree_data.c b/src/tree_data.c index ccbee7710..43927af7d 100644 --- a/src/tree_data.c +++ b/src/tree_data.c @@ -1339,7 +1339,7 @@ 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; + plugin = lysc_get_ext_plugin(mod->compiled->exts[u].def->plugin); if (plugin && !strncmp(plugin->id, "ly2 - metadata", 12) && !ly_strncmp(mod->compiled->exts[u].argument, name, name_len)) { return &mod->compiled->exts[u]; diff --git a/src/tree_data_common.c b/src/tree_data_common.c index 855d4d8c7..1722e45b3 100644 --- a/src/tree_data_common.c +++ b/src/tree_data_common.c @@ -1345,7 +1345,7 @@ ly_nested_ext_schema(const struct lyd_node *parent, const struct lysc_node *spar continue; } - ext_snode_cb = nested_exts[u].def->plugin->snode; + ext_snode_cb = lysc_get_ext_plugin(nested_exts[u].def->plugin)->snode; if (!ext_snode_cb) { /* not an extension with nested data */ continue; diff --git a/src/tree_schema.c b/src/tree_schema.c index f7d904215..30ed17458 100644 --- a/src/tree_schema.c +++ b/src/tree_schema.c @@ -1378,7 +1378,7 @@ lysp_resolve_ext_instance_records(struct lysp_ctx *pctx) u = 0; while (u < LY_ARRAY_COUNT(exts)) { ext = &exts[u]; - if (!ext->plugin || !ext->plugin->parse) { + if (!ext->plugin || !lysc_get_ext_plugin(ext->plugin)->parse) { goto next_iter; } @@ -1389,7 +1389,7 @@ lysp_resolve_ext_instance_records(struct lysp_ctx *pctx) ly_log_location(NULL, NULL, path, NULL); /* parse */ - r = ext->plugin->parse(pctx, ext); + r = lysc_get_ext_plugin(ext->plugin)->parse(pctx, ext); ly_log_location_revert(0, 0, 1, 0); free(path); @@ -2208,7 +2208,8 @@ lys_parse_in(struct ly_ctx *ctx, struct ly_in *in, LYS_INFORMAT format, const st /* resolve extension plugins and parse extension instances */ LY_ARRAY_FOR(mod->parsed->extensions, u) { - mod->parsed->extensions[u].plugin = lyplg_ext_plugin_find(mod->ctx, mod->name, mod->revision, mod->parsed->extensions[u].name); + mod->parsed->extensions[u].plugin = 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); diff --git a/src/tree_schema.h b/src/tree_schema.h index 55a18df2e..9796d4809 100644 --- a/src/tree_schema.h +++ b/src/tree_schema.h @@ -299,7 +299,7 @@ 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)) */ - struct lyplg_ext *plugin; /**< extension definition plugin, if any */ + uintptr_t plugin; /**< extension definition plugin, use ::lysc_get_ext_plugin() */ uint16_t flags; /**< LYS_STATUS_* and LYS_YINELEM_* values (@ref snodeflags) */ }; @@ -1183,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, if any */ + uintptr_t plugin; /**< plugin implementing the specific extension, use ::lysc_get_ext_plugin() */ struct lys_module *module; /**< module structure */ uint16_t flags; /**< LYS_STATUS_* value (@ref snodeflags) */ }; @@ -1806,6 +1806,15 @@ struct lysc_module { */ LIBYANG_API_DECL struct lyplg_type *lysc_get_type_plugin(uintptr_t plugin_id); +/** + * @brief Get an extension plugin. + * + * @param[in] plugin_id 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_id); + /** * @brief Get nearest @p schema parent (including the node itself) that can be instantiated in data. * diff --git a/src/tree_schema_free.c b/src/tree_schema_free.c index 4ae87b31a..aaf20cb69 100644 --- a/src/tree_schema_free.c +++ b/src/tree_schema_free.c @@ -73,8 +73,8 @@ lysp_ext_instance_free(const struct ly_ctx *ctx, struct lysp_ext_instance *ext) lydict_remove(ctx, ext->name); lydict_remove(ctx, ext->argument); ly_free_prefix_data(ext->format, ext->prefix_data); - if (ext->plugin && ext->plugin->pfree) { - ext->plugin->pfree(ctx, ext); + if (ext->plugin && lysc_get_ext_plugin(ext->plugin)->pfree) { + lysc_get_ext_plugin(ext->plugin)->pfree(ctx, ext); } LY_LIST_FOR_SAFE(ext->child, next, stmt) { @@ -639,8 +639,8 @@ lysp_module_free(const struct ly_ctx *ctx, struct lysp_module *module) void 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, ext); + if (ext->def && ext->def->plugin && lysc_get_ext_plugin(ext->def->plugin)->cfree) { + lysc_get_ext_plugin(ext->def->plugin)->cfree(ctx, ext); } lydict_remove(ctx, ext->argument); FREE_ARRAY(ctx, ext->exts, lysc_ext_instance_free); diff --git a/src/validation.c b/src/validation.c index 7b380bd07..609297b4d 100644 --- a/src/validation.c +++ b/src/validation.c @@ -457,7 +457,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_plugin(ext_v->ext->def->plugin)->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 */ @@ -474,7 +475,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_plugin(ext_n->ext->def->plugin)->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 */ @@ -1860,7 +1861,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_plugin(nested_exts[u].def->plugin)->validate) { if (ext) { /* more extension instances with validate callback */ LOGINT_RET(LYD_CTX(sibling)); @@ -1893,7 +1894,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 && lysc_get_ext_plugin(exts[u].def->plugin)->node) { /* store for validation */ ext_n = malloc(sizeof *ext_n); LY_CHECK_ERR_RET(!ext_n, LOGMEM(LYD_CTX(node)), LY_EMEM); From 2812e2bb694796a636797f03548f7b1dd700a8fd Mon Sep 17 00:00:00 2001 From: roman Date: Mon, 20 Jan 2025 15:07:20 +0100 Subject: [PATCH 28/99] context BUGFIX free plugins with printed ctx --- src/context.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/context.c b/src/context.c index 690f31f34..cf3c24374 100644 --- a/src/context.c +++ b/src/context.c @@ -1502,6 +1502,7 @@ ly_ctx_destroy(struct ly_ctx *ctx) if (ctx->opts & LY_CTX_INT_IMMUTABLE) { /* ctx data */ ly_ctx_data_del(ctx); + lyplg_clean(); return; } From 44383c8a78ed9d1c1c52b9aeaca538e781a7976b Mon Sep 17 00:00:00 2001 From: roman Date: Mon, 20 Jan 2025 15:14:45 +0100 Subject: [PATCH 29/99] test schema UPDATE finish compiled ctx print test --- tests/utests/schema/test_schema.c | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/tests/utests/schema/test_schema.c b/tests/utests/schema/test_schema.c index a1f749d34..5e29a2dae 100644 --- a/tests/utests/schema/test_schema.c +++ b/tests/utests/schema/test_schema.c @@ -2123,10 +2123,14 @@ test_lysc_backlinks(void **state) static void test_compiled_print(void **state) { - struct ly_ctx *pctx; - struct lyd_node *tree; int size, fd; - void *mem, *mem_end; + void *mem, *mem_end, *printed_ctx_mem; + struct lyd_node *tree = NULL; + struct ly_ctx *printed_ctx = NULL; + + /* recreate the context, get rid of all the plugins and use builtin/static 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 another module */ assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, "module c {yang-version 1.1; namespace urn:c;prefix c;" @@ -2167,20 +2171,27 @@ test_compiled_print(void **state) assert_int_equal(LY_SUCCESS, ly_ctx_compiled_print(UTEST_LYCTX, mem, &mem_end)); assert_int_equal((char *)mem_end - (char *)mem, size); - /* use the printed context */ - assert_int_equal(LY_SUCCESS, ly_ctx_new_printed(mem, &pctx)); + /* remap the region and parse the context from mem */ + munmap(mem, size); + + /* mmap the same address again */ + printed_ctx_mem = mmap(mem, size, PROT_READ, MAP_PRIVATE | MAP_FIXED_NOREPLACE, fd, 0); + assert_ptr_not_equal(printed_ctx_mem, MAP_FAILED); + + /* create a new printed ctx from this address */ + assert_int_equal(LY_SUCCESS, ly_ctx_new_printed(printed_ctx_mem, &printed_ctx)); - /* use it to parse some data */ - assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(pctx, + /* try to parse data with it */ + assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(printed_ctx, "/c:b" "true" "ahoi", LYD_XML, 0, LYD_VALIDATE_PRESENT, &tree)); /* cleanup */ - lyd_free_siblings(tree); - ly_ctx_destroy(pctx); - munmap(mem, size); + lyd_free_all(tree); + ly_ctx_destroy(printed_ctx); + munmap(printed_ctx_mem, size); close(fd); shm_unlink("/ly_test_schema_ctx"); } From 713ea7b01a482ee4307684976d3039062ba32ae6 Mon Sep 17 00:00:00 2001 From: roman Date: Mon, 20 Jan 2025 15:37:04 +0100 Subject: [PATCH 30/99] plugins REFACTOR add doxygen to static func --- src/plugins.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/plugins.c b/src/plugins.c index e9920081b..850c86c12 100644 --- a/src/plugins.c +++ b/src/plugins.c @@ -176,7 +176,7 @@ lysc_get_ext_plugin(uintptr_t plugin_id) /** * @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 The 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. * @return The plugin records, NULL if no more record is available. @@ -202,6 +202,17 @@ plugins_iter(const struct ly_ctx *ctx, enum LYPLG type, uint32_t *index) return plugins->objs[*index - 1]; } +/** + * @brief Find the give @p type plugin record. + * + * @param[in] ctx The context for which the plugin record is searched for, NULL for built-in 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, uint32_t *record_idx) { From ae1d26d0de9c29e0ea4b1b5a23798b9a68cc8859 Mon Sep 17 00:00:00 2001 From: roman Date: Mon, 20 Jan 2025 15:49:24 +0100 Subject: [PATCH 31/99] plugins UPDATE merge type/ext plugin find funcs --- src/plugins.c | 53 ++++++++++++++++++++++----------------------------- 1 file changed, 23 insertions(+), 30 deletions(-) diff --git a/src/plugins.c b/src/plugins.c index 850c86c12..dfbff3a75 100644 --- a/src/plugins.c +++ b/src/plugins.c @@ -205,7 +205,7 @@ plugins_iter(const struct ly_ctx *ctx, enum LYPLG type, uint32_t *index) /** * @brief Find the give @p type plugin record. * - * @param[in] ctx The context for which the plugin record is searched for, NULL for built-in plugins. + * @param[in] ctx Context for which the plugin record is searched for, NULL for built-in 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. @@ -242,20 +242,31 @@ lyplg_record_find(const struct ly_ctx *ctx, enum LYPLG type, const char *module, return NULL; } -uintptr_t -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 built-in 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 Accessor to the callbacks plugin structure, use ::lysc_get_type_plugin() + * or ::lysc_get_ext_plugin() 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_type_record *record = NULL; uint32_t record_idx = 0; if (ctx) { /* try to find context specific plugin */ - record = lyplg_record_find(ctx, LYPLG_TYPE, module, revision, name, &record_idx); + record = lyplg_record_find(ctx, type, module, revision, name, &record_idx); } if (!record) { /* try to find shared plugin */ - record = lyplg_record_find(NULL, LYPLG_TYPE, module, revision, name, &record_idx); + record = lyplg_record_find(NULL, type, module, revision, name, &record_idx); } if (!record) { @@ -273,33 +284,15 @@ lyplg_type_plugin_find(const struct ly_ctx *ctx, const char *module, const char } uintptr_t -lyplg_ext_plugin_find(const struct ly_ctx *ctx, const char *module, const char *revision, const char *name) +lyplg_type_plugin_find(const struct ly_ctx *ctx, const char *module, const char *revision, const char *name) { - struct lyplg_ext_record *record = NULL; - uint32_t record_idx = 0; - - if (ctx) { - /* try to find context specific plugin */ - record = lyplg_record_find(ctx, LYPLG_EXTENSION, module, revision, name, &record_idx); - } - - if (!record) { - /* try to find shared plugin */ - record = lyplg_record_find(NULL, LYPLG_EXTENSION, module, revision, name, &record_idx); - } - - if (!record) { - /* not found */ - return 0; - } + return lyplg_plugin_find(ctx, LYPLG_TYPE, module, revision, name); +} - if (!strncmp(record->plugin.id, "ly2 - ", 6)) { - /* internal 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 { - /* external plugin, return the pointer */ - return (uintptr_t)&record->plugin; - } +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); } /** From 03da663075cd265b1b70d774a0bfc05a6b38890f Mon Sep 17 00:00:00 2001 From: roman Date: Wed, 22 Jan 2025 10:50:55 +0100 Subject: [PATCH 32/99] plugins BUGFIX move ext plgs outside builtin only --- src/plugins.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/plugins.c b/src/plugins.c index dfbff3a75..756f8c819 100644 --- a/src/plugins.c +++ b/src/plugins.c @@ -606,14 +606,14 @@ lyplg_init(ly_bool builtin_type_plugins_only, ly_bool static_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); + #ifndef STATIC if (!static_plugins_only) { /* external types */ From 74a616710385f49a5c932e60232e3e62609e05e3 Mon Sep 17 00:00:00 2001 From: roman Date: Wed, 22 Jan 2025 10:53:00 +0100 Subject: [PATCH 33/99] printer context BUGFIX build addr ht first --- src/printer_context.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/printer_context.c b/src/printer_context.c index 6ff911d80..94e494854 100644 --- a/src/printer_context.c +++ b/src/printer_context.c @@ -1741,13 +1741,15 @@ ly_ctx_compiled_print_context(const struct ly_ctx *orig_ctx, struct ly_ctx *ctx, /* no search paths */ memset(&ctx->search_paths, 0, sizeof ctx->search_paths); - /* modules, referenced */ + /* modules, referenced, 2 loops because of augments (forward reference), build the ht first */ ctxp_set(&orig_ctx->modules, &ctx->modules, mem); for (i = 0; i < ctx->modules.count; ++i) { 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) { ctxp_module(orig_ctx->modules.objs[i], ctx->modules.objs[i], addr_ht, ptr_set, mem); } From 0bcd66ecb591cba31aa44c775e18256a45e7f0af Mon Sep 17 00:00:00 2001 From: roman Date: Wed, 22 Jan 2025 10:54:11 +0100 Subject: [PATCH 34/99] printer context BUGFIX struct ext handling --- src/printer_context.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/printer_context.c b/src/printer_context.c index 94e494854..2fa0e27dc 100644 --- a/src/printer_context.c +++ b/src/printer_context.c @@ -121,7 +121,7 @@ ctxs_exts(const struct lysc_ext_instance *exts, struct ly_ht *ht, int *size) ctxs_exts(exts[u].exts, ht, size); /* substmts */ - *size += sizeof(LY_ARRAY_COUNT_TYPE) + LY_ARRAY_COUNT(exts[u].substmts) * sizeof *exts[u].substmts; + *size += CTXS_SIZED_ARRAY(exts[u].substmts); /* compiled, substmts storage */ ext = lysc_get_ext_plugin(exts[u].def->plugin); @@ -591,6 +591,11 @@ ly_ctx_compiled_ext_stmts_storage_size(const struct lysc_ext_substmt *substmts, 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: @@ -1775,10 +1780,17 @@ ly_ctx_compiled_ext_stmts_storage_print(const struct lysc_ext_substmt *orig_subs { LY_ERR rc = LY_SUCCESS; LY_ARRAY_COUNT_TYPE u, v; + uint32_t hash; + 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: @@ -1794,7 +1806,15 @@ ly_ctx_compiled_ext_stmts_storage_print(const struct lysc_ext_substmt *orig_subs case LY_STMT_LEAF_LIST: case LY_STMT_LIST: case LY_STMT_USES: - ctxp_children(*orig_substmts[u].storage_p, (struct lysc_node **)substmts[u].storage_p, addr_ht, ptr_set, mem); + node = *(const struct lysc_node **)orig_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; + } + + ctxp_children(node, (struct lysc_node **)substmts[u].storage_p, addr_ht, ptr_set, mem); break; case LY_STMT_ARGUMENT: case LY_STMT_CONTACT: From 17b6c467d2298e0c60868654d3c32eddace2c0b1 Mon Sep 17 00:00:00 2001 From: roman Date: Wed, 22 Jan 2025 12:37:12 +0100 Subject: [PATCH 35/99] test schema UPDATE compiled print test --- tests/utests/schema/test_schema.c | 121 +++++++++++++++++++++++------- 1 file changed, 95 insertions(+), 26 deletions(-) diff --git a/tests/utests/schema/test_schema.c b/tests/utests/schema/test_schema.c index 5e29a2dae..3476b6eaf 100644 --- a/tests/utests/schema/test_schema.c +++ b/tests/utests/schema/test_schema.c @@ -2124,23 +2124,30 @@ static void test_compiled_print(void **state) { int size, fd; - void *mem, *mem_end, *printed_ctx_mem; + void *mem, *mem_end; struct lyd_node *tree = NULL; struct ly_ctx *printed_ctx = NULL; + struct lys_module *mod = NULL; + const char *yang, *xml; + struct lysc_ext_instance *ext; + const char *features[] = {"feat", NULL}; - /* recreate the context, get rid of all the plugins and use builtin/static only */ + /* 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 another module */ - assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, "module c {yang-version 1.1; namespace urn:c;prefix c;" + /* 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;" - "feature feat2;" + "container root {" "leaf a {type instance-identifier;}" - "leaf b {type boolean; must \"/a\";}" - "leaf c {type binary; when \"/c:b = 'true'\";}" + "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 \"/c:a\"; default \"/c:b\"; default \"/c:c\";}" + "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;" @@ -2152,12 +2159,48 @@ test_compiled_print(void **state) " leaf d {type empty;}" " leaf e {type int8;}" "}" + "}" "rpc h {" " input {leaf a {type string;}}" "}" - "}", LYS_IN_YANG, NULL)); + "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); + + /* get the structure extension */ + assert_non_null(ext = &mod->compiled->exts[0]); - /* get the size */ + /* get the size of the compiled ctx */ size = ly_ctx_compiled_size(UTEST_LYCTX); /* prepare the shared memory segment */ @@ -2167,31 +2210,57 @@ test_compiled_print(void **state) mem = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); assert_ptr_not_equal(mem, MAP_FAILED); - /* print the context */ + /* 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); - /* remap the region and parse the context from mem */ - munmap(mem, size); + /* create a new printed ctx from this address */ + assert_int_equal(LY_SUCCESS, ly_ctx_new_printed(mem, &printed_ctx)); + + /* 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); - /* mmap the same address again */ - printed_ctx_mem = mmap(mem, size, PROT_READ, MAP_PRIVATE | MAP_FIXED_NOREPLACE, fd, 0); - assert_ptr_not_equal(printed_ctx_mem, MAP_FAILED); + /* 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)); - /* create a new printed ctx from this address */ - assert_int_equal(LY_SUCCESS, ly_ctx_new_printed(printed_ctx_mem, &printed_ctx)); + CHECK_LYD_STRING_PARAM(tree, xml, LYD_XML, 0); - /* try to parse data with it */ - assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(printed_ctx, - "/c:b" - "true" - "ahoi", - LYD_XML, 0, LYD_VALIDATE_PRESENT, &tree)); + lyd_free_all(tree); /* cleanup */ - lyd_free_all(tree); ly_ctx_destroy(printed_ctx); - munmap(printed_ctx_mem, size); + munmap(mem, size); close(fd); shm_unlink("/ly_test_schema_ctx"); } From 705f15352a5ca2e66faf8d516fb51f1a517f66c2 Mon Sep 17 00:00:00 2001 From: roman Date: Wed, 22 Jan 2025 13:13:53 +0100 Subject: [PATCH 36/99] plguins REFACTOR various smaller docs refactoring --- src/context.h | 2 +- src/plugins.c | 8 ++++++-- src/plugins_internal.h | 2 +- src/printer_context.c | 3 ++- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/context.h b/src/context.h index 2154b393b..225cf1018 100644 --- a/src/context.h +++ b/src/context.h @@ -212,7 +212,7 @@ struct ly_ctx; #define LY_CTX_STATIC_PLUGINS_ONLY 0x2000 /**< By default, external plugins from directories the path to which is obtained from the `LIBYANG_TYPES_PLUGINS_DIR` and `LIBYANG_EXTENSIONS_PLUGINS_DIR` environmental variables are loaded. This option prevents loading of all external plugins and only - the static (built-in) plugins are loaded. */ + the static (libyang built-in) plugins are loaded. */ /* 0x80000000 reserved for internal use */ diff --git a/src/plugins.c b/src/plugins.c index 756f8c819..dd81ae362 100644 --- a/src/plugins.c +++ b/src/plugins.c @@ -176,9 +176,9 @@ lysc_get_ext_plugin(uintptr_t plugin_id) /** * @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 * @@ -222,6 +222,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)) { diff --git a/src/plugins_internal.h b/src/plugins_internal.h index 0526bdef5..5520060f5 100644 --- a/src/plugins_internal.h +++ b/src/plugins_internal.h @@ -49,7 +49,7 @@ * 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 plugins, meaning no external directories with 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. diff --git a/src/printer_context.c b/src/printer_context.c index 2fa0e27dc..a159c9f9e 100644 --- a/src/printer_context.c +++ b/src/printer_context.c @@ -1749,12 +1749,13 @@ ly_ctx_compiled_print_context(const struct ly_ctx *orig_ctx, struct ly_ctx *ctx, /* modules, referenced, 2 loops because of augments (forward reference), build the ht first */ ctxp_set(&orig_ctx->modules, &ctx->modules, mem); for (i = 0; i < ctx->modules.count; ++i) { + /* build the address ht */ 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); } From b2d1485decb76ac6ba7e4d98548bf8a5bb92e4b8 Mon Sep 17 00:00:00 2001 From: roman Date: Wed, 22 Jan 2025 13:20:33 +0100 Subject: [PATCH 37/99] plugins REFACTOR s/plugin_id/plugin_ref --- src/plugins.c | 27 ++++++++++++++------------- src/schema_compile_node.c | 30 +++++++++++++++--------------- src/tree_schema.h | 12 ++++++------ 3 files changed, 35 insertions(+), 34 deletions(-) diff --git a/src/plugins.c b/src/plugins.c index dd81ae362..45ed051a7 100644 --- a/src/plugins.c +++ b/src/plugins.c @@ -135,42 +135,43 @@ static struct ly_set plugins_extensions = {0}; /** * @brief Get the plugin of the given @p type. * - * @param[in] plugin_id Either an index of the built-in plugin (offset by +1) or a pointer to the external plugin. + * @param[in] plugin_ref Reference to a plugin. Either an index of a built-in plugin (offset by +1) + * or a pointer to an external plugin. * @param[in] type Type of the plugin to get. - * @param[in] plugins Array of the built-in plugins used in case @p plugin_id is an index of a built-in plugin. + * @param[in] plugins Array of the built-in plugins used in case @p plugin_ref is an index of a built-in plugin. * @return Plugin of the given @p type or NULL if not found. */ static void * -lysc_get_plugin(uintptr_t plugin_id, enum LYPLG type, const struct ly_set *plugins) +lysc_get_plugin(uintptr_t plugin_ref, enum LYPLG type, const struct ly_set *plugins) { - /* plugin_id is offset by +1, so 0 is invalid (NULL ptr equivalent) */ - if (!plugin_id) { + /* plugin_ref is offset by +1, so 0 is invalid (NULL ptr equivalent) */ + if (!plugin_ref) { return NULL; } - if (plugin_id <= plugins->count) { + if (plugin_ref <= plugins->count) { /* plugin is built-in, fetch it from the global list */ if (type == LYPLG_EXTENSION) { - return &((struct lyplg_ext_record *)plugins->objs[plugin_id - 1])->plugin; + return &((struct lyplg_ext_record *)plugins->objs[plugin_ref - 1])->plugin; } else { - return &((struct lyplg_type_record *)plugins->objs[plugin_id - 1])->plugin; + return &((struct lyplg_type_record *)plugins->objs[plugin_ref - 1])->plugin; } } else { /* plugin is external, return the pointer */ - return (void *)plugin_id; + return (void *)plugin_ref; } } LIBYANG_API_DEF struct lyplg_type * -lysc_get_type_plugin(uintptr_t plugin_id) +lysc_get_type_plugin(uintptr_t plugin_ref) { - return lysc_get_plugin(plugin_id, LYPLG_TYPE, &plugins_types); + return lysc_get_plugin(plugin_ref, LYPLG_TYPE, &plugins_types); } LIBYANG_API_DEF struct lyplg_ext * -lysc_get_ext_plugin(uintptr_t plugin_id) +lysc_get_ext_plugin(uintptr_t plugin_ref) { - return lysc_get_plugin(plugin_id, LYPLG_EXTENSION, &plugins_extensions); + return lysc_get_plugin(plugin_ref, LYPLG_EXTENSION, &plugins_extensions); } /** diff --git a/src/schema_compile_node.c b/src/schema_compile_node.c index 561035b96..4660891f7 100644 --- a/src/schema_compile_node.c +++ b/src/schema_compile_node.c @@ -1777,7 +1777,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 +1786,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, - uintptr_t 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 +1807,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 = plugin_ref; switch (basetype) { case LY_TYPE_BINARY: @@ -2154,7 +2154,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}; - uintptr_t plugin_id = 0; + uintptr_t plugin_ref = 0; *type = NULL; if (dflt) { @@ -2277,19 +2277,19 @@ lys_compile_type(struct lysc_ctx *ctx, struct lysp_node *context_pnode, uint16_t } /* try to find loaded user type plugins */ - plugin_id = 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_id && base) { - plugin_id = base->plugin; + if (!plugin_ref && base) { + plugin_ref = base->plugin; } - if (!plugin_id) { + if (!plugin_ref) { /* use the internal built-in type implementation */ - plugin_id = 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_id); + assert(plugin_ref); if ((basetype != LY_TYPE_LEAFREF) && (u != tpdf_chain.count - 1) && !tctx->tpdf->type.flags && - !tctx->tpdf->type.exts && (plugin_id == base->plugin)) { + !tctx->tpdf->type.exts && (plugin_ref == base->plugin)) { /* no change, reuse the compiled base */ ((struct lysp_tpdf *)tctx->tpdf)->type.compiled = base; LY_ATOMIC_INC_BARRIER(base->refcount); @@ -2310,7 +2310,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_id, &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,12 +2342,12 @@ lys_compile_type(struct lysc_ctx *ctx, struct lysp_node *context_pnode, uint16_t if (type_p->flags || type_p->exts || !base || has_leafref) { /* leaf type has changes that need to be compiled into the type */ if (base) { - plugin_id = base->plugin; + plugin_ref = base->plugin; } else { - plugin_id = lyplg_type_plugin_find(ctx->ctx, "", NULL, ly_data_type2str[basetype]); + 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_id, &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 */ diff --git a/src/tree_schema.h b/src/tree_schema.h index 9796d4809..aee22121b 100644 --- a/src/tree_schema.h +++ b/src/tree_schema.h @@ -1800,20 +1800,20 @@ struct lysc_module { /** * @brief Get a type plugin. * - * @param[in] plugin_id 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. + * @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_id); +LIBYANG_API_DECL struct lyplg_type *lysc_get_type_plugin(uintptr_t plugin_ref); /** * @brief Get an extension plugin. * - * @param[in] plugin_id 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. + * @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_id); +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. From 34ff4dcc8f61c3e79992e37ef8f9e535a04d8715 Mon Sep 17 00:00:00 2001 From: roman Date: Fri, 24 Jan 2025 11:20:44 +0100 Subject: [PATCH 38/99] plugins REFACTOR remove dash from id --- src/plugins_exts/metadata.c | 2 +- src/plugins_exts/nacm.c | 8 +++---- src/plugins_exts/schema_mount.c | 2 +- src/plugins_exts/structure.c | 4 ++-- src/plugins_exts/yangdata.c | 2 +- src/plugins_types/binary.c | 2 +- src/plugins_types/bits.c | 2 +- src/plugins_types/boolean.c | 2 +- src/plugins_types/date_and_time.c | 2 +- src/plugins_types/decimal64.c | 2 +- src/plugins_types/empty.c | 2 +- src/plugins_types/enumeration.c | 2 +- src/plugins_types/hex_string.c | 8 +++---- src/plugins_types/identityref.c | 2 +- src/plugins_types/instanceid.c | 2 +- src/plugins_types/instanceid_keys.c | 2 +- src/plugins_types/integer.c | 16 ++++++------- src/plugins_types/ipv4_address.c | 2 +- src/plugins_types/ipv4_address_no_zone.c | 2 +- src/plugins_types/ipv4_prefix.c | 2 +- src/plugins_types/ipv6_address.c | 2 +- src/plugins_types/ipv6_address_no_zone.c | 2 +- src/plugins_types/ipv6_prefix.c | 2 +- src/plugins_types/leafref.c | 2 +- src/plugins_types/lyds_tree.c | 2 +- src/plugins_types/node_instanceid.c | 4 ++-- src/plugins_types/string.c | 2 +- src/plugins_types/time_period.c | 2 +- src/plugins_types/union.c | 2 +- src/plugins_types/xpath1.0.c | 2 +- tests/utests/extensions/test_metadata.c | 8 +++---- tests/utests/extensions/test_nacm.c | 8 +++---- tests/utests/extensions/test_schema_mount.c | 26 ++++++++++----------- tests/utests/extensions/test_structure.c | 6 ++--- tests/utests/extensions/test_yangdata.c | 14 +++++------ tests/utests/types/binary.c | 2 +- tests/utests/types/bits.c | 2 +- tests/utests/types/int8.c | 2 +- tests/utests/types/string.c | 2 +- tests/utests/types/union.c | 14 +++++------ 40 files changed, 87 insertions(+), 87 deletions(-) diff --git a/src/plugins_exts/metadata.c b/src/plugins_exts/metadata.c index f6f37b45b..e699e120e 100644 --- a/src/plugins_exts/metadata.c +++ b/src/plugins_exts/metadata.c @@ -257,7 +257,7 @@ const struct lyplg_ext_record plugins_metadata[] = { .revision = "2016-08-05", .name = "annotation", - .plugin.id = "ly2 - metadata", + .plugin.id = "ly2 metadata", .plugin.parse = annotation_parse, .plugin.compile = annotation_compile, .plugin.printer_info = annotation_printer_info, diff --git a/src/plugins_exts/nacm.c b/src/plugins_exts/nacm.c index adda9d28a..faa5c6a4d 100644 --- a/src/plugins_exts/nacm.c +++ b/src/plugins_exts/nacm.c @@ -177,7 +177,7 @@ const struct lyplg_ext_record plugins_nacm[] = { .revision = "2012-02-22", .name = "default-deny-write", - .plugin.id = "ly2 - NACM", + .plugin.id = "ly2 NACM", .plugin.parse = nacm_parse, .plugin.compile = nacm_compile, .plugin.printer_info = NULL, @@ -195,7 +195,7 @@ const struct lyplg_ext_record plugins_nacm[] = { .revision = "2018-02-14", .name = "default-deny-write", - .plugin.id = "ly2 - NACM", + .plugin.id = "ly2 NACM", .plugin.parse = nacm_parse, .plugin.compile = nacm_compile, .plugin.printer_info = NULL, @@ -213,7 +213,7 @@ const struct lyplg_ext_record plugins_nacm[] = { .revision = "2012-02-22", .name = "default-deny-all", - .plugin.id = "ly2 - NACM", + .plugin.id = "ly2 NACM", .plugin.parse = nacm_parse, .plugin.compile = nacm_compile, .plugin.printer_info = NULL, @@ -231,7 +231,7 @@ const struct lyplg_ext_record plugins_nacm[] = { .revision = "2018-02-14", .name = "default-deny-all", - .plugin.id = "ly2 - NACM", + .plugin.id = "ly2 NACM", .plugin.parse = nacm_parse, .plugin.compile = nacm_compile, .plugin.printer_info = NULL, diff --git a/src/plugins_exts/schema_mount.c b/src/plugins_exts/schema_mount.c index bc23d62a8..325f8427b 100644 --- a/src/plugins_exts/schema_mount.c +++ b/src/plugins_exts/schema_mount.c @@ -1422,7 +1422,7 @@ const struct lyplg_ext_record plugins_schema_mount[] = { .revision = "2019-01-14", .name = "mount-point", - .plugin.id = "ly2 - schema mount", + .plugin.id = "ly2 schema mount", .plugin.parse = schema_mount_parse, .plugin.compile = schema_mount_compile, .plugin.printer_info = NULL, diff --git a/src/plugins_exts/structure.c b/src/plugins_exts/structure.c index b1463f912..618221368 100644 --- a/src/plugins_exts/structure.c +++ b/src/plugins_exts/structure.c @@ -563,7 +563,7 @@ const struct lyplg_ext_record plugins_structure[] = { .revision = "2020-06-17", .name = "structure", - .plugin.id = "ly2 - structure", + .plugin.id = "ly2 structure", .plugin.parse = structure_parse, .plugin.compile = structure_compile, .plugin.printer_info = structure_printer_info, @@ -582,7 +582,7 @@ const struct lyplg_ext_record plugins_structure[] = { .revision = "2020-06-17", .name = "augment-structure", - .plugin.id = "ly2 - structure", + .plugin.id = "ly2 structure", .plugin.parse = structure_aug_parse, .plugin.compile = NULL, .plugin.printer_info = NULL, diff --git a/src/plugins_exts/yangdata.c b/src/plugins_exts/yangdata.c index ea3bc9b10..917ce19dd 100644 --- a/src/plugins_exts/yangdata.c +++ b/src/plugins_exts/yangdata.c @@ -278,7 +278,7 @@ const struct lyplg_ext_record plugins_yangdata[] = { .revision = "2017-01-26", .name = "yang-data", - .plugin.id = "ly2 - yang-data", + .plugin.id = "ly2 yang-data", .plugin.parse = yangdata_parse, .plugin.compile = yangdata_compile, .plugin.printer_info = yangdata_printer_info, diff --git a/src/plugins_types/binary.c b/src/plugins_types/binary.c index 24f2c2960..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 = "ly2 - binary", + .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 cdeb84d34..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 = "ly2 - bits", + .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 42b7918d4..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 = "ly2 - boolean", + .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 c2aaf794e..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 = "ly2 - date-and-time", + .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 5a9b7ab2d..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 = "ly2 - decimal64", + .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 8b88e6154..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 = "ly2 - empty", + .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 d3159a6e3..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 = "ly2 - enumeration", + .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 285967b67..646a545ff 100644 --- a/src/plugins_types/hex_string.c +++ b/src/plugins_types/hex_string.c @@ -118,7 +118,7 @@ const struct lyplg_type_record plugins_hex_string[] = { .revision = "2013-07-15", .name = "phys-address", - .plugin.id = "ly2 - hex-string", + .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 = "ly2 - hex-string", + .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 = "ly2 - hex-string", + .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 = "ly2 - hex-string", + .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 63cd3c176..b1f867d12 100644 --- a/src/plugins_types/identityref.c +++ b/src/plugins_types/identityref.c @@ -354,7 +354,7 @@ const struct lyplg_type_record plugins_identityref[] = { .revision = NULL, .name = LY_TYPE_IDENT_STR, - .plugin.id = "ly2 - identityref", + .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 78f221b87..59da3ab9c 100644 --- a/src/plugins_types/instanceid.c +++ b/src/plugins_types/instanceid.c @@ -321,7 +321,7 @@ const struct lyplg_type_record plugins_instanceid[] = { .revision = NULL, .name = LY_TYPE_INST_STR, - .plugin.id = "ly2 - instance-identifier", + .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 6d7423cad..9ddf1e43c 100644 --- a/src/plugins_types/instanceid_keys.c +++ b/src/plugins_types/instanceid_keys.c @@ -239,7 +239,7 @@ const struct lyplg_type_record plugins_instanceid_keys[] = { .revision = NULL, .name = "instance-identifier-keys", - .plugin.id = "ly2 - instance-identifier-keys", + .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 5a52ad7fb..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 = "ly2 - integers", + .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 = "ly2 - integers", + .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 = "ly2 - integers", + .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 = "ly2 - integers", + .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 = "ly2 - integers", + .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 = "ly2 - integers", + .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 = "ly2 - integers", + .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 = "ly2 - integers", + .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 98d88c6f3..e2fedf80e 100644 --- a/src/plugins_types/ipv4_address.c +++ b/src/plugins_types/ipv4_address.c @@ -392,7 +392,7 @@ const struct lyplg_type_record plugins_ipv4_address[] = { .revision = "2013-07-15", .name = "ipv4-address", - .plugin.id = "ly2 - ipv4-address", + .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 ffe1cbac4..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 = "ly2 - ipv4-address-no-zone", + .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 7f422cce0..d92ebdfcb 100644 --- a/src/plugins_types/ipv4_prefix.c +++ b/src/plugins_types/ipv4_prefix.c @@ -339,7 +339,7 @@ const struct lyplg_type_record plugins_ipv4_prefix[] = { .revision = "2013-07-15", .name = "ipv4-prefix", - .plugin.id = "ly2 - ipv4-prefix", + .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 8b0057de4..c50be8d07 100644 --- a/src/plugins_types/ipv6_address.c +++ b/src/plugins_types/ipv6_address.c @@ -394,7 +394,7 @@ const struct lyplg_type_record plugins_ipv6_address[] = { .revision = "2013-07-15", .name = "ipv6-address", - .plugin.id = "ly2 - ipv6-address", + .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 b4422cd33..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 = "ly2 - ipv6-address-no-zone", + .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 6730172a2..752eefd2e 100644 --- a/src/plugins_types/ipv6_prefix.c +++ b/src/plugins_types/ipv6_prefix.c @@ -353,7 +353,7 @@ const struct lyplg_type_record plugins_ipv6_prefix[] = { .revision = "2013-07-15", .name = "ipv6-prefix", - .plugin.id = "ly2 - ipv6-prefix", + .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 8de07dbdd..7a3961428 100644 --- a/src/plugins_types/leafref.c +++ b/src/plugins_types/leafref.c @@ -145,7 +145,7 @@ const struct lyplg_type_record plugins_leafref[] = { .revision = NULL, .name = LY_TYPE_LEAFREF_STR, - .plugin.id = "ly2 - leafref", + .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 9dbe28e7b..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 = "ly2 - lyds_tree", + .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 34f5ff7fa..e7e720751 100644 --- a/src/plugins_types/node_instanceid.c +++ b/src/plugins_types/node_instanceid.c @@ -334,7 +334,7 @@ const struct lyplg_type_record plugins_node_instanceid[] = { .revision = "2012-02-22", .name = "node-instance-identifier", - .plugin.id = "ly2 - node-instance-identifier", + .plugin.id = "ly2 node-instance-identifier", .plugin.store = lyplg_type_store_node_instanceid, .plugin.validate = NULL, .plugin.compare = lyplg_type_compare_simple, @@ -349,7 +349,7 @@ const struct lyplg_type_record plugins_node_instanceid[] = { .revision = "2018-02-14", .name = "node-instance-identifier", - .plugin.id = "ly2 - node-instance-identifier", + .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 c998aeec8..4d18cd92c 100644 --- a/src/plugins_types/string.c +++ b/src/plugins_types/string.c @@ -130,7 +130,7 @@ const struct lyplg_type_record plugins_string[] = { .revision = NULL, .name = LY_TYPE_STRING_STR, - .plugin.id = "ly2 - string", + .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 4e76cf42a..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 = "ly2 - time-period", + .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 a10b7e72e..7a86abf7f 100644 --- a/src/plugins_types/union.c +++ b/src/plugins_types/union.c @@ -780,7 +780,7 @@ const struct lyplg_type_record plugins_union[] = { .revision = NULL, .name = LY_TYPE_UNION_STR, - .plugin.id = "ly2 - union", + .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 8af4ede6a..4d77f95ae 100644 --- a/src/plugins_types/xpath1.0.c +++ b/src/plugins_types/xpath1.0.c @@ -524,7 +524,7 @@ const struct lyplg_type_record plugins_xpath10[] = { .revision = "2013-07-15", .name = "xpath1.0", - .plugin.id = "ly2 - xpath1.0", + .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/tests/utests/extensions/test_metadata.c b/tests/utests/extensions/test_metadata.c index f526323ad..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\": 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\": 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\": 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\": 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 44daf3bf0..9cbad1e3f 100644 --- a/tests/utests/extensions/test_nacm.c +++ b/tests/utests/extensions/test_nacm.c @@ -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\": " + 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\": " + 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); } @@ -98,7 +98,7 @@ test_deny_write(void **state) "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\": " + 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\": " + 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 4b0486895..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\": " + 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\": " + 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\": " + 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\": " + CHECK_LOG_CTX("Ext plugin \"ly2 schema mount\": " "Multiple extension \"yangmnt:mount-point\" instances.", "/sm:l/{extension='yangmnt:mount-point'}/root", 0); @@ -196,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\": 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 = @@ -213,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\": 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 */ @@ -401,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\": 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\": 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\": 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\": 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); @@ -865,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\": " + 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); @@ -1121,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\": " + 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); @@ -1146,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\": " + 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 d67c001dd..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\": " + 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\": 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\": 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 424789369..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\": " + 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\": " + 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\": " + 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\": " + 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\": " + 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\": " + 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\": " + 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/types/binary.c b/tests/utests/types/binary.c index 484ac4102..5e6bf8de0 100644 --- a/tests/utests/types/binary.c +++ b/tests/utests/types/binary.c @@ -63,7 +63,7 @@ test_plugin_store(void **state) lysc_type2 = ((struct lysc_node_leaf *)mod->compiled->data->next)->type; /* check proper type */ - assert_string_equal("ly2 - binary", type->id); + assert_string_equal("ly2 binary", type->id); /* check store XML double pad */ val = "YWhveQ=="; diff --git a/tests/utests/types/bits.c b/tests/utests/types/bits.c index 65e7a0266..0ef81f9cd 100644 --- a/tests/utests/types/bits.c +++ b/tests/utests/types/bits.c @@ -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("ly2 - bits", type->id); + assert_string_equal("ly2 bits", type->id); /* check store */ diff --git a/tests/utests/types/int8.c b/tests/utests/types/int8.c index 8c5ce6bc1..8a9f2f4ca 100644 --- a/tests/utests/types/int8.c +++ b/tests/utests/types/int8.c @@ -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("ly2 - integers", type->id); + assert_string_equal("ly2 integers", type->id); /* check store * options = LY_TYPE_STORE_IMPLEMENT | LY_TYPE_STORE_DYNAMIC diff --git a/tests/utests/types/string.c b/tests/utests/types/string.c index c07f372f5..7c4742117 100644 --- a/tests/utests/types/string.c +++ b/tests/utests/types/string.c @@ -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("ly2 - string", type->id); + assert_string_equal("ly2 string", type->id); /* check store */ val_text = "20"; diff --git a/tests/utests/types/union.c b/tests/utests/types/union.c index 6131c1581..2649e0318 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" - " ly2 - leafref: Invalid type int8 value \"123456789012345678901\".\n" - " ly2 - leafref: Invalid type int64 value \"123456789012345678901\".\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", + " ly2 leafref: Invalid type int8 value \"123456789012345678901\".\n" + " ly2 leafref: Invalid type int64 value \"123456789012345678901\".\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); } @@ -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" - " ly2 - leafref: Invalid leafref value \"one\" - no target instance \"../../a/name\" with the same value.\n" - " ly2 - leafref: Invalid type uint32 value \"one\".\n", "/lref:test/community[name='test']/view", 0); + " ly2 leafref: Invalid leafref value \"one\" - no target instance \"../../a/name\" with the same value.\n" + " ly2 leafref: Invalid type uint32 value \"one\".\n", "/lref:test/community[name='test']/view", 0); lyd_free_all(tree); } From 8eabfeeb4fac37d5732e9459d6f4c8a00619a360 Mon Sep 17 00:00:00 2001 From: roman Date: Fri, 24 Jan 2025 13:20:36 +0100 Subject: [PATCH 39/99] plugins UPDATE replace plg get fn call with macro Also replace plugin by plugin_ref --- src/log.c | 9 +-- src/parser_lyb.c | 5 +- src/plugins.c | 112 +++++++++++++++--------------- src/plugins_exts.h | 3 +- src/plugins_exts/nacm.c | 5 +- src/plugins_internal.h | 44 ++++++++++++ src/plugins_types.c | 4 +- src/plugins_types/leafref.c | 12 ++-- src/plugins_types/union.c | 28 ++++---- src/printer_context.c | 11 +-- src/printer_json.c | 3 +- src/printer_lyb.c | 3 +- src/printer_tree.c | 15 ++-- src/printer_xml.c | 5 +- src/printer_yang.c | 8 +-- src/schema_compile.c | 8 +-- src/schema_compile_amend.c | 7 +- src/schema_compile_node.c | 8 +-- src/tree_data.c | 10 +-- src/tree_data_common.c | 23 +++--- src/tree_data_free.c | 5 +- src/tree_data_hash.c | 5 +- src/tree_data_new.c | 8 +-- src/tree_data_sorted.c | 2 +- src/tree_schema.c | 8 +-- src/tree_schema.h | 26 +++---- src/tree_schema_free.c | 9 +-- src/validation.c | 13 ++-- src/xpath.c | 9 +-- tests/utests/basic/test_plugins.c | 4 +- tests/utests/types/binary.c | 2 +- tests/utests/types/bits.c | 2 +- tests/utests/types/int8.c | 6 +- tests/utests/types/string.c | 2 +- tests/utests/utests.h | 32 ++++----- 35 files changed, 259 insertions(+), 197 deletions(-) diff --git a/src/log.c b/src/log.c index 829707ece..65ccdc839 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" @@ -913,7 +914,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), lysc_get_ext_plugin(ext->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); } @@ -930,7 +931,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, lysc_get_ext_plugin(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); } @@ -947,7 +948,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, lysc_get_ext_plugin(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); } @@ -968,7 +969,7 @@ _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, lysc_get_ext_plugin(ext->def->plugin)->id, eitem->level, eitem->err, + 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/parser_lyb.c b/src/parser_lyb.c index c9276da13..37bec5632 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 = lysc_get_type_plugin(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 = lysc_get_type_plugin(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) { diff --git a/src/plugins.c b/src/plugins.c index 45ed051a7..6cf44fcd8 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,51 +127,45 @@ 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}; +struct ly_set ly_plugins_types; +struct ly_set ly_plugins_extensions; -/** - * @brief Get the plugin of the given @p type. - * - * @param[in] plugin_ref Reference to a plugin. Either an index of a built-in plugin (offset by +1) - * or a pointer to an external plugin. - * @param[in] type Type of the plugin to get. - * @param[in] plugins Array of the built-in plugins used in case @p plugin_ref is an index of a built-in plugin. - * @return Plugin of the given @p type or NULL if not found. - */ -static void * -lysc_get_plugin(uintptr_t plugin_ref, enum LYPLG type, const struct ly_set *plugins) +/* 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) { - /* plugin_ref is offset by +1, so 0 is invalid (NULL ptr equivalent) */ if (!plugin_ref) { return NULL; } - if (plugin_ref <= plugins->count) { - /* plugin is built-in, fetch it from the global list */ - if (type == LYPLG_EXTENSION) { - return &((struct lyplg_ext_record *)plugins->objs[plugin_ref - 1])->plugin; - } else { - return &((struct lyplg_type_record *)plugins->objs[plugin_ref - 1])->plugin; - } + if (plugin_ref <= ly_plugins_types.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 external, return the pointer */ - return (void *)plugin_ref; + /* plugin is dynamic, return the pointer */ + return (struct lyplg_type *)plugin_ref; } } -LIBYANG_API_DEF struct lyplg_type * -lysc_get_type_plugin(uintptr_t plugin_ref) -{ - return lysc_get_plugin(plugin_ref, LYPLG_TYPE, &plugins_types); -} - LIBYANG_API_DEF struct lyplg_ext * lysc_get_ext_plugin(uintptr_t plugin_ref) { - return lysc_get_plugin(plugin_ref, LYPLG_EXTENSION, &plugins_extensions); + if (!plugin_ref) { + return NULL; + } + + if (plugin_ref <= ly_plugins_extensions.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; + } } /** @@ -190,9 +184,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) { @@ -255,35 +249,37 @@ lyplg_record_find(const struct ly_ctx *ctx, enum LYPLG type, const char *module, * @param[in] module Module name of the plugin. * @param[in] revision Revision of the @p module. * @param[in] name Name of the plugin. - * @return Accessor to the callbacks plugin structure, use ::lysc_get_type_plugin() - * or ::lysc_get_ext_plugin() on the returned value to get the actual plugin. 0 if not found. + * @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_type_record *record = NULL; - uint32_t record_idx = 0; + uint32_t record_idx = 0, static_plugin_count; if (ctx) { /* try to find context specific plugin */ 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; + } } - if (!record) { - /* try to find shared plugin */ - record = lyplg_record_find(NULL, type, module, revision, name, &record_idx); - } - + /* try to find shared plugin */ + record = lyplg_record_find(NULL, type, module, revision, name, &record_idx); if (!record) { /* not found */ return 0; } - if (!strncmp(record->plugin.id, "ly2 - ", 6)) { - /* internal plugin, return an index with an offset of +1 in order to keep 0 as an invalid index (a NULL ptr) */ + 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 { - /* external plugin, return the pointer */ + /* dynamic plugin, return the pointer to it */ return (uintptr_t)&record->plugin; } } @@ -324,7 +320,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)); @@ -332,7 +328,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)); @@ -358,9 +354,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 @@ -475,8 +472,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); @@ -496,11 +493,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; @@ -619,6 +616,11 @@ lyplg_init(ly_bool builtin_type_plugins_only, ly_bool static_plugins_only) 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 if (!static_plugins_only) { /* external types */ diff --git a/src/plugins_exts.h b/src/plugins_exts.h index 71fdee7a2..5d688700a 100644 --- a/src/plugins_exts.h +++ b/src/plugins_exts.h @@ -405,7 +405,8 @@ 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()) */ - uintptr_t plugin; /**< extension plugin, use ::lysc_get_ext_plugin() */ + uintptr_t plugin_ref; /**< reference to extension's manipulation callbacks 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 */ diff --git a/src/plugins_exts/nacm.c b/src/plugins_exts/nacm.c index faa5c6a4d..45e34f844 100644 --- a/src/plugins_exts/nacm.c +++ b/src/plugins_exts/nacm.c @@ -20,6 +20,7 @@ #include "compat.h" #include "libyang.h" #include "plugins_exts.h" +#include "plugins_internal.h" struct nacm_dfs_arg { struct lysc_ext_instance *ext; @@ -101,11 +102,11 @@ nacm_parse(struct lysp_ctx *pctx, struct lysp_ext_instance *ext) return LY_ENOT; } - ext_plugin = lysc_get_ext_plugin(ext->plugin); + ext_plugin = LYSC_GET_EXT_PLG(ext->plugin_ref); /* check for duplication */ LY_ARRAY_FOR(parent->exts, u) { - parent_ext_plugin = lysc_get_ext_plugin(parent->exts[u].plugin); + 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 diff --git a/src/plugins_internal.h b/src/plugins_internal.h index 5520060f5..3ff7188f0 100644 --- a/src/plugins_internal.h +++ b/src/plugins_internal.h @@ -43,6 +43,50 @@ #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 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 a 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. * diff --git a/src/plugins_types.c b/src/plugins_types.c index 72f6c40ad..57b5c0cde 100644 --- a/src/plugins_types.c +++ b/src/plugins_types.c @@ -906,7 +906,7 @@ lyplg_type_print_val(const struct lysc_node *node, const char *canon, LY_VALUE_F struct lyplg_type *type_plugin; type = ((struct lysc_node_leaf *)node)->type; - type_plugin = lysc_get_type_plugin(type->plugin); + type_plugin = LYSC_GET_TYPE_PLG(type->plugin_ref); /* store the value */ r = type_plugin->store(node->module->ctx, type, canon, strlen(canon), LYPLG_TYPE_STORE_ONLY, LY_VALUE_CANON, @@ -1102,7 +1102,7 @@ lyplg_type_resolve_leafref(const struct lysc_type_leafref *lref, const struct ly goto cleanup; } - type = lysc_get_type_plugin(lref->plugin); + type = LYSC_GET_TYPE_PLG(lref->plugin_ref); /* check the result */ if (target_path) { diff --git a/src/plugins_types/leafref.c b/src/plugins_types/leafref.c index 7a3961428..deb8cc424 100644 --- a/src/plugins_types/leafref.c +++ b/src/plugins_types/leafref.c @@ -47,7 +47,7 @@ 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 = lysc_get_type_plugin(type_lr->realtype->plugin)->store(ctx, type_lr->realtype, value, value_len, options, + 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 */ @@ -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 lysc_get_type_plugin(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 lysc_get_type_plugin(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 lysc_get_type_plugin(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 lysc_get_type_plugin(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) { - lysc_get_type_plugin(value->realtype->plugin)->free(ctx, value); + LYSC_GET_TYPE_PLG(value->realtype->plugin_ref)->free(ctx, value); } /** diff --git a/src/plugins_types/union.c b/src/plugins_types/union.c index 7a86abf7f..f8a49c032 100644 --- a/src/plugins_types/union.c +++ b/src/plugins_types/union.c @@ -228,7 +228,7 @@ 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 = lysc_get_type_plugin(type_u->types[ti]->plugin)->store(ctx, type_u->types[ti], value, value_len, + rc = LYSC_GET_TYPE_PLG(type_u->types[ti]->plugin_ref)->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)) { @@ -241,7 +241,7 @@ union_store_type(const struct ly_ctx *ctx, struct lysc_type_union *type_u, uint3 } assert(subvalue->value.realtype); - value = lysc_get_type_plugin(subvalue->value.realtype->plugin)->print(ctx, &subvalue->value, + 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 */ @@ -249,7 +249,7 @@ union_store_type(const struct ly_ctx *ctx, struct lysc_type_union *type_u, uint3 value = strndup(value, value_len); dynamic = 1; } - lysc_get_type_plugin(type_u->types[ti]->plugin)->free(ctx, &subvalue->value); + LYSC_GET_TYPE_PLG(type_u->types[ti]->plugin_ref)->free(ctx, &subvalue->value); format = LY_VALUE_JSON; prefix_data = NULL; @@ -268,7 +268,7 @@ union_store_type(const struct ly_ctx *ctx, struct lysc_type_union *type_u, uint3 opts |= LYPLG_TYPE_STORE_ONLY; } - type_plugin = lysc_get_type_plugin(type->plugin); + type_plugin = LYSC_GET_TYPE_PLG(type->plugin_ref); rc = type_plugin->store(ctx, type, value, value_len, opts, format, prefix_data, subvalue->hints, subvalue->ctx_node, &subvalue->value, unres, err); @@ -376,7 +376,7 @@ union_find_type(const struct ly_ctx *ctx, struct lysc_type_union *type_u, struct } } - type = lysc_get_type_plugin(type_u->types[u]->plugin); + type = LYSC_GET_TYPE_PLG(type_u->types[u]->plugin_ref); msg = ly_realloc(msg, msg_len + 4 + strlen(type->id) + 2 + strlen(errs[u]->msg) + 2); LY_CHECK_ERR_GOTO(!msg, ret = LY_EMEM, cleanup); @@ -526,7 +526,7 @@ lyplg_type_validate_union(const struct ly_ctx *ctx, const struct lysc_type *type /* 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 */ - subvalue_type = lysc_get_type_plugin(subvalue->value.realtype->plugin); + subvalue_type = LYSC_GET_TYPE_PLG(subvalue->value.realtype->plugin_ref); LY_CHECK_RET(subvalue_type->duplicate(ctx, &subvalue->value, &orig)); subvalue_type->free(ctx, &subvalue->value); @@ -558,7 +558,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 */ - lysc_get_type_plugin(orig.realtype->plugin)->free(ctx, &orig); + LYSC_GET_TYPE_PLG(orig.realtype->plugin_ref)->free(ctx, &orig); return LY_SUCCESS; } @@ -568,7 +568,7 @@ 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 lysc_get_type_plugin(val1->subvalue->value.realtype->plugin)->compare(ctx, + return LYSC_GET_TYPE_PLG(val1->subvalue->value.realtype->plugin_ref)->compare(ctx, &val1->subvalue->value, &val2->subvalue->value); } @@ -580,7 +580,7 @@ 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 lysc_get_type_plugin(val1->subvalue->value.realtype->plugin)->sort(ctx, + return LYSC_GET_TYPE_PLG(val1->subvalue->value.realtype->plugin_ref)->sort(ctx, &val1->subvalue->value, &val2->subvalue->value); } @@ -640,13 +640,13 @@ 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; } - lysc_get_type_plugin(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 *)lysc_get_type_plugin(subvalue->value.realtype->plugin)->print(NULL, &subvalue->value, LY_VALUE_LYB, + 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); @@ -695,7 +695,7 @@ lyplg_type_print_union(const struct ly_ctx *ctx, const struct lyd_value *value, } assert(format != LY_VALUE_LYB); - type = lysc_get_type_plugin(subvalue->value.realtype->plugin); + type = LYSC_GET_TYPE_PLG(subvalue->value.realtype->plugin_ref); ret = (void *)type->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 */ @@ -722,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 = lysc_get_type_plugin(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) { @@ -758,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) { - lysc_get_type_plugin(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); diff --git a/src/printer_context.c b/src/printer_context.c index a159c9f9e..79083c71f 100644 --- a/src/printer_context.c +++ b/src/printer_context.c @@ -22,6 +22,7 @@ #include "log.h" #include "ly_common.h" #include "plugins_exts.h" +#include "plugins_internal.h" #include "tree_schema_internal.h" #include "xpath.h" @@ -124,7 +125,7 @@ ctxs_exts(const struct lysc_ext_instance *exts, struct ly_ht *ht, int *size) *size += CTXS_SIZED_ARRAY(exts[u].substmts); /* compiled, substmts storage */ - ext = lysc_get_ext_plugin(exts[u].def->plugin); + ext = LYSC_GET_EXT_PLG(exts[u].def->plugin_ref); if (ext && ext->compiled_size) { *size += ext->compiled_size(&exts[u], ht); } @@ -821,8 +822,8 @@ ctxp_ext(const struct lysc_ext_instance *orig_ext, struct lysc_ext_instance *ext } /* compiled, substmts storage, use the plugin */ - if (ext->def->plugin && lysc_get_ext_plugin(ext->def->plugin)->compiled_print) { - lysc_get_ext_plugin(ext->def->plugin)->compiled_print(orig_ext, ext, addr_ht, ptr_set, mem); + if (ext->def->plugin_ref && LYSC_GET_EXT_PLG(ext->def->plugin_ref)->compiled_print) { + LYSC_GET_EXT_PLG(ext->def->plugin_ref)->compiled_print(orig_ext, ext, addr_ht, ptr_set, mem); } else { ext->compiled = NULL; } @@ -1281,7 +1282,7 @@ ctxp_type(const struct lysc_type *orig_type, struct lysc_type **type, struct ly_ } /* static structures in the shared library */ - t->plugin = orig_type->plugin; + t->plugin_ref = orig_type->plugin_ref; t->basetype = orig_type->basetype; t->refcount = orig_type->refcount; @@ -1624,7 +1625,7 @@ ctxp_extension(const struct lysc_ext *orig_extension, struct lysc_ext *extension } /* static structures in the shared library */ - extension->plugin = orig_extension->plugin; + 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; diff --git a/src/printer_json.c b/src/printer_json.c index d7f6e909f..df700394d 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" @@ -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 = lysc_get_type_plugin(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 bb8cc4b8f..544b463c5 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" @@ -620,7 +621,7 @@ lyb_print_term_value(struct lyd_node_term *term, struct ly_out *out, struct lyly lyplg_type_print_clb print; struct lyplg_type *type; - assert(term->value.realtype && (type = lysc_get_type_plugin(term->value.realtype->plugin)) && + assert(term->value.realtype && (type = LYSC_GET_TYPE_PLG(term->value.realtype->plugin_ref)) && type->print && term->schema); /* Get length of LYB data to print. */ diff --git a/src/printer_tree.c b/src/printer_tree.c index 645fde7d0..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[i].def->plugin || !lysc_get_ext_plugin(cn->exts[i].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[i].plugin || !lysc_get_ext_plugin(pn->exts[i].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 = lysc_get_ext_plugin(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 = lysc_get_ext_plugin(pe->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); @@ -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 = lysc_get_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 = lysc_get_ext_plugin(ext_pars->plugin); + plugin = LYSC_GET_EXT_PLG(ext_pars->plugin_ref); if (!plugin->printer_ptree) { *ignore = 1; return LY_SUCCESS; diff --git a/src/printer_xml.c b/src/printer_xml.c index 75542749e..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,7 @@ xml_print_meta(struct xmlpr_ctx *pctx, const struct lyd_node *node) ly_set_add(&ns_list, NULL, 0, NULL); /* print the value */ - value = lysc_get_type_plugin(meta->value.realtype->plugin)->print(LYD_CTX(node), + 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 */ @@ -359,7 +360,7 @@ xml_print_term(struct xmlpr_ctx *pctx, const struct lyd_node_term *node) } /* print the value */ - value = lysc_get_type_plugin(((struct lysc_node_leaf *)node->schema)->type->plugin)->print(LYD_CTX(node), + 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); diff --git a/src/printer_yang.c b/src/printer_yang.c index f6ac698b8..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" @@ -356,7 +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; + struct lyplg_ext *ext_plg; LY_ARRAY_FOR(exts, u) { if ((exts[u].parent_stmt != substmt) || (exts[u].parent_stmt_index != substmt_index)) { @@ -376,9 +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); - ext = lysc_get_ext_plugin(exts[u].def->plugin); - if (ext && ext->printer_info) { - ext->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--; diff --git a/src/schema_compile.c b/src/schema_compile.c index 1845948f1..b643c326f 100644 --- a/src/schema_compile.c +++ b/src/schema_compile.c @@ -132,11 +132,11 @@ lys_compile_ext(struct lysc_ctx *ctx, struct lysp_ext_instance *extp, struct lys COMPILE_EXTS_GOTO(ctx, extp->exts, ext->exts, ext, ret, cleanup); /* compile this extension */ - if (ext->def->plugin && lysc_get_ext_plugin(ext->def->plugin)->compile) { + if (ext->def->plugin_ref && LYSC_GET_EXT_PLG(ext->def->plugin_ref)->compile) { if (ext->argument) { lysc_update_path(ctx, ext->module, ext->argument); } - ret = lysc_get_ext_plugin(ext->def->plugin)->compile(ctx, extp, ext); + ret = LYSC_GET_EXT_PLG(ext->def->plugin_ref)->compile(ctx, extp, ext); if (ret == LY_ENOT) { lysc_ext_instance_free(ctx->ctx, ext); } @@ -899,7 +899,7 @@ lys_compile_unres_dflt(struct lysc_ctx *ctx, struct lysc_node *node, struct lysc struct lyplg_type *type_plugin; options = (ctx->ctx->opts & LY_CTX_REF_IMPLEMENTED) ? LYPLG_TYPE_STORE_IMPLEMENT : 0; - type_plugin = lysc_get_type_plugin(type->plugin); + type_plugin = LYSC_GET_TYPE_PLG(type->plugin_ref); rc = type_plugin->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) { @@ -1837,7 +1837,7 @@ lys_compile_extensions(struct lys_module *mod) 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 = ep->plugin; + ec->plugin_ref = ep->plugin_ref; LY_ARRAY_INCREMENT(mod->extensions); } diff --git a/src/schema_compile_amend.c b/src/schema_compile_amend.c index 81257ea3c..ab802c3c0 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" @@ -477,7 +478,7 @@ lysp_ext_dup(const struct ly_ctx *ctx, const struct lysp_module *pmod, void *par 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->plugin = orig_ext->plugin; + ext->plugin_ref = orig_ext->plugin_ref; ext->parent = parent; ext->parent_stmt = parent_stmt; @@ -485,10 +486,10 @@ lysp_ext_dup(const struct ly_ctx *ctx, const struct lysp_module *pmod, void *par ext->flags = orig_ext->flags; LY_CHECK_GOTO(ret = lysp_ext_children_dup(ctx, orig_ext->child, &ext->child), cleanup); - if (ext->plugin && lysc_get_ext_plugin(ext->plugin)->parse) { + if (ext->plugin_ref && 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 = lysc_get_ext_plugin(ext->plugin)->parse(&pctx, ext), cleanup); + LY_CHECK_GOTO(ret = LYSC_GET_EXT_PLG(ext->plugin_ref)->parse(&pctx, ext), cleanup); } cleanup: diff --git a/src/schema_compile_node.c b/src/schema_compile_node.c index 4660891f7..056b39440 100644 --- a/src/schema_compile_node.c +++ b/src/schema_compile_node.c @@ -1807,7 +1807,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_ref; + (*type)->plugin_ref = plugin_ref; switch (basetype) { case LY_TYPE_BINARY: @@ -2280,7 +2280,7 @@ lys_compile_type(struct lysc_ctx *ctx, struct lysp_node *context_pnode, uint16_t 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_ref && base) { - plugin_ref = base->plugin; + plugin_ref = base->plugin_ref; } if (!plugin_ref) { /* use the internal built-in type implementation */ @@ -2289,7 +2289,7 @@ lys_compile_type(struct lysc_ctx *ctx, struct lysp_node *context_pnode, uint16_t assert(plugin_ref); if ((basetype != LY_TYPE_LEAFREF) && (u != tpdf_chain.count - 1) && !tctx->tpdf->type.flags && - !tctx->tpdf->type.exts && (plugin_ref == 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); @@ -2342,7 +2342,7 @@ lys_compile_type(struct lysc_ctx *ctx, struct lysp_node *context_pnode, uint16_t if (type_p->flags || type_p->exts || !base || has_leafref) { /* leaf type has changes that need to be compiled into the type */ if (base) { - plugin_ref = base->plugin; + plugin_ref = base->plugin_ref; } else { plugin_ref = lyplg_type_plugin_find(ctx->ctx, "", NULL, ly_data_type2str[basetype]); } diff --git a/src/tree_data.c b/src/tree_data.c index 43927af7d..f49026bd2 100644 --- a/src/tree_data.c +++ b/src/tree_data.c @@ -1339,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 = lysc_get_ext_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]; } @@ -1883,7 +1883,7 @@ lyd_compare_meta(const struct lyd_meta *meta1, const struct lyd_meta *meta2) return LY_ENOT; } - return lysc_get_type_plugin(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); } /** @@ -2259,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 = lysc_get_type_plugin(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 */ @@ -2562,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 = lysc_get_type_plugin(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); diff --git a/src/tree_data_common.c b/src/tree_data_common.c index 1722e45b3..9cbbc2085 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" @@ -532,7 +533,7 @@ lyd_value_store(const struct ly_ctx *ctx, struct lyd_value *val, const struct ly options |= LYPLG_TYPE_STORE_ONLY; } - r = lysc_get_type_plugin(type->plugin)->store(ctx, type, value, value_len, options, + 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; @@ -563,7 +564,7 @@ lyd_value_validate_incomplete(const struct ly_ctx *ctx, const struct lysc_type * struct ly_err_item *err = NULL; struct lyplg_type *type_plugin; - type_plugin = lysc_get_type_plugin(type->plugin); + type_plugin = LYSC_GET_TYPE_PLG(type->plugin_ref); assert(type_plugin && type_plugin->validate); ret = type_plugin->validate(ctx, type, ctx_node, tree, val, &err); @@ -598,7 +599,7 @@ ly_value_validate(const struct ly_ctx *ctx, const struct lysc_node *node, const } type = ((struct lysc_node_leaf *)node)->type; - rc = lysc_get_type_plugin(type->plugin)->store(ctx ? ctx : node->module->ctx, type, value, + 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 */ @@ -612,7 +613,7 @@ ly_value_validate(const struct ly_ctx *ctx, const struct lysc_node *node, const } if (!rc) { - lysc_get_type_plugin(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; } @@ -647,7 +648,7 @@ lyd_value_validate2(const struct ly_ctx *ctx, const struct lysc_node *schema, co } type = ((struct lysc_node_leaf *)schema)->type; - type_plugin = lysc_get_type_plugin(type->plugin); + type_plugin = LYSC_GET_TYPE_PLG(type->plugin_ref); /* store */ rc = type_plugin->store(ctx, type, value, value_len, 0, format, @@ -681,7 +682,7 @@ lyd_value_validate2(const struct ly_ctx *ctx, const struct lysc_node *schema, co if (canonical) { /* return canonical value */ - realtype_plugin = lysc_get_type_plugin(val.realtype->plugin); + realtype_plugin = LYSC_GET_TYPE_PLG(val.realtype->plugin_ref); lydict_dup(ctx, realtype_plugin->print(ctx, &val, LY_VALUE_CANON, NULL, NULL, NULL), canonical); } } @@ -713,9 +714,9 @@ lyd_value_compare(const struct lyd_node_term *node, const char *value, size_t va LY_CHECK_RET(ret); /* compare values */ - ret = lysc_get_type_plugin(type->plugin)->compare(ctx, &node->value, &val); + ret = LYSC_GET_TYPE_PLG(type->plugin_ref)->compare(ctx, &node->value, &val); - lysc_get_type_plugin(type->plugin)->free(ctx, &val); + LYSC_GET_TYPE_PLG(type->plugin_ref)->free(ctx, &val); return ret; } @@ -991,7 +992,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 *)lysc_get_type_plugin(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 @@ -1340,12 +1341,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 = lysc_get_ext_plugin(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; diff --git a/src/tree_data_free.c b/src/tree_data_free.c index 11211b979..5672a56a2 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); - lysc_get_type_plugin(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); } } @@ -235,7 +236,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; - lysc_get_type_plugin(((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 32a6b2d3d..692c0278f 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" @@ -56,7 +57,7 @@ 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; - type = lysc_get_type_plugin(key->value.realtype->plugin); + type = LYSC_GET_TYPE_PLG(key->value.realtype->plugin_ref); hash_key = type->print(NULL, &key->value, LY_VALUE_LYB, NULL, &dyn, &key_len); node->hash = lyht_hash_multi(node->hash, hash_key, key_len); if (dyn) { @@ -68,7 +69,7 @@ lyd_hash(struct lyd_node *node) /* leaf-list adds its hash key */ struct lyd_node_term *llist = (struct lyd_node_term *)node; - type = lysc_get_type_plugin(llist->value.realtype->plugin); + type = LYSC_GET_TYPE_PLG(llist->value.realtype->plugin_ref); hash_key = type->print(NULL, &llist->value, LY_VALUE_LYB, NULL, &dyn, &key_len); node->hash = lyht_hash_multi(node->hash, hash_key, key_len); if (dyn) { diff --git a/src/tree_data_new.c b/src/tree_data_new.c index ceca209d9..312b30c23 100644 --- a/src/tree_data_new.c +++ b/src/tree_data_new.c @@ -1220,8 +1220,8 @@ lyd_change_node_value(struct lyd_node_term *term, struct lyd_value *val, ly_bool struct lyd_node *target, *first; struct lyplg_type *real_type, *schema_type; - real_type = lysc_get_type_plugin(term->value.realtype->plugin); - schema_type = lysc_get_type_plugin(((struct lysc_node_leaf *)term->schema)->type->plugin); + real_type = LYSC_GET_TYPE_PLG(term->value.realtype->plugin_ref); + schema_type = LYSC_GET_TYPE_PLG(((struct lysc_node_leaf *)term->schema)->type->plugin_ref); if (term->schema->nodetype == LYS_LEAFLIST) { target = (struct lyd_node *)term; @@ -1295,7 +1295,7 @@ lyd_change_term_val(struct lyd_node *term, struct lyd_value *val, ly_bool use_va type = ((struct lysc_node_leaf *)term->schema)->type; /* compare original and new value */ - if (lysc_get_type_plugin(type->plugin)->compare(LYD_CTX(term), &t->value, val)) { + if (LYSC_GET_TYPE_PLG(type->plugin_ref)->compare(LYD_CTX(term), &t->value, val)) { /* since they are different, they cannot both be default */ assert(!(term->flags & LYD_DEFAULT) || !is_dflt); @@ -1305,7 +1305,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) { - lysc_get_type_plugin(type->plugin)->free(LYD_CTX(term), val); + LYSC_GET_TYPE_PLG(type->plugin_ref)->free(LYD_CTX(term), val); } val_change = 0; } diff --git a/src/tree_data_sorted.c b/src/tree_data_sorted.c index 473bc077f..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 lysc_get_type_plugin(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 30ed17458..95f497f9b 100644 --- a/src/tree_schema.c +++ b/src/tree_schema.c @@ -1365,7 +1365,7 @@ lysp_resolve_ext_instance_records(struct lysp_ctx *pctx) /* find the extension definition, use its plugin */ LY_CHECK_RET(lysp_ext_find_definition(PARSER_CTX(pctx), ext, &mod, &ext_def)); - ext->plugin = ext_def->plugin; + ext->plugin_ref = ext_def->plugin_ref; /* resolve the argument, if needed */ LY_CHECK_RET(lysp_ext_instance_resolve_argument(PARSER_CTX(pctx), ext_def, ext)); @@ -1378,7 +1378,7 @@ lysp_resolve_ext_instance_records(struct lysp_ctx *pctx) u = 0; while (u < LY_ARRAY_COUNT(exts)) { ext = &exts[u]; - if (!ext->plugin || !lysc_get_ext_plugin(ext->plugin)->parse) { + if (!ext->plugin_ref || !LYSC_GET_EXT_PLG(ext->plugin_ref)->parse) { goto next_iter; } @@ -1389,7 +1389,7 @@ lysp_resolve_ext_instance_records(struct lysp_ctx *pctx) ly_log_location(NULL, NULL, path, NULL); /* parse */ - r = lysc_get_ext_plugin(ext->plugin)->parse(pctx, ext); + r = LYSC_GET_EXT_PLG(ext->plugin_ref)->parse(pctx, ext); ly_log_location_revert(0, 0, 1, 0); free(path); @@ -2208,7 +2208,7 @@ lys_parse_in(struct ly_ctx *ctx, struct ly_in *in, LYS_INFORMAT format, const st /* resolve extension plugins and parse extension instances */ LY_ARRAY_FOR(mod->parsed->extensions, u) { - mod->parsed->extensions[u].plugin = lyplg_ext_plugin_find(mod->ctx, mod->name, + 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); diff --git a/src/tree_schema.h b/src/tree_schema.h index aee22121b..c91da659d 100644 --- a/src/tree_schema.h +++ b/src/tree_schema.h @@ -299,7 +299,7 @@ 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; /**< extension definition plugin, use ::lysc_get_ext_plugin() */ + 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) */ }; @@ -1183,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)) */ - uintptr_t plugin; /**< plugin implementing the specific extension, use ::lysc_get_ext_plugin() */ + 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) */ }; @@ -1279,7 +1279,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)) */ - uintptr_t plugin; /**< type's manipulation callbacks plugin, use ::lysc_get_type_plugin() */ + uintptr_t plugin_ref; /**< reference to type plugin, use ::lysc_get_ext_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) */ @@ -1288,7 +1288,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)) */ - uintptr_t plugin; /**< type's manipulation callbacks plugin, use ::lysc_get_type_plugin() */ + uintptr_t plugin_ref; /**< reference to type plugin, use ::lysc_get_ext_plugin() to get the plugin */ LY_DATA_TYPE basetype; /**< base type of the type */ uint32_t refcount; /**< reference counter for type sharing */ @@ -1298,7 +1298,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)) */ - uintptr_t plugin; /**< type's manipulation callbacks plugin, use ::lysc_get_type_plugin() */ + uintptr_t plugin_ref; /**< reference to type plugin, use ::lysc_get_ext_plugin() to get the plugin */ LY_DATA_TYPE basetype; /**< base type of the type */ uint32_t refcount; /**< reference counter for type sharing */ @@ -1309,7 +1309,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)) */ - uintptr_t plugin; /**< type's manipulation callbacks plugin, use ::lysc_get_type_plugin() */ + uintptr_t plugin_ref; /**< reference to type plugin, use ::lysc_get_ext_plugin() to get the plugin */ LY_DATA_TYPE basetype; /**< base type of the type */ uint32_t refcount; /**< reference counter for type sharing */ @@ -1334,7 +1334,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)) */ - uintptr_t plugin; /**< type's manipulation callbacks plugin, use ::lysc_get_type_plugin() */ + uintptr_t plugin_ref; /**< reference to type plugin, use ::lysc_get_ext_plugin() to get the plugin */ LY_DATA_TYPE basetype; /**< base type of the type */ uint32_t refcount; /**< reference counter for type sharing */ @@ -1344,7 +1344,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)) */ - uintptr_t plugin; /**< type's manipulation callbacks plugin, use ::lysc_get_type_plugin() */ + uintptr_t plugin_ref; /**< reference to type plugin, use ::lysc_get_ext_plugin() to get the plugin */ LY_DATA_TYPE basetype; /**< base type of the type */ uint32_t refcount; /**< reference counter for type sharing */ @@ -1355,7 +1355,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)) */ - uintptr_t plugin; /**< type's manipulation callbacks plugin, use ::lysc_get_type_plugin() */ + uintptr_t plugin_ref; /**< reference to type plugin, use ::lysc_get_ext_plugin() to get the plugin */ LY_DATA_TYPE basetype; /**< base type of the type */ uint32_t refcount; /**< reference counter for type sharing */ @@ -1368,7 +1368,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)) */ - uintptr_t plugin; /**< type's manipulation callbacks plugin, use ::lysc_get_type_plugin() */ + uintptr_t plugin_ref; /**< reference to type plugin, use ::lysc_get_ext_plugin() to get the plugin */ LY_DATA_TYPE basetype; /**< base type of the type */ uint32_t refcount; /**< reference counter for type sharing */ @@ -1379,7 +1379,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)) */ - uintptr_t plugin; /**< type's manipulation callbacks plugin, use ::lysc_get_type_plugin() */ + uintptr_t plugin_ref; /**< reference to type plugin, use ::lysc_get_ext_plugin() to get the plugin */ LY_DATA_TYPE basetype; /**< base type of the type */ uint32_t refcount; /**< reference counter for type sharing */ @@ -1389,7 +1389,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)) */ - uintptr_t plugin; /**< type's manipulation callbacks plugin, use ::lysc_get_type_plugin() */ + uintptr_t plugin_ref; /**< reference to type plugin, use ::lysc_get_ext_plugin() to get the plugin */ LY_DATA_TYPE basetype; /**< base type of the type */ uint32_t refcount; /**< reference counter for type sharing */ @@ -1399,7 +1399,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)) */ - uintptr_t plugin; /**< type's manipulation callbacks plugin, use ::lysc_get_type_plugin() */ + uintptr_t plugin_ref; /**< reference to type plugin, use ::lysc_get_ext_plugin() to get the plugin */ LY_DATA_TYPE basetype; /**< base type of the type */ uint32_t refcount; /**< reference counter for type sharing */ diff --git a/src/tree_schema_free.c b/src/tree_schema_free.c index aaf20cb69..19528c348 100644 --- a/src/tree_schema_free.c +++ b/src/tree_schema_free.c @@ -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" @@ -73,8 +74,8 @@ lysp_ext_instance_free(const struct ly_ctx *ctx, struct lysp_ext_instance *ext) lydict_remove(ctx, ext->name); lydict_remove(ctx, ext->argument); ly_free_prefix_data(ext->format, ext->prefix_data); - if (ext->plugin && lysc_get_ext_plugin(ext->plugin)->pfree) { - lysc_get_ext_plugin(ext->plugin)->pfree(ctx, ext); + if (ext->plugin_ref && LYSC_GET_EXT_PLG(ext->plugin_ref)->pfree) { + LYSC_GET_EXT_PLG(ext->plugin_ref)->pfree(ctx, ext); } LY_LIST_FOR_SAFE(ext->child, next, stmt) { @@ -639,8 +640,8 @@ lysp_module_free(const struct ly_ctx *ctx, struct lysp_module *module) void lysc_ext_instance_free(const struct ly_ctx *ctx, struct lysc_ext_instance *ext) { - if (ext->def && ext->def->plugin && lysc_get_ext_plugin(ext->def->plugin)->cfree) { - lysc_get_ext_plugin(ext->def->plugin)->cfree(ctx, ext); + if (ext->def && ext->def->plugin_ref && LYSC_GET_EXT_PLG(ext->def->plugin_ref)->cfree) { + LYSC_GET_EXT_PLG(ext->def->plugin_ref)->cfree(ctx, ext); } lydict_remove(ctx, ext->argument); FREE_ARRAY(ctx, ext->exts, lysc_ext_instance_free); diff --git a/src/validation.c b/src/validation.c index 609297b4d..70f3de84c 100644 --- a/src/validation.c +++ b/src/validation.c @@ -32,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" @@ -457,7 +458,7 @@ 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 = lysc_get_ext_plugin(ext_v->ext->def->plugin)->validate(ext_v->ext, ext_v->sibling, *tree, + 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); @@ -475,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 = lysc_get_ext_plugin(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 */ @@ -1861,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 (lysc_get_ext_plugin(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)); @@ -1894,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 && lysc_get_ext_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); @@ -1946,7 +1947,7 @@ 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 (lysc_get_type_plugin(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); @@ -1954,7 +1955,7 @@ lyd_validate_subtree(struct lyd_node *root, struct ly_set *node_when, struct ly_ } if ((node->schema->nodetype & LYD_NODE_TERM) && - lysc_get_type_plugin(((struct lysc_node_leaf *)node->schema)->type->plugin)->validate) { + 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 2ae3ce215..f5f6fa587 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" @@ -1714,15 +1715,15 @@ set_comp_canonize(struct lyxp_set *set, const struct lyxp_set_node *xp_node) } /* check for built-in types without required canonization */ - if ((type->basetype == LY_TYPE_STRING) && (lysc_get_type_plugin(type->plugin)->store == lyplg_type_store_string)) { + if ((type->basetype == LY_TYPE_STRING) && (LYSC_GET_TYPE_PLG(type->plugin_ref)->store == lyplg_type_store_string)) { /* string */ return LY_SUCCESS; } - if ((type->basetype == LY_TYPE_BOOL) && (lysc_get_type_plugin(type->plugin)->store == lyplg_type_store_boolean)) { + if ((type->basetype == LY_TYPE_BOOL) && (LYSC_GET_TYPE_PLG(type->plugin_ref)->store == lyplg_type_store_boolean)) { /* boolean */ return LY_SUCCESS; } - if ((type->basetype == LY_TYPE_ENUM) && (lysc_get_type_plugin(type->plugin)->store == lyplg_type_store_enum)) { + if ((type->basetype == LY_TYPE_ENUM) && (LYSC_GET_TYPE_PLG(type->plugin_ref)->store == lyplg_type_store_enum)) { /* enumeration */ return LY_SUCCESS; } @@ -3644,7 +3645,7 @@ 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) { - type_plugin = lysc_get_type_plugin(type->plugin); + type_plugin = LYSC_GET_TYPE_PLG(type->plugin_ref); rc = type_plugin->store(set->ctx, type, value, strlen(value), 0, set->format, set->prefix_data, LYD_HINT_DATA, scnode, &storage, NULL, &err); if (rc == LY_EINCOMPLETE) { diff --git a/tests/utests/basic/test_plugins.c b/tests/utests/basic/test_plugins.c index 54c85f1c2..5c724db9c 100644 --- a/tests/utests/basic/test_plugins.c +++ b/tests/utests/basic/test_plugins.c @@ -56,12 +56,12 @@ test_add_simple(void **state) 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(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, plugin_e); + 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/types/binary.c b/tests/utests/types/binary.c index 5e6bf8de0..7ed94185e 100644 --- a/tests/utests/types/binary.c +++ b/tests/utests/types/binary.c @@ -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("", lysc_get_type_plugin(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); } diff --git a/tests/utests/types/bits.c b/tests/utests/types/bits.c index 0ef81f9cd..1259c1678 100644 --- a/tests/utests/types/bits.c +++ b/tests/utests/types/bits.c @@ -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 = lysc_get_type_plugin(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]))); diff --git a/tests/utests/types/int8.c b/tests/utests/types/int8.c index 8a9f2f4ca..48fe8f3a3 100644 --- a/tests/utests/types/int8.c +++ b/tests/utests/types/int8.c @@ -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 = lysc_get_type_plugin(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 = lysc_get_type_plugin(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 = lysc_get_type_plugin(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]))); diff --git a/tests/utests/types/string.c b/tests/utests/types/string.c index 7c4742117..56ff396ac 100644 --- a/tests/utests/types/string.c +++ b/tests/utests/types/string.c @@ -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 = lysc_get_type_plugin(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]))); diff --git a/tests/utests/utests.h b/tests/utests/utests.h index 19546f373..7823a4a52 100644 --- a/tests/utests/utests.h +++ b/tests/utests/utests.h @@ -230,7 +230,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 @@ -934,7 +934,7 @@ struct utest_context { * @param[in] CANNONICAL_VAL expected cannonical value */ #define CHECK_LYD_VALUE_EMPTY(NODE, CANNONICAL_VAL) \ - assert_non_null(lysc_get_type_plugin((NODE).realtype->plugin)->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ + assert_non_null(lysc_get_type_plugin((NODE).realtype->plugin_ref)->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ assert_string_equal((NODE)._canonical, CANNONICAL_VAL); \ assert_non_null((NODE).realtype); \ assert_int_equal((NODE).realtype->basetype, LY_TYPE_EMPTY); @@ -952,7 +952,7 @@ struct utest_context { * CHECK_LYD_VALUE_ ## TYPE_VAL. */ #define CHECK_LYD_VALUE_UNION(NODE, CANNONICAL_VAL, TYPE_VAL, ...) \ - assert_non_null(lysc_get_type_plugin((NODE).realtype->plugin)->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ + assert_non_null(lysc_get_type_plugin((NODE).realtype->plugin_ref)->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ assert_string_equal((NODE)._canonical, CANNONICAL_VAL); \ assert_non_null((NODE).realtype); \ assert_int_equal(LY_TYPE_UNION, (NODE).realtype->basetype); \ @@ -974,7 +974,7 @@ struct utest_context { * @param[in] VALUE expected array of bits names */ #define CHECK_LYD_VALUE_BITS(NODE, ...) \ - assert_non_null(lysc_get_type_plugin((NODE).realtype->plugin)->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ + assert_non_null(lysc_get_type_plugin((NODE).realtype->plugin_ref)->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ assert_string_equal((NODE)._canonical, _GETARG1(__VA_ARGS__, DUMMY)); \ assert_non_null((NODE).realtype); \ assert_int_equal(LY_TYPE_BITS, (NODE).realtype->basetype); \ @@ -998,7 +998,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(lysc_get_type_plugin((NODE).realtype->plugin)->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ + assert_non_null(lysc_get_type_plugin((NODE).realtype->plugin_ref)->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ assert_string_equal((NODE)._canonical, CANNONICAL_VAL); \ assert_non_null((NODE).realtype); \ assert_int_equal(LY_TYPE_INST, (NODE).realtype->basetype); \ @@ -1021,7 +1021,7 @@ struct utest_context { * @param[in] VALUE expected enum item name */ #define CHECK_LYD_VALUE_ENUM(NODE, CANNONICAL_VAL, VALUE) \ - assert_non_null(lysc_get_type_plugin((NODE).realtype->plugin)->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ + assert_non_null(lysc_get_type_plugin((NODE).realtype->plugin_ref)->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ assert_string_equal((NODE)._canonical, CANNONICAL_VAL); \ assert_non_null((NODE).realtype); \ assert_int_equal(LY_TYPE_ENUM, (NODE).realtype->basetype); \ @@ -1036,7 +1036,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(lysc_get_type_plugin((NODE).realtype->plugin)->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ + assert_non_null(lysc_get_type_plugin((NODE).realtype->plugin_ref)->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ assert_string_equal((NODE)._canonical, CANNONICAL_VAL); \ assert_non_null((NODE).realtype); \ assert_int_equal(LY_TYPE_INT8, (NODE).realtype->basetype); \ @@ -1051,7 +1051,7 @@ struct utest_context { * @param[in] VALUE expected inteager value. */ #define CHECK_LYD_VALUE_INT16(NODE, CANNONICAL_VAL, VALUE) \ - assert_non_null(lysc_get_type_plugin((NODE).realtype->plugin)->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ + assert_non_null(lysc_get_type_plugin((NODE).realtype->plugin_ref)->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ assert_string_equal((NODE)._canonical, CANNONICAL_VAL); \ assert_non_null((NODE).realtype); \ assert_int_equal(LY_TYPE_INT16, (NODE).realtype->basetype); \ @@ -1066,7 +1066,7 @@ struct utest_context { * @param[in] VALUE expected inteager (0 to 255). */ #define CHECK_LYD_VALUE_UINT8(NODE, CANNONICAL_VAL, VALUE) \ - assert_non_null(lysc_get_type_plugin((NODE).realtype->plugin)->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ + assert_non_null(lysc_get_type_plugin((NODE).realtype->plugin_ref)->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ assert_string_equal((NODE)._canonical, CANNONICAL_VAL); \ assert_non_null((NODE).realtype); \ assert_int_equal(LY_TYPE_UINT8, (NODE).realtype->basetype); \ @@ -1081,7 +1081,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(lysc_get_type_plugin((NODE).realtype->plugin)->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ + assert_non_null(lysc_get_type_plugin((NODE).realtype->plugin_ref)->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ assert_string_equal((NODE)._canonical, CANNONICAL_VAL); \ assert_non_null((NODE).realtype); \ assert_int_equal(LY_TYPE_UINT32, (NODE).realtype->basetype); \ @@ -1095,7 +1095,7 @@ struct utest_context { * @param[in] CANNONICAL_VAL expected cannonical value */ #define CHECK_LYD_VALUE_STRING(NODE, CANNONICAL_VAL) \ - assert_non_null(lysc_get_type_plugin((NODE).realtype->plugin)->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ + assert_non_null(lysc_get_type_plugin((NODE).realtype->plugin_ref)->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ assert_string_equal((NODE)._canonical, CANNONICAL_VAL); \ assert_non_null((NODE).realtype); \ assert_int_equal(LY_TYPE_STRING, (NODE).realtype->basetype); @@ -1108,7 +1108,7 @@ struct utest_context { * @param[in] CANNONICAL_VAL expected cannonical value */ #define CHECK_LYD_VALUE_LEAFREF(NODE, CANNONICAL_VAL) \ - assert_non_null(lysc_get_type_plugin((NODE).realtype->plugin)->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ + assert_non_null(lysc_get_type_plugin((NODE).realtype->plugin_ref)->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ assert_string_equal((NODE)._canonical, CANNONICAL_VAL); \ assert_non_null((NODE).realtype); \ assert_int_equal(LY_TYPE_LEAFREF, (NODE).realtype->basetype); \ @@ -1123,7 +1123,7 @@ struct utest_context { * @param[in] VALUE expected value 64bit inteager */ #define CHECK_LYD_VALUE_DEC64(NODE, CANNONICAL_VAL, VALUE) \ - assert_non_null(lysc_get_type_plugin((NODE).realtype->plugin)->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ + assert_non_null(lysc_get_type_plugin((NODE).realtype->plugin_ref)->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ assert_string_equal((NODE)._canonical, CANNONICAL_VAL); \ assert_non_null((NODE).realtype); \ assert_int_equal(LY_TYPE_DEC64, (NODE).realtype->basetype); \ @@ -1144,7 +1144,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(lysc_get_type_plugin((NODE).realtype->plugin)->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ + assert_non_null(lysc_get_type_plugin((NODE).realtype->plugin_ref)->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ assert_string_equal((NODE)._canonical, CANNONICAL_VAL); \ assert_non_null((NODE).realtype); \ assert_int_equal(LY_TYPE_BINARY, (NODE).realtype->basetype); \ @@ -1159,7 +1159,7 @@ struct utest_context { * @param[in] VALUE expected boolean value 0,1 */ #define CHECK_LYD_VALUE_BOOL(NODE, CANNONICAL_VAL, VALUE) \ - assert_non_null(lysc_get_type_plugin((NODE).realtype->plugin)->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ + assert_non_null(lysc_get_type_plugin((NODE).realtype->plugin_ref)->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ assert_string_equal((NODE)._canonical, CANNONICAL_VAL); \ assert_non_null((NODE).realtype); \ assert_int_equal(LY_TYPE_BOOL, (NODE).realtype->basetype); \ @@ -1174,7 +1174,7 @@ struct utest_context { * @param[in] VALUE expected ident name */ #define CHECK_LYD_VALUE_IDENT(NODE, CANNONICAL_VAL, VALUE) \ - assert_non_null(lysc_get_type_plugin((NODE).realtype->plugin)->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ + assert_non_null(lysc_get_type_plugin((NODE).realtype->plugin_ref)->print(UTEST_LYCTX, &(NODE), LY_VALUE_CANON, NULL, NULL, NULL)); \ assert_string_equal((NODE)._canonical, CANNONICAL_VAL); \ assert_non_null((NODE).realtype); \ assert_int_equal(LY_TYPE_IDENT, (NODE).realtype->basetype); \ From fe466392089c5845f43746abef196756193cbdcc Mon Sep 17 00:00:00 2001 From: roman Date: Fri, 24 Jan 2025 13:24:10 +0100 Subject: [PATCH 40/99] context UPDATE clarify static and builtin flags --- src/context.h | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/context.h b/src/context.h index 225cf1018..081206a32 100644 --- a/src/context.h +++ b/src/context.h @@ -202,17 +202,20 @@ 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 /**< By default, external plugins from directories the path to which is obtained - from the `LIBYANG_TYPES_PLUGINS_DIR` and `LIBYANG_EXTENSIONS_PLUGINS_DIR` environmental variables - are loaded. This option prevents loading of all external plugins and only - the static (libyang built-in) plugins are loaded. */ +#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 */ From fd9aff004cfbeaf8269a06718d3234a25fb8f8b7 Mon Sep 17 00:00:00 2001 From: roman Date: Fri, 24 Jan 2025 14:59:42 +0100 Subject: [PATCH 41/99] tests UPDATE replace canonical print by func call --- tests/utests/utests.h | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/tests/utests/utests.h b/tests/utests/utests.h index 7823a4a52..5e775bb6e 100644 --- a/tests/utests/utests.h +++ b/tests/utests/utests.h @@ -934,7 +934,7 @@ struct utest_context { * @param[in] CANNONICAL_VAL expected cannonical value */ #define CHECK_LYD_VALUE_EMPTY(NODE, CANNONICAL_VAL) \ - assert_non_null(lysc_get_type_plugin((NODE).realtype->plugin_ref)->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); @@ -952,7 +952,7 @@ struct utest_context { * CHECK_LYD_VALUE_ ## TYPE_VAL. */ #define CHECK_LYD_VALUE_UNION(NODE, CANNONICAL_VAL, TYPE_VAL, ...) \ - assert_non_null(lysc_get_type_plugin((NODE).realtype->plugin_ref)->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); \ @@ -974,7 +974,7 @@ struct utest_context { * @param[in] VALUE expected array of bits names */ #define CHECK_LYD_VALUE_BITS(NODE, ...) \ - assert_non_null(lysc_get_type_plugin((NODE).realtype->plugin_ref)->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); \ @@ -998,7 +998,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(lysc_get_type_plugin((NODE).realtype->plugin_ref)->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); \ @@ -1021,7 +1021,7 @@ struct utest_context { * @param[in] VALUE expected enum item name */ #define CHECK_LYD_VALUE_ENUM(NODE, CANNONICAL_VAL, VALUE) \ - assert_non_null(lysc_get_type_plugin((NODE).realtype->plugin_ref)->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); \ @@ -1036,7 +1036,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(lysc_get_type_plugin((NODE).realtype->plugin_ref)->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); \ @@ -1051,7 +1051,7 @@ struct utest_context { * @param[in] VALUE expected inteager value. */ #define CHECK_LYD_VALUE_INT16(NODE, CANNONICAL_VAL, VALUE) \ - assert_non_null(lysc_get_type_plugin((NODE).realtype->plugin_ref)->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); \ @@ -1066,7 +1066,7 @@ struct utest_context { * @param[in] VALUE expected inteager (0 to 255). */ #define CHECK_LYD_VALUE_UINT8(NODE, CANNONICAL_VAL, VALUE) \ - assert_non_null(lysc_get_type_plugin((NODE).realtype->plugin_ref)->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); \ @@ -1081,7 +1081,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(lysc_get_type_plugin((NODE).realtype->plugin_ref)->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); \ @@ -1095,7 +1095,7 @@ struct utest_context { * @param[in] CANNONICAL_VAL expected cannonical value */ #define CHECK_LYD_VALUE_STRING(NODE, CANNONICAL_VAL) \ - assert_non_null(lysc_get_type_plugin((NODE).realtype->plugin_ref)->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); @@ -1108,7 +1108,7 @@ struct utest_context { * @param[in] CANNONICAL_VAL expected cannonical value */ #define CHECK_LYD_VALUE_LEAFREF(NODE, CANNONICAL_VAL) \ - assert_non_null(lysc_get_type_plugin((NODE).realtype->plugin_ref)->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); \ @@ -1123,7 +1123,7 @@ struct utest_context { * @param[in] VALUE expected value 64bit inteager */ #define CHECK_LYD_VALUE_DEC64(NODE, CANNONICAL_VAL, VALUE) \ - assert_non_null(lysc_get_type_plugin((NODE).realtype->plugin_ref)->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); \ @@ -1144,7 +1144,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(lysc_get_type_plugin((NODE).realtype->plugin_ref)->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); \ @@ -1159,7 +1159,7 @@ struct utest_context { * @param[in] VALUE expected boolean value 0,1 */ #define CHECK_LYD_VALUE_BOOL(NODE, CANNONICAL_VAL, VALUE) \ - assert_non_null(lysc_get_type_plugin((NODE).realtype->plugin_ref)->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); \ @@ -1174,7 +1174,7 @@ struct utest_context { * @param[in] VALUE expected ident name */ #define CHECK_LYD_VALUE_IDENT(NODE, CANNONICAL_VAL, VALUE) \ - assert_non_null(lysc_get_type_plugin((NODE).realtype->plugin_ref)->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); \ From aa0977c0cc152f70db54a0bac9e0699cf050aa65 Mon Sep 17 00:00:00 2001 From: roman Date: Fri, 24 Jan 2025 15:04:50 +0100 Subject: [PATCH 42/99] printer lyb BUGFIX move assignment from assert --- src/printer_lyb.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/printer_lyb.c b/src/printer_lyb.c index 544b463c5..5310456c1 100644 --- a/src/printer_lyb.c +++ b/src/printer_lyb.c @@ -619,16 +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; + struct lyplg_type *type_plg; - assert(term->value.realtype && (type = LYSC_GET_TYPE_PLG(term->value.realtype->plugin_ref)) && - type->print && term->schema); + assert(term->value.realtype && term->value.realtype->plugin_ref && + LYSC_GET_TYPE_PLG(term->value.realtype->plugin_ref)->print && term->schema); + + type_plg = LYSC_GET_TYPE_PLG(term->value.realtype->plugin_ref); /* Get length of LYB data to print. */ - lyb_data_len = type->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 = type->print; + print = type_plg->print; if (lyb_data_len < 0) { /* Variable-length data. */ From 12b8de3c74d3e16424054c9b008b01badecdcf51 Mon Sep 17 00:00:00 2001 From: roman Date: Fri, 24 Jan 2025 15:05:25 +0100 Subject: [PATCH 43/99] printer context UPDATE clarify addr_ht building --- src/printer_context.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/printer_context.c b/src/printer_context.c index 79083c71f..885858ae5 100644 --- a/src/printer_context.c +++ b/src/printer_context.c @@ -1747,10 +1747,10 @@ ly_ctx_compiled_print_context(const struct ly_ctx *orig_ctx, struct ly_ctx *ctx, /* no search paths */ memset(&ctx->search_paths, 0, sizeof ctx->search_paths); - /* modules, referenced, 2 loops because of augments (forward reference), build the ht first */ + /* 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) { - /* build the address ht */ + /* 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]); From e54a283a74da72e6da7bad273de4e5e14be9b1db Mon Sep 17 00:00:00 2001 From: roman Date: Fri, 24 Jan 2025 15:30:23 +0100 Subject: [PATCH 44/99] plugins BUGFIX use correct array bound --- src/plugins.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins.c b/src/plugins.c index 6cf44fcd8..673b1068f 100644 --- a/src/plugins.c +++ b/src/plugins.c @@ -143,7 +143,7 @@ lysc_get_type_plugin(uintptr_t plugin_ref) return NULL; } - if (plugin_ref <= ly_plugins_types.count) { + 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 { @@ -159,7 +159,7 @@ lysc_get_ext_plugin(uintptr_t plugin_ref) return NULL; } - if (plugin_ref <= ly_plugins_extensions.count) { + 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 { From b46ab814f94743e68375baf2e1ca30be7290d9c8 Mon Sep 17 00:00:00 2001 From: roman Date: Fri, 24 Jan 2025 16:34:05 +0100 Subject: [PATCH 45/99] plugins REFACTOR various small changes --- src/plugins.c | 10 +++++----- src/plugins_exts.h | 3 +-- src/plugins_internal.h | 8 ++++---- src/plugins_types.c | 18 +++++++++--------- src/plugins_types/union.c | 36 ++++++++++++++++++------------------ src/printer_context.c | 13 +++++++------ src/schema_compile.c | 15 ++++++++------- src/schema_compile_amend.c | 5 +++-- src/tree_data_common.c | 30 ++++++++++++++++-------------- src/tree_data_hash.c | 9 ++++----- src/tree_data_new.c | 24 +++++++++++++----------- src/tree_schema.c | 5 +++-- src/tree_schema_free.c | 11 +++++++---- src/xpath.c | 17 ++++++++++------- 14 files changed, 108 insertions(+), 96 deletions(-) diff --git a/src/plugins.c b/src/plugins.c index 673b1068f..4a2adb0b9 100644 --- a/src/plugins.c +++ b/src/plugins.c @@ -198,9 +198,9 @@ plugins_iter(const struct ly_ctx *ctx, enum LYPLG type, uint32_t *index) } /** - * @brief Find the give @p type plugin record. + * @brief Find the given @p type plugin record. * - * @param[in] ctx Context for which the plugin record is searched for, NULL for built-in plugins. + * @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. @@ -244,13 +244,13 @@ lyplg_record_find(const struct ly_ctx *ctx, enum LYPLG type, const char *module, /** * @brief Find the plugin of the given @p type. * - * @param[in] ctx Context for which the plugin record is searched for, NULL for built-in plugins. + * @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. + * @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) diff --git a/src/plugins_exts.h b/src/plugins_exts.h index 5d688700a..5539b5d3d 100644 --- a/src/plugins_exts.h +++ b/src/plugins_exts.h @@ -405,8 +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()) */ - uintptr_t plugin_ref; /**< reference to extension's manipulation callbacks plugin, - use ::lysc_get_ext_plugin() to get the plugin */ + 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 */ diff --git a/src/plugins_internal.h b/src/plugins_internal.h index 3ff7188f0..29ffbfada 100644 --- a/src/plugins_internal.h +++ b/src/plugins_internal.h @@ -66,7 +66,7 @@ extern uint32_t ly_static_ext_plugins_count; /** * @brief Get a type plugin. * - * @param[in] PLUGIN_REF Reference to a plugin. Either an index of a static plugin (offset by +1) + * @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. */ @@ -78,7 +78,7 @@ extern uint32_t ly_static_ext_plugins_count; /** * @brief Get an extension plugin. * - * @param[in] PLUGIN_REF Reference to a plugin. Either an index of a static plugin (offset by +1) + * @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. */ @@ -115,7 +115,7 @@ void lyplg_clean(void); * only the plugins with NULL revision specified. * @param[in] name Name of the type which the plugin implements. * @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(). + * by passing the returned ID to ::lysc_get_type_plugin() or ::LYSC_GET_TYPE_PLG. */ uintptr_t lyplg_type_plugin_find(const struct ly_ctx *ctx, const char *module, const char *revision, const char *name); @@ -128,7 +128,7 @@ uintptr_t lyplg_type_plugin_find(const struct ly_ctx *ctx, const char *module, c * only the plugins with NULL revision specified. * @param[in] name Name of the extension which the plugin implements. * @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(). + * by passing the returned ID to ::lysc_get_ext_plugin() or ::LYSC_GET_EXT_PLG. */ uintptr_t lyplg_ext_plugin_find(const struct ly_ctx *ctx, const char *module, const char *revision, const char *name); diff --git a/src/plugins_types.c b/src/plugins_types.c index 57b5c0cde..ace812d81 100644 --- a/src/plugins_types.c +++ b/src/plugins_types.c @@ -903,13 +903,13 @@ lyplg_type_print_val(const struct lysc_node *node, const char *canon, LY_VALUE_F struct ly_err_item *err = NULL; const char *v; ly_bool dyn; - struct lyplg_type *type_plugin; + struct lyplg_type *type_plg; type = ((struct lysc_node_leaf *)node)->type; - type_plugin = LYSC_GET_TYPE_PLG(type->plugin_ref); + type_plg = LYSC_GET_TYPE_PLG(type->plugin_ref); /* store the value */ - r = type_plugin->store(node->module->ctx, type, canon, strlen(canon), LYPLG_TYPE_STORE_ONLY, LY_VALUE_CANON, + 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) { @@ -920,7 +920,7 @@ lyplg_type_print_val(const struct lysc_node *node, const char *canon, LY_VALUE_F } /* print it in the specific format */ - v = type_plugin->print(node->module->ctx, &storage, format, prefix_data, &dyn, NULL); + v = type_plg->print(node->module->ctx, &storage, format, prefix_data, &dyn, NULL); /* store it in the dictionary, storage will be freed */ if (dyn) { @@ -929,7 +929,7 @@ lyplg_type_print_val(const struct lysc_node *node, const char *canon, LY_VALUE_F lydict_dup(node->module->ctx, v, value); } - type_plugin->free(node->module->ctx, &storage); + type_plg->free(node->module->ctx, &storage); return LY_SUCCESS; } @@ -1055,7 +1055,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; + struct lyplg_type *type_plg; LY_CHECK_ARG_RET(NULL, lref, node, value, errmsg, LY_EINVAL); @@ -1102,7 +1102,7 @@ lyplg_type_resolve_leafref(const struct lysc_type_leafref *lref, const struct ly goto cleanup; } - type = LYSC_GET_TYPE_PLG(lref->plugin_ref); + type_plg = LYSC_GET_TYPE_PLG(lref->plugin_ref); /* check the result */ if (target_path) { @@ -1118,7 +1118,7 @@ lyplg_type_resolve_leafref(const struct lysc_type_leafref *lref, const struct ly continue; } - if (!type->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; } } @@ -1143,7 +1143,7 @@ lyplg_type_resolve_leafref(const struct lysc_type_leafref *lref, const struct ly continue; } - if (!type->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); } diff --git a/src/plugins_types/union.c b/src/plugins_types/union.c index f8a49c032..55525a358 100644 --- a/src/plugins_types/union.c +++ b/src/plugins_types/union.c @@ -220,7 +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_plugin; + struct lyplg_type *type_plg; *err = NULL; @@ -228,7 +228,8 @@ 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 = LYSC_GET_TYPE_PLG(type_u->types[ti]->plugin_ref)->store(ctx, type_u->types[ti], value, value_len, + 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)) { @@ -249,7 +250,7 @@ union_store_type(const struct ly_ctx *ctx, struct lysc_type_union *type_u, uint3 value = strndup(value, value_len); dynamic = 1; } - LYSC_GET_TYPE_PLG(type_u->types[ti]->plugin_ref)->free(ctx, &subvalue->value); + type_plg->free(ctx, &subvalue->value); format = LY_VALUE_JSON; prefix_data = NULL; @@ -268,9 +269,9 @@ union_store_type(const struct ly_ctx *ctx, struct lysc_type_union *type_u, uint3 opts |= LYPLG_TYPE_STORE_ONLY; } - type_plugin = LYSC_GET_TYPE_PLG(type->plugin_ref); + type_plg = LYSC_GET_TYPE_PLG(type->plugin_ref); - rc = type_plugin->store(ctx, type, value, value_len, opts, format, prefix_data, + 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 */ @@ -283,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; } } @@ -325,7 +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; + struct lyplg_type *type_plg; *err = NULL; @@ -376,11 +377,11 @@ union_find_type(const struct ly_ctx *ctx, struct lysc_type_union *type_u, struct } } - type = LYSC_GET_TYPE_PLG(type_u->types[u]->plugin_ref); + type_plg = LYSC_GET_TYPE_PLG(type_u->types[u]->plugin_ref); - msg = ly_realloc(msg, msg_len + 4 + strlen(type->id) + 2 + strlen(errs[u]->msg) + 2); + 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->id, errs[u]->msg); + msg_len += sprintf(msg + msg_len, " %s: %s\n", type_plg->id, errs[u]->msg); } if (!use_err_app_tag) { @@ -519,16 +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; + 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 */ - subvalue_type = LYSC_GET_TYPE_PLG(subvalue->value.realtype->plugin_ref); - LY_CHECK_RET(subvalue_type->duplicate(ctx, &subvalue->value, &orig)); - subvalue_type->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 */ @@ -675,7 +676,6 @@ lyplg_type_print_union(const struct ly_ctx *ctx, const struct lyd_value *value, struct lyd_value_union *subvalue = value->subvalue; struct lysc_type_union *type_u = (struct lysc_type_union *)value->realtype; size_t lyb_data_len = 0; - struct lyplg_type *type; if ((format == LY_VALUE_LYB) && (subvalue->format == LY_VALUE_LYB)) { /* The return value is already ready. */ @@ -695,8 +695,8 @@ lyplg_type_print_union(const struct ly_ctx *ctx, const struct lyd_value *value, } assert(format != LY_VALUE_LYB); - type = LYSC_GET_TYPE_PLG(subvalue->value.realtype->plugin_ref); - ret = (void *)type->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); diff --git a/src/printer_context.c b/src/printer_context.c index 885858ae5..73b6d43bd 100644 --- a/src/printer_context.c +++ b/src/printer_context.c @@ -113,7 +113,7 @@ 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; + struct lyplg_ext *ext_plg; /* sized array */ *size += CTXS_SIZED_ARRAY(exts); @@ -125,9 +125,9 @@ ctxs_exts(const struct lysc_ext_instance *exts, struct ly_ht *ht, int *size) *size += CTXS_SIZED_ARRAY(exts[u].substmts); /* compiled, substmts storage */ - ext = LYSC_GET_EXT_PLG(exts[u].def->plugin_ref); - if (ext && ext->compiled_size) { - *size += ext->compiled_size(&exts[u], ht); + ext_plg = LYSC_GET_EXT_PLG(exts[u].def->plugin_ref); + if (ext_plg && ext_plg->compiled_size) { + *size += ext_plg->compiled_size(&exts[u], ht); } } } @@ -789,6 +789,7 @@ ctxp_ext(const struct lysc_ext_instance *orig_ext, struct lysc_ext_instance *ext 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 */ @@ -822,8 +823,8 @@ ctxp_ext(const struct lysc_ext_instance *orig_ext, struct lysc_ext_instance *ext } /* compiled, substmts storage, use the plugin */ - if (ext->def->plugin_ref && LYSC_GET_EXT_PLG(ext->def->plugin_ref)->compiled_print) { - LYSC_GET_EXT_PLG(ext->def->plugin_ref)->compiled_print(orig_ext, ext, addr_ht, ptr_set, mem); + 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; } diff --git a/src/schema_compile.c b/src/schema_compile.c index b643c326f..2833fd442 100644 --- a/src/schema_compile.c +++ b/src/schema_compile.c @@ -114,6 +114,7 @@ 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; @@ -132,11 +133,11 @@ lys_compile_ext(struct lysc_ctx *ctx, struct lysp_ext_instance *extp, struct lys COMPILE_EXTS_GOTO(ctx, extp->exts, ext->exts, ext, ret, cleanup); /* compile this extension */ - if (ext->def->plugin_ref && LYSC_GET_EXT_PLG(ext->def->plugin_ref)->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 = LYSC_GET_EXT_PLG(ext->def->plugin_ref)->compile(ctx, extp, ext); + ret = ext_plg->compile(ctx, extp, ext); if (ret == LY_ENOT) { lysc_ext_instance_free(ctx->ctx, ext); } @@ -896,11 +897,11 @@ lys_compile_unres_dflt(struct lysc_ctx *ctx, struct lysc_node *node, struct lysc struct lyd_value storage = {0}, *val; struct ly_err_item *err = NULL; LY_VALUE_FORMAT format; - struct lyplg_type *type_plugin; + struct lyplg_type *type_plg; options = (ctx->ctx->opts & LY_CTX_REF_IMPLEMENTED) ? LYPLG_TYPE_STORE_IMPLEMENT : 0; - type_plugin = LYSC_GET_TYPE_PLG(type->plugin_ref); - rc = type_plugin->store(ctx->ctx, type, dflt, strlen(dflt), options, LY_VALUE_SCHEMA, (void *)dflt_pmod, + 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 */ @@ -938,8 +939,8 @@ lys_compile_unres_dflt(struct lysc_ctx *ctx, struct lysc_node *node, struct lysc ly_path_free(val->target); val->target = NULL; } - type_plugin->free(ctx->ctx, &storage); - return LY_SUCCESS; + type_plg->free(ctx->ctx, &storage); + return rc; } /** diff --git a/src/schema_compile_amend.c b/src/schema_compile_amend.c index ab802c3c0..7d58fe1bf 100644 --- a/src/schema_compile_amend.c +++ b/src/schema_compile_amend.c @@ -473,6 +473,7 @@ 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); @@ -486,10 +487,10 @@ lysp_ext_dup(const struct ly_ctx *ctx, const struct lysp_module *pmod, void *par ext->flags = orig_ext->flags; LY_CHECK_GOTO(ret = lysp_ext_children_dup(ctx, orig_ext->child, &ext->child), cleanup); - if (ext->plugin_ref && LYSC_GET_EXT_PLG(ext->plugin_ref)->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 = LYSC_GET_EXT_PLG(ext->plugin_ref)->parse(&pctx, ext), cleanup); + LY_CHECK_GOTO(ret = ext_plg->parse(&pctx, ext), cleanup); } cleanup: diff --git a/src/tree_data_common.c b/src/tree_data_common.c index 9cbbc2085..bd1c0fa58 100644 --- a/src/tree_data_common.c +++ b/src/tree_data_common.c @@ -562,19 +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_plugin; + struct lyplg_type *type_plg; - type_plugin = LYSC_GET_TYPE_PLG(type->plugin_ref); - assert(type_plugin && 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; } @@ -637,7 +637,7 @@ lyd_value_validate2(const struct ly_ctx *ctx, const struct lysc_node *schema, co struct lysc_type *type; struct lyd_value val = {0}; ly_bool stored = 0, log = 1; - struct lyplg_type *type_plugin, *realtype_plugin; + struct lyplg_type *type_plg; if (!ctx) { ctx = schema->module->ctx; @@ -648,10 +648,10 @@ lyd_value_validate2(const struct ly_ctx *ctx, const struct lysc_node *schema, co } type = ((struct lysc_node_leaf *)schema)->type; - type_plugin = LYSC_GET_TYPE_PLG(type->plugin_ref); + type_plg = LYSC_GET_TYPE_PLG(type->plugin_ref); /* store */ - rc = type_plugin->store(ctx, type, value, value_len, 0, format, + 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; @@ -659,7 +659,7 @@ lyd_value_validate2(const struct ly_ctx *ctx, const struct lysc_node *schema, co 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) { @@ -682,14 +682,14 @@ lyd_value_validate2(const struct ly_ctx *ctx, const struct lysc_node *schema, co if (canonical) { /* return canonical value */ - realtype_plugin = LYSC_GET_TYPE_PLG(val.realtype->plugin_ref); - lydict_dup(ctx, realtype_plugin->print(ctx, &val, LY_VALUE_CANON, NULL, NULL, NULL), 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, &val); + type_plg->free(ctx, &val); } return rc; } @@ -701,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); @@ -714,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 = LYSC_GET_TYPE_PLG(type->plugin_ref)->compare(ctx, &node->value, &val); + type_plg = LYSC_GET_TYPE_PLG(type->plugin_ref); + ret = type_plg->compare(ctx, &node->value, &val); - LYSC_GET_TYPE_PLG(type->plugin_ref)->free(ctx, &val); + type_plg->free(ctx, &val); return ret; } diff --git a/src/tree_data_hash.c b/src/tree_data_hash.c index 692c0278f..d82e9203f 100644 --- a/src/tree_data_hash.c +++ b/src/tree_data_hash.c @@ -34,7 +34,6 @@ lyd_hash(struct lyd_node *node) const void *hash_key; ly_bool dyn; size_t key_len; - struct lyplg_type *type; if (!node->schema) { return LY_SUCCESS; @@ -57,8 +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; - type = LYSC_GET_TYPE_PLG(key->value.realtype->plugin_ref); - hash_key = type->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); @@ -69,8 +68,8 @@ lyd_hash(struct lyd_node *node) /* leaf-list adds its hash key */ struct lyd_node_term *llist = (struct lyd_node_term *)node; - type = LYSC_GET_TYPE_PLG(llist->value.realtype->plugin_ref); - hash_key = type->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_new.c b/src/tree_data_new.c index 312b30c23..f45df542d 100644 --- a/src/tree_data_new.c +++ b/src/tree_data_new.c @@ -1218,10 +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 *real_type, *schema_type; + struct lyplg_type *realtype_plg, *schema_type_plg; - real_type = LYSC_GET_TYPE_PLG(term->value.realtype->plugin_ref); - schema_type = LYSC_GET_TYPE_PLG(((struct lysc_node_leaf *)term->schema)->type->plugin_ref); + 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; @@ -1229,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 */ - real_type->free(LYD_CTX(term), &term->value); + realtype_plg->free(LYD_CTX(term), &term->value); if (use_val) { term->value = *val; } else { - rc = schema_type->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 */ @@ -1249,11 +1249,11 @@ lyd_change_node_value(struct lyd_node_term *term, struct lyd_value *val, ly_bool lyd_unlink_tree(target); /* change value */ - real_type->free(LYD_CTX(term), &term->value); + realtype_plg->free(LYD_CTX(term), &term->value); if (use_val) { term->value = *val; } else { - rc = schema_type->duplicate(LYD_CTX(term), val, &term->value); + rc = schema_type_plg->duplicate(LYD_CTX(term), val, &term->value); } /* update hash */ @@ -1266,11 +1266,11 @@ lyd_change_node_value(struct lyd_node_term *term, struct lyd_value *val, ly_bool lyd_unlink_hash(target); /* change value */ - real_type->free(LYD_CTX(term), &term->value); + realtype_plg->free(LYD_CTX(term), &term->value); if (use_val) { term->value = *val; } else { - LY_CHECK_RET(schema_type->duplicate(LYD_CTX(term), val, &term->value)); + LY_CHECK_RET(schema_type_plg->duplicate(LYD_CTX(term), val, &term->value)); } /* update hash */ @@ -1290,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 (LYSC_GET_TYPE_PLG(type->plugin_ref)->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); @@ -1305,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) { - LYSC_GET_TYPE_PLG(type->plugin_ref)->free(LYD_CTX(term), val); + type_plg->free(LYD_CTX(term), val); } val_change = 0; } diff --git a/src/tree_schema.c b/src/tree_schema.c index 95f497f9b..c99c7cda2 100644 --- a/src/tree_schema.c +++ b/src/tree_schema.c @@ -1356,6 +1356,7 @@ lysp_resolve_ext_instance_records(struct lysp_ctx *pctx) 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) { @@ -1378,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->plugin_ref || !LYSC_GET_EXT_PLG(ext->plugin_ref)->parse) { + if (!ext->plugin_ref || !(ext_plg = LYSC_GET_EXT_PLG(ext->plugin_ref))->parse) { goto next_iter; } @@ -1389,7 +1390,7 @@ lysp_resolve_ext_instance_records(struct lysp_ctx *pctx) ly_log_location(NULL, NULL, path, NULL); /* parse */ - r = LYSC_GET_EXT_PLG(ext->plugin_ref)->parse(pctx, ext); + r = ext_plg->parse(pctx, ext); ly_log_location_revert(0, 0, 1, 0); free(path); diff --git a/src/tree_schema_free.c b/src/tree_schema_free.c index 19528c348..e4c26343d 100644 --- a/src/tree_schema_free.c +++ b/src/tree_schema_free.c @@ -70,12 +70,13 @@ void 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, ext->name); lydict_remove(ctx, ext->argument); ly_free_prefix_data(ext->format, ext->prefix_data); - if (ext->plugin_ref && LYSC_GET_EXT_PLG(ext->plugin_ref)->pfree) { - LYSC_GET_EXT_PLG(ext->plugin_ref)->pfree(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) { @@ -640,8 +641,10 @@ lysp_module_free(const struct ly_ctx *ctx, struct lysp_module *module) void lysc_ext_instance_free(const struct ly_ctx *ctx, struct lysc_ext_instance *ext) { - if (ext->def && ext->def->plugin_ref && LYSC_GET_EXT_PLG(ext->def->plugin_ref)->cfree) { - LYSC_GET_EXT_PLG(ext->def->plugin_ref)->cfree(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, ext->argument); FREE_ARRAY(ctx, ext->exts, lysc_ext_instance_free); diff --git a/src/xpath.c b/src/xpath.c index f5f6fa587..ea30c18a3 100644 --- a/src/xpath.c +++ b/src/xpath.c @@ -1699,6 +1699,7 @@ set_comp_canonize(struct lyxp_set *set, const struct lyxp_set_node *xp_node) const struct lysc_type *type = 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,16 +1715,18 @@ 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) && (LYSC_GET_TYPE_PLG(type->plugin_ref)->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) && (LYSC_GET_TYPE_PLG(type->plugin_ref)->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) && (LYSC_GET_TYPE_PLG(type->plugin_ref)->store == lyplg_type_store_enum)) { + if ((type->basetype == LY_TYPE_ENUM) && (type_plg->store == lyplg_type_store_enum)) { /* enumeration */ return LY_SUCCESS; } @@ -3620,7 +3623,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_plugin; + 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))) { @@ -3645,8 +3648,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) { - type_plugin = LYSC_GET_TYPE_PLG(type->plugin_ref); - 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 +3666,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); From 8e466d6686924482228873a42fdbe3ec0d98e584 Mon Sep 17 00:00:00 2001 From: roman Date: Mon, 27 Jan 2025 15:15:31 +0100 Subject: [PATCH 46/99] log BUGFIX add missing unlock --- src/log.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/log.c b/src/log.c index 65ccdc839..cb1e11161 100644 --- a/src/log.c +++ b/src/log.c @@ -182,21 +182,26 @@ ly_err_data_get(const struct ly_ctx *ctx) struct ly_ctx_data *ctx_data; pthread_t tid = pthread_self(); uint32_t i; + struct ly_ctx_data_err *data_err = NULL; /* get context data */ ctx_data = ly_ctx_data_get(ctx); + /* ERR READ LOCK */ pthread_rwlock_rdlock(&ctx_data->err_rwlock); /* find the thread-specific err */ for (i = 0; i < ctx_data->err_count; ++i) { if (!memcmp(&ctx_data->errs[i]->tid, &tid, sizeof tid)) { - return ctx_data->errs[i]; + data_err = ctx_data->errs[i]; + goto cleanup; } } + /* ERR UNLOCK */ pthread_rwlock_unlock(&ctx_data->err_rwlock); + /* ERR WRITE LOCK */ pthread_rwlock_wrlock(&ctx_data->err_rwlock); /* no need to retry the search, this thread is executing this function */ @@ -208,7 +213,12 @@ ly_err_data_get(const struct ly_ctx *ctx) ++ctx_data->err_count; - return ctx_data->errs[ctx_data->err_count - 1]; + data_err = ctx_data->errs[ctx_data->err_count - 1]; + +cleanup: + /* ERR UNLOCK */ + pthread_rwlock_unlock(&ctx_data->err_rwlock); + return data_err; } LIBYANG_API_DEF const struct ly_err_item * From 734ba302e1ddeb0d32910caab628fce5c927d290 Mon Sep 17 00:00:00 2001 From: roman Date: Mon, 27 Jan 2025 15:15:56 +0100 Subject: [PATCH 47/99] xpath BUGFIX pass correct format to validate --- src/xpath.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/xpath.c b/src/xpath.c index ea30c18a3..5d2babea0 100644 --- a/src/xpath.c +++ b/src/xpath.c @@ -1732,7 +1732,8 @@ set_comp_canonize(struct lyxp_set *set, const struct lyxp_set_node *xp_node) } /* print canonized string, ignore errors, the value may not satisfy schema constraints */ - r = lyd_value_validate(set->ctx, xp_node->node->schema, set->val.str, strlen(set->val.str), NULL, NULL, &canon); + 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, fine */ return LY_SUCCESS; From b1951f18d995f064b74cb73426745fa2ac67692a Mon Sep 17 00:00:00 2001 From: roman Date: Wed, 29 Jan 2025 09:10:26 +0100 Subject: [PATCH 48/99] printer context BUGFIX check for NULL ext --- src/printer_context.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/printer_context.c b/src/printer_context.c index 73b6d43bd..eb2530278 100644 --- a/src/printer_context.c +++ b/src/printer_context.c @@ -125,8 +125,7 @@ ctxs_exts(const struct lysc_ext_instance *exts, struct ly_ht *ht, int *size) *size += CTXS_SIZED_ARRAY(exts[u].substmts); /* compiled, substmts storage */ - ext_plg = LYSC_GET_EXT_PLG(exts[u].def->plugin_ref); - if (ext_plg && ext_plg->compiled_size) { + 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); } } From e149e8fbf4b0d472f2c51ce441de304007e6a35a Mon Sep 17 00:00:00 2001 From: roman Date: Wed, 29 Jan 2025 09:10:51 +0100 Subject: [PATCH 49/99] printer context BUGFIX index expr repeat correctly --- src/printer_context.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/printer_context.c b/src/printer_context.c index eb2530278..25bffe948 100644 --- a/src/printer_context.c +++ b/src/printer_context.c @@ -161,7 +161,7 @@ ctxs_expr(const struct lyxp_expr *exp, int *size) continue; } - for (j = 0; exp->repeat[j]; ++j) {} + for (j = 0; exp->repeat[i][j]; ++j) {} *size += (j + 1) * sizeof **exp->repeat; } } From e66d11ae799585bdea56b575cec04dc8f88eed88 Mon Sep 17 00:00:00 2001 From: roman Date: Fri, 21 Feb 2025 15:03:33 +0100 Subject: [PATCH 50/99] context UPDATE add is ctx printed API --- src/context.c | 6 ++++++ src/context.h | 8 ++++++++ 2 files changed, 14 insertions(+) diff --git a/src/context.c b/src/context.c index cf3c24374..b1328c13c 100644 --- a/src/context.c +++ b/src/context.c @@ -1489,6 +1489,12 @@ ly_ctx_new_printed(const void *mem, struct ly_ctx **ctx) 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) { diff --git a/src/context.h b/src/context.h index 081206a32..f57a21ab4 100644 --- a/src/context.h +++ b/src/context.h @@ -696,6 +696,14 @@ LIBYANG_API_DECL LY_ERR ly_ctx_compiled_print(const struct ly_ctx *ctx, void *me */ 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. * From 80cb131c5d4cc8139845f65a6043437613885f3b Mon Sep 17 00:00:00 2001 From: roman Date: Fri, 21 Feb 2025 15:13:18 +0100 Subject: [PATCH 51/99] context UPDATE unify ctx data creation --- src/context.c | 45 +++++++++++------------------------ src/ly_common.c | 62 ++++++++++++++++++++++++++++++++++++++++++++----- src/ly_common.h | 19 ++++++++++++--- 3 files changed, 86 insertions(+), 40 deletions(-) diff --git a/src/context.c b/src/context.c index b1328c13c..f2f3789f1 100644 --- a/src/context.c +++ b/src/context.c @@ -259,10 +259,7 @@ 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 leafref links hash table record. - */ -static ly_bool +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; @@ -275,7 +272,6 @@ ly_ctx_new(const char *search_dir, uint32_t options, struct ly_ctx **new_ctx) { struct ly_ctx *ctx = NULL; struct lys_module *module; - struct ly_ctx_data *ctx_data; char *search_dir_list, *sep, *dir; const char **imp_f, *all_f[] = {"*", NULL}; uint32_t i; @@ -297,21 +293,14 @@ ly_ctx_new(const char *search_dir, uint32_t options, struct ly_ctx **new_ctx) 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); + /* options */ + ctx->opts = options; + /* ctx data */ - ctx_data = ly_ctx_data_add(ctx); - - 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_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(!ctx_data->leafref_links_ht, rc = LY_EMEM, cleanup); - } + rc = ly_ctx_data_add(ctx); + LY_CHECK_GOTO(rc, cleanup); /* modules list */ - ctx->opts = options; if (search_dir) { search_dir_list = strdup(search_dir); LY_CHECK_ERR_GOTO(!search_dir_list, LOGMEM(NULL); rc = LY_EMEM, cleanup); @@ -1455,7 +1444,6 @@ LIBYANG_API_DEF LY_ERR ly_ctx_new_printed(const void *mem, struct ly_ctx **ctx) { LY_ERR rc = LY_SUCCESS; - struct ly_ctx_data *ctx_data = NULL; ly_bool builtin_plugins_only, static_plugins_only; LY_CHECK_ARG_RET(NULL, mem, ctx, LY_EINVAL); @@ -1463,26 +1451,21 @@ ly_ctx_new_printed(const void *mem, struct ly_ctx **ctx) *ctx = (void *)mem; /* ctx data */ - ctx_data = ly_ctx_data_add(*ctx); + rc = ly_ctx_data_add(*ctx); + if (rc) { + if (rc == LY_EEXIST) { + LOGERR(NULL, LY_EEXIST, "Printed context was already created on the provided address."); + } + 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); - /* data dictionary */ - ctx_data->data_dict = malloc(sizeof *ctx_data->data_dict); - LY_CHECK_ERR_GOTO(!ctx_data->data_dict, rc = LY_EMEM, cleanup); - lydict_init(ctx_data->data_dict); - - /* leafref set */ - if ((*ctx)->opts & LY_CTX_LEAFREF_LINKING) { - 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_GOTO(!ctx_data->leafref_links_ht, rc = LY_EMEM, cleanup); - } - cleanup: - if (rc && ctx_data) { + if (rc) { ly_ctx_data_del(*ctx); *ctx = NULL; } diff --git a/src/ly_common.c b/src/ly_common.c index 89918d86e..70c0726f4 100644 --- a/src/ly_common.c +++ b/src/ly_common.c @@ -100,6 +100,7 @@ ly_ctx_data_get(const struct ly_ctx *ctx) struct ly_ctx_data *ctx_data = NULL; uint32_t i; + /* RD LOCK */ pthread_rwlock_rdlock(&ly_ctx_data_rwlock); for (i = 0; i < ly_ctx_data_count; ++i) { @@ -109,6 +110,7 @@ ly_ctx_data_get(const struct ly_ctx *ctx) } } + /* RD UNLOCK */ pthread_rwlock_unlock(&ly_ctx_data_rwlock); if (!ctx_data) { @@ -119,27 +121,73 @@ ly_ctx_data_get(const struct ly_ctx *ctx) return ctx_data; } -struct ly_ctx_data * -ly_ctx_data_add(const struct ly_ctx *ctx) +struct ly_dict * +ly_ctx_data_dict_get(const struct ly_ctx *ctx) { struct ly_ctx_data *ctx_data; + ctx_data = ly_ctx_data_get(ctx); + if (!ctx_data) { + return NULL; + } + + return ctx_data->data_dict; +} + +LY_ERR +ly_ctx_data_add(const struct ly_ctx *ctx) +{ + LY_ERR rc = LY_SUCCESS; + struct ly_ctx_data *ctx_data = NULL; + uint32_t i; + + /* WR LOCK */ pthread_rwlock_wrlock(&ly_ctx_data_rwlock); + /* check for duplicates */ + for (i = 0; i < ly_ctx_data_count; i++) { + if (ly_ctx_data[i]->ctx == ctx) { + rc = LY_EEXIST; + goto cleanup; + } + } + /* realloc */ ly_ctx_data = ly_realloc(ly_ctx_data, (ly_ctx_data_count + 1) * sizeof *ly_ctx_data); + LY_CHECK_ERR_GOTO(!ly_ctx_data, rc = LY_EMEM, cleanup); /* alloc */ ctx_data = ly_ctx_data[ly_ctx_data_count] = calloc(1, sizeof **ly_ctx_data); + LY_CHECK_ERR_GOTO(!ctx_data, rc = LY_EMEM, cleanup); /* fill */ - ly_ctx_data[ly_ctx_data_count]->ctx = ctx; + ctx_data->ctx = ctx; + + /* 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 + * */ + 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_GOTO(!ctx_data->leafref_links_ht, rc = LY_EMEM, cleanup); + } + + /* data dictionary */ + ctx_data->data_dict = malloc(sizeof *ctx_data->data_dict); + LY_CHECK_ERR_GOTO(!ctx_data->data_dict, rc = LY_EMEM, cleanup); + lydict_init(ctx_data->data_dict); ++ly_ctx_data_count; +cleanup: + /* WR UNLOCK */ pthread_rwlock_unlock(&ly_ctx_data_rwlock); - - return ctx_data; + if (rc && ctx_data) { + ly_ctx_data_del(ctx); + } + return rc; } void @@ -148,6 +196,7 @@ ly_ctx_data_del(const struct ly_ctx *ctx) uint32_t i; struct ly_ctx_data *ctx_data = NULL; + /* WR LOCK */ pthread_rwlock_wrlock(&ly_ctx_data_rwlock); /* find the ctx data */ @@ -158,8 +207,8 @@ ly_ctx_data_del(const struct ly_ctx *ctx) } } if (!ctx_data) { + /* WR UNLOCK */ pthread_rwlock_unlock(&ly_ctx_data_rwlock); - LOGINT(NULL); return; } @@ -174,6 +223,7 @@ ly_ctx_data_del(const struct ly_ctx *ctx) ly_ctx_data = NULL; } + /* WR UNLOCK */ pthread_rwlock_unlock(&ly_ctx_data_rwlock); /* clear */ diff --git a/src/ly_common.h b/src/ly_common.h index 52351c029..f0e25dd47 100644 --- a/src/ly_common.h +++ b/src/ly_common.h @@ -352,7 +352,7 @@ struct ly_ctx_data { uint32_t err_count; /**< count of items in the errs array */ struct ly_ht *leafref_links_ht; /**< hash table of leafref links between term data nodes */ - struct ly_dict *data_dict; /**< dictionary for data trees, for immutable contexts */ + struct ly_dict *data_dict; /**< dictionary for data trees */ }; extern pthread_rwlock_t ly_ctx_data_rwlock; /**< lock for accessing ly_ctx_data */ @@ -394,9 +394,9 @@ void ly_ctx_new_change(struct ly_ctx *ctx); * @brief Add a ctx data for a new context. * * @param[in] ctx Newly created context. - * @return Newly created data. + * @return LY_SUCCESS on success, LY_EEXIST if the context data already exists or LY_EMEM on memory allocation failure. */ -struct ly_ctx_data *ly_ctx_data_add(const struct ly_ctx *ctx); +LY_ERR ly_ctx_data_add(const struct ly_ctx *ctx); /** * @brief Remove a ctx data of a destroyed context. @@ -413,6 +413,19 @@ void ly_ctx_data_del(const struct ly_ctx *ctx); */ struct ly_ctx_data *ly_ctx_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. + */ +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. * From e349b022ffffc25549204eee59aaab6d0e1727ba Mon Sep 17 00:00:00 2001 From: roman Date: Fri, 21 Feb 2025 15:37:01 +0100 Subject: [PATCH 52/99] dict UPDATE ctx use separate data and schema dicts --- src/dict.c | 127 ++++++++++++----- src/ly_common.h | 62 +++++++++ src/parser_common.c | 94 ++++++------- src/parser_yang.c | 24 ++-- src/parser_yin.c | 100 ++++++------- src/plugins_exts.c | 2 +- src/plugins_exts/nacm.c | 3 +- src/plugins_exts/structure.c | 3 +- src/printer_json.c | 4 +- src/schema_compile.c | 4 +- src/schema_compile.h | 6 +- src/schema_compile_amend.c | 30 ++-- src/schema_compile_node.c | 24 ++-- src/tree_schema.c | 92 ++++++------ src/tree_schema_common.c | 2 +- src/tree_schema_free.c | 224 +++++++++++++++--------------- src/tree_schema_free.h | 2 +- tests/utests/schema/test_schema.c | 32 +++-- tests/utests/schema/test_yang.c | 2 +- tests/utests/schema/test_yin.c | 34 ++--- 20 files changed, 498 insertions(+), 373 deletions(-) diff --git a/src/dict.c b/src/dict.c index 8188aec97..fb121c2d5 100644 --- a/src/dict.c +++ b/src/dict.c @@ -116,27 +116,22 @@ 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; uint32_t hash; struct ly_dict_rec rec, *match = NULL; char *val_p; - struct ly_ctx_data *ctx_data; - struct ly_dict *dict; - - if (!ctx || !value) { - return LY_SUCCESS; - } - - if (ctx->opts & LY_CTX_INT_IMMUTABLE) { - ctx_data = ly_ctx_data_get(ctx); - dict = ctx_data->data_dict; - } else { - dict = (struct ly_dict *)&ctx->dict; - } LOGDBG(LY_LDGDICT, "removing \"%s\"", value); @@ -147,7 +142,6 @@ lydict_remove(const struct ly_ctx *ctx, const char *value) rec.value = (char *)value; rec.refcount = 0; - pthread_mutex_lock(&dict->lock); /* set len as data for compare callback */ lyht_set_cb_data(dict->hash_tab, (void *)&len); /* check if value is already inserted */ @@ -176,10 +170,48 @@ lydict_remove(const struct ly_ctx *ctx, const char *value) } 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(struct ly_dict *dict, char *value, size_t len, ly_bool zerocopy, const char **str_p) { @@ -229,11 +261,27 @@ dict_insert(struct ly_dict *dict, char *value, size_t len, ly_bool zerocopy, con 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 rc; - struct ly_ctx_data *ctx_data; struct ly_dict *dict; LY_CHECK_ARG_RET(ctx, ctx, str_p, LY_EINVAL); @@ -247,12 +295,7 @@ lydict_insert(const struct ly_ctx *ctx, const char *value, size_t len, const cha len = strlen(value); } - if (ctx->opts & LY_CTX_INT_IMMUTABLE) { - ctx_data = ly_ctx_data_get(ctx); - dict = ctx_data->data_dict; - } else { - dict = (struct ly_dict *)&ctx->dict; - } + dict = ly_ctx_data_dict_get(ctx); pthread_mutex_lock(&dict->lock); rc = dict_insert(dict, (char *)value, len, 0, str_p); @@ -261,11 +304,21 @@ lydict_insert(const struct ly_ctx *ctx, const char *value, size_t len, const cha return rc; } +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 rc; - struct ly_ctx_data *ctx_data; struct ly_dict *dict; LY_CHECK_ARG_RET(ctx, ctx, str_p, LY_EINVAL); @@ -275,12 +328,7 @@ lydict_insert_zc(const struct ly_ctx *ctx, char *value, const char **str_p) return LY_SUCCESS; } - if (ctx->opts & LY_CTX_INT_IMMUTABLE) { - ctx_data = ly_ctx_data_get(ctx); - dict = ctx_data->data_dict; - } else { - dict = (struct ly_dict *)&ctx->dict; - } + dict = ly_ctx_data_dict_get(ctx); pthread_mutex_lock(&dict->lock); rc = dict_insert(dict, value, strlen(value), 1, str_p); @@ -316,11 +364,21 @@ dict_dup(struct ly_dict *dict, char *value, const char **str_p) 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 rc; - struct ly_ctx_data *ctx_data; struct ly_dict *dict; LY_CHECK_ARG_RET(ctx, ctx, str_p, LY_EINVAL); @@ -330,12 +388,7 @@ lydict_dup(const struct ly_ctx *ctx, const char *value, const char **str_p) return LY_SUCCESS; } - if (ctx->opts & LY_CTX_INT_IMMUTABLE) { - ctx_data = ly_ctx_data_get(ctx); - dict = ctx_data->data_dict; - } else { - dict = (struct ly_dict *)&ctx->dict; - } + dict = ly_ctx_data_dict_get(ctx); pthread_mutex_lock(&dict->lock); rc = dict_dup(dict, (char *)value, str_p); diff --git a/src/ly_common.h b/src/ly_common.h index f0e25dd47..f7dd7804b 100644 --- a/src/ly_common.h +++ b/src/ly_common.h @@ -444,6 +444,68 @@ void ly_ctx_ht_leafref_links_rec_free(void *val_p); */ struct lys_module *ly_ctx_get_module_implemented2(const struct ly_ctx *ctx, const char *name, size_t name_len); +/****************************************************************************** + * Dictionary + *****************************************************************************/ + +/* + * The following lysdict_*() functions operate on the internal schema dictionary of the given context. + * They do NOT lock a mutex as opposed to their lydict_*() counterparts, 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 the internal schema dictionary of @p ctx. Use ::lydict_insert() 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(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. *****************************************************************************/ diff --git a/src/parser_common.c b/src/parser_common.c index 4a8620f3e..6f5a0456e 100644 --- a/src/parser_common.c +++ b/src/parser_common.c @@ -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_yang.c b/src/parser_yang.c index c4b7ec843..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)); @@ -2136,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); @@ -2196,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) { @@ -2301,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; @@ -2872,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; @@ -2993,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: diff --git a/src/parser_yin.c b/src/parser_yin.c index f962227c3..134245a2f 100644 --- a/src/parser_yin.c +++ b/src/parser_yin.c @@ -51,14 +51,14 @@ struct lys_glob_unres; * @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. + * 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(lydict_insert_zc(CTX, (char *)(STRING), &(TARGET))); \ + LY_CHECK_RET(lysdict_insert_zc(CTX, (char *)(STRING), &(TARGET))); \ } else { \ - LY_CHECK_RET(lydict_insert(CTX, LEN ? (STRING) : "", LEN, &(TARGET))); \ + LY_CHECK_RET(lysdict_insert(CTX, LEN ? (STRING) : "", LEN, &(TARGET))); \ } \ DYNAMIC = 0 @@ -644,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; @@ -690,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; @@ -733,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; } @@ -741,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[] = { @@ -946,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)); @@ -984,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)); @@ -1215,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; } @@ -1241,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)); @@ -1416,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; } @@ -1445,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; } @@ -1453,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; @@ -1541,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)); @@ -1844,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[] = { @@ -1926,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)); @@ -1961,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)); @@ -1997,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)); @@ -2069,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)); @@ -2106,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)); @@ -2179,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)); @@ -2673,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; @@ -2754,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 */ @@ -2856,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); @@ -3257,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, @@ -3296,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) { @@ -3382,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, @@ -3406,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)); diff --git a/src/plugins_exts.c b/src/plugins_exts.c index f7bb45c4b..256daff3d 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: diff --git a/src/plugins_exts/nacm.c b/src/plugins_exts/nacm.c index 45e34f844..8a04d90de 100644 --- a/src/plugins_exts/nacm.c +++ b/src/plugins_exts/nacm.c @@ -19,6 +19,7 @@ #include "compat.h" #include "libyang.h" +#include "ly_common.h" #include "plugins_exts.h" #include "plugins_internal.h" @@ -56,7 +57,7 @@ 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; } } diff --git a/src/plugins_exts/structure.c b/src/plugins_exts/structure.c index 618221368..aaa1e8fc9 100644 --- a/src/plugins_exts/structure.c +++ b/src/plugins_exts/structure.c @@ -19,6 +19,7 @@ #include "compat.h" #include "libyang.h" +#include "ly_common.h" #include "plugins_exts.h" struct lysp_ext_instance_structure { @@ -440,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; diff --git a/src/printer_json.c b/src/printer_json.c index df700394d..d2b270f6c 100644 --- a/src/printer_json.c +++ b/src/printer_json.c @@ -328,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 ? " " : ""); diff --git a/src/schema_compile.c b/src/schema_compile.c index 2833fd442..2c9bcf4b4 100644 --- a/src/schema_compile.c +++ b/src/schema_compile.c @@ -913,7 +913,7 @@ lys_compile_unres_dflt(struct lysc_ctx *ctx, struct lysc_node *node, struct lysc if (!rc) { /* store the original value with the resolved prefixes */ - LY_CHECK_GOTO(rc = lydict_insert(ctx->ctx, dflt, 0, &value->str), cleanup); + 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 { @@ -1674,7 +1674,7 @@ lys_compile_enabled_features(struct lys_module *mod) 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 = lydict_dup(mod->ctx, f->name, feat_p), cleanup); + LY_CHECK_GOTO(rc = lysdict_dup(mod->ctx, f->name, feat_p), cleanup); } } diff --git a/src/schema_compile.h b/src/schema_compile.h index 7dce5770e..401443acc 100644 --- a/src/schema_compile.h +++ b/src/schema_compile.h @@ -159,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) { \ diff --git a/src/schema_compile_amend.c b/src/schema_compile_amend.c index 7d58fe1bf..571f7eb9b 100644 --- a/src/schema_compile_amend.c +++ b/src/schema_compile_amend.c @@ -54,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); @@ -125,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 */ @@ -134,7 +134,7 @@ 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; @@ -916,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: @@ -937,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: @@ -947,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); } @@ -991,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); } @@ -1345,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; } @@ -1376,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: @@ -1387,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: @@ -1445,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); } @@ -1455,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: diff --git a/src/schema_compile_node.c b/src/schema_compile_node.c index 056b39440..96764144c 100644 --- a/src/schema_compile_node.c +++ b/src/schema_compile_node.c @@ -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 */ @@ -1393,7 +1393,7 @@ lys_compile_type_patterns(struct lysc_ctx *ctx, const struct lysp_restr *pattern if (patterns_p[u].arg.str[0] == LYSP_RESTR_PATTERN_NACK) { (*pattern)->inverted = 1; } - 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); @@ -1752,7 +1752,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); } @@ -3047,7 +3047,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; } @@ -3093,7 +3093,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; } diff --git a/src/tree_schema.c b/src/tree_schema.c index c99c7cda2..2f34854d2 100644 --- a/src/tree_schema.c +++ b/src/tree_schema.c @@ -1664,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; @@ -1674,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; @@ -1683,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; @@ -1692,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; @@ -1701,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; @@ -1710,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; @@ -1719,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; @@ -1730,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; @@ -1740,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; @@ -1749,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; @@ -1758,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; @@ -1769,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; @@ -1781,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; @@ -1791,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; @@ -1912,13 +1912,13 @@ lysp_add_internal_ietf_netconf(struct lysp_ctx *pctx, struct lysp_module *mod) /* 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; @@ -1944,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; @@ -1954,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; @@ -1974,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; @@ -2002,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; @@ -2021,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; @@ -2062,7 +2062,7 @@ lys_compile_submodules(struct lys_module *mod) 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 = lydict_insert(mod->ctx, submodp->revs[0].date, 0, &submod->revision), cleanup); + 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); } @@ -2113,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 */ diff --git a/src/tree_schema_common.c b/src/tree_schema_common.c index ca8a7f5c1..e80ddc37d 100644 --- a/src/tree_schema_common.c +++ b/src/tree_schema_common.c @@ -2388,7 +2388,7 @@ lysp_ext_instance_resolve_argument(const struct ly_ctx *ctx, const struct lysp_e } 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; } } diff --git a/src/tree_schema_free.c b/src/tree_schema_free.c index e4c26343d..e0a239832 100644 --- a/src/tree_schema_free.c +++ b/src/tree_schema_free.c @@ -40,7 +40,7 @@ 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); } } @@ -55,8 +55,8 @@ 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) { @@ -72,8 +72,8 @@ 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, ext->name); - lydict_remove(ctx, ext->argument); + lysdict_remove(ctx, ext->name); + lysdict_remove(ctx, ext->argument); ly_free_prefix_data(ext->format, ext->prefix_data); if (ext->plugin_ref && (ext_plg = LYSC_GET_EXT_PLG(ext->plugin_ref))->pfree) { ext_plg->pfree(ctx, ext); @@ -96,10 +96,10 @@ static void 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, import->name); - lydict_remove(ctx, import->prefix); - lydict_remove(ctx, import->dsc); - lydict_remove(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); } @@ -121,9 +121,9 @@ lysp_include_free_(const struct ly_ctx *ctx, struct lysp_include *include, ly_bo if (main_module && include->submodule) { lysp_module_free(ctx, (struct lysp_module *)include->submodule); } - lydict_remove(ctx, include->name); - lydict_remove(ctx, include->dsc); - lydict_remove(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); } @@ -160,8 +160,8 @@ lysp_include_free(const struct ly_ctx *ctx, struct lysp_include *include) static void lysp_revision_free(const struct ly_ctx *ctx, struct lysp_revision *rev) { - lydict_remove(ctx, rev->dsc); - lydict_remove(ctx, rev->ref); + lysdict_remove(ctx, rev->dsc); + lysdict_remove(ctx, rev->ref); FREE_ARRAY(ctx, rev->exts, lysp_ext_instance_free); } @@ -174,10 +174,10 @@ lysp_revision_free(const struct ly_ctx *ctx, struct lysp_revision *rev) static void lysp_ext_free(const struct ly_ctx *ctx, struct lysp_ext *ext) { - lydict_remove(ctx, ext->name); - lydict_remove(ctx, ext->argname); - lydict_remove(ctx, ext->dsc); - lydict_remove(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); } @@ -190,12 +190,12 @@ lysp_ext_free(const struct ly_ctx *ctx, struct lysp_ext *ext) static void lysp_feature_free(const struct ly_ctx *ctx, struct lysp_feature *feat) { - lydict_remove(ctx, feat->name); + 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, feat->dsc); - lydict_remove(ctx, feat->ref); + lysdict_remove(ctx, feat->dsc); + lysdict_remove(ctx, feat->ref); FREE_ARRAY(ctx, feat->exts, lysp_ext_instance_free); } @@ -208,22 +208,22 @@ lysp_feature_free(const struct ly_ctx *ctx, struct lysp_feature *feat) static void lysp_ident_free(const struct ly_ctx *ctx, struct lysp_ident *ident) { - lydict_remove(ctx, ident->name); + lysdict_remove(ctx, ident->name); FREE_ARRAY(ctx, ident->iffeatures, lysp_qname_free); FREE_STRINGS(ctx, ident->bases); - lydict_remove(ctx, ident->dsc); - lydict_remove(ctx, ident->ref); + lysdict_remove(ctx, ident->dsc); + lysdict_remove(ctx, ident->ref); FREE_ARRAY(ctx, ident->exts, lysp_ext_instance_free); } void lysp_restr_free(const struct ly_ctx *ctx, struct lysp_restr *restr) { - lydict_remove(ctx, restr->arg.str); - lydict_remove(ctx, restr->emsg); - lydict_remove(ctx, restr->eapptag); - lydict_remove(ctx, restr->dsc); - lydict_remove(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); } @@ -236,9 +236,9 @@ lysp_restr_free(const struct ly_ctx *ctx, struct lysp_restr *restr) static void lysp_type_enum_free(const struct ly_ctx *ctx, struct lysp_type_enum *item) { - lydict_remove(ctx, item->name); - lydict_remove(ctx, item->dsc); - lydict_remove(ctx, item->ref); + 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); } @@ -250,7 +250,7 @@ lysp_type_free(const struct ly_ctx *ctx, struct lysp_type *type) return; } - lydict_remove(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); @@ -274,11 +274,11 @@ lysp_type_free(const struct ly_ctx *ctx, struct lysp_type *type) static void lysp_tpdf_free(const struct ly_ctx *ctx, struct lysp_tpdf *tpdf) { - lydict_remove(ctx, tpdf->name); - lydict_remove(ctx, tpdf->units); - lydict_remove(ctx, tpdf->dflt.str); - lydict_remove(ctx, tpdf->dsc); - lydict_remove(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); @@ -314,9 +314,9 @@ lysp_grp_free(const struct ly_ctx *ctx, struct lysp_node_grp *grp) void lysp_when_free(const struct ly_ctx *ctx, struct lysp_when *when) { - lydict_remove(ctx, when->cond); - lydict_remove(ctx, when->dsc); - lydict_remove(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); } @@ -359,14 +359,14 @@ lysp_deviate_free(const struct ly_ctx *ctx, struct lysp_deviate *d) break; case LYS_DEV_ADD: case LYS_DEV_DELETE: /* compatible for dynamically allocated data */ - lydict_remove(ctx, add->units); + lysdict_remove(ctx, add->units); FREE_ARRAY(ctx, add->musts, lysp_restr_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, rpl->units); + lysdict_remove(ctx, rpl->units); lysp_qname_free(ctx, &rpl->dflt); break; default: @@ -380,9 +380,9 @@ lysp_deviation_free(const struct ly_ctx *ctx, struct lysp_deviation *dev) { struct lysp_deviate *next, *iter; - lydict_remove(ctx, dev->nodeid); - lydict_remove(ctx, dev->dsc); - lydict_remove(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); @@ -399,12 +399,12 @@ lysp_deviation_free(const struct ly_ctx *ctx, struct lysp_deviation *dev) static void lysp_refine_free(const struct ly_ctx *ctx, struct lysp_refine *ref) { - lydict_remove(ctx, ref->nodeid); - lydict_remove(ctx, ref->dsc); - lydict_remove(ctx, ref->ref); + 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, ref->presence); + lysdict_remove(ctx, ref->presence); FREE_ARRAY(ctx, ref->dflts, lysp_qname_free); FREE_ARRAY(ctx, ref->exts, lysp_ext_instance_free); } @@ -426,9 +426,9 @@ lysp_node_free(const struct ly_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, node->name); - lydict_remove(ctx, node->dsc); - lydict_remove(ctx, node->ref); + 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); @@ -439,7 +439,7 @@ lysp_node_free(const struct ly_ctx *ctx, struct lysp_node *node) case LYS_CONTAINER: cont = (struct lysp_node_container *)node; - lydict_remove(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) { @@ -464,20 +464,20 @@ lysp_node_free(const struct ly_ctx *ctx, struct lysp_node *node) leaf = (struct lysp_node_leaf *)node; lysp_type_free(ctx, &leaf->type); - lydict_remove(ctx, leaf->units); - lydict_remove(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, llist->units); + 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, 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) { @@ -505,7 +505,7 @@ lysp_node_free(const struct ly_ctx *ctx, struct lysp_node *node) LY_LIST_FOR_SAFE(choice->child, next, child) { lysp_node_free(ctx, child); } - lydict_remove(ctx, choice->dflt.str); + lysdict_remove(ctx, choice->dflt.str); break; case LYS_CASE: cas = (struct lysp_node_case *)node; @@ -626,13 +626,13 @@ lysp_module_free(const struct ly_ctx *ctx, struct lysp_module *module) if (module->is_submod) { struct lysp_submodule *submod = (struct lysp_submodule *)module; - lydict_remove(ctx, submod->name); - lydict_remove(ctx, submod->filepath); - lydict_remove(ctx, submod->prefix); - lydict_remove(ctx, submod->org); - lydict_remove(ctx, submod->contact); - lydict_remove(ctx, submod->dsc); - lydict_remove(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); @@ -646,7 +646,7 @@ lysc_ext_instance_free(const struct ly_ctx *ctx, struct lysc_ext_instance *ext) 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, ext->argument); + lysdict_remove(ctx, ext->argument); FREE_ARRAY(ctx, ext->exts, lysc_ext_instance_free); } @@ -672,8 +672,8 @@ lysc_when_free(const struct ly_ctx *ctx, struct lysc_when **w) lyxp_expr_free(ctx, (*w)->cond); ly_free_prefix_data(LY_VALUE_SCHEMA_RESOLVED, (*w)->prefixes); - lydict_remove(ctx, (*w)->dsc); - lydict_remove(ctx, (*w)->ref); + lysdict_remove(ctx, (*w)->dsc); + lysdict_remove(ctx, (*w)->ref); FREE_ARRAY(ctx, (*w)->exts, lysc_ext_instance_free); free(*w); } @@ -694,10 +694,10 @@ lysc_must_free(const struct ly_ctx *ctx, struct lysc_must *must) lyxp_expr_free(ctx, must->cond); ly_free_prefix_data(LY_VALUE_SCHEMA_RESOLVED, must->prefixes); - lydict_remove(ctx, must->emsg); - lydict_remove(ctx, must->eapptag); - lydict_remove(ctx, must->dsc); - lydict_remove(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); } @@ -801,9 +801,9 @@ lysc_ident_derived_unlink(const struct lysc_ident *ident) static void lysc_ident_free(const struct ly_ctx *ctx, struct lysc_ident *ident) { - lydict_remove(ctx, ident->name); - lydict_remove(ctx, ident->dsc); - lydict_remove(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); } @@ -812,10 +812,10 @@ static void lysc_range_free(const struct ly_ctx *ctx, struct lysc_range *range) { LY_ARRAY_FREE(range->parts); - lydict_remove(ctx, range->eapptag); - lydict_remove(ctx, range->emsg); - lydict_remove(ctx, range->dsc); - lydict_remove(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); } @@ -826,11 +826,11 @@ lysc_pattern_free(const struct ly_ctx *ctx, struct lysc_pattern **pattern) return; } pcre2_code_free((*pattern)->code); - lydict_remove(ctx, (*pattern)->expr); - lydict_remove(ctx, (*pattern)->eapptag); - lydict_remove(ctx, (*pattern)->emsg); - lydict_remove(ctx, (*pattern)->dsc); - lydict_remove(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); } @@ -838,9 +838,9 @@ lysc_pattern_free(const struct ly_ctx *ctx, struct lysc_pattern **pattern) void lysc_enum_item_free(const struct ly_ctx *ctx, struct lysc_type_bitenum_item *item) { - lydict_remove(ctx, item->name); - lydict_remove(ctx, item->dsc); - lydict_remove(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); } @@ -910,7 +910,7 @@ lysc_type_free(const struct ly_ctx *ctx, struct lysc_type *type) break; } - lydict_remove(ctx, type->name); + lysdict_remove(ctx, type->name); FREE_ARRAY(ctx, type->exts, lysc_ext_instance_free); free(type); } @@ -992,7 +992,7 @@ lysc_node_container_free(const struct ly_ctx *ctx, struct lysc_node_container *n void lysc_value_free(const struct ly_ctx *ctx, struct lysc_value *val) { - lydict_remove(ctx, val->str); + lysdict_remove(ctx, val->str); ly_free_prefix_data(LY_VALUE_SCHEMA_RESOLVED, val->prefixes); } @@ -1011,7 +1011,7 @@ lysc_node_leaf_free(const struct ly_ctx *ctx, struct lysc_node_leaf *node) if (node->type) { lysc_type_free(ctx, node->type); } - lydict_remove(ctx, node->units); + lysdict_remove(ctx, node->units); lysc_value_free(ctx, &node->dflt); } @@ -1030,7 +1030,7 @@ lysc_node_leaflist_free(const struct ly_ctx *ctx, struct lysc_node_leaflist *nod if (node->type) { lysc_type_free(ctx, node->type); } - lydict_remove(ctx, node->units); + lysdict_remove(ctx, node->units); FREE_ARRAY(ctx, node->dflts, lysc_value_free); } @@ -1129,9 +1129,9 @@ lysc_node_free_(const struct ly_ctx *ctx, struct lysc_node *node) ly_bool inout = 0; /* common part */ - lydict_remove(ctx, node->name); - lydict_remove(ctx, node->dsc); - lydict_remove(ctx, node->ref); + lysdict_remove(ctx, node->name); + lysdict_remove(ctx, node->dsc); + lysdict_remove(ctx, node->ref); /* nodetype-specific part */ switch (node->nodetype) { @@ -1283,9 +1283,9 @@ lysc_module_free(const struct ly_ctx *ctx, struct lysc_module *module) static void lysc_submodule_free(const struct ly_ctx *ctx, struct lysc_submodule *submodule) { - lydict_remove(ctx, submodule->name); - lydict_remove(ctx, submodule->revision); - lydict_remove(ctx, submodule->filepath); + lysdict_remove(ctx, submodule->name); + lysdict_remove(ctx, submodule->revision); + lysdict_remove(ctx, submodule->filepath); } /** @@ -1297,8 +1297,8 @@ lysc_submodule_free(const struct ly_ctx *ctx, struct lysc_submodule *submodule) static void lysc_extension_free(const struct ly_ctx *ctx, struct lysc_ext *ext) { - lydict_remove(ctx, ext->name); - lydict_remove(ctx, ext->argname); + lysdict_remove(ctx, ext->name); + lysdict_remove(ctx, ext->argname); FREE_ARRAY(ctx, ext->exts, lysc_ext_instance_free); } @@ -1334,15 +1334,15 @@ lys_module_free(const struct ly_ctx *ctx, struct lys_module *module, ly_bool rem LY_ARRAY_FREE(module->augmented_by); LY_ARRAY_FREE(module->deviated_by); - lydict_remove(ctx, module->name); - lydict_remove(ctx, module->revision); - lydict_remove(ctx, module->ns); - lydict_remove(ctx, module->prefix); - lydict_remove(ctx, module->filepath); - lydict_remove(ctx, module->org); - lydict_remove(ctx, module->contact); - lydict_remove(ctx, module->dsc); - lydict_remove(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); } @@ -1389,7 +1389,7 @@ 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: @@ -1479,7 +1479,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: @@ -1600,7 +1600,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: diff --git a/src/tree_schema_free.h b/src/tree_schema_free.h index 2fffe50a5..bd300841c 100644 --- a/src/tree_schema_free.h +++ b/src/tree_schema_free.h @@ -37,7 +37,7 @@ struct lysp_yin_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. diff --git a/tests/utests/schema/test_schema.c b/tests/utests/schema/test_schema.c index 3476b6eaf..ebb68ff09 100644 --- a/tests/utests/schema/test_schema.c +++ b/tests/utests/schema/test_schema.c @@ -1719,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; @@ -1728,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; @@ -1741,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; @@ -1753,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(); } @@ -2126,7 +2126,7 @@ test_compiled_print(void **state) int size, fd; void *mem, *mem_end; struct lyd_node *tree = NULL; - struct ly_ctx *printed_ctx = NULL; + struct ly_ctx *printed_ctx = NULL, *printed_ctx2; struct lys_module *mod = NULL; const char *yang, *xml; struct lysc_ext_instance *ext; @@ -2197,8 +2197,8 @@ test_compiled_print(void **state) "}}"; UTEST_ADD_MODULE(yang, LYS_IN_YANG, NULL, NULL); - /* get the structure extension */ - assert_non_null(ext = &mod->compiled->exts[0]); + /* 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); @@ -2217,6 +2217,14 @@ test_compiled_print(void **state) /* create a new printed ctx from this address */ assert_int_equal(LY_SUCCESS, ly_ctx_new_printed(mem, &printed_ctx)); + /* try to create a new printed ctx from the same address, which is not allowed */ + assert_int_equal(LY_EEXIST, ly_ctx_new_printed(mem, &printed_ctx2)); + CHECK_LOG_LASTMSG("Printed context was already created on the provided address."); + + /* 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" diff --git a/tests/utests/schema/test_yang.c b/tests/utests/schema/test_yang.c index 8657c2939..75f89a54e 100644 --- a/tests/utests/schema/test_yang.c +++ b/tests/utests/schema/test_yang.c @@ -740,7 +740,7 @@ submod_renew(struct lysp_yang_ctx *ctx) 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; diff --git a/tests/utests/schema/test_yin.c b/tests/utests/schema/test_yin.c index 775dd74aa..654b91e85 100644 --- a/tests/utests/schema/test_yin.c +++ b/tests/utests/schema/test_yin.c @@ -330,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 */ @@ -350,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 */ @@ -1392,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 @@ -1401,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); @@ -1552,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 @@ -1672,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 @@ -1759,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; } @@ -1773,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; } @@ -1786,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 @@ -2209,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); @@ -2225,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); @@ -3172,7 +3172,7 @@ submod_renew(struct lysp_yin_ctx *ctx, const char *belongs_to) 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; @@ -3425,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" " Date: Fri, 21 Feb 2025 15:38:26 +0100 Subject: [PATCH 53/99] printer context BUGFIX add ext stmt to addr_ht --- src/printer_context.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/printer_context.c b/src/printer_context.c index 25bffe948..f47e7131b 100644 --- a/src/printer_context.c +++ b/src/printer_context.c @@ -1782,7 +1782,6 @@ ly_ctx_compiled_ext_stmts_storage_print(const struct lysc_ext_substmt *orig_subs { LY_ERR rc = LY_SUCCESS; LY_ARRAY_COUNT_TYPE u, v; - uint32_t hash; const struct lysc_node *node; LY_ARRAY_FOR(orig_substmts, u) { @@ -1811,8 +1810,7 @@ ly_ctx_compiled_ext_stmts_storage_print(const struct lysc_ext_substmt *orig_subs node = *(const struct lysc_node **)orig_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) { + if (ly_ctx_compiled_addr_ht_get(addr_ht, node, 1)) { break; } From d2d6d336e67091d854b9c7a1ada79fde9b84c69c Mon Sep 17 00:00:00 2001 From: roman Date: Fri, 21 Feb 2025 15:39:07 +0100 Subject: [PATCH 54/99] printer context BUGFIX use correct ht val eq cb --- src/printer_context.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/printer_context.c b/src/printer_context.c index f47e7131b..7454126ba 100644 --- a/src/printer_context.c +++ b/src/printer_context.c @@ -751,7 +751,7 @@ ctxp_dict_ht(const struct ly_ht *orig_ht, struct ly_ht *ht, struct ly_ht *addr_h /* hash table, must not be modified in the context */ *ht = *orig_ht; - ht->val_equal = NULL; + ht->val_equal = orig_ht->val_equal; ht->cb_data = NULL; /* hlists */ From 2e66f3adce30958f4bb22a3dacc7c42ff9838fd9 Mon Sep 17 00:00:00 2001 From: roman Date: Fri, 21 Feb 2025 15:40:00 +0100 Subject: [PATCH 55/99] xpath UPDATE use separate schema and data dicts --- src/xpath.c | 126 ++++++++++++++++++++++++++-------------------------- 1 file changed, 64 insertions(+), 62 deletions(-) diff --git a/src/xpath.c b/src/xpath.c index 5d2babea0..14ed50ee2 100644 --- a/src/xpath.c +++ b/src/xpath.c @@ -53,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: @@ -2802,7 +2802,7 @@ lyxp_expr_free(const struct ly_ctx *ctx, struct lyxp_expr *expr) return; } - lydict_remove(ctx, expr->expr); + lysdict_remove(ctx, expr->expr); free(expr->tokens); free(expr->tok_pos); free(expr->tok_len); @@ -2915,7 +2915,7 @@ 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); + LY_CHECK_GOTO(ret = lysdict_insert(ctx, expr_str, expr_len, &expr->expr), error); expr->used = 0; expr->size = LYXP_EXPR_SIZE_START; expr->tokens = malloc(expr->size * sizeof *expr->tokens); @@ -3301,7 +3301,7 @@ 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); + LY_CHECK_GOTO(ret = lysdict_insert(ctx, expr_start, expr_len, &dup->expr), cleanup); cleanup: if (ret) { @@ -5599,7 +5599,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) { @@ -5608,7 +5608,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); } /** @@ -5763,7 +5763,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, @@ -5771,10 +5772,9 @@ 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; - ly_bool same_dict = 0; if ((node_type == LYXP_NODE_ROOT_CONFIG) || (node_type == LYXP_NODE_ROOT)) { assert(node_type == set->root_type); @@ -5813,16 +5813,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)) && !(set->ctx->opts & LY_CTX_INT_IMMUTABLE)) { - same_dict = 1; - } - - if (same_dict && (schema->name != node_name)) { - return LY_ENOT; - } else if (!same_dict && 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 */ @@ -6123,14 +6115,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; @@ -6155,7 +6148,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; @@ -6317,13 +6310,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) { @@ -6369,7 +6363,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; } @@ -6761,14 +6755,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; @@ -6806,7 +6801,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; } @@ -6823,7 +6818,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)) { @@ -6851,12 +6846,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; @@ -6883,7 +6880,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); @@ -6941,13 +6938,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; @@ -6960,7 +6958,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; @@ -7014,12 +7012,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; @@ -7059,13 +7059,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)); } } @@ -7078,12 +7078,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; @@ -7109,7 +7110,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; @@ -7185,12 +7186,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; @@ -7210,7 +7213,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; @@ -7235,7 +7238,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; @@ -8152,7 +8155,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; @@ -8212,22 +8215,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); } @@ -8252,14 +8255,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); @@ -8290,7 +8293,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); @@ -8300,7 +8303,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); } @@ -8322,7 +8325,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); } From 99252c5d9946b713b083fe5525dca83c83b46303 Mon Sep 17 00:00:00 2001 From: roman Date: Thu, 6 Mar 2025 12:28:27 +0100 Subject: [PATCH 56/99] context BUGFIX do not free existing ctx data --- src/context.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/context.c b/src/context.c index f2f3789f1..3b3dbf362 100644 --- a/src/context.c +++ b/src/context.c @@ -1466,7 +1466,10 @@ ly_ctx_new_printed(const void *mem, struct ly_ctx **ctx) cleanup: if (rc) { - ly_ctx_data_del(*ctx); + if (rc != LY_EEXIST) { + /* do not delete ctx data of an existing context */ + ly_ctx_data_del(*ctx); + } *ctx = NULL; } return rc; From 4b3bf5b23e62841fab855f68c28eb36f3a7498c5 Mon Sep 17 00:00:00 2001 From: roman Date: Thu, 6 Mar 2025 12:29:23 +0100 Subject: [PATCH 57/99] plugins UPDATE use correct plugin getter --- src/diff.c | 4 +++- src/validation.c | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/diff.c b/src/diff.c index 37ffbade4..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; diff --git a/src/validation.c b/src/validation.c index 70f3de84c..b0562dc7b 100644 --- a/src/validation.c +++ b/src/validation.c @@ -349,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); } From a7655c13b64f12ce17337bbd6ddb7a1809b1da29 Mon Sep 17 00:00:00 2001 From: roman Date: Thu, 6 Mar 2025 12:29:54 +0100 Subject: [PATCH 58/99] tree schema free UPDATE delete static fn decl --- src/tree_schema_free.c | 7 +++++++ src/tree_schema_free.h | 9 --------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/tree_schema_free.c b/src/tree_schema_free.c index e0a239832..18d4114fe 100644 --- a/src/tree_schema_free.c +++ b/src/tree_schema_free.c @@ -808,6 +808,13 @@ lysc_ident_free(const struct ly_ctx *ctx, struct lysc_ident *ident) FREE_ARRAY(ctx, ident->exts, lysc_ext_instance_free); } +/** + * @brief Free the compiled range structure. + * + * @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. + */ static void lysc_range_free(const struct ly_ctx *ctx, struct lysc_range *range) { diff --git a/src/tree_schema_free.h b/src/tree_schema_free.h index bd300841c..042960dcd 100644 --- a/src/tree_schema_free.h +++ b/src/tree_schema_free.h @@ -129,15 +129,6 @@ void lysc_ext_instance_free(const struct ly_ctx *ctx, struct lysc_ext_instance * */ 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,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); - /** * @brief Free a compiled pattern. * From 9be60f377374143d440d825dba3668c9c2c53c5f Mon Sep 17 00:00:00 2001 From: roman Date: Thu, 6 Mar 2025 12:30:46 +0100 Subject: [PATCH 59/99] test union BUGFIX check correct error messages --- tests/utests/types/union.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/utests/types/union.c b/tests/utests/types/union.c index 2649e0318..d06774421 100644 --- a/tests/utests/types/union.c +++ b/tests/utests/types/union.c @@ -105,8 +105,8 @@ 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" - " ly2 leafref: Invalid type int8 value \"123456789012345678901\".\n" - " ly2 leafref: Invalid type int64 value \"123456789012345678901\".\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", @@ -295,7 +295,8 @@ test_validation(void **state) 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" " ly2 leafref: Invalid leafref value \"one\" - no target instance \"../../a/name\" with the same value.\n" - " ly2 leafref: Invalid type uint32 value \"one\".\n", "/lref:test/community[name='test']/view", 0); + " 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); } From f3e85f64fee38025a739e15a01b3478a2593386e Mon Sep 17 00:00:00 2001 From: roman Date: Thu, 6 Mar 2025 12:31:34 +0100 Subject: [PATCH 60/99] schema compile node UPDATE dont free range schema --- src/schema_compile_node.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/schema_compile_node.c b/src/schema_compile_node.c index 96764144c..fe08476d6 100644 --- a/src/schema_compile_node.c +++ b/src/schema_compile_node.c @@ -388,10 +388,9 @@ lysc_range_dup(struct lysc_ctx *ctx, const struct lysc_range *orig, struct ly_se return dup; error: - if (dup) { - lysc_range_free(&ctx->free_ctx, dup); - free(dup); - } + free(dup); + /* set but not used due to the return type */ + (void) ret; return NULL; } From d8a1f9be412f4be4f8eedea9611ada20d3d1aa33 Mon Sep 17 00:00:00 2001 From: roman Date: Thu, 6 Mar 2025 14:42:59 +0100 Subject: [PATCH 61/99] context UPDATE clarify freeing parsed mods in docs --- src/context.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/context.h b/src/context.h index f57a21ab4..df6acfe53 100644 --- a/src/context.h +++ b/src/context.h @@ -680,6 +680,9 @@ 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. From b07ebec034faf5bc6f302cf42e23a3aecb8afd83 Mon Sep 17 00:00:00 2001 From: roman Date: Thu, 20 Mar 2025 13:52:10 +0100 Subject: [PATCH 62/99] context UPDATE allow multiple contexts from same address --- src/context.c | 8 +------- src/ly_common.c | 13 ++++++++++++- src/ly_common.h | 4 +++- tests/utests/schema/test_schema.c | 12 +++++++++--- 4 files changed, 25 insertions(+), 12 deletions(-) diff --git a/src/context.c b/src/context.c index 3b3dbf362..06befad35 100644 --- a/src/context.c +++ b/src/context.c @@ -1453,9 +1453,6 @@ ly_ctx_new_printed(const void *mem, struct ly_ctx **ctx) /* ctx data */ rc = ly_ctx_data_add(*ctx); if (rc) { - if (rc == LY_EEXIST) { - LOGERR(NULL, LY_EEXIST, "Printed context was already created on the provided address."); - } goto cleanup; } @@ -1466,10 +1463,7 @@ ly_ctx_new_printed(const void *mem, struct ly_ctx **ctx) cleanup: if (rc) { - if (rc != LY_EEXIST) { - /* do not delete ctx data of an existing context */ - ly_ctx_data_del(*ctx); - } + ly_ctx_data_del(*ctx); *ctx = NULL; } return rc; diff --git a/src/ly_common.c b/src/ly_common.c index 70c0726f4..faeb45c3f 100644 --- a/src/ly_common.c +++ b/src/ly_common.c @@ -147,7 +147,7 @@ ly_ctx_data_add(const struct ly_ctx *ctx) /* check for duplicates */ for (i = 0; i < ly_ctx_data_count; i++) { if (ly_ctx_data[i]->ctx == ctx) { - rc = LY_EEXIST; + ++ly_ctx_data[i]->refcount; goto cleanup; } } @@ -179,6 +179,9 @@ ly_ctx_data_add(const struct ly_ctx *ctx) LY_CHECK_ERR_GOTO(!ctx_data->data_dict, rc = LY_EMEM, cleanup); lydict_init(ctx_data->data_dict); + /* refcount */ + ctx_data->refcount = 1; + ++ly_ctx_data_count; cleanup: @@ -212,6 +215,14 @@ ly_ctx_data_del(const struct ly_ctx *ctx) return; } + /* decrease refcount */ + --ctx_data->refcount; + if (ctx_data->refcount) { + /* WR UNLOCK */ + pthread_rwlock_unlock(&ly_ctx_data_rwlock); + return; + } + /* remove the ctx data, replace by the last */ --ly_ctx_data_count; if (ly_ctx_data_count) { diff --git a/src/ly_common.h b/src/ly_common.h index f7dd7804b..050a9f7bc 100644 --- a/src/ly_common.h +++ b/src/ly_common.h @@ -353,6 +353,8 @@ struct ly_ctx_data { struct ly_ht *leafref_links_ht; /**< hash table of leafref links between term data nodes */ struct ly_dict *data_dict; /**< dictionary for data trees */ + + int refcount; /**< reference count for the given context */ }; extern pthread_rwlock_t ly_ctx_data_rwlock; /**< lock for accessing ly_ctx_data */ @@ -394,7 +396,7 @@ void ly_ctx_new_change(struct ly_ctx *ctx); * @brief Add a ctx data for a new context. * * @param[in] ctx Newly created context. - * @return LY_SUCCESS on success, LY_EEXIST if the context data already exists or LY_EMEM on memory allocation failure. + * @return LY_SUCCESS on success or LY_EMEM on memory allocation failure. */ LY_ERR ly_ctx_data_add(const struct ly_ctx *ctx); diff --git a/tests/utests/schema/test_schema.c b/tests/utests/schema/test_schema.c index ebb68ff09..79d87e36f 100644 --- a/tests/utests/schema/test_schema.c +++ b/tests/utests/schema/test_schema.c @@ -2217,9 +2217,8 @@ test_compiled_print(void **state) /* create a new printed ctx from this address */ assert_int_equal(LY_SUCCESS, ly_ctx_new_printed(mem, &printed_ctx)); - /* try to create a new printed ctx from the same address, which is not allowed */ - assert_int_equal(LY_EEXIST, ly_ctx_new_printed(mem, &printed_ctx2)); - CHECK_LOG_LASTMSG("Printed context was already created on the provided address."); + /* create a new printed ctx from the same address */ + assert_int_equal(LY_SUCCESS, ly_ctx_new_printed(mem, &printed_ctx2)); /* get the structure extension from the printed context */ mod = ly_ctx_get_module_implemented(printed_ctx, "m3"); @@ -2254,6 +2253,12 @@ test_compiled_print(void **state) CHECK_LYD_STRING_PARAM(tree, xml, LYD_XML, 0); lyd_free_all(tree); + /* now try it with the second printed context from the same address */ + assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(printed_ctx2, 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" @@ -2268,6 +2273,7 @@ test_compiled_print(void **state) /* cleanup */ ly_ctx_destroy(printed_ctx); + ly_ctx_destroy(printed_ctx2); munmap(mem, size); close(fd); shm_unlink("/ly_test_schema_ctx"); From 3101d8b5d6bcba14dc5cc7e99e09a442785e3f26 Mon Sep 17 00:00:00 2001 From: roman Date: Thu, 20 Mar 2025 13:54:45 +0100 Subject: [PATCH 63/99] identityref BUGFIX check for parsed explicitely --- src/plugins_types/identityref.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins_types/identityref.c b/src/plugins_types/identityref.c index b1f867d12..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); From e31ab69bc1a583b28100a6b2ddbc39319eaf89c8 Mon Sep 17 00:00:00 2001 From: roman Date: Thu, 20 Mar 2025 13:55:37 +0100 Subject: [PATCH 64/99] printer context BUGFIX choice default value --- src/printer_context.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/printer_context.c b/src/printer_context.c index 7454126ba..300e64b61 100644 --- a/src/printer_context.c +++ b/src/printer_context.c @@ -1398,6 +1398,10 @@ ctxp_node(const struct lysc_node *orig_node, struct lysc_node *node, struct ly_h 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; From 543820c771fc5d2ac6934eeab46ad0bf551d779f Mon Sep 17 00:00:00 2001 From: roman Date: Thu, 20 Mar 2025 13:58:52 +0100 Subject: [PATCH 65/99] xpath UPDATE dont store expr in dict Storing expr in dict cause issues when using printed context and data/schema dicts being separated. --- src/xpath.c | 8 +++++--- src/xpath.h | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/xpath.c b/src/xpath.c index 14ed50ee2..e748aa699 100644 --- a/src/xpath.c +++ b/src/xpath.c @@ -2802,7 +2802,7 @@ lyxp_expr_free(const struct ly_ctx *ctx, struct lyxp_expr *expr) return; } - lysdict_remove(ctx, expr->expr); + free(expr->expr); free(expr->tokens); free(expr->tok_pos); free(expr->tok_len); @@ -2915,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 = lysdict_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); @@ -3301,7 +3302,8 @@ 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 = lysdict_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) { diff --git a/src/xpath.h b/src/xpath.h index e5c30086d..3829cc952 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. */ }; /* From 1246b5d2f099e42eab421e486e3804d86444ea59 Mon Sep 17 00:00:00 2001 From: roman Date: Thu, 20 Mar 2025 14:01:33 +0100 Subject: [PATCH 66/99] xpath UPDATE remove ctx arg from lyxp_expr_free --- src/path.c | 6 +++--- src/plugins_types.c | 4 ++-- src/plugins_types/node_instanceid.c | 2 +- src/plugins_types/xpath1.0.c | 2 +- src/schema_compile_amend.c | 4 ++-- src/tree_data.c | 6 +++--- src/tree_data_new.c | 4 ++-- src/tree_schema.c | 8 ++++---- src/tree_schema_free.c | 10 +++++----- src/xpath.c | 12 ++++++------ src/xpath.h | 3 +-- tests/utests/data/test_tree_data.c | 2 +- tests/utests/schema/test_tree_schema_compile.c | 2 +- 13 files changed, 32 insertions(+), 33 deletions(-) diff --git a/src/path.c b/src/path.c index 68c886977..2a956f1b4 100644 --- a/src/path.c +++ b/src/path.c @@ -316,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; } @@ -458,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; } @@ -502,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; } diff --git a/src/plugins_types.c b/src/plugins_types.c index ace812d81..9f78a3c90 100644 --- a/src/plugins_types.c +++ b/src/plugins_types.c @@ -871,7 +871,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); @@ -1151,7 +1151,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/node_instanceid.c b/src/plugins_types/node_instanceid.c index e7e720751..67dcdda71 100644 --- a/src/plugins_types/node_instanceid.c +++ b/src/plugins_types/node_instanceid.c @@ -252,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); } diff --git a/src/plugins_types/xpath1.0.c b/src/plugins_types/xpath1.0.c index 4d77f95ae..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); diff --git a/src/schema_compile_amend.c b/src/schema_compile_amend.c index 571f7eb9b..3a923ba6b 100644 --- a/src/schema_compile_amend.c +++ b/src/schema_compile_amend.c @@ -141,7 +141,7 @@ lys_precompile_nodeid(const struct ly_ctx *ctx, const char *str, struct lysc_nod } cleanup: - lyxp_expr_free(ctx, exp); + lyxp_expr_free(exp); if (rc) { lysc_nodeid_free(ctx, *nodeid); *nodeid = NULL; @@ -280,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; } diff --git a/src/tree_data.c b/src/tree_data.c index f49026bd2..77c55ef27 100644 --- a/src/tree_data.c +++ b/src/tree_data.c @@ -3555,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; } @@ -3686,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; @@ -3715,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; } diff --git a/src/tree_data_new.c b/src/tree_data_new.c index f45df542d..d8266a8f5 100644 --- a/src/tree_data_new.c +++ b/src/tree_data_new.c @@ -183,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; } @@ -1858,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); diff --git a/src/tree_schema.c b/src/tree_schema.c index 2f34854d2..75d0bee71 100644 --- a/src/tree_schema.c +++ b/src/tree_schema.c @@ -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; } diff --git a/src/tree_schema_free.c b/src/tree_schema_free.c index 18d4114fe..13665c66f 100644 --- a/src/tree_schema_free.c +++ b/src/tree_schema_free.c @@ -256,7 +256,7 @@ lysp_type_free(const struct ly_ctx *ctx, struct lysp_type *type) 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, type->path); + 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); @@ -670,7 +670,7 @@ lysc_when_free(const struct ly_ctx *ctx, struct lysc_when **w) return; } - lyxp_expr_free(ctx, (*w)->cond); + lyxp_expr_free((*w)->cond); ly_free_prefix_data(LY_VALUE_SCHEMA_RESOLVED, (*w)->prefixes); lysdict_remove(ctx, (*w)->dsc); lysdict_remove(ctx, (*w)->ref); @@ -692,7 +692,7 @@ lysc_must_free(const struct ly_ctx *ctx, struct lysc_must *must) return; } - lyxp_expr_free(ctx, must->cond); + lyxp_expr_free(must->cond); ly_free_prefix_data(LY_VALUE_SCHEMA_RESOLVED, must->prefixes); lysdict_remove(ctx, must->emsg); lysdict_remove(ctx, must->eapptag); @@ -905,7 +905,7 @@ lysc_type_free(const struct ly_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, ((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; @@ -1504,7 +1504,7 @@ lyplg_ext_pfree_instance_substatements(const struct ly_ctx *ctx, struct lysp_ext 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: diff --git a/src/xpath.c b/src/xpath.c index e748aa699..922d2cad0 100644 --- a/src/xpath.c +++ b/src/xpath.c @@ -2794,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; @@ -3228,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; } @@ -3307,7 +3307,7 @@ lyxp_expr_dup(const struct ly_ctx *ctx, const struct lyxp_expr *exp, uint32_t st cleanup: if (ret) { - lyxp_expr_free(ctx, dup); + lyxp_expr_free(dup); } else { *dup_p = dup; } @@ -7822,7 +7822,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; } @@ -7988,7 +7988,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; } @@ -8915,7 +8915,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 3829cc952..7a2a029ec 100644 --- a/src/xpath.h +++ b/src/xpath.h @@ -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/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/schema/test_tree_schema_compile.c b/tests/utests/schema/test_tree_schema_compile.c index b57a65334..96d88cb93 100644 --- a/tests/utests/schema/test_tree_schema_compile.c +++ b/tests/utests/schema/test_tree_schema_compile.c @@ -1727,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;" From f4fe4cae6eda0b03c4b436cd2620b2622d755182 Mon Sep 17 00:00:00 2001 From: roman Date: Thu, 20 Mar 2025 14:03:05 +0100 Subject: [PATCH 67/99] printer context UPDATE expr not in dict --- src/printer_context.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/printer_context.c b/src/printer_context.c index 300e64b61..bb47c3159 100644 --- a/src/printer_context.c +++ b/src/printer_context.c @@ -152,6 +152,7 @@ ctxs_expr(const struct lyxp_expr *exp, int *size) *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; @@ -830,10 +831,14 @@ ctxp_ext(const struct lysc_ext_instance *orig_ext, struct lysc_ext_instance *ext } static void -ctxp_expr(const struct lyxp_expr *orig_exp, struct lyxp_expr *exp, struct ly_ht *addr_ht, void **mem) +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); @@ -863,7 +868,6 @@ ctxp_expr(const struct lyxp_expr *orig_exp, struct lyxp_expr *exp, struct ly_ht exp->used = orig_exp->used; exp->size = orig_exp->used; - exp->expr = ly_ctx_compiled_addr_ht_get(addr_ht, orig_exp->expr, 0); } static void @@ -899,7 +903,7 @@ ctxp_must(const struct lysc_must *orig_must, struct lysc_must *must, struct ly_h must->cond = *mem; *mem = (char *)*mem + sizeof *must->cond; - ctxp_expr(orig_must->cond, must->cond, addr_ht, mem); + ctxp_expr(orig_must->cond, must->cond, mem); CTXP_SIZED_ARRAY(orig_must->prefixes, must->prefixes, mem); LY_ARRAY_FOR(orig_must->prefixes, u) { @@ -941,7 +945,7 @@ ctxp_when(const struct lysc_when *orig_when, struct lysc_when **when, struct ly_ w->cond = *mem; *mem = (char *)*mem + sizeof *w->cond; - ctxp_expr(orig_when->cond, w->cond, addr_ht, mem); + 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); @@ -1247,7 +1251,7 @@ ctxp_type(const struct lysc_type *orig_type, struct lysc_type **type, struct ly_ t_lref->path = *mem; *mem = (char *)*mem + sizeof *t_lref->path; - ctxp_expr(orig_type_lref->path, t_lref->path, addr_ht, mem); + 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) { From 1314736a530c354f74ac098ca02c1cf4233c9ab5 Mon Sep 17 00:00:00 2001 From: roman Date: Thu, 20 Mar 2025 15:11:59 +0100 Subject: [PATCH 68/99] lyb UPDATE check ctx_set_opt return value --- src/parser_lyb.c | 4 ++-- src/printer_lyb.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/parser_lyb.c b/src/parser_lyb.c index 37bec5632..ceff905a4 100644 --- a/src/parser_lyb.c +++ b/src/parser_lyb.c @@ -822,7 +822,7 @@ lyb_parse_schema_nested_ext(struct lyd_lyb_ctx *lybctx, const struct lyd_node *p if (!((*snode)->module->ctx->opts & LY_CTX_LYB_HASHES)) { /* generate LYB hashes */ - ly_ctx_set_options((*snode)->module->ctx, LY_CTX_LYB_HASHES); + LY_CHECK_GOTO(rc = ly_ctx_set_options((*snode)->module->ctx, LY_CTX_LYB_HASHES), cleanup); } cleanup: @@ -1612,7 +1612,7 @@ lyd_parse_lyb(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, str if (!(ctx->opts & LY_CTX_LYB_HASHES)) { /* generate LYB hashes */ - ly_ctx_set_options((struct ly_ctx *)ctx, LY_CTX_LYB_HASHES); + LY_CHECK_GOTO(rc = ly_ctx_set_options((struct ly_ctx *)ctx, LY_CTX_LYB_HASHES), cleanup); } if (subtree_sibling) { diff --git a/src/printer_lyb.c b/src/printer_lyb.c index 5310456c1..b5c29081f 100644 --- a/src/printer_lyb.c +++ b/src/printer_lyb.c @@ -1168,7 +1168,7 @@ 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_ctx_set_options((struct ly_ctx *)LYD_CTX(node), 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 */ @@ -1259,7 +1259,7 @@ lyb_print_data(struct ly_out *out, const struct lyd_node *root, uint32_t options if (!(ctx->opts & LY_CTX_LYB_HASHES)) { /* generate LYB hashes */ - ly_ctx_set_options((struct ly_ctx *)ctx, LY_CTX_LYB_HASHES); + LY_CHECK_GOTO(ret = ly_ctx_set_options((struct ly_ctx *)ctx, LY_CTX_LYB_HASHES), cleanup); } } From 06e7a459a658b1b68a40d2ccd4c49db443b53257 Mon Sep 17 00:00:00 2001 From: roman Date: Tue, 27 May 2025 10:39:12 +0200 Subject: [PATCH 69/99] printer context BUGFIX action printing --- src/printer_context.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/printer_context.c b/src/printer_context.c index bb47c3159..e50bdf040 100644 --- a/src/printer_context.c +++ b/src/printer_context.c @@ -1537,8 +1537,13 @@ ctxp_node(const struct lysc_node *orig_node, struct lysc_node *node, struct ly_h ctxp_when(orig_act->when[u], &act->when[u], addr_ht, ptr_set, mem); } - /* input children, input is the parent */ + /* 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 */ @@ -1547,8 +1552,13 @@ ctxp_node(const struct lysc_node *orig_node, struct lysc_node *node, struct ly_h ctxp_must(&orig_act->input.musts[u], &act->input.musts[u], addr_ht, ptr_set, mem); } - /* output children, output is the parent */ + /* 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 */ @@ -1576,6 +1586,10 @@ ctxp_node(const struct lysc_node *orig_node, struct lysc_node *node, struct ly_h 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; From 9253d1ca3b90c847b8dc569f5b73c2c3c87e7424 Mon Sep 17 00:00:00 2001 From: roman Date: Tue, 27 May 2025 11:14:07 +0200 Subject: [PATCH 70/99] schema mount BUGFIX shared ctx mem print --- src/plugins_exts/schema_mount.c | 37 ++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/src/plugins_exts/schema_mount.c b/src/plugins_exts/schema_mount.c index 325f8427b..e6ee70ffa 100644 --- a/src/plugins_exts/schema_mount.c +++ b/src/plugins_exts/schema_mount.c @@ -1383,24 +1383,27 @@ schema_mount_compiled_print(const struct lysc_ext_instance *orig_ext, struct lys sm_data->shared->ref_count = orig_sm_data->shared->ref_count; /* sm_data->shared->schemas */ - sm_data->shared->schemas = *mem; - *mem = (char *)*mem + sm_data->shared->schema_count * sizeof *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)); - - /* 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; + 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 */ From 209b360cefb2a7be4ec2c3d18ee9177197fddddc Mon Sep 17 00:00:00 2001 From: roman Date: Tue, 27 May 2025 11:16:09 +0200 Subject: [PATCH 71/99] schema mount BUGFIX no locks when printed context --- src/plugins_exts/schema_mount.c | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/src/plugins_exts/schema_mount.c b/src/plugins_exts/schema_mount.c index e6ee70ffa..45d6642bd 100644 --- a/src/plugins_exts/schema_mount.c +++ b/src/plugins_exts/schema_mount.c @@ -30,6 +30,7 @@ #include "parser_data.h" #include "plugins_exts.h" #include "plugins_types.h" +#include "tree.h" #include "tree_data.h" #include "tree_schema.h" @@ -405,15 +406,21 @@ 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 */ @@ -433,6 +440,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; @@ -461,11 +478,15 @@ schema_mount_get_ctx_shared(struct lysc_ext_instance *ext, const struct lyd_node } /* 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; } From 13d30df0c3e6bbdf0dab8b6835f41a252fe74e0c Mon Sep 17 00:00:00 2001 From: roman Date: Tue, 27 May 2025 11:20:17 +0200 Subject: [PATCH 72/99] schema mount UPDATE add sm contexts manip API Add API for explicit creation/deletion of shared/inline schema mount contexts. --- CMakeLists.txt | 1 + src/libyang.h | 1 + src/plugins_exts/schema_mount.c | 114 ++++++++++++++++++++++++++++++++ src/plugins_exts/schema_mount.h | 68 +++++++++++++++++++ 4 files changed, 184 insertions(+) create mode 100644 src/plugins_exts/schema_mount.h diff --git a/CMakeLists.txt b/CMakeLists.txt index e83200936..ddaa2ad50 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -176,6 +176,7 @@ set(headers src/plugins.h src/plugins_exts.h src/plugins_exts/metadata.h + src/plugins_exts/schema_mount.h src/plugins_types.h src/printer_data.h src/printer_schema.h diff --git a/src/libyang.h b/src/libyang.h index c2095da22..197f29df9 100644 --- a/src/libyang.h +++ b/src/libyang.h @@ -34,6 +34,7 @@ extern "C" { #include "parser_schema.h" #include "printer_data.h" #include "printer_schema.h" +#include "schema_mount.h" #include "set.h" #include "tree.h" #include "tree_data.h" diff --git a/src/plugins_exts/schema_mount.c b/src/plugins_exts/schema_mount.c index 45d6642bd..c9374b7bc 100644 --- a/src/plugins_exts/schema_mount.c +++ b/src/plugins_exts/schema_mount.c @@ -15,6 +15,8 @@ #define _GNU_SOURCE +#include "schema_mount.h" + #include #include #include @@ -491,6 +493,118 @@ schema_mount_get_ctx_shared(struct lysc_ext_instance *ext, const struct lyd_node 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. diff --git a/src/plugins_exts/schema_mount.h b/src/plugins_exts/schema_mount.h new file mode 100644 index 000000000..40b719bd9 --- /dev/null +++ b/src/plugins_exts/schema_mount.h @@ -0,0 +1,68 @@ +/** + * @file schema_mount.h + * @author Roman Janota + * @brief ietf-yang-schema-mount API + * + * Copyright (c) 2025 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 + */ + + #ifndef LY_PLUGINS_EXTS_SCHEMA_MOUNT_H_ + #define LY_PLUGINS_EXTS_SCHEMA_MOUNT_H_ + + #include "context.h" + + #ifdef __cplusplus + extern "C" { + #endif + +/** + * @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. + * + * Inline contexts are 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); + + #ifdef __cplusplus + } + #endif + + #endif /* LY_PLUGINS_EXTS_SCHEMA_MOUNT_H_ */ From ccbd44065e2898b69fd10e5889982eb7098d7192 Mon Sep 17 00:00:00 2001 From: roman Date: Tue, 3 Jun 2025 10:54:37 +0200 Subject: [PATCH 73/99] context BUGFIX add refcount check to destroy --- src/context.c | 9 +++++++++ src/ly_common.c | 13 +++++++++++++ src/ly_common.h | 8 ++++++++ 3 files changed, 30 insertions(+) diff --git a/src/context.c b/src/context.c index 06befad35..32da38217 100644 --- a/src/context.c +++ b/src/context.c @@ -1492,6 +1492,15 @@ ly_ctx_destroy(struct ly_ctx *ctx) return; } + /* check if this is the last instance of the context */ + if (ly_ctx_data_refcount_get(ctx) > 1) { + /* not the last instance, just decrease the ctx and plg reference counts, + * since other instances might still be using parsed, compiled, and other 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) { diff --git a/src/ly_common.c b/src/ly_common.c index faeb45c3f..be734e76d 100644 --- a/src/ly_common.c +++ b/src/ly_common.c @@ -121,6 +121,19 @@ ly_ctx_data_get(const struct ly_ctx *ctx) return ctx_data; } +int +ly_ctx_data_refcount_get(const struct ly_ctx *ctx) +{ + struct ly_ctx_data *ctx_data; + + ctx_data = ly_ctx_data_get(ctx); + if (!ctx_data) { + return -1; + } + + return ctx_data->refcount; +} + struct ly_dict * ly_ctx_data_dict_get(const struct ly_ctx *ctx) { diff --git a/src/ly_common.h b/src/ly_common.h index 050a9f7bc..1e411b261 100644 --- a/src/ly_common.h +++ b/src/ly_common.h @@ -415,6 +415,14 @@ void ly_ctx_data_del(const struct ly_ctx *ctx); */ struct ly_ctx_data *ly_ctx_data_get(const struct ly_ctx *ctx); +/** + * @brief Get context's data reference count. + * + * @param[in] ctx Context whose data reference count to get. + * @return Reference count of the context's data, -1 if the context data was not found. + */ +int ly_ctx_data_refcount_get(const struct ly_ctx *ctx); + /** * @brief Get context's data dictionary. * From 571b3f688d44684b96672491f48e5ca1ae411e98 Mon Sep 17 00:00:00 2001 From: roman Date: Tue, 3 Jun 2025 10:55:00 +0200 Subject: [PATCH 74/99] test context UPDATE add refcount test --- tests/utests/basic/test_context.c | 54 +++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/tests/utests/basic/test_context.c b/tests/utests/basic/test_context.c index d4f68d133..0acb2605f 100644 --- a/tests/utests/basic/test_context.c +++ b/tests/utests/basic/test_context.c @@ -1111,6 +1111,59 @@ test_free_parsed(void **state) UTEST_LYCTX = NULL; } +static void +test_refcount(void **state) +{ + ly_bool builtin_plugins_only, static_plugins_only; + uint32_t options; + struct lyd_node *tree = NULL; + const char *data = "test"; + struct ly_ctx_data *ctx_data; + + (void)state; + + /* load a simple module */ + assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, + "module a {namespace urn:a;prefix a;container c { leaf l {type string;}}}", LYS_IN_YANG, NULL)); + + /* try parsing the module's data */ + CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); + lyd_free_all(tree); + + /* get the ctx data */ + ctx_data = ly_ctx_data_get(UTEST_LYCTX); + assert_non_null(ctx_data); + + /* check that the refcount is 1 */ + assert_int_equal(ctx_data->refcount, 1); + + /* mock the creation of the same context */ + assert_int_equal(LY_SUCCESS, ly_ctx_data_add(UTEST_LYCTX)); + + /* increase the plugin refcount */ + options = ly_ctx_get_options(UTEST_LYCTX); + builtin_plugins_only = options & LY_CTX_BUILTIN_PLUGINS_ONLY; + static_plugins_only = options & LY_CTX_STATIC_PLUGINS_ONLY; + assert_int_equal(LY_SUCCESS, lyplg_init(builtin_plugins_only, static_plugins_only)); + + /* check that the refcount increased */ + assert_int_equal(ctx_data->refcount, 2); + + /* try parsing the module's data again */ + CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); + lyd_free_all(tree); + + /* free the context */ + ly_ctx_destroy(UTEST_LYCTX); + + /* check that the refcount decreased */ + assert_int_equal(ctx_data->refcount, 1); + + /* try parsing the module's data again */ + CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); + lyd_free_all(tree); +} + int main(void) { @@ -1124,6 +1177,7 @@ main(void) UTEST(test_set_priv_parsed), UTEST(test_explicit_compile), UTEST(test_free_parsed), + UTEST(test_refcount), }; return cmocka_run_group_tests(tests, NULL, NULL); From eb8550bbf8eb26574b7c44a710b3325de1cb37c4 Mon Sep 17 00:00:00 2001 From: roman Date: Tue, 3 Jun 2025 10:55:16 +0200 Subject: [PATCH 75/99] ly common UPDATE add assertion --- src/ly_common.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ly_common.c b/src/ly_common.c index be734e76d..ddade475a 100644 --- a/src/ly_common.c +++ b/src/ly_common.c @@ -141,6 +141,8 @@ ly_ctx_data_dict_get(const struct ly_ctx *ctx) ctx_data = ly_ctx_data_get(ctx); if (!ctx_data) { + LOGERR(NULL, LY_EINT, "Context data not found."); + assert(0); return NULL; } From f50b833a8168f2450cac2b10fa6974ab1ffc031a Mon Sep 17 00:00:00 2001 From: roman Date: Tue, 3 Jun 2025 10:59:15 +0200 Subject: [PATCH 76/99] schema mount UPDATE check for ctx existance --- src/plugins_exts/schema_mount.c | 43 ++++++++++++++++++++++++++++++--- src/plugins_exts/schema_mount.h | 4 +-- 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/src/plugins_exts/schema_mount.c b/src/plugins_exts/schema_mount.c index c9374b7bc..c08160e8f 100644 --- a/src/plugins_exts/schema_mount.c +++ b/src/plugins_exts/schema_mount.c @@ -31,6 +31,7 @@ #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" @@ -530,7 +531,7 @@ lyplg_ext_schema_mount_destroy_shared_contexts(struct lysc_ext_instance *ext) struct lyplg_ext_sm *sm_data; ly_bool ctx_is_printed; - LY_CHECK_ARG_RET(NULL, ext,); + LY_CHECK_ARG_RET(NULL, ext, ); sm_data = ext->compiled; ctx_is_printed = ly_ctx_is_printed(ext->module->ctx); @@ -574,7 +575,7 @@ lyplg_ext_schema_mount_destroy_inline_contexts(struct lysc_ext_instance *ext) struct lyplg_ext_sm *sm_data; uint32_t i; - LY_CHECK_ARG_RET(NULL, ext,); + LY_CHECK_ARG_RET(NULL, ext, ); sm_data = ext->compiled; @@ -1213,8 +1214,14 @@ lyplg_ext_schema_mount_create_context(const struct lysc_ext_instance *ext, const { struct lyd_node *ext_data = NULL; struct ly_ctx_data *ctx_data; - ly_bool ext_data_free = 0, config; + 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_CHECK_ARG_RET(NULL, ext, ctx, LY_EINVAL); + + sm_data = ext->compiled; ctx_data = ly_ctx_data_get(ext->def->module->ctx); if (!ctx_data->ext_clb) { @@ -1231,7 +1238,35 @@ lyplg_ext_schema_mount_create_context(const struct lysc_ext_instance *ext, const } /* 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; } diff --git a/src/plugins_exts/schema_mount.h b/src/plugins_exts/schema_mount.h index 40b719bd9..89d5424bc 100644 --- a/src/plugins_exts/schema_mount.h +++ b/src/plugins_exts/schema_mount.h @@ -18,7 +18,7 @@ #include "context.h" #ifdef __cplusplus - extern "C" { +extern "C" { #endif /** @@ -62,7 +62,7 @@ LIBYANG_API_DECL void lyplg_ext_schema_mount_destroy_shared_contexts(struct lysc LIBYANG_API_DECL void lyplg_ext_schema_mount_destroy_inline_contexts(struct lysc_ext_instance *ext); #ifdef __cplusplus - } +} #endif #endif /* LY_PLUGINS_EXTS_SCHEMA_MOUNT_H_ */ From 2ce01757e4473f6d5bbd35b1036bbd893a75c349 Mon Sep 17 00:00:00 2001 From: roman Date: Tue, 3 Jun 2025 11:02:55 +0200 Subject: [PATCH 77/99] schema mount REFACTOR move api decl to plugins_ext --- CMakeLists.txt | 1 - src/plugins_exts.h | 40 +++++++++++++++++++ src/plugins_exts/schema_mount.h | 68 --------------------------------- 3 files changed, 40 insertions(+), 69 deletions(-) delete mode 100644 src/plugins_exts/schema_mount.h diff --git a/CMakeLists.txt b/CMakeLists.txt index ddaa2ad50..e83200936 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -176,7 +176,6 @@ set(headers src/plugins.h src/plugins_exts.h src/plugins_exts/metadata.h - src/plugins_exts/schema_mount.h src/plugins_types.h src/printer_data.h src/printer_schema.h diff --git a/src/plugins_exts.h b/src/plugins_exts.h index 5539b5d3d..cbdcae6d7 100644 --- a/src/plugins_exts.h +++ b/src/plugins_exts.h @@ -1140,6 +1140,46 @@ LIBYANG_API_DECL LY_ERR lyplg_ext_schema_mount_get_parent_ref(const struct lysc_ 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. + * + * Inline contexts are 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 */ #ifdef __cplusplus diff --git a/src/plugins_exts/schema_mount.h b/src/plugins_exts/schema_mount.h deleted file mode 100644 index 89d5424bc..000000000 --- a/src/plugins_exts/schema_mount.h +++ /dev/null @@ -1,68 +0,0 @@ -/** - * @file schema_mount.h - * @author Roman Janota - * @brief ietf-yang-schema-mount API - * - * Copyright (c) 2025 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 - */ - - #ifndef LY_PLUGINS_EXTS_SCHEMA_MOUNT_H_ - #define LY_PLUGINS_EXTS_SCHEMA_MOUNT_H_ - - #include "context.h" - - #ifdef __cplusplus -extern "C" { - #endif - -/** - * @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. - * - * Inline contexts are 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); - - #ifdef __cplusplus -} - #endif - - #endif /* LY_PLUGINS_EXTS_SCHEMA_MOUNT_H_ */ From c9ca47d7b2ba527f95a4b07350ed6414f23713fb Mon Sep 17 00:00:00 2001 From: roman Date: Fri, 13 Jun 2025 11:05:56 +0200 Subject: [PATCH 78/99] printer context BUGFIX hashing patterns Hash the address of the pattern instead of the pattern itself --- src/printer_context.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/printer_context.c b/src/printer_context.c index e50bdf040..f43a4221a 100644 --- a/src/printer_context.c +++ b/src/printer_context.c @@ -232,7 +232,7 @@ ctxs_patterns(const struct lysc_pattern **patterns, struct ly_ht *ht, int *size) *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); + hash = lyht_hash((const char *)&patterns[u], sizeof patterns[u]); if (lyht_insert(ht, (void *)patterns[u], hash, NULL) == LY_EEXIST) { continue; } From e9ca8aa4314c01a37316d63985fbcd38efc32de4 Mon Sep 17 00:00:00 2001 From: roman Date: Tue, 1 Jul 2025 11:23:46 +0200 Subject: [PATCH 79/99] libyang REFACTOR remove leftover include --- src/libyang.h | 1 - src/plugins_exts/schema_mount.c | 2 -- 2 files changed, 3 deletions(-) diff --git a/src/libyang.h b/src/libyang.h index 197f29df9..c2095da22 100644 --- a/src/libyang.h +++ b/src/libyang.h @@ -34,7 +34,6 @@ extern "C" { #include "parser_schema.h" #include "printer_data.h" #include "printer_schema.h" -#include "schema_mount.h" #include "set.h" #include "tree.h" #include "tree_data.h" diff --git a/src/plugins_exts/schema_mount.c b/src/plugins_exts/schema_mount.c index c08160e8f..7d4457c9d 100644 --- a/src/plugins_exts/schema_mount.c +++ b/src/plugins_exts/schema_mount.c @@ -15,8 +15,6 @@ #define _GNU_SOURCE -#include "schema_mount.h" - #include #include #include From 915508e180e8c48d50841974e38353ef713d17e2 Mon Sep 17 00:00:00 2001 From: roman Date: Tue, 1 Jul 2025 13:19:06 +0200 Subject: [PATCH 80/99] printer context UPDATE store pattern codes in ht Moved pcre2 pattern code from pattern struct to a hash table inside a context. The reason being the usability of patterns inside printed contexts. pcre2 lib is dynamically loaded and a printed pattern code contains pointers to e.g. malloc(), which caused issues with printed contexts. This way such codes are serialized and deserialized whenever they are needed, which is portable in the same sense as a printed context. --- src/ly_common.c | 148 ++++++++++++++++++++++++++++ src/ly_common.h | 17 +++- src/parser_common.c | 2 +- src/plugins_types.c | 10 +- src/plugins_types.h | 3 +- src/plugins_types/hex_string.c | 2 +- src/plugins_types/instanceid_keys.c | 2 +- src/plugins_types/ipv4_address.c | 2 +- src/plugins_types/ipv4_prefix.c | 2 +- src/plugins_types/ipv6_address.c | 2 +- src/plugins_types/ipv6_prefix.c | 2 +- src/plugins_types/string.c | 2 +- src/printer_context.c | 11 --- src/schema_compile_node.c | 5 +- src/tree_schema.h | 1 - src/tree_schema_free.c | 1 - src/tree_schema_internal.h | 9 ++ src/xpath.c | 15 +-- tests/utests/utests.h | 1 - 19 files changed, 198 insertions(+), 39 deletions(-) diff --git a/src/ly_common.c b/src/ly_common.c index ddade475a..26052e54a 100644 --- a/src/ly_common.c +++ b/src/ly_common.c @@ -37,6 +37,7 @@ #include #include "compat.h" +#include "schema_compile_node.h" #include "tree_data_internal.h" #include "tree_schema_internal.h" #include "version.h" @@ -149,6 +150,34 @@ ly_ctx_data_dict_get(const struct ly_ctx *ctx) return ctx_data->data_dict; } +/** + * @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->serialized_pattern) { + /* free the pcode */ + pcre2_serialize_free(val->serialized_pattern); + } +} + LY_ERR ly_ctx_data_add(const struct ly_ctx *ctx) { @@ -194,6 +223,11 @@ ly_ctx_data_add(const struct ly_ctx *ctx) LY_CHECK_ERR_GOTO(!ctx_data->data_dict, rc = LY_EMEM, cleanup); lydict_init(ctx_data->data_dict); + /* pattern hash table */ + ctx_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(!ctx_data->pattern_ht, rc = LY_EMEM, cleanup); + /* refcount */ ctx_data->refcount = 1; @@ -261,9 +295,123 @@ ly_ctx_data_del(const struct ly_ctx *ctx) lyht_free(ctx_data->leafref_links_ht, ly_ctx_ht_leafref_links_rec_free); lydict_clean(ctx_data->data_dict); free(ctx_data->data_dict); + lyht_free(ctx_data->pattern_ht, ly_ctx_ht_pattern_free_cb); free(ctx_data); } +/** + * @brief Serialize a PCRE2 compiled code. + * + * @param[in] pcode PCRE2 compiled code to serialize. + * @param[out] serialized_code Pointer to the serialized code, must be freed by the caller. + * @return LY_SUCCESS on success, LY_EINT on serialization error. + */ +static LY_ERR +ly_pcode_serialize(const pcre2_code *pcode, uint8_t **serialized_code) +{ + int r; + uint8_t *ser_code = NULL; + PCRE2_SIZE ser_code_size = 0; + + *serialized_code = NULL; + + r = pcre2_serialize_encode(&pcode, 1, &ser_code, &ser_code_size, NULL); + if (r < 0) { + PCRE2_UCHAR err_msg[LY_PCRE2_MSG_LIMIT] = {0}; + + pcre2_get_error_message(r, err_msg, LY_PCRE2_MSG_LIMIT); + LOGERR(NULL, LY_EINT, "PCRE2 compiled code serialization failed (%s).", err_msg); + return LY_EINT; + } + + *serialized_code = ser_code; + return LY_SUCCESS; +} + +/** + * @brief Deserialize a PCRE2 compiled code from its serialized form. + * + * This code does not have to be recompiled, it can be used directly. + * + * @param[in] serialized_code Serialized PCRE2 compiled code. + * @param[out] pcode Pointer to the deserialized PCRE2 code, must be freed by the caller. + * @return LY_SUCCESS on success, LY_EINT on deserialization error. + */ +static LY_ERR +ly_pcode_deserialize(const uint8_t *serialized_code, pcre2_code **pcode) +{ + int r; + pcre2_code *pcode_tmp = NULL; + + *pcode = NULL; + + /* deserialize the pcode */ + r = pcre2_serialize_decode(&pcode_tmp, 1, serialized_code, NULL); + if (r < 0) { + PCRE2_UCHAR err_msg[LY_PCRE2_MSG_LIMIT] = {0}; + + pcre2_get_error_message(r, err_msg, LY_PCRE2_MSG_LIMIT); + LOGERR(NULL, LY_EINT, "PCRE2 compiled code deserialization failed (%s).", err_msg); + return LY_EINT; + } + + *pcode = pcode_tmp; + return LY_SUCCESS; +} + +LY_ERR +ly_ctx_get_or_create_pattern_code(const struct ly_ctx *ctx, const char *pattern, pcre2_code **pcode) +{ + LY_ERR ret = LY_SUCCESS; + struct ly_ctx_data *ctx_data; + uint32_t hash; + struct ly_pattern_ht_rec rec = {0}, *found_rec = NULL; + pcre2_code *pcode_tmp = NULL; + uint8_t *serialized_pcode = NULL; + + assert(ctx && pattern); + + ctx_data = ly_ctx_data_get(ctx); + LY_CHECK_RET(!ctx_data, LY_EINT); + + /* try to find the record */ + rec.pattern = pattern; + rec.serialized_pattern = NULL; + hash = lyht_hash(pattern, strlen(pattern)); + + if (!lyht_find(ctx_data->pattern_ht, &rec, hash, (void **)&found_rec)) { + /* found it, deserialize the pcode */ + LY_CHECK_GOTO(ret = ly_pcode_deserialize(found_rec->serialized_pattern, &pcode_tmp), cleanup); + if (pcode) { + *pcode = pcode_tmp; + pcode_tmp = NULL; + } + goto cleanup; + } + + /* record not found, we need to compile the pattern and insert it */ + LY_CHECK_GOTO(ret = lys_compile_type_pattern_check(ctx, pattern, &pcode_tmp), cleanup); + + /* serialize the pcode */ + LY_CHECK_GOTO(ret = ly_pcode_serialize(pcode_tmp, &serialized_pcode), cleanup); + rec.serialized_pattern = serialized_pcode; + + /* insert the record */ + LY_CHECK_GOTO(ret = lyht_insert_no_check(ctx_data->pattern_ht, &rec, hash, (void **)&found_rec), cleanup); + + if (pcode) { + /* transfer pcode ownership to the caller */ + *pcode = pcode_tmp; + pcode_tmp = NULL; + } + serialized_pcode = NULL; + +cleanup: + pcre2_code_free(pcode_tmp); + pcre2_serialize_free(serialized_pcode); + return ret; +} + void * ly_realloc(void *ptr, size_t size) { diff --git a/src/ly_common.h b/src/ly_common.h index 1e411b261..d587f26e6 100644 --- a/src/ly_common.h +++ b/src/ly_common.h @@ -354,6 +354,10 @@ struct ly_ctx_data { struct ly_ht *leafref_links_ht; /**< hash table of leafref links between term data nodes */ struct ly_dict *data_dict; /**< dictionary for data trees */ + 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. */ + int refcount; /**< reference count for the given context */ }; @@ -454,13 +458,24 @@ void ly_ctx_ht_leafref_links_rec_free(void *val_p); */ struct lys_module *ly_ctx_get_module_implemented2(const struct ly_ctx *ctx, const char *name, size_t name_len); +/** + * @brief Gets or creates a PCRE2 pattern code in the context's pattern hash table. + * + * If the pattern is not found, it is compiled, serialized and cached in @p ctx . + * + * @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 pointer to the pattern code, if not NULL, it will be set to the compiled pattern code. + */ +LY_ERR ly_ctx_get_or_create_pattern_code(const struct ly_ctx *ctx, const char *pattern, pcre2_code **pcode); + /****************************************************************************** * Dictionary *****************************************************************************/ /* * The following lysdict_*() functions operate on the internal schema dictionary of the given context. - * They do NOT lock a mutex as opposed to their lydict_*() counterparts, because they do not operate on data. + * 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. */ diff --git a/src/parser_common.c b/src/parser_common.c index 6f5a0456e..ad75f6b7c 100644 --- a/src/parser_common.c +++ b/src/parser_common.c @@ -114,7 +114,7 @@ lyd_parser_notif_eventtime_validate(const struct lyd_node *node) /* validate */ value = lyd_get_value(node); - rc = lyplg_type_validate_patterns(patterns, value, strlen(value), &err); + rc = lyplg_type_validate_patterns(ctx, patterns, value, strlen(value), &err); } cleanup: diff --git a/src/plugins_types.c b/src/plugins_types.c index 9f78a3c90..4ac266d09 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; + 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 the compiled pattern */ + LY_CHECK_RET(ly_ctx_get_or_create_pattern_code(ctx, patterns[u]->expr, &pcode)); + + /* match the pattern */ + r = ly_pattern_code_match(pcode, str, str_len, err); + pcre2_code_free(pcode); LY_CHECK_RET(r && (r != LY_ENOT), r); if (((r == LY_ENOT) && !patterns[u]->inverted) || ((r == LY_SUCCESS) && patterns[u]->inverted)) { diff --git a/src/plugins_types.h b/src/plugins_types.h index e3c116499..24f2ec1ee 100644 --- a/src/plugins_types.h +++ b/src/plugins_types.h @@ -1277,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. @@ -1286,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/hex_string.c b/src/plugins_types/hex_string.c index 646a545ff..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); } diff --git a/src/plugins_types/instanceid_keys.c b/src/plugins_types/instanceid_keys.c index 9ddf1e43c..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 */ diff --git a/src/plugins_types/ipv4_address.c b/src/plugins_types/ipv4_address.c index e2fedf80e..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); } diff --git a/src/plugins_types/ipv4_prefix.c b/src/plugins_types/ipv4_prefix.c index d92ebdfcb..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); } diff --git a/src/plugins_types/ipv6_address.c b/src/plugins_types/ipv6_address.c index c50be8d07..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); } diff --git a/src/plugins_types/ipv6_prefix.c b/src/plugins_types/ipv6_prefix.c index 752eefd2e..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); } diff --git a/src/plugins_types/string.c b/src/plugins_types/string.c index 4d18cd92c..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); } diff --git a/src/printer_context.c b/src/printer_context.c index f43a4221a..92cc53e10 100644 --- a/src/printer_context.c +++ b/src/printer_context.c @@ -226,7 +226,6 @@ static void ctxs_patterns(const struct lysc_pattern **patterns, struct ly_ht *ht, int *size) { uint32_t hash; - size_t code_size; LY_ARRAY_COUNT_TYPE u; *size += CTXS_SIZED_ARRAY(patterns); @@ -238,9 +237,6 @@ ctxs_patterns(const struct lysc_pattern **patterns, struct ly_ht *ht, int *size) } *size += sizeof *patterns[u]; - - pcre2_pattern_info(patterns[u]->code, PCRE2_INFO_SIZE, &code_size); - *size += CTXP_MEM_SIZE(code_size); ctxs_exts(patterns[u]->exts, ht, size); } } @@ -1060,7 +1056,6 @@ ctxp_pattern(const struct lysc_pattern *orig_pattern, struct lysc_pattern **patt { LY_ARRAY_COUNT_TYPE u; struct lysc_pattern *p; - size_t code_size; /* may have already been printed */ p = ly_ctx_compiled_addr_ht_get(addr_ht, orig_pattern, 1); @@ -1079,12 +1074,6 @@ ctxp_pattern(const struct lysc_pattern *orig_pattern, struct lysc_pattern **patt p->expr = ly_ctx_compiled_addr_ht_get(addr_ht, orig_pattern->expr, 0); - /* TODO code->tables - seems to be static, probably in the PCRE2 lib */ - pcre2_pattern_info(orig_pattern->code, PCRE2_INFO_SIZE, &code_size); - p->code = *mem; - *mem = (char *)*mem + CTXP_MEM_SIZE(code_size); - memcpy(p->code, orig_pattern->code, code_size); - 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); diff --git a/src/schema_compile_node.c b/src/schema_compile_node.c index fe08476d6..fb99103a3 100644 --- a/src/schema_compile_node.c +++ b/src/schema_compile_node.c @@ -1386,8 +1386,8 @@ 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_create_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; @@ -1399,6 +1399,7 @@ lys_compile_type_patterns(struct lysc_ctx *ctx, const struct lysp_restr *pattern 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; } diff --git a/src/tree_schema.h b/src/tree_schema.h index c91da659d..57d59fdc3 100644 --- a/src/tree_schema.h +++ b/src/tree_schema.h @@ -1256,7 +1256,6 @@ 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 */ diff --git a/src/tree_schema_free.c b/src/tree_schema_free.c index 13665c66f..829df78df 100644 --- a/src/tree_schema_free.c +++ b/src/tree_schema_free.c @@ -832,7 +832,6 @@ lysc_pattern_free(const struct ly_ctx *ctx, struct lysc_pattern **pattern) if (--(*pattern)->refcount) { return; } - pcre2_code_free((*pattern)->code); lysdict_remove(ctx, (*pattern)->expr); lysdict_remove(ctx, (*pattern)->eapptag); lysdict_remove(ctx, (*pattern)->emsg); diff --git a/src/tree_schema_internal.h b/src/tree_schema_internal.h index ff8d63bf3..a2e3a6feb 100644 --- a/src/tree_schema_internal.h +++ b/src/tree_schema_internal.h @@ -181,6 +181,15 @@ 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 and for comparison. */ + uint8_t *serialized_pattern; /**< Serialized pattern code for this pattern, + can be deserialized to pcre2_code that can be used directly. */ +}; + /** * @brief Check that @p c is valid UTF8 code point for YANG string. * diff --git a/src/xpath.c b/src/xpath.c index 922d2cad0..0e812a617 100644 --- a/src/xpath.c +++ b/src/xpath.c @@ -4982,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)) { diff --git a/tests/utests/utests.h b/tests/utests/utests.h index 5e775bb6e..4d5529ab4 100644 --- a/tests/utests/utests.h +++ b/tests/utests/utests.h @@ -313,7 +313,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); \ From 5cbbfb0defb7b951ce2b5fbe342e71c95c0e2b8a Mon Sep 17 00:00:00 2001 From: roman Date: Mon, 7 Jul 2025 13:30:04 +0200 Subject: [PATCH 81/99] context UPDATE move hash computing --- src/context.c | 9 ++++++--- src/schema_compile.c | 2 -- src/tree_schema.c | 12 ++++++------ 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/context.c b/src/context.c index 32da38217..55e263aa8 100644 --- a/src/context.c +++ b/src/context.c @@ -245,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) { @@ -590,6 +590,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 */ diff --git a/src/schema_compile.c b/src/schema_compile.c index 2c9bcf4b4..e8728d4dd 100644 --- a/src/schema_compile.c +++ b/src/schema_compile.c @@ -1799,8 +1799,6 @@ lys_compile(struct lys_module *mod, struct lys_depset_unres *unres) lysc_module_dfs_full(mod, lyb_cache_node_hash_cb, NULL); } - ly_ctx_new_change(mod->ctx); - cleanup: ly_log_location_revert(0, 0, 1, 0); lys_compile_unres_mod_erase(&ctx, ret); diff --git a/src/tree_schema.c b/src/tree_schema.c index 75d0bee71..6486d77cb 100644 --- a/src/tree_schema.c +++ b/src/tree_schema.c @@ -1189,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) { @@ -2310,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) { From 3e3238f6933fde5b6897cbbb4bae2aa5d5996f65 Mon Sep 17 00:00:00 2001 From: roman Date: Mon, 7 Jul 2025 13:30:54 +0200 Subject: [PATCH 82/99] schema mount UPDATE do not create redundant ctxs --- src/ly_common.h | 4 +++- src/plugins_exts/schema_mount.c | 6 +++--- src/tree_schema.c | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/ly_common.h b/src/ly_common.h index d587f26e6..eec0bc7d8 100644 --- a/src/ly_common.h +++ b/src/ly_common.h @@ -817,9 +817,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/plugins_exts/schema_mount.c b/src/plugins_exts/schema_mount.c index 7d4457c9d..5d210c70c 100644 --- a/src/plugins_exts/schema_mount.c +++ b/src/plugins_exts/schema_mount.c @@ -774,8 +774,8 @@ schema_mount_get_ctx_inline(struct lysc_ext_instance *ext, const struct lyd_node * @param[out] ext_ctx Schema to use for parsing the data. * @return LY_ERR value. */ -static LY_ERR -schema_mount_get_ctx(struct lysc_ext_instance *ext, const struct lyd_node *parent, 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) { LY_ERR ret = LY_SUCCESS, r; struct lyd_node *iter, *ext_data = NULL; @@ -836,7 +836,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 = schema_mount_get_ctx(ext, parent, &ext_ctx))) { + if ((r = lyplg_ext_schema_mount_get_ctx(ext, parent, &ext_ctx))) { return r; } diff --git a/src/tree_schema.c b/src/tree_schema.c index 6486d77cb..896bcc788 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_create_context(&parent->exts[u], NULL, &sm_ctx); + lyplg_ext_schema_mount_get_ctx(&parent->exts[u], NULL, &sm_ctx); if (sm_ctx) { /* some usable context created */ break; From f015740c055095ba69d3f3bd71d799b5ccc9d417 Mon Sep 17 00:00:00 2001 From: roman Date: Mon, 7 Jul 2025 13:31:25 +0200 Subject: [PATCH 83/99] libyang UPDATE cleanup after rebase of so4 on devel --- src/tree_schema.c | 88 ++++++++++++++++++++-------------------- src/tree_schema_common.c | 55 +++++++++++++++---------- 2 files changed, 78 insertions(+), 65 deletions(-) diff --git a/src/tree_schema.c b/src/tree_schema.c index 896bcc788..24f8a554f 100644 --- a/src/tree_schema.c +++ b/src/tree_schema.c @@ -1594,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) { @@ -1619,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; @@ -1814,98 +1814,98 @@ 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) */ @@ -2221,10 +2221,10 @@ lys_parse_in(struct ly_ctx *ctx, struct ly_in *in, LYS_INFORMAT format, const st LY_CHECK_GOTO(rc = lysp_check_dup_identities(pctx, mod->parsed), cleanup); /* compile features, extensions, identities, and submodules */ - LY_CHECK_GOTO(ret = lys_compile_feature_iffeatures(mod->parsed), cleanup); - LY_CHECK_GOTO(ret = lys_compile_extensions(mod), cleanup); - LY_CHECK_GOTO(ret = lys_compile_identities(mod), cleanup); - LY_CHECK_GOTO(ret = lys_compile_submodules(mod), cleanup); + LY_CHECK_GOTO(rc = lys_compile_feature_iffeatures(mod->parsed), cleanup); + 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) { diff --git a/src/tree_schema_common.c b/src/tree_schema_common.c index e80ddc37d..a4d4b0617 100644 --- a/src/tree_schema_common.c +++ b/src/tree_schema_common.c @@ -1151,28 +1151,41 @@ lysp_load_submod_from_clb_or_file(struct lysp_ctx *pctx, const char *name, const struct lysp_load_module_data mod_data = {0}; struct ly_in *in; - if (ctx->imp_clb(PARSER_CUR_PMOD(pctx)->mod->name, NULL, inc->name, - inc->rev[0] ? inc->rev : NULL, ctx->imp_clb_data, - &format, &submodule_data, &submodule_data_free) == LY_SUCCESS) { - LY_CHECK_RET(ly_in_new_memory(submodule_data, &in)); - check_data.name = inc->name; - check_data.revision = inc->rev[0] ? inc->rev : NULL; - check_data.submoduleof = PARSER_CUR_PMOD(pctx)->mod->name; - lys_parse_submodule(ctx, in, format, pctx->main_ctx, lysp_load_module_check, &check_data, new_mods, - &submod); - - /* update inc pointer - parsing another (YANG 1.0) submodule can cause injecting - * submodule's include into main module, where it is missing */ - inc = &pmod->includes[u]; - - ly_in_free(in, 0); - if (submodule_data_free) { - submodule_data_free((void *)submodule_data, ctx->imp_clb_data); - } + assert(!submod_latest || (submod_latest->latest_revision != 2)); + + *submod = NULL; + + if (!ctx->imp_clb) { + /* no callback to call */ + clb_used = 1; + } else { + clb_used = 0; + } + + if (ctx->opts & LY_CTX_DISABLE_SEARCHDIRS) { + /* searchdirs disabled */ + searchdirs_used = 1; + } else { + searchdirs_used = 0; + } + + while (!found && (!clb_used || !searchdirs_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 */ + LY_CHECK_RET(ly_in_new_memory(submodule_data, &in)); + mod_data.name = name; + mod_data.revision = revision; + mod_data.submoduleof = PARSER_CUR_PMOD(pctx)->mod->name; + r = lys_parse_submodule(ctx, in, format, pctx->main_ctx, &mod_data, 0, new_mods, submod); + ly_in_free(in, 0); + if (submodule_data_free) { + submodule_data_free((void *)submodule_data, ctx->imp_clb_data); } - } - if (!submod && !(ctx->opts & LY_CTX_PREFER_SEARCHDIRS)) { - goto search_file; + LY_CHECK_RET(r); + + found = 1; } clb_used = 1; } else if (!searchdirs_used) { From 935c708b65c10309933260efe3299e75f1f2717e Mon Sep 17 00:00:00 2001 From: roman Date: Mon, 7 Jul 2025 13:43:00 +0200 Subject: [PATCH 84/99] printer context UPDATE store ctx hash --- src/printer_context.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/printer_context.c b/src/printer_context.c index 92cc53e10..eb02dd13b 100644 --- a/src/printer_context.c +++ b/src/printer_context.c @@ -1782,6 +1782,9 @@ ly_ctx_compiled_print_context(const struct ly_ctx *orig_ctx, struct ly_ctx *ctx, 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); From 9a82ba0b8ca8c9b69ff3023c825c2693ccff7f13 Mon Sep 17 00:00:00 2001 From: roman Date: Mon, 21 Jul 2025 09:36:05 +0200 Subject: [PATCH 85/99] cmd_data REFACTOR format --- tools/lint/cmd_data.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/lint/cmd_data.c b/tools/lint/cmd_data.c index 856b46f1c..af7b33aa7 100644 --- a/tools/lint/cmd_data.c +++ b/tools/lint/cmd_data.c @@ -607,7 +607,7 @@ parse_input_by_type(struct ly_ctx *ctx, enum lyd_type type, struct cmdline_file /* 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, LYD_PARSE_STRICT, - &envp, op); + &envp, op); if (ret) { YLMSG_E("Failed to parse source NETCONF RPC operation file \"%s\".", reply_rpc->path); goto cleanup; From 12d00584a7d6d76c403d4b62e059a7ded922136b Mon Sep 17 00:00:00 2001 From: roman Date: Mon, 21 Jul 2025 16:37:15 +0200 Subject: [PATCH 86/99] context UPDATE differentiate priv/shared ctx data --- src/context.c | 26 ++- src/context.h | 3 + src/log.c | 122 ++++---------- src/ly_common.c | 270 +++++++++++++++++++----------- src/ly_common.h | 69 +++++--- src/plugins_exts.c | 4 +- src/plugins_exts/schema_mount.c | 4 +- src/tree_data.c | 4 +- src/tree_data_free.c | 4 +- tests/utests/basic/test_context.c | 54 ------ tests/utests/schema/test_schema.c | 13 +- 11 files changed, 273 insertions(+), 300 deletions(-) diff --git a/src/context.c b/src/context.c index 55e263aa8..7eaeaf35a 100644 --- a/src/context.c +++ b/src/context.c @@ -614,7 +614,7 @@ LIBYANG_API_DEF LY_ERR ly_ctx_set_options(struct ly_ctx *ctx, uint32_t option) { LY_ERR lyrc = LY_SUCCESS; - struct ly_ctx_data *ctx_data; + struct ly_ctx_private_data *ctx_data; struct lys_module *mod; uint32_t i; @@ -637,7 +637,7 @@ ly_ctx_set_options(struct ly_ctx *ctx, uint32_t option) } if (!(ctx->opts & LY_CTX_LEAFREF_LINKING) && (option & LY_CTX_LEAFREF_LINKING)) { - ctx_data = ly_ctx_data_get(ctx); + ctx_data = ly_ctx_private_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); } @@ -699,13 +699,13 @@ 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_data *ctx_data; + struct ly_ctx_private_data *ctx_data; 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->opts & LY_CTX_LEAFREF_LINKING) && (option & LY_CTX_LEAFREF_LINKING)) { - ctx_data = ly_ctx_data_get(ctx); + ctx_data = ly_ctx_private_data_get(ctx); lyht_free(ctx_data->leafref_links_ht, ly_ctx_ht_leafref_links_rec_free); ctx_data->leafref_links_ht = NULL; } @@ -828,12 +828,12 @@ 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(const struct ly_ctx *ctx, ly_ext_data_clb clb, void *user_data) { - struct ly_ctx_data *ctx_data; + struct ly_ctx_private_data *ctx_data; ly_ext_data_clb prev; LY_CHECK_ARG_RET(ctx, ctx, NULL); - ctx_data = ly_ctx_data_get(ctx); + ctx_data = ly_ctx_private_data_get(ctx); prev = ctx_data->ext_clb; ctx_data->ext_clb = clb; ctx_data->ext_clb_data = user_data; @@ -1466,7 +1466,10 @@ ly_ctx_new_printed(const void *mem, struct ly_ctx **ctx) cleanup: if (rc) { - ly_ctx_data_del(*ctx); + if (rc != LY_EEXIST) { + /* do not free another context's data */ + ly_ctx_data_del(*ctx); + } *ctx = NULL; } return rc; @@ -1495,15 +1498,6 @@ ly_ctx_destroy(struct ly_ctx *ctx) return; } - /* check if this is the last instance of the context */ - if (ly_ctx_data_refcount_get(ctx) > 1) { - /* not the last instance, just decrease the ctx and plg reference counts, - * since other instances might still be using parsed, compiled, and other 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) { diff --git a/src/context.h b/src/context.h index df6acfe53..368e79030 100644 --- a/src/context.h +++ b/src/context.h @@ -693,6 +693,9 @@ LIBYANG_API_DECL LY_ERR ly_ctx_compiled_print(const struct ly_ctx *ctx, void *me /** * @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. diff --git a/src/log.c b/src/log.c index cb1e11161..3676b4a05 100644 --- a/src/log.c +++ b/src/log.c @@ -176,100 +176,46 @@ ly_err_new(struct ly_err_item **err, LY_ERR ecode, LY_VECODE vecode, char *data_ return e->err; } -static struct ly_ctx_data_err * -ly_err_data_get(const struct ly_ctx *ctx) -{ - struct ly_ctx_data *ctx_data; - pthread_t tid = pthread_self(); - uint32_t i; - struct ly_ctx_data_err *data_err = NULL; - - /* get context data */ - ctx_data = ly_ctx_data_get(ctx); - - /* ERR READ LOCK */ - pthread_rwlock_rdlock(&ctx_data->err_rwlock); - - /* find the thread-specific err */ - for (i = 0; i < ctx_data->err_count; ++i) { - if (!memcmp(&ctx_data->errs[i]->tid, &tid, sizeof tid)) { - data_err = ctx_data->errs[i]; - goto cleanup; - } - } - - /* ERR UNLOCK */ - pthread_rwlock_unlock(&ctx_data->err_rwlock); - - /* ERR WRITE LOCK */ - pthread_rwlock_wrlock(&ctx_data->err_rwlock); - - /* no need to retry the search, this thread is executing this function */ - - /* not found, so create it */ - ctx_data->errs = ly_realloc(ctx_data->errs, (ctx_data->err_count + 1) * sizeof *ctx_data->errs); - ctx_data->errs[ctx_data->err_count] = calloc(1, sizeof **ctx_data->errs); - memcpy(&ctx_data->errs[ctx_data->err_count]->tid, &tid, sizeof tid); - - ++ctx_data->err_count; - - data_err = ctx_data->errs[ctx_data->err_count - 1]; - -cleanup: - /* ERR UNLOCK */ - pthread_rwlock_unlock(&ctx_data->err_rwlock); - return data_err; -} - LIBYANG_API_DEF const struct ly_err_item * ly_err_first(const struct ly_ctx *ctx) { - struct ly_ctx_data_err *err_data; - - if (!ctx) { - return NULL; - } + struct ly_ctx_private_data *ctx_data; - /* get context err data */ - err_data = ly_err_data_get(ctx); + LY_CHECK_ARG_RET(NULL, ctx, NULL); - return err_data ? err_data->err : NULL; + ctx_data = ly_ctx_private_data_get(ctx); + return ctx_data->errs; } LIBYANG_API_DEF const struct ly_err_item * ly_err_last(const struct ly_ctx *ctx) { - struct ly_ctx_data_err *err_data; - - if (!ctx) { - return NULL; - } + struct ly_ctx_private_data *ctx_data; - /* get context err data */ - err_data = ly_err_data_get(ctx); + LY_CHECK_ARG_RET(NULL, ctx, NULL); - if (!err_data) { - return NULL; - } - - return err_data->err ? err_data->err->prev : NULL; + ctx_data = ly_ctx_private_data_get(ctx); + 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_data_err *err_data; - struct ly_err_item *err = NULL; + struct ly_ctx_private_data *src_data, *trg_data; + struct ly_err_item *errs = NULL; - /* get src context err data */ - err_data = ly_err_data_get(src_ctx); - err = err_data->err; - err_data->err = NULL; + /* get src context errs */ + src_data = ly_ctx_private_data_get(src_ctx); + errs = src_data->errs; + src_data->errs = NULL; + + /* get and free the trg context errs */ + trg_data = ly_ctx_private_data_get(trg_ctx); + ly_err_free(trg_data->errs); /* set them for trg */ - err_data = ly_err_data_get(trg_ctx); - ly_err_free(err_data->err); - err_data->err = err; + ly_err_free(trg_data->errs); + trg_data->errs = errs; } LIBYANG_API_DEF void @@ -290,24 +236,28 @@ ly_err_free(void *ptr) LIBYANG_API_DEF void ly_err_clean(const struct ly_ctx *ctx, struct ly_err_item *eitem) { - struct ly_ctx_data_err *err_data; + struct ly_ctx_private_data *ctx_data; struct ly_err_item *e; - err_data = ly_err_data_get(ctx); - if (err_data->err == eitem) { + if (!ctx) { + return; + } + + ctx_data = ly_ctx_private_data_get(ctx); + if (ctx_data->errs == eitem) { eitem = NULL; } if (!eitem) { /* free all err */ - ly_err_free(err_data->err); - err_data->err = NULL; + ly_err_free(ctx_data->errs); + ctx_data->errs = NULL; } else { /* disconnect the error */ - for (e = err_data->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; - err_data->err->prev = e; + ctx_data->errs->prev = e; /* free this err and newer */ ly_err_free(eitem); @@ -456,15 +406,15 @@ 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_data_err *err_data; + struct ly_ctx_private_data *ctx_data; struct ly_err_item *e, *last; assert(ctx && (level < LY_LLVRB)); - /* get context err data */ - err_data = ly_err_data_get(ctx); + /* get context private data */ + ctx_data = ly_ctx_private_data_get(ctx); - e = err_data->err; + e = ctx_data->errs; if (!e) { /* if we are only to fill in path, there must have been an error stored */ assert(msg); @@ -473,7 +423,7 @@ log_store(const struct ly_ctx *ctx, LY_LOG_LEVEL level, LY_ERR err, LY_VECODE ve e->prev = e; e->next = NULL; - err_data->err = e; + ctx_data->errs = e; } else if (!msg) { /* only filling the path */ assert(data_path || schema_path); diff --git a/src/ly_common.c b/src/ly_common.c index 26052e54a..6439d5e74 100644 --- a/src/ly_common.c +++ b/src/ly_common.c @@ -43,9 +43,14 @@ #include "version.h" #include "xml.h" +/* lock for creating/destroying ctx data */ pthread_rwlock_t ly_ctx_data_rwlock = PTHREAD_RWLOCK_INITIALIZER; -struct ly_ctx_data **ly_ctx_data; -uint32_t ly_ctx_data_count; + +/* sized array of thread-specific context data */ +struct ly_ctx_private_data *ly_private_ctx_data; + +/* sized array of shared context data */ +struct ly_ctx_shared_data *ly_shared_ctx_data; LIBYANG_API_DEF uint32_t ly_version_so_major(void) @@ -95,59 +100,114 @@ ly_version_proj_str(void) return LY_PROJ_VERSION; } -struct ly_ctx_data * -ly_ctx_data_get(const struct ly_ctx *ctx) +/** + * @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[out] idx Optional index of the private data in the array. + */ +static struct ly_ctx_private_data * +_ly_ctx_private_data_get(const struct ly_ctx *ctx, ly_bool lock, LY_ARRAY_COUNT_TYPE *idx) { - struct ly_ctx_data *ctx_data = NULL; - uint32_t i; + struct ly_ctx_private_data *iter; + ly_bool found = 0; + pthread_t tid = pthread_self(); - /* RD LOCK */ - pthread_rwlock_rdlock(&ly_ctx_data_rwlock); + if (lock) { + /* RD LOCK */ + pthread_rwlock_rdlock(&ly_ctx_data_rwlock); + } - for (i = 0; i < ly_ctx_data_count; ++i) { - if (ly_ctx_data[i]->ctx == ctx) { - ctx_data = ly_ctx_data[i]; + LY_ARRAY_FOR(ly_private_ctx_data, struct ly_ctx_private_data, iter) { + if ((iter->tid == tid) && (iter->ctx == ctx)) { + if (idx) { + *idx = iter - ly_private_ctx_data; + } + found = 1; break; } } - /* RD UNLOCK */ - pthread_rwlock_unlock(&ly_ctx_data_rwlock); - - if (!ctx_data) { - LOGINT(NULL); + if (lock) { + /* RD UNLOCK */ + pthread_rwlock_unlock(&ly_ctx_data_rwlock); } /* pointer to the structure, cannot be changed so lock is not required */ - return ctx_data; + return found ? iter : NULL; } -int -ly_ctx_data_refcount_get(const struct ly_ctx *ctx) +struct ly_ctx_private_data * +ly_ctx_private_data_get(const struct ly_ctx *ctx) { - struct ly_ctx_data *ctx_data; + struct ly_ctx_private_data *private_data; + + private_data = _ly_ctx_private_data_get(ctx, 1, NULL); - ctx_data = ly_ctx_data_get(ctx); - if (!ctx_data) { - return -1; + if (!private_data) { + /* NULL to avoid infinite loop in LOGERR */ + LOGERR(NULL, LY_EINT, "Context private data not found"); + assert(0); } + return private_data; +} - return ctx_data->refcount; +/** + * @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, LY_ARRAY_COUNT_TYPE *idx) +{ + 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) { + if (idx) { + *idx = iter - ly_shared_ctx_data; + } + 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_dict * -ly_ctx_data_dict_get(const struct ly_ctx *ctx) +struct ly_ctx_shared_data * +ly_ctx_shared_data_get(const struct ly_ctx *ctx) { - struct ly_ctx_data *ctx_data; + struct ly_ctx_shared_data *shared_data; - ctx_data = ly_ctx_data_get(ctx); - if (!ctx_data) { - LOGERR(NULL, LY_EINT, "Context data not found."); + shared_data = _ly_ctx_shared_data_get(ctx, 1, NULL); + if (!shared_data) { + /* NULL to avoid infinite loop in LOGERR */ + LOGERR(NULL, LY_EINT, "Context shared data not found."); assert(0); - return NULL; } + return shared_data; +} - return ctx_data->data_dict; +struct ly_dict * +ly_ctx_data_dict_get(const struct ly_ctx *ctx) +{ + return ly_ctx_private_data_get(ctx)->data_dict; } /** @@ -182,30 +242,31 @@ LY_ERR ly_ctx_data_add(const struct ly_ctx *ctx) { LY_ERR rc = LY_SUCCESS; - struct ly_ctx_data *ctx_data = NULL; - uint32_t i; + struct ly_ctx_private_data *private_data; + struct ly_ctx_shared_data *shared_data; + pthread_t tid = pthread_self(); /* WR LOCK */ pthread_rwlock_wrlock(&ly_ctx_data_rwlock); - /* check for duplicates */ - for (i = 0; i < ly_ctx_data_count; i++) { - if (ly_ctx_data[i]->ctx == ctx) { - ++ly_ctx_data[i]->refcount; - goto cleanup; - } - } + /* check for duplicates in private context data, not allowed */ + private_data = _ly_ctx_private_data_get(ctx, 0, NULL); + if (private_data) { + /* ctx pointers can match only if the context is printed */ + assert(private_data->ctx->opts & LY_CTX_INT_IMMUTABLE); - /* realloc */ - ly_ctx_data = ly_realloc(ly_ctx_data, (ly_ctx_data_count + 1) * sizeof *ly_ctx_data); - LY_CHECK_ERR_GOTO(!ly_ctx_data, rc = LY_EMEM, cleanup); + /* 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; + } - /* alloc */ - ctx_data = ly_ctx_data[ly_ctx_data_count] = calloc(1, sizeof **ly_ctx_data); - LY_CHECK_ERR_GOTO(!ctx_data, rc = LY_EMEM, cleanup); + /* create the private context data */ + LY_ARRAY_NEW_GOTO(ctx, ly_private_ctx_data, private_data, rc, cleanup); /* fill */ - ctx_data->ctx = ctx; + private_data->tid = tid; + private_data->ctx = ctx; /* leafref set */ if (ctx->opts & LY_CTX_LEAFREF_LINKING) { @@ -214,89 +275,96 @@ ly_ctx_data_add(const struct ly_ctx *ctx) * 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_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(!ctx_data->leafref_links_ht, rc = LY_EMEM, cleanup); + private_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(!private_data->leafref_links_ht, rc = LY_EMEM, cleanup); } /* data dictionary */ - ctx_data->data_dict = malloc(sizeof *ctx_data->data_dict); - LY_CHECK_ERR_GOTO(!ctx_data->data_dict, rc = LY_EMEM, cleanup); - lydict_init(ctx_data->data_dict); + private_data->data_dict = malloc(sizeof *private_data->data_dict); + LY_CHECK_ERR_GOTO(!private_data->data_dict, rc = LY_EMEM, cleanup); + lydict_init(private_data->data_dict); + + /* check for duplicates in shared context data */ + shared_data = _ly_ctx_shared_data_get(ctx, 0, NULL); + if (shared_data) { + /* found, we can end */ + ++shared_data->refcount; + goto cleanup; + } + + /* create the shared context data */ + LY_ARRAY_NEW_GOTO(ctx, ly_shared_ctx_data, shared_data, rc, cleanup); + + /* fill */ + shared_data->ctx = ctx; /* pattern hash table */ - ctx_data->pattern_ht = lyht_new(LYHT_MIN_SIZE, sizeof(struct ly_pattern_ht_rec), + shared_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(!ctx_data->pattern_ht, rc = LY_EMEM, cleanup); + LY_CHECK_ERR_GOTO(!shared_data->pattern_ht, rc = LY_EMEM, cleanup); /* refcount */ - ctx_data->refcount = 1; - - ++ly_ctx_data_count; + shared_data->refcount = 1; cleanup: /* WR UNLOCK */ pthread_rwlock_unlock(&ly_ctx_data_rwlock); - if (rc && ctx_data) { - ly_ctx_data_del(ctx); - } return rc; } void ly_ctx_data_del(const struct ly_ctx *ctx) { - uint32_t i; - struct ly_ctx_data *ctx_data = NULL; + struct ly_ctx_private_data *private_data; + struct ly_ctx_shared_data *shared_data; + LY_ARRAY_COUNT_TYPE u; /* WR LOCK */ pthread_rwlock_wrlock(&ly_ctx_data_rwlock); - /* find the ctx data */ - for (i = 0; i < ly_ctx_data_count; ++i) { - if (ly_ctx_data[i]->ctx == ctx) { - ctx_data = ly_ctx_data[i]; - break; - } + /* get the private context data */ + private_data = _ly_ctx_private_data_get(ctx, 0, &u); + if (!private_data) { + /* not found, shared context data can not be found either */ + goto cleanup; } - if (!ctx_data) { - /* WR UNLOCK */ - pthread_rwlock_unlock(&ly_ctx_data_rwlock); - return; + + /* free the private members */ + ly_err_free(private_data->errs); + lyht_free(private_data->leafref_links_ht, ly_ctx_ht_leafref_links_rec_free); + lydict_clean(private_data->data_dict); + free(private_data->data_dict); + if (u < LY_ARRAY_COUNT(ly_private_ctx_data) - 1) { + /* replace the private data with the last one */ + ly_private_ctx_data[u] = ly_private_ctx_data[LY_ARRAY_COUNT(ly_private_ctx_data) - 1]; + } + LY_ARRAY_DECREMENT_FREE(ly_private_ctx_data); + + /* get the shared context data */ + shared_data = _ly_ctx_shared_data_get(ctx, 0, &u); + if (!shared_data) { + /* not found, nothing to do */ + goto cleanup; } + assert(shared_data->refcount); /* decrease refcount */ - --ctx_data->refcount; - if (ctx_data->refcount) { - /* WR UNLOCK */ - pthread_rwlock_unlock(&ly_ctx_data_rwlock); - return; + --shared_data->refcount; + if (shared_data->refcount) { + goto cleanup; } - /* remove the ctx data, replace by the last */ - --ly_ctx_data_count; - if (ly_ctx_data_count) { - if (i < ly_ctx_data_count) { - ly_ctx_data[i] = ly_ctx_data[ly_ctx_data_count]; - } - } else { - free(ly_ctx_data); - ly_ctx_data = NULL; + /* free the shared members */ + lyht_free(shared_data->pattern_ht, ly_ctx_ht_pattern_free_cb); + if (u < LY_ARRAY_COUNT(ly_shared_ctx_data) - 1) { + /* replace the shared data with the last one */ + ly_shared_ctx_data[u] = ly_shared_ctx_data[LY_ARRAY_COUNT(ly_shared_ctx_data) - 1]; } + LY_ARRAY_DECREMENT_FREE(ly_shared_ctx_data); +cleanup: /* WR UNLOCK */ pthread_rwlock_unlock(&ly_ctx_data_rwlock); - - /* clear */ - for (i = 0; i < ctx_data->err_count; ++i) { - ly_err_free(ctx_data->errs[i]->err); - free(ctx_data->errs[i]); - } - free(ctx_data->errs); - lyht_free(ctx_data->leafref_links_ht, ly_ctx_ht_leafref_links_rec_free); - lydict_clean(ctx_data->data_dict); - free(ctx_data->data_dict); - lyht_free(ctx_data->pattern_ht, ly_ctx_ht_pattern_free_cb); - free(ctx_data); } /** @@ -363,7 +431,7 @@ LY_ERR ly_ctx_get_or_create_pattern_code(const struct ly_ctx *ctx, const char *pattern, pcre2_code **pcode) { LY_ERR ret = LY_SUCCESS; - struct ly_ctx_data *ctx_data; + struct ly_ctx_shared_data *ctx_data; uint32_t hash; struct ly_pattern_ht_rec rec = {0}, *found_rec = NULL; pcre2_code *pcode_tmp = NULL; @@ -371,7 +439,7 @@ ly_ctx_get_or_create_pattern_code(const struct ly_ctx *ctx, const char *pattern, assert(ctx && pattern); - ctx_data = ly_ctx_data_get(ctx); + ctx_data = ly_ctx_shared_data_get(ctx); LY_CHECK_RET(!ctx_data, LY_EINT); /* try to find the record */ diff --git a/src/ly_common.h b/src/ly_common.h index eec0bc7d8..9b3e4ce24 100644 --- a/src/ly_common.h +++ b/src/ly_common.h @@ -335,35 +335,46 @@ int LY_VCODE_INSTREXP_len(const char *str); *****************************************************************************/ /** - * @brief Context error hash table record. - */ -struct ly_ctx_data_err { - pthread_t tid; /** pthread thread ID */ - struct ly_err_item *err; /** pointer to the error items, if any */ -}; + * @brief Private context data. + * + * Run-time data for a context, used by the library internally. + */ +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_ctx_data { - const struct ly_ctx *ctx; 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 */ - pthread_rwlock_t err_rwlock; /**< lock protecting errs */ - struct ly_ctx_data_err **errs; /**< array of thread-specific errors related to the context */ - uint32_t err_count; /**< count of items in the errs array */ + struct ly_err_item *errs; /**< thread-specific errors related to the context */ struct ly_ht *leafref_links_ht; /**< hash table of leafref links between term data nodes */ struct ly_dict *data_dict; /**< dictionary for data trees */ +}; + +/** + * @brief Shared context data. + * + * The data is shared only when using printed contexts that are created from the same memory address. + */ +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. */ - - int refcount; /**< reference count for the given context */ }; -extern pthread_rwlock_t ly_ctx_data_rwlock; /**< lock for accessing ly_ctx_data */ -extern struct ly_ctx_data **ly_ctx_data; /**< array of pointers to context-specific data */ -extern uint32_t ly_ctx_data_count; /**< count of ly_ctx_data items */ +extern pthread_rwlock_t ly_ctx_data_rwlock; /**< lock for creating and destroying both private & shared context data */ +extern struct ly_ctx_private_data *ly_private_ctx_data; /**< 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. */ +extern struct ly_ctx_shared_data *ly_shared_ctx_data; /**< sized array ([sized array](@ref sizedarrays)) of shared context data. + * The context is identified by the memory address of the context. */ #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 */ @@ -399,8 +410,13 @@ 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 or LY_EMEM on memory allocation failure. + * @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); @@ -412,26 +428,29 @@ LY_ERR ly_ctx_data_add(const struct ly_ctx *ctx); void ly_ctx_data_del(const struct ly_ctx *ctx); /** - * @brief Get context-specific data of the process. + * @brief Get private (thread-specific) context data. * * @param[in] ctx Context whose data to get. - * @return Context data of @p ctx. + * @return Context data of @p ctx, NULL if not found. */ -struct ly_ctx_data *ly_ctx_data_get(const struct ly_ctx *ctx); +struct ly_ctx_private_data *ly_ctx_private_data_get(const struct ly_ctx *ctx); /** - * @brief Get context's data reference count. + * @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 data reference count to get. - * @return Reference count of the context's data, -1 if the context data was not found. + * @param[in] ctx Context whose shared data to get. + * @return Context shared data of @p ctx, NULL if not found. */ -int ly_ctx_data_refcount_get(const struct ly_ctx *ctx); +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. + * @return Context's data dictionary, NULL if not found. */ struct ly_dict *ly_ctx_data_dict_get(const struct ly_ctx *ctx); diff --git a/src/plugins_exts.c b/src/plugins_exts.c index 256daff3d..0dac87b1b 100644 --- a/src/plugins_exts.c +++ b/src/plugins_exts.c @@ -712,9 +712,9 @@ lyplg_ext_get_data(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext void **ext_data, ly_bool *ext_data_free) { LY_ERR rc; - struct ly_ctx_data *ctx_data; + struct ly_ctx_private_data *ctx_data; - ctx_data = ly_ctx_data_get(ctx); + ctx_data = ly_ctx_private_data_get(ctx); if (!ctx_data->ext_clb) { lyplg_ext_compile_log(NULL, ext, LY_LLERR, LY_EINVAL, "Failed to get extension data, no callback set."); diff --git a/src/plugins_exts/schema_mount.c b/src/plugins_exts/schema_mount.c index 5d210c70c..4df0b538a 100644 --- a/src/plugins_exts/schema_mount.c +++ b/src/plugins_exts/schema_mount.c @@ -1211,7 +1211,7 @@ lyplg_ext_schema_mount_create_context(const struct lysc_ext_instance *ext, const struct ly_ctx **ctx) { struct lyd_node *ext_data = NULL; - struct ly_ctx_data *ctx_data; + struct ly_ctx_private_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; @@ -1221,7 +1221,7 @@ lyplg_ext_schema_mount_create_context(const struct lysc_ext_instance *ext, const sm_data = ext->compiled; - ctx_data = ly_ctx_data_get(ext->def->module->ctx); + ctx_data = ly_ctx_private_data_get(ext->def->module->ctx); if (!ctx_data->ext_clb) { return LY_EINVAL; } diff --git a/src/tree_data.c b/src/tree_data.c index 77c55ef27..7cab2e978 100644 --- a/src/tree_data.c +++ b/src/tree_data.c @@ -3745,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_ctx_data *ctx_data; + struct ly_ctx_private_data *ctx_data; LY_ERR ret = LY_SUCCESS; uint32_t hash; struct lyd_leafref_links_rec rec = {0}; @@ -3761,7 +3761,7 @@ lyd_get_or_create_leafref_links_record(const struct lyd_node_term *node, struct return LY_EDENIED; } - ctx_data = ly_ctx_data_get(LYD_CTX(node)); + ctx_data = ly_ctx_private_data_get(LYD_CTX(node)); rec.node = node; hash = lyht_hash((const char *)&node, sizeof node); diff --git a/src/tree_data_free.c b/src/tree_data_free.c index 5672a56a2..0a545e14f 100644 --- a/src/tree_data_free.c +++ b/src/tree_data_free.c @@ -176,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_ctx_data *ctx_data; + struct ly_ctx_private_data *ctx_data; uint32_t hash; struct lyd_leafref_links_rec *rec; @@ -190,7 +190,7 @@ lyd_free_leafref_nodes(const struct lyd_node_term *node) lyd_free_leafref_links_rec(rec); /* free entry itself from hash table */ - ctx_data = ly_ctx_data_get(LYD_CTX(node)); + ctx_data = ly_ctx_private_data_get(LYD_CTX(node)); hash = lyht_hash((const char *)&node, sizeof node); lyht_remove(ctx_data->leafref_links_ht, &rec, hash); free(rec); diff --git a/tests/utests/basic/test_context.c b/tests/utests/basic/test_context.c index 0acb2605f..d4f68d133 100644 --- a/tests/utests/basic/test_context.c +++ b/tests/utests/basic/test_context.c @@ -1111,59 +1111,6 @@ test_free_parsed(void **state) UTEST_LYCTX = NULL; } -static void -test_refcount(void **state) -{ - ly_bool builtin_plugins_only, static_plugins_only; - uint32_t options; - struct lyd_node *tree = NULL; - const char *data = "test"; - struct ly_ctx_data *ctx_data; - - (void)state; - - /* load a simple module */ - assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, - "module a {namespace urn:a;prefix a;container c { leaf l {type string;}}}", LYS_IN_YANG, NULL)); - - /* try parsing the module's data */ - CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); - lyd_free_all(tree); - - /* get the ctx data */ - ctx_data = ly_ctx_data_get(UTEST_LYCTX); - assert_non_null(ctx_data); - - /* check that the refcount is 1 */ - assert_int_equal(ctx_data->refcount, 1); - - /* mock the creation of the same context */ - assert_int_equal(LY_SUCCESS, ly_ctx_data_add(UTEST_LYCTX)); - - /* increase the plugin refcount */ - options = ly_ctx_get_options(UTEST_LYCTX); - builtin_plugins_only = options & LY_CTX_BUILTIN_PLUGINS_ONLY; - static_plugins_only = options & LY_CTX_STATIC_PLUGINS_ONLY; - assert_int_equal(LY_SUCCESS, lyplg_init(builtin_plugins_only, static_plugins_only)); - - /* check that the refcount increased */ - assert_int_equal(ctx_data->refcount, 2); - - /* try parsing the module's data again */ - CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); - lyd_free_all(tree); - - /* free the context */ - ly_ctx_destroy(UTEST_LYCTX); - - /* check that the refcount decreased */ - assert_int_equal(ctx_data->refcount, 1); - - /* try parsing the module's data again */ - CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); - lyd_free_all(tree); -} - int main(void) { @@ -1177,7 +1124,6 @@ main(void) UTEST(test_set_priv_parsed), UTEST(test_explicit_compile), UTEST(test_free_parsed), - UTEST(test_refcount), }; return cmocka_run_group_tests(tests, NULL, NULL); diff --git a/tests/utests/schema/test_schema.c b/tests/utests/schema/test_schema.c index 79d87e36f..2d1f285d8 100644 --- a/tests/utests/schema/test_schema.c +++ b/tests/utests/schema/test_schema.c @@ -2126,7 +2126,7 @@ test_compiled_print(void **state) int size, fd; void *mem, *mem_end; struct lyd_node *tree = NULL; - struct ly_ctx *printed_ctx = NULL, *printed_ctx2; + struct ly_ctx *printed_ctx = NULL, *printed_ctx2 = NULL; struct lys_module *mod = NULL; const char *yang, *xml; struct lysc_ext_instance *ext; @@ -2217,8 +2217,8 @@ test_compiled_print(void **state) /* create a new printed ctx from this address */ assert_int_equal(LY_SUCCESS, ly_ctx_new_printed(mem, &printed_ctx)); - /* create a new printed ctx from the same address */ - assert_int_equal(LY_SUCCESS, ly_ctx_new_printed(mem, &printed_ctx2)); + /* 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"); @@ -2253,12 +2253,6 @@ test_compiled_print(void **state) CHECK_LYD_STRING_PARAM(tree, xml, LYD_XML, 0); lyd_free_all(tree); - /* now try it with the second printed context from the same address */ - assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(printed_ctx2, 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" @@ -2273,7 +2267,6 @@ test_compiled_print(void **state) /* cleanup */ ly_ctx_destroy(printed_ctx); - ly_ctx_destroy(printed_ctx2); munmap(mem, size); close(fd); shm_unlink("/ly_test_schema_ctx"); From 05e73b43a657c1da28b47bd08b185b8b032da2ce Mon Sep 17 00:00:00 2001 From: roman Date: Wed, 23 Jul 2025 10:52:05 +0200 Subject: [PATCH 87/99] context UPDATE move some data from priv to shared --- src/context.c | 21 ++- src/log.c | 15 +- src/ly_common.c | 282 +++++++++++++++++++++++--------- src/ly_common.h | 23 ++- src/plugins_exts.c | 17 +- src/plugins_exts/schema_mount.c | 16 +- src/tree_data.c | 16 +- src/tree_data_free.c | 12 +- 8 files changed, 287 insertions(+), 115 deletions(-) diff --git a/src/context.c b/src/context.c index 7eaeaf35a..67a206ef1 100644 --- a/src/context.c +++ b/src/context.c @@ -614,7 +614,7 @@ LIBYANG_API_DEF LY_ERR ly_ctx_set_options(struct ly_ctx *ctx, uint32_t option) { LY_ERR lyrc = LY_SUCCESS; - struct ly_ctx_private_data *ctx_data; + struct ly_ctx_shared_data *ctx_data; struct lys_module *mod; uint32_t i; @@ -637,7 +637,8 @@ ly_ctx_set_options(struct ly_ctx *ctx, uint32_t option) } if (!(ctx->opts & LY_CTX_LEAFREF_LINKING) && (option & LY_CTX_LEAFREF_LINKING)) { - ctx_data = ly_ctx_private_data_get(ctx); + /* 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); } @@ -699,13 +700,14 @@ 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_private_data *ctx_data; + struct ly_ctx_shared_data *ctx_data; 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->opts & LY_CTX_LEAFREF_LINKING) && (option & LY_CTX_LEAFREF_LINKING)) { - ctx_data = ly_ctx_private_data_get(ctx); + /* 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; } @@ -828,16 +830,23 @@ 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(const struct ly_ctx *ctx, ly_ext_data_clb clb, void *user_data) { - struct ly_ctx_private_data *ctx_data; + struct ly_ctx_shared_data *ctx_data; ly_ext_data_clb prev; LY_CHECK_ARG_RET(ctx, ctx, NULL); - ctx_data = ly_ctx_private_data_get(ctx); + 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; } diff --git a/src/log.c b/src/log.c index 3676b4a05..0cb76ae8f 100644 --- a/src/log.c +++ b/src/log.c @@ -183,7 +183,8 @@ ly_err_first(const struct ly_ctx *ctx) LY_CHECK_ARG_RET(NULL, ctx, NULL); - ctx_data = ly_ctx_private_data_get(ctx); + ctx_data = ly_ctx_private_data_get_or_create(ctx); + LY_CHECK_RET(!ctx_data, NULL); return ctx_data->errs; } @@ -194,7 +195,8 @@ ly_err_last(const struct ly_ctx *ctx) LY_CHECK_ARG_RET(NULL, ctx, NULL); - ctx_data = ly_ctx_private_data_get(ctx); + 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; } @@ -205,12 +207,12 @@ ly_err_move(struct ly_ctx *src_ctx, struct ly_ctx *trg_ctx) struct ly_err_item *errs = NULL; /* get src context errs */ - src_data = ly_ctx_private_data_get(src_ctx); + 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(trg_ctx); + trg_data = ly_ctx_private_data_get_or_create(trg_ctx); ly_err_free(trg_data->errs); /* set them for trg */ @@ -243,7 +245,7 @@ ly_err_clean(const struct ly_ctx *ctx, struct ly_err_item *eitem) return; } - ctx_data = ly_ctx_private_data_get(ctx); + ctx_data = ly_ctx_private_data_get_or_create(ctx); if (ctx_data->errs == eitem) { eitem = NULL; } @@ -412,7 +414,8 @@ log_store(const struct ly_ctx *ctx, LY_LOG_LEVEL level, LY_ERR err, LY_VECODE ve assert(ctx && (level < LY_LLVRB)); /* get context private data */ - ctx_data = ly_ctx_private_data_get(ctx); + ctx_data = ly_ctx_private_data_get_or_create(ctx); + LY_CHECK_GOTO(!ctx_data, mem_fail); e = ctx_data->errs; if (!e) { diff --git a/src/ly_common.c b/src/ly_common.c index 6439d5e74..2c3e820c9 100644 --- a/src/ly_common.c +++ b/src/ly_common.c @@ -100,15 +100,73 @@ ly_version_proj_str(void) return LY_PROJ_VERSION; } +/** + * @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[out] idx Optional index of the private data in the array. + * @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_ARRAY_COUNT_TYPE *idx) +_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; @@ -120,10 +178,8 @@ _ly_ctx_private_data_get(const struct ly_ctx *ctx, ly_bool lock, LY_ARRAY_COUNT_ } LY_ARRAY_FOR(ly_private_ctx_data, struct ly_ctx_private_data, iter) { - if ((iter->tid == tid) && (iter->ctx == ctx)) { - if (idx) { - *idx = iter - ly_private_ctx_data; - } + /* 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; } @@ -139,20 +195,123 @@ _ly_ctx_private_data_get(const struct ly_ctx *ctx, ly_bool lock, LY_ARRAY_COUNT_ } struct ly_ctx_private_data * -ly_ctx_private_data_get(const struct ly_ctx *ctx) +ly_ctx_private_data_get_or_create(const struct ly_ctx *ctx) { struct ly_ctx_private_data *private_data; + LY_ERR r; - private_data = _ly_ctx_private_data_get(ctx, 1, NULL); + /* try to find existing data */ + private_data = _ly_ctx_private_data_get(ctx, 1, 1); + if (private_data) { + return private_data; + } - if (!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, LY_EINT, "Context private data not found"); + 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. * @@ -161,7 +320,7 @@ ly_ctx_private_data_get(const struct ly_ctx *ctx) * @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, LY_ARRAY_COUNT_TYPE *idx) +_ly_ctx_shared_data_get(const struct ly_ctx *ctx, ly_bool lock) { struct ly_ctx_shared_data *iter; ly_bool found = 0; @@ -173,9 +332,6 @@ _ly_ctx_shared_data_get(const struct ly_ctx *ctx, ly_bool lock, LY_ARRAY_COUNT_T LY_ARRAY_FOR(ly_shared_ctx_data, struct ly_ctx_shared_data, iter) { if (iter->ctx == ctx) { - if (idx) { - *idx = iter - ly_shared_ctx_data; - } found = 1; break; } @@ -195,7 +351,7 @@ 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, NULL); + 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."); @@ -207,7 +363,10 @@ ly_ctx_shared_data_get(const struct ly_ctx *ctx) struct ly_dict * ly_ctx_data_dict_get(const struct ly_ctx *ctx) { - return ly_ctx_private_data_get(ctx)->data_dict; + struct ly_ctx_shared_data *shared_data; + + shared_data = ly_ctx_shared_data_get(ctx); + return shared_data ? shared_data->data_dict : NULL; } /** @@ -244,15 +403,14 @@ 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; - pthread_t tid = pthread_self(); /* 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, NULL); + private_data = _ly_ctx_private_data_get(ctx, 0, 1); if (private_data) { - /* ctx pointers can match only if the context is printed */ + /* 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 */ @@ -261,50 +419,29 @@ ly_ctx_data_add(const struct ly_ctx *ctx) goto cleanup; } - /* create the private context data */ - LY_ARRAY_NEW_GOTO(ctx, ly_private_ctx_data, private_data, rc, cleanup); - - /* fill */ - private_data->tid = tid; - private_data->ctx = ctx; - - /* 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 - * */ - private_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(!private_data->leafref_links_ht, rc = LY_EMEM, 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; } - /* data dictionary */ - private_data->data_dict = malloc(sizeof *private_data->data_dict); - LY_CHECK_ERR_GOTO(!private_data->data_dict, rc = LY_EMEM, cleanup); - lydict_init(private_data->data_dict); - /* check for duplicates in shared context data */ - shared_data = _ly_ctx_shared_data_get(ctx, 0, NULL); + shared_data = _ly_ctx_shared_data_get(ctx, 0); if (shared_data) { /* found, we can end */ - ++shared_data->refcount; + ATOMIC_INC_RELAXED(shared_data->refcount); goto cleanup; } /* create the shared context data */ - LY_ARRAY_NEW_GOTO(ctx, ly_shared_ctx_data, shared_data, rc, cleanup); - - /* fill */ - shared_data->ctx = ctx; - - /* pattern hash table */ - shared_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(!shared_data->pattern_ht, rc = LY_EMEM, cleanup); - - /* refcount */ - shared_data->refcount = 1; + 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 */ @@ -317,50 +454,33 @@ ly_ctx_data_del(const struct ly_ctx *ctx) { struct ly_ctx_private_data *private_data; struct ly_ctx_shared_data *shared_data; - LY_ARRAY_COUNT_TYPE u; + LY_ARRAY_COUNT_TYPE idx; /* WR LOCK */ pthread_rwlock_wrlock(&ly_ctx_data_rwlock); - /* get the private context data */ - private_data = _ly_ctx_private_data_get(ctx, 0, &u); - if (!private_data) { - /* not found, shared context data can not be found either */ - goto cleanup; + /* 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); } - /* free the private members */ - ly_err_free(private_data->errs); - lyht_free(private_data->leafref_links_ht, ly_ctx_ht_leafref_links_rec_free); - lydict_clean(private_data->data_dict); - free(private_data->data_dict); - if (u < LY_ARRAY_COUNT(ly_private_ctx_data) - 1) { - /* replace the private data with the last one */ - ly_private_ctx_data[u] = ly_private_ctx_data[LY_ARRAY_COUNT(ly_private_ctx_data) - 1]; - } - LY_ARRAY_DECREMENT_FREE(ly_private_ctx_data); - /* get the shared context data */ - shared_data = _ly_ctx_shared_data_get(ctx, 0, &u); + shared_data = _ly_ctx_shared_data_get(ctx, 0); if (!shared_data) { /* not found, nothing to do */ goto cleanup; } - assert(shared_data->refcount); + assert(ATOMIC_LOAD_RELAXED(shared_data->refcount)); /* decrease refcount */ - --shared_data->refcount; - if (shared_data->refcount) { + ATOMIC_DEC_RELAXED(shared_data->refcount); + if (ATOMIC_LOAD_RELAXED(shared_data->refcount)) { goto cleanup; } /* free the shared members */ - lyht_free(shared_data->pattern_ht, ly_ctx_ht_pattern_free_cb); - if (u < LY_ARRAY_COUNT(ly_shared_ctx_data) - 1) { - /* replace the shared data with the last one */ - ly_shared_ctx_data[u] = ly_shared_ctx_data[LY_ARRAY_COUNT(ly_shared_ctx_data) - 1]; - } - LY_ARRAY_DECREMENT_FREE(ly_shared_ctx_data); + ly_ctx_shared_data_remove_and_free(shared_data); cleanup: /* WR UNLOCK */ diff --git a/src/ly_common.h b/src/ly_common.h index 9b3e4ce24..9b18a5cdc 100644 --- a/src/ly_common.h +++ b/src/ly_common.h @@ -343,13 +343,7 @@ 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 */ - 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_err_item *errs; /**< thread-specific errors related to the context */ - - struct ly_ht *leafref_links_ht; /**< hash table of leafref links between term data nodes */ - struct ly_dict *data_dict; /**< dictionary for data trees */ }; /** @@ -366,7 +360,18 @@ struct ly_ctx_shared_data { 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. */ + * 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 */ }; extern pthread_rwlock_t ly_ctx_data_rwlock; /**< lock for creating and destroying both private & shared context data */ @@ -428,12 +433,12 @@ LY_ERR ly_ctx_data_add(const struct ly_ctx *ctx); void ly_ctx_data_del(const struct ly_ctx *ctx); /** - * @brief Get private (thread-specific) context data. + * @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 if not found. */ -struct ly_ctx_private_data *ly_ctx_private_data_get(const struct ly_ctx *ctx); +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. diff --git a/src/plugins_exts.c b/src/plugins_exts.c index 0dac87b1b..069e0906f 100644 --- a/src/plugins_exts.c +++ b/src/plugins_exts.c @@ -712,17 +712,28 @@ lyplg_ext_get_data(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext void **ext_data, ly_bool *ext_data_free) { LY_ERR rc; - struct ly_ctx_private_data *ctx_data; + struct ly_ctx_shared_data *ctx_data; - ctx_data = ly_ctx_private_data_get(ctx); + 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_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/schema_mount.c b/src/plugins_exts/schema_mount.c index 4df0b538a..120274540 100644 --- a/src/plugins_exts/schema_mount.c +++ b/src/plugins_exts/schema_mount.c @@ -1211,18 +1211,28 @@ lyplg_ext_schema_mount_create_context(const struct lysc_ext_instance *ext, const struct ly_ctx **ctx) { struct lyd_node *ext_data = NULL; - struct ly_ctx_private_data *ctx_data; + 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; - ctx_data = ly_ctx_private_data_get(ext->def->module->ctx); - if (!ctx_data->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; } diff --git a/src/tree_data.c b/src/tree_data.c index 7cab2e978..aeda95bef 100644 --- a/src/tree_data.c +++ b/src/tree_data.c @@ -3745,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_ctx_private_data *ctx_data; + struct ly_ctx_shared_data *ctx_data; LY_ERR ret = LY_SUCCESS; uint32_t hash; struct lyd_leafref_links_rec rec = {0}; @@ -3761,19 +3761,21 @@ lyd_get_or_create_leafref_links_record(const struct lyd_node_term *node, struct return LY_EDENIED; } - ctx_data = ly_ctx_private_data_get(LYD_CTX(node)); + ctx_data = ly_ctx_shared_data_get(LYD_CTX(node)); rec.node = node; hash = lyht_hash((const char *)&node, sizeof node); - if (lyht_find(ctx_data->leafref_links_ht, &rec_p, hash, (void **)&rec_p2) == 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) { 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(ctx_data->leafref_links_ht, &rec_p, hash, (void **)&rec_p2); LY_CHECK_ERR_GOTO(ret, free(rec_p), cleanup); - } else { - return LY_ENOTFOUND; } } @@ -3781,6 +3783,10 @@ lyd_get_or_create_leafref_links_record(const struct lyd_node_term *node, struct if (!ret) { *record = *rec_p2; } + + /* LL UNLOCK */ + pthread_mutex_unlock(&ctx_data->leafref_links_lock); + return ret; } diff --git a/src/tree_data_free.c b/src/tree_data_free.c index 0a545e14f..811c924c0 100644 --- a/src/tree_data_free.c +++ b/src/tree_data_free.c @@ -176,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_ctx_private_data *ctx_data; + struct ly_ctx_shared_data *ctx_data; uint32_t hash; struct lyd_leafref_links_rec *rec; @@ -190,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 */ - ctx_data = ly_ctx_private_data_get(LYD_CTX(node)); + ctx_data = ly_ctx_shared_data_get(LYD_CTX(node)); hash = lyht_hash((const char *)&node, sizeof node); + + /* 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); } From 4a48d8edcbc27ff3b3e1272d5945c5411fb6be72 Mon Sep 17 00:00:00 2001 From: roman Date: Wed, 23 Jul 2025 11:50:36 +0200 Subject: [PATCH 88/99] ly common UPDATE pattern code handling functions --- src/ly_common.c | 155 ++++++++++++++++++++++++-------------- src/ly_common.h | 18 ++++- src/plugins_types.c | 2 +- src/schema_compile_node.c | 2 +- 4 files changed, 115 insertions(+), 62 deletions(-) diff --git a/src/ly_common.c b/src/ly_common.c index 2c3e820c9..e0233843c 100644 --- a/src/ly_common.c +++ b/src/ly_common.c @@ -100,6 +100,34 @@ ly_version_proj_str(void) return LY_PROJ_VERSION; } +/** + * @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->serialized_pattern) { + /* free the pcode */ + pcre2_serialize_free(val->serialized_pattern); + } +} + /** * @brief Remove private context data from the sized array and free its contents. * @@ -369,34 +397,6 @@ ly_ctx_data_dict_get(const struct ly_ctx *ctx) return shared_data ? shared_data->data_dict : NULL; } -/** - * @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->serialized_pattern) { - /* free the pcode */ - pcre2_serialize_free(val->serialized_pattern); - } -} - LY_ERR ly_ctx_data_add(const struct ly_ctx *ctx) { @@ -454,7 +454,6 @@ ly_ctx_data_del(const struct ly_ctx *ctx) { struct ly_ctx_private_data *private_data; struct ly_ctx_shared_data *shared_data; - LY_ARRAY_COUNT_TYPE idx; /* WR LOCK */ pthread_rwlock_wrlock(&ly_ctx_data_rwlock); @@ -547,57 +546,101 @@ ly_pcode_deserialize(const uint8_t *serialized_code, pcre2_code **pcode) return LY_SUCCESS; } -LY_ERR -ly_ctx_get_or_create_pattern_code(const struct ly_ctx *ctx, const char *pattern, pcre2_code **pcode) +/** + * @brief Get a compiled PCRE2 pattern code from the context's pattern hash table. + * + * @param[in] ctx Context to get the pattern code from. + * @param[in] pattern Pattern string to search for. + * @param[in] pattern_ht Pattern hash table to search in. + * @param[out] pcode Optional compiled pattern code, must be freed by the caller. + * If NULL, the function only checks if the pattern exists in the hash table. + * @return LY_SUCCESS on success, LY_ENOTFOUND if the pattern was not found, + * other LY_ERR values on error. + */ +static LY_ERR +_ly_ctx_get_pattern_code(const struct ly_ctx *ctx, const char *pattern, + struct ly_ht *pattern_ht, pcre2_code **pcode) { - LY_ERR ret = LY_SUCCESS; - struct ly_ctx_shared_data *ctx_data; + LY_ERR rc = LY_SUCCESS; uint32_t hash; struct ly_pattern_ht_rec rec = {0}, *found_rec = NULL; - pcre2_code *pcode_tmp = NULL; - uint8_t *serialized_pcode = NULL; - - assert(ctx && pattern); - ctx_data = ly_ctx_shared_data_get(ctx); - LY_CHECK_RET(!ctx_data, LY_EINT); + assert(ctx && pattern && pattern_ht); - /* try to find the record */ + /* use the pattern as a key */ rec.pattern = pattern; rec.serialized_pattern = NULL; hash = lyht_hash(pattern, strlen(pattern)); - if (!lyht_find(ctx_data->pattern_ht, &rec, hash, (void **)&found_rec)) { + /* try to find the record */ + LY_CHECK_GOTO(rc = lyht_find(pattern_ht, &rec, hash, (void **)&found_rec), cleanup); + + if (pcode) { /* found it, deserialize the pcode */ - LY_CHECK_GOTO(ret = ly_pcode_deserialize(found_rec->serialized_pattern, &pcode_tmp), cleanup); - if (pcode) { - *pcode = pcode_tmp; - pcode_tmp = NULL; - } + LY_CHECK_GOTO(rc = ly_pcode_deserialize(found_rec->serialized_pattern, pcode), cleanup); + } + +cleanup: + return rc; +} + +LY_ERR +ly_ctx_get_pattern_code(const struct ly_ctx *ctx, const char *pattern, pcre2_code **pcode) +{ + LY_ERR rc = LY_SUCCESS; + struct ly_ctx_shared_data *ctx_data; + + ctx_data = ly_ctx_shared_data_get(ctx); + LY_CHECK_RET(!ctx_data, LY_EINT); + + rc = _ly_ctx_get_pattern_code(ctx, pattern, ctx_data->pattern_ht, pcode); + if (rc) { + LOGERR(ctx, rc, "Failed to get pattern code for \"%s\".", pattern); + } + + return rc; +} + +LY_ERR +ly_ctx_compile_and_cache_pattern_code(const struct ly_ctx *ctx, const char *pattern) +{ + LY_ERR rc = LY_SUCCESS; + struct ly_ctx_shared_data *ctx_data; + uint8_t *serialized_pcode = NULL; + pcre2_code *pcode_tmp = NULL; + struct ly_pattern_ht_rec rec = {0}; + uint32_t hash; + + ctx_data = ly_ctx_shared_data_get(ctx); + LY_CHECK_RET(!ctx_data, LY_EINT); + + /* check for existing pattern code */ + rc = _ly_ctx_get_pattern_code(ctx, pattern, ctx_data->pattern_ht, NULL); + LY_CHECK_GOTO(rc && (rc != LY_ENOTFOUND), cleanup); + if (!rc) { + /* pattern is already compiled and stored, nothing to do */ goto cleanup; } /* record not found, we need to compile the pattern and insert it */ - LY_CHECK_GOTO(ret = lys_compile_type_pattern_check(ctx, pattern, &pcode_tmp), cleanup); + LY_CHECK_GOTO(rc = lys_compile_type_pattern_check(ctx, pattern, &pcode_tmp), cleanup); /* serialize the pcode */ - LY_CHECK_GOTO(ret = ly_pcode_serialize(pcode_tmp, &serialized_pcode), cleanup); - rec.serialized_pattern = serialized_pcode; + LY_CHECK_GOTO(rc = ly_pcode_serialize(pcode_tmp, &serialized_pcode), cleanup); /* insert the record */ - LY_CHECK_GOTO(ret = lyht_insert_no_check(ctx_data->pattern_ht, &rec, hash, (void **)&found_rec), cleanup); + hash = lyht_hash(pattern, strlen(pattern)); + rec.pattern = pattern; + rec.serialized_pattern = serialized_pcode; + LY_CHECK_GOTO(rc = lyht_insert_no_check(ctx_data->pattern_ht, &rec, hash, NULL), cleanup); - if (pcode) { - /* transfer pcode ownership to the caller */ - *pcode = pcode_tmp; - pcode_tmp = NULL; - } + /* dont free the serialized pcode, it is now owned by the record in the hash table */ serialized_pcode = NULL; cleanup: pcre2_code_free(pcode_tmp); pcre2_serialize_free(serialized_pcode); - return ret; + return rc; } void * diff --git a/src/ly_common.h b/src/ly_common.h index 9b18a5cdc..befd68629 100644 --- a/src/ly_common.h +++ b/src/ly_common.h @@ -483,15 +483,25 @@ void ly_ctx_ht_leafref_links_rec_free(void *val_p); struct lys_module *ly_ctx_get_module_implemented2(const struct ly_ctx *ctx, const char *name, size_t name_len); /** - * @brief Gets or creates a PCRE2 pattern code in the context's pattern hash table. + * @brief Get a compiled PCRE2 pattern code from the context's pattern hash table. * - * If the pattern is not found, it is compiled, serialized and cached in @p ctx . + * @param[in] ctx Context to get the pattern code from. + * @param[in] pattern Pattern string to search for. + * @param[out] pcode Compiled pattern code. + * @return LY_ERR value. + */ +LY_ERR ly_ctx_get_pattern_code(const struct ly_ctx *ctx, const char *pattern, pcre2_code **pcode); + +/** + * @brief Compile a pattern string into a PCRE2 code and store it in the context's pattern hash table. + * + * If the pattern is already compiled and stored, it is not recompiled. * * @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 pointer to the pattern code, if not NULL, it will be set to the compiled pattern code. + * @return LY_ERR value. */ -LY_ERR ly_ctx_get_or_create_pattern_code(const struct ly_ctx *ctx, const char *pattern, pcre2_code **pcode); +LY_ERR ly_ctx_compile_and_cache_pattern_code(const struct ly_ctx *ctx, const char *pattern); /****************************************************************************** * Dictionary diff --git a/src/plugins_types.c b/src/plugins_types.c index 4ac266d09..d1d7da4b4 100644 --- a/src/plugins_types.c +++ b/src/plugins_types.c @@ -536,7 +536,7 @@ lyplg_type_validate_patterns(const struct ly_ctx *ctx, struct lysc_pattern **pat LY_ARRAY_FOR(patterns, u) { /* get the compiled pattern */ - LY_CHECK_RET(ly_ctx_get_or_create_pattern_code(ctx, patterns[u]->expr, &pcode)); + LY_CHECK_RET(ly_ctx_get_pattern_code(ctx, patterns[u]->expr, &pcode)); /* match the pattern */ r = ly_pattern_code_match(pcode, str, str_len, err); diff --git a/src/schema_compile_node.c b/src/schema_compile_node.c index fb99103a3..c3ed31fb6 100644 --- a/src/schema_compile_node.c +++ b/src/schema_compile_node.c @@ -1387,7 +1387,7 @@ lys_compile_type_patterns(struct lysc_ctx *ctx, const struct lysp_restr *pattern ++(*pattern)->refcount; /* compile and insert the pattern into the context hash table, if it wasnt already compiled */ - LY_CHECK_GOTO(ret = ly_ctx_get_or_create_pattern_code(ctx->ctx, &patterns_p[u].arg.str[1], NULL), done); + LY_CHECK_GOTO(ret = ly_ctx_compile_and_cache_pattern_code(ctx->ctx, &patterns_p[u].arg.str[1]), done); if (patterns_p[u].arg.str[0] == LYSP_RESTR_PATTERN_NACK) { (*pattern)->inverted = 1; From 404ed52bcfab93dc875cb785b7eb15b412b34bf8 Mon Sep 17 00:00:00 2001 From: roman Date: Thu, 24 Jul 2025 12:42:40 +0200 Subject: [PATCH 89/99] schema compile node BUGFIX free on error --- src/schema_compile_node.c | 7 ++++--- src/tree_schema_free.c | 9 +-------- src/tree_schema_free.h | 9 +++++++++ 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/schema_compile_node.c b/src/schema_compile_node.c index c3ed31fb6..a0141bc35 100644 --- a/src/schema_compile_node.c +++ b/src/schema_compile_node.c @@ -388,9 +388,10 @@ lysc_range_dup(struct lysc_ctx *ctx, const struct lysc_range *orig, struct ly_se return dup; error: - free(dup); - /* set but not used due to the return type */ - (void) ret; + if (dup) { + lysc_range_free(ctx->ctx, dup); + free(dup); + } return NULL; } diff --git a/src/tree_schema_free.c b/src/tree_schema_free.c index 829df78df..8f06b145e 100644 --- a/src/tree_schema_free.c +++ b/src/tree_schema_free.c @@ -808,14 +808,7 @@ lysc_ident_free(const struct ly_ctx *ctx, struct lysc_ident *ident) FREE_ARRAY(ctx, ident->exts, lysc_ext_instance_free); } -/** - * @brief Free the compiled range structure. - * - * @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. - */ -static void +void lysc_range_free(const struct ly_ctx *ctx, struct lysc_range *range) { LY_ARRAY_FREE(range->parts); diff --git a/src/tree_schema_free.h b/src/tree_schema_free.h index 042960dcd..6b9b4ee9a 100644 --- a/src/tree_schema_free.h +++ b/src/tree_schema_free.h @@ -129,6 +129,15 @@ void lysc_ext_instance_free(const struct ly_ctx *ctx, struct lysc_ext_instance * */ void lysc_iffeature_free(const struct ly_ctx *ctx, struct lysc_iffeature *iff); +/** + * @brief Free the compiled range structure. + * + * @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(const struct ly_ctx *ctx, struct lysc_range *range); + /** * @brief Free a compiled pattern. * From 248176334e6297dbdb7bf3b31a08f65264e6f1f4 Mon Sep 17 00:00:00 2001 From: roman Date: Thu, 24 Jul 2025 14:08:12 +0200 Subject: [PATCH 90/99] ly_common UPDATE make global ctx data static --- src/ly_common.c | 14 ++++++++------ src/ly_common.h | 7 ------- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/src/ly_common.c b/src/ly_common.c index e0233843c..a55034749 100644 --- a/src/ly_common.c +++ b/src/ly_common.c @@ -43,14 +43,16 @@ #include "version.h" #include "xml.h" -/* lock for creating/destroying ctx data */ -pthread_rwlock_t ly_ctx_data_rwlock = PTHREAD_RWLOCK_INITIALIZER; +/**< lock for creating and destroying both private & shared context data */ +static pthread_rwlock_t ly_ctx_data_rwlock = PTHREAD_RWLOCK_INITIALIZER; -/* sized array of thread-specific context data */ -struct ly_ctx_private_data *ly_private_ctx_data; +/**< 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 of shared context data */ -struct ly_ctx_shared_data *ly_shared_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) diff --git a/src/ly_common.h b/src/ly_common.h index befd68629..e491cdafb 100644 --- a/src/ly_common.h +++ b/src/ly_common.h @@ -374,13 +374,6 @@ struct ly_ctx_shared_data { struct ly_ht *leafref_links_ht; /**< hash table of leafref links between term data nodes */ }; -extern pthread_rwlock_t ly_ctx_data_rwlock; /**< lock for creating and destroying both private & shared context data */ -extern struct ly_ctx_private_data *ly_private_ctx_data; /**< 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. */ -extern struct ly_ctx_shared_data *ly_shared_ctx_data; /**< sized array ([sized array](@ref sizedarrays)) of shared context data. - * The context is identified by the memory address of the context. */ - #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 */ From f8974e9eae15ce8f206790508021a8dca42dceb8 Mon Sep 17 00:00:00 2001 From: roman Date: Thu, 24 Jul 2025 14:09:08 +0200 Subject: [PATCH 91/99] libyang REFACTOR comments --- src/context.h | 2 +- src/plugins.c | 2 ++ src/tree_schema.h | 22 +++++++++++----------- src/tree_schema_internal.h | 7 ++++--- tools/lint/common.h | 2 +- 5 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/context.h b/src/context.h index 368e79030..79bf03a19 100644 --- a/src/context.h +++ b/src/context.h @@ -461,7 +461,7 @@ LIBYANG_API_DECL void ly_ctx_set_module_imp_clb(struct ly_ctx *ctx, ly_module_im * * @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 be NULL! + * (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. diff --git a/src/plugins.c b/src/plugins.c index 4a2adb0b9..ee0d89b0b 100644 --- a/src/plugins.c +++ b/src/plugins.c @@ -129,6 +129,8 @@ struct lyplg_record { #ifndef STATIC static struct ly_set plugins_handlers; #endif + +/* global sets of loaded plugins */ struct ly_set ly_plugins_types; struct ly_set ly_plugins_extensions; diff --git a/src/tree_schema.h b/src/tree_schema.h index 57d59fdc3..256595336 100644 --- a/src/tree_schema.h +++ b/src/tree_schema.h @@ -1278,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)) */ - uintptr_t plugin_ref; /**< reference to type plugin, use ::lysc_get_ext_plugin() to get the 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) */ @@ -1287,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)) */ - uintptr_t plugin_ref; /**< reference to type plugin, use ::lysc_get_ext_plugin() to get the 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 */ @@ -1297,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)) */ - uintptr_t plugin_ref; /**< reference to type plugin, use ::lysc_get_ext_plugin() to get the 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 */ @@ -1308,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)) */ - uintptr_t plugin_ref; /**< reference to type plugin, use ::lysc_get_ext_plugin() to get the 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 */ @@ -1333,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)) */ - uintptr_t plugin_ref; /**< reference to type plugin, use ::lysc_get_ext_plugin() to get the 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 */ @@ -1343,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)) */ - uintptr_t plugin_ref; /**< reference to type plugin, use ::lysc_get_ext_plugin() to get the 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 */ @@ -1354,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)) */ - uintptr_t plugin_ref; /**< reference to type plugin, use ::lysc_get_ext_plugin() to get the 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 */ @@ -1367,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)) */ - uintptr_t plugin_ref; /**< reference to type plugin, use ::lysc_get_ext_plugin() to get the 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 */ @@ -1378,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)) */ - uintptr_t plugin_ref; /**< reference to type plugin, use ::lysc_get_ext_plugin() to get the 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 */ @@ -1388,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)) */ - uintptr_t plugin_ref; /**< reference to type plugin, use ::lysc_get_ext_plugin() to get the 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 */ @@ -1398,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)) */ - uintptr_t plugin_ref; /**< reference to type plugin, use ::lysc_get_ext_plugin() to get the 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 */ diff --git a/src/tree_schema_internal.h b/src/tree_schema_internal.h index a2e3a6feb..0842e1008 100644 --- a/src/tree_schema_internal.h +++ b/src/tree_schema_internal.h @@ -185,9 +185,10 @@ struct lysp_yin_ctx { * @brief Internal pattern hash table record. */ struct ly_pattern_ht_rec { - const char *pattern; /**< Pattern string, used both as key and for comparison. */ - uint8_t *serialized_pattern; /**< Serialized pattern code for this pattern, - can be deserialized to pcre2_code that can be used directly. */ + const char *pattern; /**< Pattern string, used both as key to hash and value to search for. */ + uint8_t *serialized_pattern; /**< Serialized pattern code for this pattern. + Can be deserialized to a compiled pcre2_code that can be used directly, + see ::ly_pcode_deserialize(). */ }; /** diff --git a/tools/lint/common.h b/tools/lint/common.h index f342cc208..9e909a3b0 100644 --- a/tools/lint/common.h +++ b/tools/lint/common.h @@ -122,7 +122,7 @@ 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 aprent, unused. + * @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. From 08871a68b954bf785cde82e5f027d739f2e28afc Mon Sep 17 00:00:00 2001 From: roman Date: Thu, 24 Jul 2025 14:09:50 +0200 Subject: [PATCH 92/99] tree data BUGFIX missing mutex unlock --- src/tree_data.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/tree_data.c b/src/tree_data.c index aeda95bef..7cfc9ba12 100644 --- a/src/tree_data.c +++ b/src/tree_data.c @@ -3769,14 +3769,13 @@ lyd_get_or_create_leafref_links_record(const struct lyd_node_term *node, struct 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) { - 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(ctx_data->leafref_links_ht, &rec_p, hash, (void **)&rec_p2); - LY_CHECK_ERR_GOTO(ret, free(rec_p), cleanup); - } + 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: From 37e1ae2ef9643192157fcb9b24d37fc85bea4d37 Mon Sep 17 00:00:00 2001 From: roman Date: Thu, 24 Jul 2025 14:10:15 +0200 Subject: [PATCH 93/99] test schema UPDATE use malloc instead of mmap --- tests/utests/schema/test_schema.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/tests/utests/schema/test_schema.c b/tests/utests/schema/test_schema.c index 2d1f285d8..c23d8383c 100644 --- a/tests/utests/schema/test_schema.c +++ b/tests/utests/schema/test_schema.c @@ -2123,7 +2123,7 @@ test_lysc_backlinks(void **state) static void test_compiled_print(void **state) { - int size, fd; + int size; void *mem, *mem_end; struct lyd_node *tree = NULL; struct ly_ctx *printed_ctx = NULL, *printed_ctx2 = NULL; @@ -2203,12 +2203,9 @@ test_compiled_print(void **state) /* get the size of the compiled ctx */ size = ly_ctx_compiled_size(UTEST_LYCTX); - /* prepare the shared memory segment */ - fd = shm_open("/ly_test_schema_ctx", O_RDWR | O_CREAT, 00600); - assert_int_not_equal(fd, -1); - ftruncate(fd, size); - mem = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - assert_ptr_not_equal(mem, MAP_FAILED); + /* 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)); @@ -2267,9 +2264,7 @@ test_compiled_print(void **state) /* cleanup */ ly_ctx_destroy(printed_ctx); - munmap(mem, size); - close(fd); - shm_unlink("/ly_test_schema_ctx"); + free(mem); } int From 6a5ca8545efb452fc1b92eea55a0aaa892a40cfa Mon Sep 17 00:00:00 2001 From: roman Date: Thu, 24 Jul 2025 16:00:12 +0200 Subject: [PATCH 94/99] ly common UPDATE do not store serialized pcodes --- src/ly_common.c | 162 +++++++------------------------------ src/ly_common.h | 17 +--- src/plugins_types.c | 8 +- src/schema_compile_node.c | 2 +- src/tree_data_common.c | 2 +- src/tree_data_internal.h | 2 +- src/tree_schema_internal.h | 4 +- 7 files changed, 40 insertions(+), 157 deletions(-) diff --git a/src/ly_common.c b/src/ly_common.c index a55034749..09e5a5bb3 100644 --- a/src/ly_common.c +++ b/src/ly_common.c @@ -124,9 +124,9 @@ ly_ctx_ht_pattern_free_cb(void *val_p) { struct ly_pattern_ht_rec *val = val_p; - if (val->serialized_pattern) { + if (val->pcode) { /* free the pcode */ - pcre2_serialize_free(val->serialized_pattern); + pcre2_code_free(val->pcode); } } @@ -488,160 +488,54 @@ ly_ctx_data_del(const struct ly_ctx *ctx) pthread_rwlock_unlock(&ly_ctx_data_rwlock); } -/** - * @brief Serialize a PCRE2 compiled code. - * - * @param[in] pcode PCRE2 compiled code to serialize. - * @param[out] serialized_code Pointer to the serialized code, must be freed by the caller. - * @return LY_SUCCESS on success, LY_EINT on serialization error. - */ -static LY_ERR -ly_pcode_serialize(const pcre2_code *pcode, uint8_t **serialized_code) -{ - int r; - uint8_t *ser_code = NULL; - PCRE2_SIZE ser_code_size = 0; - - *serialized_code = NULL; - - r = pcre2_serialize_encode(&pcode, 1, &ser_code, &ser_code_size, NULL); - if (r < 0) { - PCRE2_UCHAR err_msg[LY_PCRE2_MSG_LIMIT] = {0}; - - pcre2_get_error_message(r, err_msg, LY_PCRE2_MSG_LIMIT); - LOGERR(NULL, LY_EINT, "PCRE2 compiled code serialization failed (%s).", err_msg); - return LY_EINT; - } - - *serialized_code = ser_code; - return LY_SUCCESS; -} - -/** - * @brief Deserialize a PCRE2 compiled code from its serialized form. - * - * This code does not have to be recompiled, it can be used directly. - * - * @param[in] serialized_code Serialized PCRE2 compiled code. - * @param[out] pcode Pointer to the deserialized PCRE2 code, must be freed by the caller. - * @return LY_SUCCESS on success, LY_EINT on deserialization error. - */ -static LY_ERR -ly_pcode_deserialize(const uint8_t *serialized_code, pcre2_code **pcode) -{ - int r; - pcre2_code *pcode_tmp = NULL; - - *pcode = NULL; - - /* deserialize the pcode */ - r = pcre2_serialize_decode(&pcode_tmp, 1, serialized_code, NULL); - if (r < 0) { - PCRE2_UCHAR err_msg[LY_PCRE2_MSG_LIMIT] = {0}; - - pcre2_get_error_message(r, err_msg, LY_PCRE2_MSG_LIMIT); - LOGERR(NULL, LY_EINT, "PCRE2 compiled code deserialization failed (%s).", err_msg); - return LY_EINT; - } - - *pcode = pcode_tmp; - return LY_SUCCESS; -} - -/** - * @brief Get a compiled PCRE2 pattern code from the context's pattern hash table. - * - * @param[in] ctx Context to get the pattern code from. - * @param[in] pattern Pattern string to search for. - * @param[in] pattern_ht Pattern hash table to search in. - * @param[out] pcode Optional compiled pattern code, must be freed by the caller. - * If NULL, the function only checks if the pattern exists in the hash table. - * @return LY_SUCCESS on success, LY_ENOTFOUND if the pattern was not found, - * other LY_ERR values on error. - */ -static LY_ERR -_ly_ctx_get_pattern_code(const struct ly_ctx *ctx, const char *pattern, - struct ly_ht *pattern_ht, pcre2_code **pcode) -{ - LY_ERR rc = LY_SUCCESS; - uint32_t hash; - struct ly_pattern_ht_rec rec = {0}, *found_rec = NULL; - - assert(ctx && pattern && pattern_ht); - - /* use the pattern as a key */ - rec.pattern = pattern; - rec.serialized_pattern = NULL; - hash = lyht_hash(pattern, strlen(pattern)); - - /* try to find the record */ - LY_CHECK_GOTO(rc = lyht_find(pattern_ht, &rec, hash, (void **)&found_rec), cleanup); - - if (pcode) { - /* found it, deserialize the pcode */ - LY_CHECK_GOTO(rc = ly_pcode_deserialize(found_rec->serialized_pattern, pcode), cleanup); - } - -cleanup: - return rc; -} - LY_ERR -ly_ctx_get_pattern_code(const struct ly_ctx *ctx, const char *pattern, pcre2_code **pcode) +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; - ctx_data = ly_ctx_shared_data_get(ctx); - LY_CHECK_RET(!ctx_data, LY_EINT); + assert(ctx && pattern); - rc = _ly_ctx_get_pattern_code(ctx, pattern, ctx_data->pattern_ht, pcode); - if (rc) { - LOGERR(ctx, rc, "Failed to get pattern code for \"%s\".", pattern); + if (pcode) { + *pcode = NULL; } - return rc; -} - -LY_ERR -ly_ctx_compile_and_cache_pattern_code(const struct ly_ctx *ctx, const char *pattern) -{ - LY_ERR rc = LY_SUCCESS; - struct ly_ctx_shared_data *ctx_data; - uint8_t *serialized_pcode = NULL; - pcre2_code *pcode_tmp = NULL; - struct ly_pattern_ht_rec rec = {0}; - uint32_t hash; - ctx_data = ly_ctx_shared_data_get(ctx); LY_CHECK_RET(!ctx_data, LY_EINT); - /* check for existing pattern code */ - rc = _ly_ctx_get_pattern_code(ctx, pattern, ctx_data->pattern_ht, NULL); - LY_CHECK_GOTO(rc && (rc != LY_ENOTFOUND), cleanup); - if (!rc) { - /* pattern is already compiled and stored, nothing to do */ + /* 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; } - /* record not found, we need to compile the pattern and insert it */ + /* didnt find it, need to compile it */ LY_CHECK_GOTO(rc = lys_compile_type_pattern_check(ctx, pattern, &pcode_tmp), cleanup); - /* serialize the pcode */ - LY_CHECK_GOTO(rc = ly_pcode_serialize(pcode_tmp, &serialized_pcode), cleanup); - - /* insert the record */ + /* store the compiled pattern code in the hash table */ hash = lyht_hash(pattern, strlen(pattern)); rec.pattern = pattern; - rec.serialized_pattern = serialized_pcode; + rec.pcode = pcode_tmp; LY_CHECK_GOTO(rc = lyht_insert_no_check(ctx_data->pattern_ht, &rec, hash, NULL), cleanup); - /* dont free the serialized pcode, it is now owned by the record in the hash table */ - serialized_pcode = NULL; + if (pcode) { + *pcode = pcode_tmp; + pcode_tmp = NULL; + } cleanup: - pcre2_code_free(pcode_tmp); - pcre2_serialize_free(serialized_pcode); + if (rc) { + /* only free the pcode if we failed, because it belongs to the hash table */ + pcre2_code_free(pcode_tmp); + } return rc; } diff --git a/src/ly_common.h b/src/ly_common.h index e491cdafb..db95f0b1d 100644 --- a/src/ly_common.h +++ b/src/ly_common.h @@ -476,25 +476,16 @@ void ly_ctx_ht_leafref_links_rec_free(void *val_p); struct lys_module *ly_ctx_get_module_implemented2(const struct ly_ctx *ctx, const char *name, size_t name_len); /** - * @brief Get a compiled PCRE2 pattern code from the context's pattern hash table. + * @brief Get or compile a PCRE2 pattern code. * - * @param[in] ctx Context to get the pattern code from. - * @param[in] pattern Pattern string to search for. - * @param[out] pcode Compiled pattern code. - * @return LY_ERR value. - */ -LY_ERR ly_ctx_get_pattern_code(const struct ly_ctx *ctx, const char *pattern, pcre2_code **pcode); - -/** - * @brief Compile a pattern string into a PCRE2 code and store it in the context's pattern hash table. - * - * If the pattern is already compiled and stored, it is not recompiled. + * 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_compile_and_cache_pattern_code(const struct ly_ctx *ctx, const char *pattern); +LY_ERR ly_ctx_get_or_compile_pattern_code(const struct ly_ctx *ctx, const char *pattern, const pcre2_code **pcode); /****************************************************************************** * Dictionary diff --git a/src/plugins_types.c b/src/plugins_types.c index d1d7da4b4..4158837fb 100644 --- a/src/plugins_types.c +++ b/src/plugins_types.c @@ -528,19 +528,19 @@ lyplg_type_validate_patterns(const struct ly_ctx *ctx, struct lysc_pattern **pat { LY_ERR r; LY_ARRAY_COUNT_TYPE u; - pcre2_code *pcode; + const pcre2_code *pcode; LY_CHECK_ARG_RET(NULL, str, err, LY_EINVAL); *err = NULL; LY_ARRAY_FOR(patterns, u) { - /* get the compiled pattern */ - LY_CHECK_RET(ly_ctx_get_pattern_code(ctx, patterns[u]->expr, &pcode)); + /* 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); - pcre2_code_free(pcode); LY_CHECK_RET(r && (r != LY_ENOT), r); if (((r == LY_ENOT) && !patterns[u]->inverted) || ((r == LY_SUCCESS) && patterns[u]->inverted)) { diff --git a/src/schema_compile_node.c b/src/schema_compile_node.c index a0141bc35..1ee469751 100644 --- a/src/schema_compile_node.c +++ b/src/schema_compile_node.c @@ -1388,7 +1388,7 @@ lys_compile_type_patterns(struct lysc_ctx *ctx, const struct lysp_restr *pattern ++(*pattern)->refcount; /* compile and insert the pattern into the context hash table, if it wasnt already compiled */ - LY_CHECK_GOTO(ret = ly_ctx_compile_and_cache_pattern_code(ctx->ctx, &patterns_p[u].arg.str[1]), done); + 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; diff --git a/src/tree_data_common.c b/src/tree_data_common.c index bd1c0fa58..30babc7f6 100644 --- a/src/tree_data_common.c +++ b/src/tree_data_common.c @@ -1855,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_internal.h b/src/tree_data_internal.h index f35253a6a..9c67e73cb 100644 --- a/src/tree_data_internal.h +++ b/src/tree_data_internal.h @@ -797,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_schema_internal.h b/src/tree_schema_internal.h index 0842e1008..d4981a59f 100644 --- a/src/tree_schema_internal.h +++ b/src/tree_schema_internal.h @@ -186,9 +186,7 @@ struct lysp_yin_ctx { */ struct ly_pattern_ht_rec { const char *pattern; /**< Pattern string, used both as key to hash and value to search for. */ - uint8_t *serialized_pattern; /**< Serialized pattern code for this pattern. - Can be deserialized to a compiled pcre2_code that can be used directly, - see ::ly_pcode_deserialize(). */ + pcre2_code *pcode; /**< Compiled PCRE2 pattern code. */ }; /** From f1e83af7e18d3f95144a52d9e026849869fca021 Mon Sep 17 00:00:00 2001 From: roman Date: Mon, 28 Jul 2025 10:38:43 +0200 Subject: [PATCH 95/99] build UPDATE move define from cmake to where its used --- CMakeLists.txt | 2 +- src/ly_common.c | 2 ++ tests/utests/utests.h | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e83200936..2d2d8bd66 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -76,7 +76,7 @@ if(WIN32) set(CMAKE_C_FLAGS "/Zc:preprocessor /W3 /wd4711 /w14013 /utf-8 ${CMAKE_C_FLAGS}") else() # global C flags (POSIX source because of pthread_rwlock_t) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wpedantic -std=c11 -D_POSIX_C_SOURCE=200809L") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wpedantic -std=c11") endif() include_directories(${PROJECT_BINARY_DIR}/libyang ${PROJECT_SOURCE_DIR}/src ${PROJECT_SOURCE_DIR}/src/plugins_exts) diff --git a/src/ly_common.c b/src/ly_common.c index 09e5a5bb3..abf0daba7 100644 --- a/src/ly_common.c +++ b/src/ly_common.c @@ -43,6 +43,8 @@ #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; diff --git a/tests/utests/utests.h b/tests/utests/utests.h index 4d5529ab4..8449b3e07 100644 --- a/tests/utests/utests.h +++ b/tests/utests/utests.h @@ -17,6 +17,8 @@ #ifndef _UTESTS_H_ #define _UTESTS_H_ +#define _GNU_SOURCE /* strdup, setenv, tzset */ + #include #include #include From e3aec66c3ba12d7d6b0e2745c8c1326126c498a7 Mon Sep 17 00:00:00 2001 From: roman Date: Mon, 28 Jul 2025 11:27:07 +0200 Subject: [PATCH 96/99] context REFACTOR move leafref links cb to ly_common --- src/context.c | 17 ----------------- src/ly_common.c | 23 +++++++++++++++++++++++ 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/src/context.c b/src/context.c index 67a206ef1..d53f0eb93 100644 --- a/src/context.c +++ b/src/context.c @@ -259,14 +259,6 @@ ly_ctx_load_module(struct ly_ctx *ctx, const char *name, const char *revision, c return mod; } -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; -} - LIBYANG_API_DEF LY_ERR ly_ctx_new(const char *search_dir, uint32_t options, struct ly_ctx **new_ctx) { @@ -685,15 +677,6 @@ lysc_node_clear_priv_dfs_cb(struct lysc_node *node, void *UNUSED(data), ly_bool return LY_SUCCESS; } -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_unset_options(struct ly_ctx *ctx, uint32_t option) { diff --git a/src/ly_common.c b/src/ly_common.c index abf0daba7..3539ddbf4 100644 --- a/src/ly_common.c +++ b/src/ly_common.c @@ -104,6 +104,29 @@ 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. */ From 07f391d1e574dd27185e7c2833f238f3d57c1db8 Mon Sep 17 00:00:00 2001 From: roman Date: Mon, 28 Jul 2025 11:27:42 +0200 Subject: [PATCH 97/99] ly_common REFACTOR clarify printed and shared data --- src/ly_common.h | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/ly_common.h b/src/ly_common.h index db95f0b1d..5a8602b7e 100644 --- a/src/ly_common.h +++ b/src/ly_common.h @@ -335,9 +335,12 @@ int LY_VCODE_INSTREXP_len(const char *str); *****************************************************************************/ /** - * @brief Private context data. + * @brief Private run-time context data. * - * Run-time data for a context, used by the library internally. + * 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 */ @@ -347,9 +350,12 @@ struct ly_ctx_private_data { }; /** - * @brief Shared context data. + * @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. * - * The data is shared only when using printed contexts that are created from the same memory address. + * Members need to be protected by locks. */ struct ly_ctx_shared_data { const struct ly_ctx *ctx; /**< context to which this data belongs */ @@ -429,7 +435,7 @@ 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 if not found. + * @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); From e98dd602f2a767db77174991e8a64c0e0a26b6c4 Mon Sep 17 00:00:00 2001 From: roman Date: Mon, 28 Jul 2025 11:28:04 +0200 Subject: [PATCH 98/99] schema mount BUGFIX check for printed context Check for printed context before trying to lock/find/create any inline sm contexts - they do not get printed so they cant be found, it would just crash. --- src/plugins_exts/schema_mount.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/plugins_exts/schema_mount.c b/src/plugins_exts/schema_mount.c index 120274540..3afeab040 100644 --- a/src/plugins_exts/schema_mount.c +++ b/src/plugins_exts/schema_mount.c @@ -718,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)); From 38f6cb2f121371e8778ebc003af7fbeb5b6d77e8 Mon Sep 17 00:00:00 2001 From: roman Date: Mon, 28 Jul 2025 11:37:17 +0200 Subject: [PATCH 99/99] plugins exts REFACTOR clarify inline destroy usecase --- src/plugins_exts.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/plugins_exts.h b/src/plugins_exts.h index cbdcae6d7..1733712ad 100644 --- a/src/plugins_exts.h +++ b/src/plugins_exts.h @@ -1172,8 +1172,10 @@ LIBYANG_API_DECL void lyplg_ext_schema_mount_destroy_shared_contexts(struct lysc * @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 not supported in printed 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.