validation BUGFIX keeping track of first top-level sibling
diff --git a/src/tree_data_helpers.c b/src/tree_data_helpers.c
index 2d9ba62..7fd4582 100644
--- a/src/tree_data_helpers.c
+++ b/src/tree_data_helpers.c
@@ -215,6 +215,57 @@
return schema->module;
}
+void
+lyd_first_module_sibling(struct lyd_node **node, const struct lys_module *mod)
+{
+ int cmp;
+ struct lyd_node *first;
+
+ assert(node && mod);
+
+ if (!*node) {
+ return;
+ }
+
+ first = *node;
+ cmp = strcmp(lyd_owner_module(first)->name, mod->name);
+ if (cmp > 0) {
+ /* there may be some preceding data */
+ while (first->prev->next) {
+ first = first->prev;
+ if (lyd_owner_module(first) == mod) {
+ cmp = 0;
+ break;
+ }
+ }
+ }
+
+ if (cmp == 0) {
+ /* there may be some preceding data belonging to this module */
+ while (first->prev->next) {
+ if (lyd_owner_module(first->prev) != mod) {
+ break;
+ }
+ first = first->prev;
+ }
+ }
+
+ if (cmp < 0) {
+ /* there may be some following data */
+ LY_LIST_FOR(first, first) {
+ if (lyd_owner_module(first) == mod) {
+ cmp = 0;
+ break;
+ }
+ }
+ }
+
+ if (cmp == 0) {
+ /* we have found the first module data node */
+ *node = first;
+ }
+}
+
const struct lys_module *
lyd_mod_next_module(struct lyd_node *tree, const struct lys_module *module, const struct ly_ctx *ctx, uint32_t *i,
struct lyd_node **first)
@@ -467,10 +518,11 @@
return;
}
- *root = (*root)->next;
- if (mod && *root && (lyd_owner_module(to_del) != lyd_owner_module(*root))) {
- /* there are no more nodes from mod */
+ if (mod && (*root)->prev->next && (!(*root)->next || (lyd_owner_module(to_del) != lyd_owner_module((*root)->next)))) {
+ /* there are no more nodes from mod, simply get the first top-level sibling */
*root = lyd_first_sibling(*root);
+ } else {
+ *root = (*root)->next;
}
}
diff --git a/src/tree_data_internal.h b/src/tree_data_internal.h
index fb5e4af..0d98567 100644
--- a/src/tree_data_internal.h
+++ b/src/tree_data_internal.h
@@ -392,6 +392,14 @@
/** @} datahash */
/**
+ * @brief Update node pointer to point to the first data node of a module, leave unchanged if there is none.
+ *
+ * @param[in,out] node Node pointer, may be updated.
+ * @param[in] mod Module whose data to search for.
+ */
+void lyd_first_module_sibling(struct lyd_node **node, const struct lys_module *mod);
+
+/**
* @brief Iterate over implemented modules for functions that accept specific modules or the whole context.
*
* @param[in] tree Data tree.
diff --git a/src/validation.c b/src/validation.c
index e916930..a95f3c5 100644
--- a/src/validation.c
+++ b/src/validation.c
@@ -1491,8 +1491,12 @@
LY_CHECK_GOTO(ret, cleanup);
/* our first module node pointer may no longer be the first */
- while (*first2 && (*first2)->prev->next && (lyd_owner_module(*first2) == lyd_owner_module((*first2)->prev))) {
- *first2 = (*first2)->prev;
+ first = *first2;
+ lyd_first_module_sibling(&first, mod);
+ if (!first || (first == *tree)) {
+ first2 = tree;
+ } else {
+ first2 = &first;
}
if (validate_subtree) {