schema tree FEATURE functions for lysc node full dfs
diff --git a/src/plugins_exts_nacm.c b/src/plugins_exts_nacm.c
index 7012e66..8589bce 100644
--- a/src/plugins_exts_nacm.c
+++ b/src/plugins_exts_nacm.c
@@ -24,6 +24,49 @@
LYEXT_VERSION_CHECK
*/
+struct nacm_dfs_arg {
+ struct lysc_ext_instance *c_ext;
+ struct lysc_node *parent;
+};
+
+/**
+ * @brief DFS callback implementation for inheriting the NACM extension.
+ */
+static LY_ERR
+nacm_inherit_clb(struct lysc_node *node, void *data, ly_bool *dfs_continue)
+{
+ struct nacm_dfs_arg *arg = data;
+ struct lysc_ext_instance *inherited;
+ LY_ARRAY_COUNT_TYPE u;
+
+ /* ignore the parent from which we inherit and input/output nodes */
+ if ((node != arg->parent) && !(node->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
+ /* check that the node does not have its own NACM extension instance */
+ LY_ARRAY_FOR(node->exts, u) {
+ if (node->exts[u].def == arg->c_ext->def) {
+ /* the child already have its own NACM flag, so skip the subtree */
+ *dfs_continue = 1;
+ return LY_SUCCESS;
+ }
+ }
+
+ /* duplicate this one to inherit it to the child */
+ LY_ARRAY_NEW_RET(node->module->ctx, node->exts, inherited, LY_EMEM);
+
+ inherited->def = lysc_ext_dup(arg->c_ext->def);
+ inherited->parent = node;
+ inherited->parent_type = LYEXT_PAR_NODE;
+ if (arg->c_ext->argument) {
+ LY_CHECK_RET(lydict_insert(node->module->ctx, arg->c_ext->argument, strlen(arg->c_ext->argument),
+ &inherited->argument));
+ }
+ /* TODO duplicate extension instances */
+ inherited->data = arg->c_ext->data;
+ }
+
+ return LY_SUCCESS;
+}
+
/**
* @brief Compile NAMC's extension instances.
*
@@ -32,9 +75,9 @@
LY_ERR
nacm_compile(struct lysc_ctx *cctx, const struct lysp_ext_instance *p_ext, struct lysc_ext_instance *c_ext)
{
- struct lysc_node *parent = NULL, *iter;
- struct lysc_ext_instance *inherited;
+ struct lysc_node *parent = NULL;
LY_ARRAY_COUNT_TYPE u;
+ struct nacm_dfs_arg dfs_arg;
static const uint8_t nacm_deny_all = 1;
static const uint8_t nacm_deny_write = 2;
@@ -85,33 +128,9 @@
}
/* inherit the extension instance to all the children nodes */
- LYSC_TREE_DFS_BEGIN(parent, iter) {
- /* ignore the parent from which we inherit and input/output nodes */
- if ((iter != parent) && !(iter->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
- /* check that the node does not have its own NACM extension instance */
- LY_ARRAY_FOR(iter->exts, u) {
- if (iter->exts[u].def == c_ext->def) {
- /* the child already have its own NACM flag, so skip the subtree */
- LYSC_TREE_DFS_continue = 1;
- break;
- }
- }
- if (!LYSC_TREE_DFS_continue) {
- /* duplicate this one to inherit it to the child */
- LY_ARRAY_NEW_RET(cctx->ctx, iter->exts, inherited, LY_EMEM);
-
- inherited->def = lysc_ext_dup(c_ext->def);
- inherited->parent = iter;
- inherited->parent_type = LYEXT_PAR_NODE;
- if (c_ext->argument) {
- LY_CHECK_RET(lydict_insert(cctx->ctx, c_ext->argument, strlen(c_ext->argument), &inherited->argument));
- }
- /* TODO duplicate extension instances */
- inherited->data = c_ext->data;
- }
- }
- LYSC_TREE_DFS_END(parent, iter)
- }
+ dfs_arg.c_ext = c_ext;
+ dfs_arg.parent = parent;
+ LY_CHECK_RET(lysc_tree_dfs_full(parent, nacm_inherit_clb, &dfs_arg));
return LY_SUCCESS;
}
diff --git a/src/tree_schema.c b/src/tree_schema.c
index a898cb1..204fb51 100644
--- a/src/tree_schema.c
+++ b/src/tree_schema.c
@@ -42,6 +42,67 @@
#include "tree_schema_internal.h"
#include "xpath.h"
+API LY_ERR
+lysc_tree_dfs_full(const struct lysc_node *root, lysc_dfs_clb dfs_clb, void *data)
+{
+ struct lysc_node *elem, *ops, *elem2;
+ LY_ARRAY_COUNT_TYPE u;
+
+ LY_CHECK_ARG_RET(NULL, root, dfs_clb, LY_EINVAL);
+
+ LYSC_TREE_DFS_BEGIN(root, elem) {
+ /* schema node */
+ LY_CHECK_RET(dfs_clb(elem, data, &LYSC_TREE_DFS_continue));
+
+ ops = (struct lysc_node *)lysc_node_actions(elem);
+ LY_ARRAY_FOR(ops, u) {
+ LYSC_TREE_DFS_BEGIN(&ops[u], elem2) {
+ /* action subtree */
+ LY_CHECK_RET(dfs_clb(elem2, data, &LYSC_TREE_DFS_continue));
+
+ LYSC_TREE_DFS_END(&ops[u], elem2);
+ }
+ }
+
+ ops = (struct lysc_node *)lysc_node_notifs(elem);
+ LY_ARRAY_FOR(ops, u) {
+ LYSC_TREE_DFS_BEGIN(&ops[u], elem2) {
+ /* notification subtree */
+ LY_CHECK_RET(dfs_clb(elem2, data, &LYSC_TREE_DFS_continue));
+
+ LYSC_TREE_DFS_END(&ops[u], elem2);
+ }
+ }
+
+ LYSC_TREE_DFS_END(root, elem);
+ }
+
+ return LY_SUCCESS;
+}
+
+API LY_ERR
+lysc_module_dfs_full(const struct lys_module *mod, lysc_dfs_clb dfs_clb, void *data)
+{
+ LY_ARRAY_COUNT_TYPE u;
+
+ LY_CHECK_ARG_RET(NULL, mod, mod->compiled, dfs_clb, LY_EINVAL);
+
+ /* schema nodes */
+ LY_CHECK_RET(lysc_tree_dfs_full(mod->compiled->data, dfs_clb, data));
+
+ /* RPCs */
+ LY_ARRAY_FOR(mod->compiled->rpcs, u) {
+ LY_CHECK_RET(lysc_tree_dfs_full((struct lysc_node *)&mod->compiled->rpcs[u], dfs_clb, data));
+ }
+
+ /* notifications */
+ LY_ARRAY_FOR(mod->compiled->notifs, u) {
+ LY_CHECK_RET(lysc_tree_dfs_full((struct lysc_node *)&mod->compiled->notifs[u], dfs_clb, data));
+ }
+
+ return LY_SUCCESS;
+}
+
API const struct lysc_node *
lys_getnext(const struct lysc_node *last, const struct lysc_node *parent, const struct lysc_module *module, uint32_t options)
{
diff --git a/src/tree_schema.h b/src/tree_schema.h
index 8872ad3..f5b7697 100644
--- a/src/tree_schema.h
+++ b/src/tree_schema.h
@@ -1882,6 +1882,48 @@
const struct lysc_node *lysc_node_parent_full(const struct lysc_node *node);
/**
+ * @brief Callback to be called for every schema node in a DFS traversal.
+ *
+ * @param[in] node Current node.
+ * @param[in] data Arbitrary user data.
+ * @param[out] dfs_continue Set to true if the current subtree should be skipped and continue with siblings instead.
+ * @return LY_SUCCESS on success,
+ * @return LY_ERR value to terminate DFS and return this value.
+ */
+typedef LY_ERR (*lysc_dfs_clb)(struct lysc_node *node, void *data, ly_bool *dfs_continue);
+
+/**
+ * @brief DFS traversal of all the schema nodes in a (sub)tree including any actions and nested notifications.
+ *
+ * Node with children, actions, and notifications is traversed in this order:
+ * 1) each child subtree;
+ * 2) each action subtree;
+ * 3) each notification subtree.
+ *
+ * For algorithm illustration or traversal with actions and notifications skipped, see ::LYSC_TREE_DFS_BEGIN.
+ *
+ * @param[in] root Schema root to fully traverse.
+ * @param[in] dfs_clb Callback to call for each node.
+ * @param[in] data Arbitrary user data passed to @p dfs_clb.
+ * @return LY_SUCCESS on success,
+ * @return LY_ERR value returned by @p dfs_clb.
+ */
+LY_ERR lysc_tree_dfs_full(const struct lysc_node *root, lysc_dfs_clb dfs_clb, void *data);
+
+/**
+ * @brief DFS traversal of all the schema nodes in a module including RPCs and notifications.
+ *
+ * For more details, see ::lysc_tree_dfs_full().
+ *
+ * @param[in] mod Module to fully traverse.
+ * @param[in] dfs_clb Callback to call for each node.
+ * @param[in] data Arbitrary user data passed to @p dfs_clb.
+ * @return LY_SUCCESS on success,
+ * @return LY_ERR value returned by @p dfs_clb.
+ */
+LY_ERR lysc_module_dfs_full(const struct lys_module *mod, lysc_dfs_clb dfs_clb, void *data);
+
+/**
* @brief Examine whether a node is user-ordered list or leaf-list.
*
* @param[in] schema Schema node to examine.