data tree CHANGE preserve default flags in diff nodes
Both when duplicating nodes or adding metadata.
diff --git a/src/diff.c b/src/diff.c
index c2e3935..3f5f5b4 100644
--- a/src/diff.c
+++ b/src/diff.c
@@ -109,7 +109,7 @@
/* duplicate the subtree (and connect to the diff if possible) */
LY_CHECK_RET(lyd_dup_single(node, (struct lyd_node_inner *)diff_parent,
- LYD_DUP_RECURSIVE | LYD_DUP_NO_META | LYD_DUP_WITH_PARENTS, &dup));
+ LYD_DUP_RECURSIVE | LYD_DUP_NO_META | LYD_DUP_WITH_PARENTS | LYD_DUP_WITH_FLAGS, &dup));
/* find the first duplicated parent */
if (!diff_parent) {
@@ -138,35 +138,35 @@
/* add parent operation, if any */
if (diff_parent && (diff_parent != dup)) {
- LY_CHECK_RET(lyd_new_meta(diff_parent, yang_mod, "operation", "none", NULL));
+ LY_CHECK_RET(lyd_new_meta(LYD_CTX(node), diff_parent, yang_mod, "operation", "none", 0, NULL));
}
/* add subtree operation */
- LY_CHECK_RET(lyd_new_meta(dup, yang_mod, "operation", lyd_diff_op2str(op), NULL));
+ LY_CHECK_RET(lyd_new_meta(LYD_CTX(node), dup, yang_mod, "operation", lyd_diff_op2str(op), 0, NULL));
/* orig-default */
if (orig_default) {
- LY_CHECK_RET(lyd_new_meta(dup, yang_mod, "orig-default", orig_default, NULL));
+ LY_CHECK_RET(lyd_new_meta(LYD_CTX(node), dup, yang_mod, "orig-default", orig_default, 0, NULL));
}
/* orig-value */
if (orig_value) {
- LY_CHECK_RET(lyd_new_meta(dup, yang_mod, "orig-value", orig_value, NULL));
+ LY_CHECK_RET(lyd_new_meta(LYD_CTX(node), dup, yang_mod, "orig-value", orig_value, 0, NULL));
}
/* key */
if (key) {
- LY_CHECK_RET(lyd_new_meta(dup, yang_mod, "key", key, NULL));
+ LY_CHECK_RET(lyd_new_meta(LYD_CTX(node), dup, yang_mod, "key", key, 0, NULL));
}
/* value */
if (value) {
- LY_CHECK_RET(lyd_new_meta(dup, yang_mod, "value", value, NULL));
+ LY_CHECK_RET(lyd_new_meta(LYD_CTX(node), dup, yang_mod, "value", value, 0, NULL));
}
/* orig-key */
if (orig_key) {
- LY_CHECK_RET(lyd_new_meta(dup, yang_mod, "orig-key", orig_key, NULL));
+ LY_CHECK_RET(lyd_new_meta(LYD_CTX(node), dup, yang_mod, "orig-key", orig_key, 0, NULL));
}
return LY_SUCCESS;
@@ -1062,6 +1062,7 @@
/**
* @brief Set a specific operation of a node. Delete the previous operation, if any.
+ * Does not change the default flag.
*
* @param[in] node Node to change.
* @param[in] op Operation to set.
@@ -1079,7 +1080,7 @@
}
}
- return lyd_new_meta(node, NULL, "yang:operation", lyd_diff_op2str(op), NULL);
+ return lyd_new_meta(LYD_CTX(node), node, NULL, "yang:operation", lyd_diff_op2str(op), 0, NULL);
}
/**
@@ -1199,6 +1200,7 @@
{
struct lyd_node *child;
const struct lysc_node_leaf *sleaf;
+ uint32_t trg_flags;
switch (cur_op) {
case LYD_DIFF_OP_DELETE:
@@ -1208,34 +1210,23 @@
sleaf = NULL;
}
+ /* remember current flags */
+ trg_flags = diff_match->flags;
+
if (sleaf && sleaf->dflt &&
!sleaf->dflt->realtype->plugin->compare(sleaf->dflt, &((struct lyd_node_term *)src_diff)->value)) {
/* we deleted it, so a default value was in-use, and it matches the created value -> operation NONE */
LY_CHECK_RET(lyd_diff_change_op(diff_match, LYD_DIFF_OP_NONE));
-
- if (diff_match->schema->nodetype & LYD_NODE_TERM) {
- /* add orig-dflt metadata */
- LY_CHECK_RET(lyd_new_meta(diff_match, NULL, "yang:orig-default",
- diff_match->flags & LYD_DEFAULT ? "true" : "false", NULL));
- }
} else if (!lyd_compare_single(diff_match, src_diff, 0)) {
/* deleted + created -> operation NONE */
LY_CHECK_RET(lyd_diff_change_op(diff_match, LYD_DIFF_OP_NONE));
-
- if (diff_match->schema->nodetype & LYD_NODE_TERM) {
- /* add orig-dflt metadata */
- LY_CHECK_RET(lyd_new_meta(diff_match, NULL, "yang:orig-default",
- diff_match->flags & LYD_DEFAULT ? "true" : "false", NULL));
- }
} else {
- assert(sleaf);
/* we deleted it, but it was created with a different value -> operation REPLACE */
LY_CHECK_RET(lyd_diff_change_op(diff_match, LYD_DIFF_OP_REPLACE));
- }
- if (lyd_compare_single(diff_match, src_diff, 0)) {
/* current value is the previous one (meta) */
- LY_CHECK_RET(lyd_new_meta(diff_match, NULL, "yang:orig-value", LYD_CANON_VALUE(diff_match), NULL));
+ LY_CHECK_RET(lyd_new_meta(LYD_CTX(src_diff), diff_match, NULL, "yang:orig-value",
+ LYD_CANON_VALUE(diff_match), 0, NULL));
/* update the value itself */
LY_CHECK_RET(lyd_change_term(diff_match, LYD_CANON_VALUE(src_diff)));
@@ -1283,8 +1274,8 @@
if (diff_match->schema->nodetype & LYD_NODE_TERM) {
/* add orig-default meta because it is expected */
- LY_CHECK_RET(lyd_new_meta(diff_match, NULL, "yang:orig-default",
- diff_match->flags & LYD_DEFAULT ? "true" : "false", NULL));
+ LY_CHECK_RET(lyd_new_meta(LYD_CTX(src_diff), diff_match, NULL, "yang:orig-default",
+ diff_match->flags & LYD_DEFAULT ? "true" : "false", 0, NULL));
} else {
/* keep operation for all descendants (for now) */
LY_LIST_FOR(lyd_child_no_keys(diff_match), child) {
@@ -1448,7 +1439,8 @@
}
} else {
/* add new diff node with all descendants */
- LY_CHECK_RET(lyd_dup_single(src_diff, (struct lyd_node_inner *)diff_parent, LYD_DUP_RECURSIVE, &diff_node));
+ LY_CHECK_RET(lyd_dup_single(src_diff, (struct lyd_node_inner *)diff_parent, LYD_DUP_RECURSIVE | LYD_DUP_WITH_FLAGS,
+ &diff_node));
/* insert node into diff if not already */
if (!diff_parent) {
diff --git a/src/in.c b/src/in.c
index 0a69853..f802010 100644
--- a/src/in.c
+++ b/src/in.c
@@ -439,7 +439,7 @@
}
LY_CHECK_RET(lyd_create_meta(parent, meta, mod, name, name_len, value, value_len, dynamic, format, prefix_data,
- hints, &incomplete));
+ hints, 0, &incomplete));
if (incomplete && !(lydctx->parse_options & LYD_PARSE_ONLY)) {
LY_CHECK_RET(ly_set_add(&lydctx->unres_meta_type, *meta, 1, NULL));
diff --git a/src/parser_xml.c b/src/parser_xml.c
index dc899de..e19b86f 100644
--- a/src/parser_xml.c
+++ b/src/parser_xml.c
@@ -596,7 +596,7 @@
/* add metadata/attributes */
if (snode) {
- lyd_insert_meta(node, meta);
+ lyd_insert_meta(node, meta, 0);
} else {
lyd_insert_attr(node, attr);
}
diff --git a/src/tree_data.c b/src/tree_data.c
index 2706378..2627811 100644
--- a/src/tree_data.c
+++ b/src/tree_data.c
@@ -961,23 +961,24 @@
}
API LY_ERR
-lyd_new_meta(struct lyd_node *parent, const struct lys_module *module, const char *name, const char *val_str,
- struct lyd_meta **meta)
+lyd_new_meta(const struct ly_ctx *ctx, struct lyd_node *parent, const struct lys_module *module, const char *name,
+ const char *val_str, ly_bool clear_dflt, struct lyd_meta **meta)
{
- struct lyd_meta *ret = NULL;
- const struct ly_ctx *ctx;
const char *prefix, *tmp;
size_t pref_len, name_len;
- LY_CHECK_ARG_RET(NULL, parent, name, module || strchr(name, ':'), LY_EINVAL);
+ LY_CHECK_ARG_RET(NULL, ctx, name, module || strchr(name, ':'), parent || meta, LY_EINVAL);
- ctx = LYD_CTX(parent);
+ if (parent && !parent->schema) {
+ LOGERR(ctx, LY_EINVAL, "Cannot add metadata to an opaque node \"%s\".", ((struct lyd_node_opaq *)parent)->name);
+ return LY_EINVAL;
+ }
/* parse the name */
tmp = name;
if (ly_parse_nodeid(&tmp, &prefix, &pref_len, &name, &name_len) || tmp[0]) {
LOGERR(ctx, LY_EINVAL, "Metadata name \"%s\" is not valid.", name);
- return LY_EVALID;
+ return LY_EINVAL;
}
/* find the module */
@@ -991,13 +992,11 @@
val_str = "";
}
- LY_CHECK_RET(lyd_create_meta(parent, &ret, module, name, name_len, val_str, strlen(val_str), NULL, LY_PREF_JSON,
- NULL, LYD_HINT_DATA, NULL));
+ return lyd_create_meta(parent, meta, module, name, name_len, val_str, strlen(val_str), NULL, LY_PREF_JSON,
+ NULL, LYD_HINT_DATA, clear_dflt, NULL);
+}
- if (meta) {
- *meta = ret;
}
- return LY_SUCCESS;
}
API LY_ERR
@@ -1157,7 +1156,7 @@
/* parse the new value into a new meta structure */
LY_CHECK_GOTO(ret = lyd_create_meta(NULL, &m2, meta->annotation->module, meta->name, strlen(meta->name), val_str,
- strlen(val_str), NULL, LY_PREF_JSON, NULL, LYD_HINT_DATA, NULL), cleanup);
+ strlen(val_str), NULL, LY_PREF_JSON, NULL, LYD_HINT_DATA, 0, NULL), cleanup);
/* compare original and new value */
if (lyd_compare_meta(meta, m2)) {
@@ -2086,7 +2085,7 @@
}
void
-lyd_insert_meta(struct lyd_node *parent, struct lyd_meta *meta)
+lyd_insert_meta(struct lyd_node *parent, struct lyd_meta *meta, ly_bool clear_dflt)
{
struct lyd_meta *last, *iter;
@@ -2109,7 +2108,7 @@
}
/* remove default flags from NP containers */
- while (parent && (parent->schema->nodetype == LYS_CONTAINER) && (parent->flags & LYD_DEFAULT)) {
+ while (clear_dflt && parent && (parent->schema->nodetype == LYS_CONTAINER) && (parent->flags & LYD_DEFAULT)) {
parent->flags &= ~LYD_DEFAULT;
parent = (struct lyd_node *)parent->parent;
}
@@ -2118,7 +2117,7 @@
LY_ERR
lyd_create_meta(struct lyd_node *parent, struct lyd_meta **meta, const struct lys_module *mod, const char *name,
size_t name_len, const char *value, size_t value_len, ly_bool *dynamic, LY_PREFIX_FORMAT format,
- void *prefix_data, uint32_t hints, ly_bool *incomplete)
+ void *prefix_data, uint32_t hints, ly_bool clear_dflt, ly_bool *incomplete)
{
LY_ERR rc;
struct lysc_ext_instance *ant = NULL;
@@ -2154,7 +2153,7 @@
/* insert as the last attribute */
if (parent) {
- lyd_insert_meta(parent, mt);
+ lyd_insert_meta(parent, mt, clear_dflt);
} else if (*meta) {
for (last = *meta; last->next; last = last->next) {}
last->next = mt;
diff --git a/src/tree_data.h b/src/tree_data.h
index 0027364..1fe05c9 100644
--- a/src/tree_data.h
+++ b/src/tree_data.h
@@ -906,19 +906,21 @@
LYD_ANYDATA_VALUETYPE value_type, ly_bool output, struct lyd_node **node);
/**
- * @brief Create new metadata for a data node.
+ * @brief Create new metadata.
*
- * @param[in] parent Parent node for the metadata being created.
+ * @param[in] ctx libyang context,
+ * @param[in] parent Optional parent node for the metadata being created. Must be set if @p meta is NULL.
* @param[in] module Module of the metadata being created. If NULL, @p name must include module name as the prefix.
* @param[in] name Annotation name of the new metadata. It can include the annotation module as the prefix.
* If the prefix is specified it is always used but if not specified, @p module must be set.
* @param[in] val_str String form of the value of the metadata. In case of an instance-identifier or identityref
* value, the JSON format is expected (module names instead of prefixes).
- * @param[out] meta Optional created metadata.
+ * @param[in] clear_dflt Whether to clear the default flag starting from @p parent, recursively all NP containers.
+ * @param[out] meta Optional created metadata. Must be set if @p parent is NULL.
* @return LY_ERR value.
*/
-LY_ERR lyd_new_meta(struct lyd_node *parent, const struct lys_module *module, const char *name, const char *val_str,
- struct lyd_meta **meta);
+LY_ERR lyd_new_meta(const struct ly_ctx *ctx, struct lyd_node *parent, const struct lys_module *module, const char *name,
+ const char *val_str, ly_bool clear_dflt, struct lyd_meta **meta);
/**
* @brief Create a new opaque node in the data tree.
diff --git a/src/tree_data_internal.h b/src/tree_data_internal.h
index bc181af..a633873 100644
--- a/src/tree_data_internal.h
+++ b/src/tree_data_internal.h
@@ -227,8 +227,9 @@
*
* @param[in] parent Parent of the metadata.
* @param[in] meta Metadata (list) to be added into the @p parent.
+ * @param[in] clear_dflt Whether to clear dflt flag starting from @p parent, recursively all NP containers.
*/
-void lyd_insert_meta(struct lyd_node *parent, struct lyd_meta *meta);
+void lyd_insert_meta(struct lyd_node *parent, struct lyd_meta *meta, ly_bool clear_dflt);
/**
* @brief Create and insert a metadata (last) into a parent.
@@ -244,6 +245,7 @@
* @param[in] format Input format of @p value.
* @param[in] prefix_data Format-specific data for resolving any prefixes (see ::ly_resolve_prefix).
* @param[in] hints [Value hints](@ref lydvalhints) from the parser regarding the value type.
+ * @param[in] clear_dflt Whether to clear dflt flag starting from @p parent, recursively all NP containers.
* @param[out] incomplete Whether the value needs to be resolved.
* @return LY_SUCCESS on success.
* @return LY_EINCOMPLETE in case data tree is needed to finish the validation.
@@ -251,7 +253,7 @@
*/
LY_ERR lyd_create_meta(struct lyd_node *parent, struct lyd_meta **meta, const struct lys_module *mod, const char *name,
size_t name_len, const char *value, size_t value_len, ly_bool *dynamic, LY_PREFIX_FORMAT format,
- void *prefix_data, uint32_t hints, ly_bool *incomplete);
+ void *prefix_data, uint32_t hints, ly_bool clear_dlft, ly_bool *incomplete);
/**
* @brief Insert an attribute (last) into a parent