data tree CHANGE insert updates
Always remove default flag from
container parents and check new node
placing when inserting top-level with
an anchor.
diff --git a/src/tree_data.c b/src/tree_data.c
index ae5818f..1902f0d 100644
--- a/src/tree_data.c
+++ b/src/tree_data.c
@@ -819,6 +819,8 @@
static void
lyd_insert_after_node(struct lyd_node *sibling, struct lyd_node *node)
{
+ struct lyd_node_inner *par;
+
assert(!node->next && (node->prev == node));
node->next = sibling->next;
@@ -837,6 +839,16 @@
sibling->prev = node;
}
node->parent = sibling->parent;
+
+ if (!(node->flags & LYD_DEFAULT)) {
+ /* remove default flags from NP containers */
+ for (par = node->parent; par && (par->flags & LYD_DEFAULT); par = par->parent) {
+ par->flags &= ~LYD_DEFAULT;
+ }
+ }
+
+ /* insert into hash table */
+ lyd_insert_hash(node);
}
/**
@@ -848,6 +860,8 @@
static void
lyd_insert_before_node(struct lyd_node *sibling, struct lyd_node *node)
{
+ struct lyd_node_inner *par;
+
assert(!node->next && (node->prev == node));
node->next = sibling;
@@ -862,6 +876,16 @@
sibling->parent->child = node;
}
node->parent = sibling->parent;
+
+ if (!(node->flags & LYD_DEFAULT)) {
+ /* remove default flags from NP containers */
+ for (par = node->parent; par && (par->flags & LYD_DEFAULT); par = par->parent) {
+ par->flags &= ~LYD_DEFAULT;
+ }
+ }
+
+ /* insert into hash table */
+ lyd_insert_hash(node);
}
/**
@@ -875,7 +899,7 @@
{
struct lyd_node_inner *par;
- assert(!node->next && (node->prev == node));
+ assert(parent && !node->next && (node->prev == node));
assert(parent->schema->nodetype & LYD_NODE_INNER);
par = (struct lyd_node_inner *)parent;
@@ -888,6 +912,16 @@
par->child->prev = node;
}
node->parent = par;
+
+ if (!(node->flags & LYD_DEFAULT)) {
+ /* remove default flags from NP containers */
+ for (; par && (par->flags & LYD_DEFAULT); par = par->parent) {
+ par->flags &= ~LYD_DEFAULT;
+ }
+ }
+
+ /* insert into hash table */
+ lyd_insert_hash(node);
}
void
@@ -934,17 +968,6 @@
/* the only sibling */
*first_sibling = node;
}
-
- if (!(node->flags & LYD_DEFAULT)) {
- /* remove default flags from NP containers */
- while (parent && (parent->flags & LYD_DEFAULT)) {
- parent->flags &= ~LYD_DEFAULT;
- parent = (struct lyd_node *)parent->parent;
- }
- }
-
- /* insert into hash table */
- lyd_insert_hash(node);
}
static LY_ERR
@@ -1033,6 +1056,54 @@
return LY_SUCCESS;
}
+static LY_ERR
+lyd_insert_after_check_place(struct lyd_node *anchor, struct lyd_node *sibling, struct lyd_node *node)
+{
+ if (sibling->parent) {
+ /* nested, we do not care for the order */
+ return LY_SUCCESS;
+ }
+
+ if (anchor) {
+ if (anchor->next && (lyd_top_node_module(anchor) == lyd_top_node_module(anchor->next))
+ && (lyd_top_node_module(node) != lyd_top_node_module(anchor))) {
+ LOGERR(sibling->schema->module->ctx, LY_EINVAL, "Cannot insert top-level module \"%s\" data into module \"%s\" data.",
+ lyd_top_node_module(node)->name, lyd_top_node_module(anchor)->name);
+ return LY_EINVAL;
+ }
+
+ if ((lyd_top_node_module(node) == lyd_top_node_module(anchor))
+ || (anchor->next && (lyd_top_node_module(node) == lyd_top_node_module(anchor->next)))) {
+ /* inserting before/after its module data */
+ return LY_SUCCESS;
+ }
+ }
+
+ /* find first sibling */
+ while (sibling->prev->next) {
+ sibling = sibling->prev;
+ }
+
+ if (!anchor) {
+ if (lyd_top_node_module(node) == lyd_top_node_module(sibling)) {
+ /* inserting before its module data */
+ return LY_SUCCESS;
+ }
+ }
+
+ /* check there are no data of this module */
+ LY_LIST_FOR(sibling, sibling) {
+ if (lyd_top_node_module(node) == lyd_top_node_module(sibling)) {
+ /* some data of this module found */
+ LOGERR(sibling->schema->module->ctx, LY_EINVAL, "Top-level data of module \"%s\" already exist,"
+ " they must be directly connected.", lyd_top_node_module(node)->name);
+ return LY_EINVAL;
+ }
+ }
+
+ return LY_SUCCESS;
+}
+
API LY_ERR
lyd_insert_before(struct lyd_node *sibling, struct lyd_node *node)
{
@@ -1050,6 +1121,8 @@
return LY_EINVAL;
}
+ LY_CHECK_RET(lyd_insert_after_check_place(sibling->prev->next ? sibling->prev : NULL, sibling, node));
+
if (node->parent || node->prev->next) {
lyd_unlink_tree(node);
}
@@ -1086,6 +1159,8 @@
return LY_EINVAL;
}
+ LY_CHECK_RET(lyd_insert_after_check_place(sibling, sibling, node));
+
if (node->parent || node->prev->next) {
lyd_unlink_tree(node);
}