data tree REFACTOR data DFS should match schema DFS
diff --git a/src/diff.c b/src/diff.c
index a4c1f06..251d259 100644
--- a/src/diff.c
+++ b/src/diff.c
@@ -1656,7 +1656,7 @@
{
LY_ERR ret = LY_SUCCESS;
const struct lys_module *mod;
- struct lyd_node *root, *next, *elem;
+ struct lyd_node *root, *elem;
enum lyd_diff_op op;
LY_CHECK_ARG_RET(NULL, diff, LY_EINVAL);
@@ -1674,7 +1674,7 @@
LY_CHECK_ERR_GOTO(!mod, LOGINT(LYD_NODE_CTX(src_diff)); ret = LY_EINT, cleanup);
LY_LIST_FOR(*diff, root) {
- LYD_TREE_DFS_BEGIN(root, next, elem) {
+ LYD_TREE_DFS_BEGIN(root, elem) {
/* find operation attribute, if any */
LY_CHECK_GOTO(ret = lyd_diff_get_op(elem, &op), cleanup);
@@ -1726,7 +1726,7 @@
break;
}
- LYD_TREE_DFS_END(root, next, elem);
+ LYD_TREE_DFS_END(root, elem);
}
}
diff --git a/src/parser_lyb.c b/src/parser_lyb.c
index 65fdb19..fc74236 100644
--- a/src/parser_lyb.c
+++ b/src/parser_lyb.c
@@ -1199,11 +1199,11 @@
}
/* find request OP */
- LYD_TREE_DFS_BEGIN((struct lyd_node *)request, iter, req_op) {
+ LYD_TREE_DFS_BEGIN((struct lyd_node *)request, req_op) {
if (req_op->schema->nodetype & (LYS_RPC | LYS_ACTION)) {
break;
}
- LYD_TREE_DFS_END(request, iter, req_op);
+ LYD_TREE_DFS_END(request, req_op);
}
if (!(req_op->schema->nodetype & (LYS_RPC | LYS_ACTION))) {
LOGERR(LYD_NODE_CTX(request), LY_EINVAL, "No RPC/action in the request found.");
diff --git a/src/parser_xml.c b/src/parser_xml.c
index bc8b7e7..a3c8acf 100644
--- a/src/parser_xml.c
+++ b/src/parser_xml.c
@@ -1071,11 +1071,11 @@
}
/* find request OP */
- LYD_TREE_DFS_BEGIN((struct lyd_node *)request, iter, req_op) {
+ LYD_TREE_DFS_BEGIN((struct lyd_node *)request, req_op) {
if (req_op->schema->nodetype & (LYS_RPC | LYS_ACTION)) {
break;
}
- LYD_TREE_DFS_END(request, iter, req_op);
+ LYD_TREE_DFS_END(request, req_op);
}
if (!(req_op->schema->nodetype & (LYS_RPC | LYS_ACTION))) {
LOGERR(LYD_NODE_CTX(request), LY_EINVAL, "No RPC/action in the request found.");
diff --git a/src/printer.c b/src/printer.c
index 0e89500..2fcd436 100644
--- a/src/printer.c
+++ b/src/printer.c
@@ -112,7 +112,7 @@
int
ly_should_print(const struct lyd_node *node, int options)
{
- const struct lyd_node *next, *elem;
+ const struct lyd_node *elem;
if (options & LYD_PRINT_WD_TRIM) {
/* do not print default nodes */
@@ -128,23 +128,23 @@
} else if ((node->flags & LYD_DEFAULT) && !(options & LYD_PRINT_WD_MASK) && !(node->schema->flags & LYS_CONFIG_R)) {
/* LYDP_WD_EXPLICIT
* - print only if it contains status data in its subtree */
- LYD_TREE_DFS_BEGIN(node, next, elem) {
+ LYD_TREE_DFS_BEGIN(node, elem) {
if ((elem->schema->nodetype != LYS_CONTAINER) || (elem->schema->flags & LYS_PRESENCE)) {
if (elem->schema->flags & LYS_CONFIG_R) {
return 1;
}
}
- LYD_TREE_DFS_END(node, next, elem)
+ LYD_TREE_DFS_END(node, elem)
}
return 0;
} else if ((node->flags & LYD_DEFAULT) && (node->schema->nodetype == LYS_CONTAINER) && !(options & LYD_PRINT_KEEPEMPTYCONT)) {
/* avoid empty default containers */
- LYD_TREE_DFS_BEGIN(node, next, elem) {
+ LYD_TREE_DFS_BEGIN(node, elem) {
if (elem->schema->nodetype != LYS_CONTAINER) {
return 1;
}
assert(elem->flags & LYD_DEFAULT);
- LYD_TREE_DFS_END(node, next, elem)
+ LYD_TREE_DFS_END(node, elem)
}
return 0;
}
diff --git a/src/tree_data.c b/src/tree_data.c
index 69852d0..8bfaaa3 100644
--- a/src/tree_data.c
+++ b/src/tree_data.c
@@ -1439,7 +1439,7 @@
API LY_ERR
lyd_new_implicit_tree(struct lyd_node *tree, int implicit_options, struct lyd_node **diff)
{
- struct lyd_node *next, *node;
+ struct lyd_node *node;
LY_ERR ret = LY_SUCCESS;
LY_CHECK_ARG_RET(NULL, tree, LY_EINVAL);
@@ -1447,7 +1447,7 @@
*diff = NULL;
}
- LYD_TREE_DFS_BEGIN(tree, next, node) {
+ LYD_TREE_DFS_BEGIN(tree, node) {
/* skip added default nodes */
if (((node->flags & (LYD_DEFAULT | LYD_NEW)) != (LYD_DEFAULT | LYD_NEW))
&& (node->schema->nodetype & LYD_NODE_INNER)) {
@@ -1455,7 +1455,7 @@
NULL, implicit_options, diff), cleanup);
}
- LYD_TREE_DFS_END(tree, next, node);
+ LYD_TREE_DFS_END(tree, node);
}
cleanup:
@@ -2667,7 +2667,7 @@
{
LY_ERR ret;
const struct lyd_node *child_src, *tmp, *sibling_src;
- struct lyd_node *match_trg, *dup_src, *next, *elem;
+ struct lyd_node *match_trg, *dup_src, *elem;
struct lysc_type *type;
sibling_src = *sibling_src_p;
@@ -2720,9 +2720,9 @@
}
/* set LYD_NEW for all the new nodes, required for validation */
- LYD_TREE_DFS_BEGIN(dup_src, next, elem) {
+ LYD_TREE_DFS_BEGIN(dup_src, elem) {
elem->flags |= LYD_NEW;
- LYD_TREE_DFS_END(dup_src, next, elem);
+ LYD_TREE_DFS_END(dup_src, elem);
}
lyd_insert_node(parent_trg, first_trg, dup_src);
diff --git a/src/tree_data.h b/src/tree_data.h
index bb33b43..24ab7e7 100644
--- a/src/tree_data.h
+++ b/src/tree_data.h
@@ -54,51 +54,54 @@
* </pre>
*
* Use the same parameters for #LYD_TREE_DFS_BEGIN and #LYD_TREE_DFS_END. While
- * START can be any of the lyd_node* types, NEXT and ELEM variables are expected
- * to be pointers to a generic struct lyd_node.
+ * START can be any of the lyd_node* types, ELEM variable must be a pointer to
+ * the generic struct lyd_node.
*
- * Since the next node is selected as part of #LYD_TREE_DFS_END, do not use
- * continue statement between the #LYD_TREE_DFS_BEGIN and #LYD_TREE_DFS_END.
+ * To skip a particular subtree, instead of the continue statement, set LYD_TREE_DFS_continue
+ * variable to non-zero value.
*
* Use with opening curly bracket '{' after the macro.
*
* @param START Pointer to the starting element processed first.
- * @param NEXT Temporary storage, do not use.
* @param ELEM Iterator intended for use in the block.
*/
-#define LYD_TREE_DFS_BEGIN(START, NEXT, ELEM) \
- for ((ELEM) = (NEXT) = (START); \
+#define LYD_TREE_DFS_BEGIN(START, ELEM) \
+ { int LYD_TREE_DFS_continue = 0; struct lyd_node *LYD_TREE_DFS_next; \
+ for ((ELEM) = (LYD_TREE_DFS_next) = (struct lyd_node *)(START); \
(ELEM); \
- (ELEM) = (NEXT))
+ (ELEM) = (LYD_TREE_DFS_next), LYD_TREE_DFS_continue = 0)
/**
* @brief Macro to iterate via all elements in a tree. This is the closing part
* to the #LYD_TREE_DFS_BEGIN - they always have to be used together.
*
* Use the same parameters for #LYD_TREE_DFS_BEGIN and #LYD_TREE_DFS_END. While
- * START can be any of the lyd_node* types, NEXT and ELEM variables are expected
- * to be pointers to a generic struct lyd_node.
+ * START can be any of the lyd_node* types, ELEM variable must be a pointer
+ * to the generic struct lyd_node.
*
* Use with closing curly bracket '}' after the macro.
*
* @param START Pointer to the starting element processed first.
- * @param NEXT Temporary storage, do not use.
* @param ELEM Iterator intended for use in the block.
*/
-#define LYD_TREE_DFS_END(START, NEXT, ELEM) \
+#define LYD_TREE_DFS_END(START, ELEM) \
/* select element for the next run - children first */ \
- (NEXT) = lyd_node_children((struct lyd_node*)ELEM, 0); \
- if (!(NEXT)) { \
+ if (LYD_TREE_DFS_continue) { \
+ (LYD_TREE_DFS_next) = NULL; \
+ } else { \
+ (LYD_TREE_DFS_next) = lyd_node_children(ELEM, 0); \
+ }\
+ if (!(LYD_TREE_DFS_next)) { \
/* no children */ \
if ((ELEM) == (struct lyd_node*)(START)) { \
/* we are done, (START) has no children */ \
break; \
} \
/* try siblings */ \
- (NEXT) = (ELEM)->next; \
+ (LYD_TREE_DFS_next) = (ELEM)->next; \
} \
- while (!(NEXT)) { \
+ while (!(LYD_TREE_DFS_next)) { \
/* parent is already processed, go to its sibling */ \
(ELEM) = (struct lyd_node*)(ELEM)->parent; \
/* no siblings, go back through parents */ \
@@ -106,8 +109,8 @@
/* we are done, no next element to process */ \
break; \
} \
- (NEXT) = (ELEM)->next; \
- }
+ (LYD_TREE_DFS_next) = (ELEM)->next; \
+ } } \
/**
* @brief Macro to get context from a data tree node.
diff --git a/src/validation.c b/src/validation.c
index 9f556f2..9c39173 100644
--- a/src/validation.c
+++ b/src/validation.c
@@ -1028,9 +1028,9 @@
struct ly_set *when_check, int val_opts, struct lyd_node **diff)
{
const struct lyd_meta *meta;
- struct lyd_node *next, *node;
+ struct lyd_node *node;
- LYD_TREE_DFS_BEGIN(root, next, node) {
+ LYD_TREE_DFS_BEGIN(root, node) {
/* skip added default nodes */
if ((node->flags & (LYD_DEFAULT | LYD_NEW)) != (LYD_DEFAULT | LYD_NEW)) {
LY_LIST_FOR(node->meta, meta) {
@@ -1057,7 +1057,7 @@
}
}
- LYD_TREE_DFS_END(root, next, node);
+ LYD_TREE_DFS_END(root, node);
}
return LY_SUCCESS;
@@ -1205,7 +1205,7 @@
lyd_validate_op(struct lyd_node *op_tree, const struct lyd_node *tree, LYD_VALIDATE_OP op, struct lyd_node **diff)
{
LY_ERR ret;
- struct lyd_node *tree_sibling, *op_subtree, *op_next, *op_node, *op_parent;
+ struct lyd_node *tree_sibling, *op_subtree, *op_node, *op_parent;
struct ly_set type_check = {0}, type_meta_check = {0}, when_check = {0};
LY_CHECK_ARG_RET(NULL, op_tree, !op_tree->parent, !tree || !tree->parent,
@@ -1215,13 +1215,13 @@
}
/* find the operation/notification */
- LYD_TREE_DFS_BEGIN(op_tree, op_next, op_node) {
+ LYD_TREE_DFS_BEGIN(op_tree, op_node) {
if ((op == LYD_VALIDATE_OP_RPC || op == LYD_VALIDATE_OP_REPLY) && (op_node->schema->nodetype & (LYS_RPC | LYS_ACTION))) {
break;
} else if ((op == LYD_VALIDATE_OP_NOTIF) && (op_node->schema->nodetype == LYS_NOTIF)) {
break;
}
- LYD_TREE_DFS_END(op_tree, op_next, op_node);
+ LYD_TREE_DFS_END(op_tree, op_node);
}
if (op == LYD_VALIDATE_OP_RPC || op == LYD_VALIDATE_OP_REPLY) {
if (!(op_node->schema->nodetype & (LYS_RPC | LYS_ACTION))) {
diff --git a/src/xpath.c b/src/xpath.c
index c104dd3..61edb2d 100644
--- a/src/xpath.c
+++ b/src/xpath.c
@@ -1301,7 +1301,7 @@
get_node_pos(const struct lyd_node *node, enum lyxp_node_type node_type, const struct lyd_node *root,
enum lyxp_node_type root_type, const struct lyd_node **prev, uint32_t *prev_pos)
{
- const struct lyd_node *next, *elem = NULL, *top_sibling;
+ const struct lyd_node *elem = NULL, *top_sibling;
uint32_t pos = 1;
assert(prev && prev_pos && !root->prev->next);
@@ -1312,55 +1312,31 @@
if (*prev) {
/* start from the previous element instead from the root */
- elem = next = *prev;
pos = *prev_pos;
- for (top_sibling = elem; top_sibling->parent; top_sibling = (struct lyd_node *)top_sibling->parent);
+ for (top_sibling = *prev; top_sibling->parent; top_sibling = (struct lyd_node *)top_sibling->parent);
goto dfs_search;
}
for (top_sibling = root; top_sibling; top_sibling = top_sibling->next) {
- /* TREE DFS */
- LYD_TREE_DFS_BEGIN(top_sibling, next, elem) {
+ LYD_TREE_DFS_BEGIN(top_sibling, elem) {
dfs_search:
+ if (*prev && !elem) {
+ /* resume previous DFS */
+ elem = LYD_TREE_DFS_next = (struct lyd_node *)*prev;
+ LYD_TREE_DFS_continue = 0;
+ }
+
if ((root_type == LYXP_NODE_ROOT_CONFIG) && (elem->schema->flags & LYS_CONFIG_R)) {
- goto skip_children;
- }
-
- if (elem == node) {
- break;
- }
- ++pos;
-
- /* TREE DFS END */
- /* select element for the next run - children first,
- * child exception for lyd_node_leaf and lyd_node_leaflist, but not the root */
- if (elem->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA)) {
- next = NULL;
+ /* skip */
+ LYD_TREE_DFS_continue = 1;
} else {
- next = lyd_node_children(elem, 0);
- }
- if (!next) {
-skip_children:
- /* no children */
- if (elem == top_sibling) {
- /* we are done, root has no children */
- elem = NULL;
+ if (elem == node) {
break;
}
- /* try siblings */
- next = elem->next;
+ ++pos;
}
- while (!next) {
- /* no siblings, go back through parents */
- if (elem->parent == top_sibling->parent) {
- /* we are done, no next element to process */
- elem = NULL;
- break;
- }
- /* parent is already processed, go to its sibling */
- elem = (struct lyd_node *)elem->parent;
- next = elem->next;
- }
+
+ LYD_TREE_DFS_END(top_sibling, elem);
}
/* node found */
@@ -1372,13 +1348,13 @@
if (!elem) {
if (!(*prev)) {
/* we went from root and failed to find it, cannot be */
- LOGINT(node->schema->module->ctx);
+ LOGINT(LYD_NODE_CTX(node));
return 0;
} else {
- *prev = NULL;
- *prev_pos = 0;
+ /* start the search again from the beginning */
+ *prev = root;
- elem = next = top_sibling = root;
+ top_sibling = root;
pos = 1;
goto dfs_search;
}
diff --git a/tests/utests/data/test_lyb.c b/tests/utests/data/test_lyb.c
index 2a509d3..ebb69cb 100644
--- a/tests/utests/data/test_lyb.c
+++ b/tests/utests/data/test_lyb.c
@@ -38,10 +38,33 @@
}
loop_begin:
- LYD_TREE_DFS_BEGIN(*start, *next, *elem) {
+ /* LYD_TREE_DFS_BEGIN */
+ for (*elem = *next = *start; *elem; *elem = *next) {
return;
loop_next:
- LYD_TREE_DFS_END(*start, *next, *elem);
+ /* LYD_TREE_DFS_END */
+
+ /* select element for the next run - children first */
+ *next = lyd_node_children(*elem, 0);
+ if (!*next) {
+ /* no children */
+ if (*elem == *start) {
+ /* we are done, (START) has no children */
+ break;
+ }
+ /* try siblings */
+ *next = (*elem)->next;
+ }
+ while (!*next) {
+ /* parent is already processed, go to its sibling */
+ *elem = (struct lyd_node *)(*elem)->parent;
+ /* no siblings, go back through parents */
+ if ((*elem)->parent == (*start)->parent) {
+ /* we are done, no next element to process */
+ break;
+ }
+ *next = (*elem)->next;
+ }
}
if (!*next) {