context FEATURE added LY_CTX_SET_PRIV_PARSED
With this option, libyang sets ::lysc_node.priv pointers
as a reference to the corresponding ::lysp_node.
This was introduced due to the printer tree module (RFC 8340),
which needs both a compiled and a parsed tree to print.
diff --git a/src/context.c b/src/context.c
index 7ef2cde..de6e4c3 100644
--- a/src/context.c
+++ b/src/context.c
@@ -473,12 +473,30 @@
API LY_ERR
ly_ctx_set_options(struct ly_ctx *ctx, uint16_t option)
{
+ LY_ERR lyrc;
LY_CHECK_ARG_RET(ctx, ctx, LY_EINVAL);
LY_CHECK_ERR_RET(option & LY_CTX_NO_YANGLIBRARY, LOGARG(ctx, option), LY_EINVAL);
+ lyrc = LY_SUCCESS;
+
+ if (!(ctx->flags & LY_CTX_SET_PRIV_PARSED) && (option & LY_CTX_SET_PRIV_PARSED)) {
+ ctx->flags |= LY_CTX_SET_PRIV_PARSED;
+ if ((lyrc = lys_recompile(ctx, 0))) {
+ ly_ctx_unset_options(ctx, LY_CTX_SET_PRIV_PARSED);
+ }
+ }
/* set the option(s) */
- ctx->flags |= option;
+ if (!lyrc) {
+ ctx->flags |= option;
+ }
+ return lyrc;
+}
+
+static LY_ERR
+lysc_node_clear_priv_dfs_cb(struct lysc_node *node, void *UNUSED(data), ly_bool *UNUSED(dfs_continue))
+{
+ node->priv = NULL;
return LY_SUCCESS;
}
@@ -488,6 +506,22 @@
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_SET_PRIV_PARSED) && (option & LY_CTX_SET_PRIV_PARSED)) {
+ struct lys_module *mod;
+ uint32_t index;
+
+ index = 0;
+ while ((mod = (struct lys_module *)ly_ctx_get_module_iter(ctx, &index))) {
+ /* ignore modules that didn't compile */
+ if (!mod->compiled) {
+ continue;
+ }
+
+ /* set NULL for all ::lysc_node.priv pointers in module */
+ lysc_module_dfs_full(mod, lysc_node_clear_priv_dfs_cb, NULL);
+ }
+ }
+
/* unset the option(s) */
ctx->flags &= ~option;
diff --git a/src/context.h b/src/context.h
index eba0fa2..cda1212 100644
--- a/src/context.h
+++ b/src/context.h
@@ -185,6 +185,12 @@
directory, which is by default searched automatically (despite not
recursively). */
#define LY_CTX_PREFER_SEARCHDIRS 0x20 /**< When searching for schema, prefer searchdirs instead of user callback. */
+#define LY_CTX_SET_PRIV_PARSED 0x40 /**< For all compiled nodes, their private objects (::lysc_node.priv) are used
+ by libyang as a reference to the corresponding parsed node (::lysp_node).
+ So if this option is set, the user must not change private objects.
+ Setting this option by ::ly_ctx_set_options() may result in context recompilation.
+ Resetting this option by ::ly_ctx_unset_options() cause that private
+ objects will be set to NULL. */
/** @} contextoptions */
@@ -314,6 +320,8 @@
* @brief Set some of the context's options, see @ref contextoptions.
* @param[in] ctx Context to be modified.
* @param[in] option Combination of the context's options to be set, see @ref contextoptions.
+ * If there is to be a change to ::LY_CTX_SET_PRIV_PARSED, the context will be recompiled
+ * and all ::lysc_node.priv in the modules will be overwritten, see ::LY_CTX_SET_PRIV_PARSED.
* @return LY_ERR value.
*/
LY_ERR ly_ctx_set_options(struct ly_ctx *ctx, uint16_t option);
diff --git a/src/schema_compile_node.c b/src/schema_compile_node.c
index c022261..2808430 100644
--- a/src/schema_compile_node.c
+++ b/src/schema_compile_node.c
@@ -2395,6 +2395,7 @@
node->module = ctx->cur_mod;
node->parent = parent;
node->prev = node;
+ node->priv = ctx->ctx->flags & 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);
diff --git a/src/tree_schema.h b/src/tree_schema.h
index 9be02a3..d54ac09 100644
--- a/src/tree_schema.h
+++ b/src/tree_schema.h
@@ -72,7 +72,8 @@
* the default nodes are not added into any data tree and mandatory nodes are not checked in the data trees.
*
* The compiled schema tree nodes are able to hold private objects (::lysc_node.priv as a pointer to a structure,
- * function, variable, ...) used by a caller application.
+ * function, variable, ...) used by a caller application unless ::LY_CTX_SET_PRIV_PARSED is set, in that case
+ * the ::lysc_node.priv pointers are used by libyang.
* Note that the object is not freed by libyang when the context is being destroyed. So the caller is responsible
* for freeing the provided structure after the context is destroyed or the private pointer is set to NULL in
* appropriate schema nodes where the object was previously set. This can be automated via destructor function
@@ -1653,7 +1654,7 @@
const char *dsc; /**< description */
const char *ref; /**< reference */
struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
- void *priv; /**< private arbitrary user data, not used by libyang */
+ void *priv; /**< private arbitrary user data, not used by libyang unless ::LY_CTX_SET_PRIV_PARSED is set */
};
struct lysc_node_action_inout {
@@ -1671,7 +1672,7 @@
const char *dsc; /**< ALWAYS NULL, compatibility member with ::lysc_node */
const char *ref; /**< ALWAYS NULL, compatibility member with ::lysc_node */
struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
- void *priv; /** private arbitrary user data, not used by libyang */
+ void *priv; /** private arbitrary user data, not used by libyang unless ::LY_CTX_SET_PRIV_PARSED is set */
};
};
@@ -1697,7 +1698,7 @@
const char *dsc; /**< description */
const char *ref; /**< reference */
struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
- void *priv; /** private arbitrary user data, not used by libyang */
+ void *priv; /** private arbitrary user data, not used by libyang unless ::LY_CTX_SET_PRIV_PARSED is set */
};
};
@@ -1727,7 +1728,7 @@
const char *dsc; /**< description */
const char *ref; /**< reference */
struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
- void *priv; /** private arbitrary user data, not used by libyang */
+ void *priv; /** private arbitrary user data, not used by libyang unless ::LY_CTX_SET_PRIV_PARSED is set */
};
};
@@ -1756,7 +1757,7 @@
const char *dsc; /**< description */
const char *ref; /**< reference */
struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
- void *priv; /**< private arbitrary user data, not used by libyang */
+ void *priv; /**< private arbitrary user data, not used by libyang unless ::LY_CTX_SET_PRIV_PARSED is set */
};
};
@@ -1785,7 +1786,7 @@
const char *dsc; /**< description */
const char *ref; /**< reference */
struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
- void *priv; /**< private arbitrary user data, not used by libyang */
+ void *priv; /**< private arbitrary user data, not used by libyang unless ::LY_CTX_SET_PRIV_PARSED is set */
};
};
@@ -1812,7 +1813,7 @@
const char *dsc; /**< description */
const char *ref; /**< reference */
struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
- void *priv; /**< private arbitrary user data, not used by libyang */
+ void *priv; /**< private arbitrary user data, not used by libyang unless ::LY_CTX_SET_PRIV_PARSED is set */
};
};
@@ -1841,7 +1842,7 @@
const char *dsc; /**< description */
const char *ref; /**< reference */
struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
- void *priv; /**< private arbitrary user data, not used by libyang */
+ void *priv; /**< private arbitrary user data, not used by libyang unless ::LY_CTX_SET_PRIV_PARSED is set */
};
};
@@ -1871,7 +1872,7 @@
const char *dsc; /**< description */
const char *ref; /**< reference */
struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
- void *priv; /**< private arbitrary user data, not used by libyang */
+ void *priv; /**< private arbitrary user data, not used by libyang unless ::LY_CTX_SET_PRIV_PARSED is set */
};
};
@@ -1905,7 +1906,7 @@
const char *dsc; /**< description */
const char *ref; /**< reference */
struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
- void *priv; /**< private arbitrary user data, not used by libyang */
+ void *priv; /**< private arbitrary user data, not used by libyang unless ::LY_CTX_SET_PRIV_PARSED is set */
};
};
@@ -1938,7 +1939,7 @@
const char *dsc; /**< description */
const char *ref; /**< reference */
struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
- void *priv; /**< private arbitrary user data, not used by libyang */
+ void *priv; /**< private arbitrary user data, not used by libyang unless ::LY_CTX_SET_PRIV_PARSED is set */
};
};
diff --git a/src/tree_schema_free.c b/src/tree_schema_free.c
index f39c296..c125e7f 100644
--- a/src/tree_schema_free.c
+++ b/src/tree_schema_free.c
@@ -956,6 +956,10 @@
/* TODO use the destructor, this just suppress warning about unused parameter */
(void) private_destructor;
+ /* TODO if (module->mod->ctx->flags & LY_CTX_SET_PRIV_PARSED) is true, then
+ * don't use the destructor because private pointers are used by libyang.
+ */
+
if (module) {
lysc_module_free_(module);
}