data tree FEATURE option to skip list key children
diff --git a/src/path.c b/src/path.c
index bcbfe01..23e0cfb 100644
--- a/src/path.c
+++ b/src/path.c
@@ -772,7 +772,7 @@
if (lysc_data_parent(path[0].node)) {
/* relative path, start from the parent children */
- start = lyd_node_children(start);
+ start = lyd_node_children(start, 0);
} else {
/* absolute path, start from the first top-level sibling */
while (start->parent) {
@@ -823,7 +823,7 @@
prev_node = node;
/* next path segment, if any */
- start = lyd_node_children(node);
+ start = lyd_node_children(node, 0);
}
if (node) {
diff --git a/src/tree_data.c b/src/tree_data.c
index f55f10c..fc08039 100644
--- a/src/tree_data.c
+++ b/src/tree_data.c
@@ -1340,18 +1340,18 @@
if (parent) {
if (node->schema && (node->schema->flags & LYS_KEY)) {
/* it is key and we need to insert it at the correct place */
- anchor = lyd_get_prev_key_anchor(lyd_node_children(parent), node->schema);
+ anchor = lyd_get_prev_key_anchor(lyd_node_children(parent, 0), node->schema);
if (anchor) {
lyd_insert_after_node(anchor, node);
- } else if (lyd_node_children(parent)) {
- lyd_insert_before_node(lyd_node_children(parent), node);
+ } else if (lyd_node_children(parent, 0)) {
+ lyd_insert_before_node(lyd_node_children(parent, 0), node);
} else {
lyd_insert_last_node(parent, node);
}
/* hash list if all its keys were added */
assert(parent->schema->nodetype == LYS_LIST);
- anchor = lyd_node_children(parent);
+ anchor = lyd_node_children(parent, 0);
has_keys = 1;
while ((skey = lys_getnext(skey, parent->schema, NULL, 0)) && (skey->flags & LYS_KEY)) {
if (!anchor || (anchor->schema != skey)) {
@@ -2269,12 +2269,7 @@
lyd_free_tree(dup_src);
} else {
/* check descendants, recursively */
- LY_LIST_FOR_SAFE(lyd_node_children(sibling_src), tmp, child_src) {
- if ((child_src->schema->nodetype == LYS_LEAF) && (child_src->schema->flags & LYS_KEY)) {
- /* skip keys */
- continue;
- }
-
+ LY_LIST_FOR_SAFE(LYD_CHILD(sibling_src), tmp, child_src) {
LY_CHECK_RET(lyd_merge_sibling_r(lyd_node_children_p(match_trg), match_trg, &child_src, options));
}
}
@@ -2383,7 +2378,7 @@
char quot;
LY_ERR rc;
- for (key = lyd_node_children(node); key && (key->schema->flags & LYS_KEY); key = key->next) {
+ for (key = lyd_node_children(node, 0); key && (key->schema->flags & LYS_KEY); key = key->next) {
val = lyd_value2str((struct lyd_node_term *)key, &dynamic);
len = 1 + strlen(key->schema->name) + 2 + strlen(val) + 2;
rc = lyd_path_str_enlarge(buffer, buflen, *bufused + len, is_static);
@@ -2626,7 +2621,7 @@
/* compare all set keys */
LY_ARRAY_FOR(predicates, u) {
/* find key */
- rc = lyd_find_sibling_val(lyd_node_children(node), predicates[u].key, NULL, 0, (struct lyd_node **)&term);
+ rc = lyd_find_sibling_val(lyd_node_children(node, 0), predicates[u].key, NULL, 0, (struct lyd_node **)&term);
if (rc == LY_ENOTFOUND) {
/* all keys must always exist */
LOGINT_RET(schema->module->ctx);
diff --git a/src/tree_data.h b/src/tree_data.h
index 1c4e9c0..235062d 100644
--- a/src/tree_data.h
+++ b/src/tree_data.h
@@ -88,7 +88,7 @@
#define LYD_TREE_DFS_END(START, NEXT, ELEM) \
/* select element for the next run - children first */ \
- (NEXT) = lyd_node_children((struct lyd_node*)ELEM); \
+ (NEXT) = lyd_node_children((struct lyd_node*)ELEM, 0); \
if (!(NEXT)) { \
/* no children */ \
if ((ELEM) == (struct lyd_node*)(START)) { \
@@ -517,13 +517,23 @@
//#define LYD_OPT_DATA_TEMPLATE 0x1000000 /**< Data represents YANG data template. */
/**
+ * @defgroup children_options Children traversal options.
+ * @ingroup datatree
+ */
+
+#define LYD_CHILDREN_SKIP_KEYS 0x01 /**< If list children are returned, skip its keys. */
+
+/** @} children_options */
+
+/**
* @brief Get the node's children list if any.
*
* Decides the node's type and in case it has a children list, returns it.
* @param[in] node Node to check.
+ * @param[in] options Bitmask of options, see @ref
* @return Pointer to the first child node (if any) of the \p node.
*/
-struct lyd_node *lyd_node_children(const struct lyd_node *node);
+struct lyd_node *lyd_node_children(const struct lyd_node *node, int options);
/**
* @brief Get the owner module of the data node. It is the module of the top-level schema node. Generally,
diff --git a/src/tree_data_free.c b/src/tree_data_free.c
index 7975b87..43bafee 100644
--- a/src/tree_data_free.c
+++ b/src/tree_data_free.c
@@ -136,7 +136,7 @@
opaq = (struct lyd_node_opaq *)node;
/* free the children */
- children = lyd_node_children(node);
+ children = lyd_node_children(node, 0);
LY_LIST_FOR_SAFE(children, next, iter) {
lyd_free_subtree(iter, 0);
}
@@ -158,7 +158,7 @@
((struct lyd_node_inner *)node)->children_ht = NULL;
/* free the children */
- children = lyd_node_children(node);
+ children = lyd_node_children(node, 0);
LY_LIST_FOR_SAFE(children, next, iter) {
lyd_free_subtree(iter, 0);
}
diff --git a/src/tree_data_helpers.c b/src/tree_data_helpers.c
index 798f238..4e85ebe 100644
--- a/src/tree_data_helpers.c
+++ b/src/tree_data_helpers.c
@@ -45,17 +45,23 @@
}
API struct lyd_node *
-lyd_node_children(const struct lyd_node *node)
+lyd_node_children(const struct lyd_node *node, int options)
{
- struct lyd_node **children;
+ struct lyd_node **children, *child;
if (!node) {
return NULL;
}
- children = lyd_node_children_p((struct lyd_node*)node);
+ children = lyd_node_children_p((struct lyd_node *)node);
if (children) {
- return *children;
+ child = *children;
+ if (options & LYD_CHILDREN_SKIP_KEYS) {
+ while (child && (child->schema->flags & LYS_KEY)) {
+ child = child->next;
+ }
+ }
+ return child;
} else {
return NULL;
}
@@ -140,7 +146,7 @@
assert(node->schema->nodetype == LYS_LIST);
- key = lyd_node_children(node);
+ key = lyd_node_children(node, 0);
while ((skey = lys_getnext(skey, node->schema, NULL, 0)) && (skey->flags & LYS_KEY)) {
if (!key || (key->schema != skey)) {
LOGVAL(node->schema->module->ctx, LY_VLOG_LYD, node, LY_VCODE_NOKEY, skey->name);
diff --git a/src/tree_data_internal.h b/src/tree_data_internal.h
index 6596aa8..439ad6c 100644
--- a/src/tree_data_internal.h
+++ b/src/tree_data_internal.h
@@ -31,6 +31,14 @@
#define LYD_DEL_IS_ROOT(first, to_del) (((first) == (to_del)) && !(first)->parent && !(first)->prev->next)
/**
+ * @brief Shorthand for getting data children without its keys.
+ *
+ * @param[in] node Node, whose children to traverse.
+ * @return Node children, skipping any keys of a list.
+ */
+#define LYD_CHILD(node) lyd_node_children(node, LYD_CHILDREN_SKIP_KEYS)
+
+/**
* @brief Get address of a node's child pointer if any.
*
* @param[in] node Node to check.
diff --git a/src/validation.c b/src/validation.c
index 1219d89..22919f0 100644
--- a/src/validation.c
+++ b/src/validation.c
@@ -518,7 +518,7 @@
/* find iter instance in children */
assert(iter->nodetype & (LYS_CONTAINER | LYS_LEAF));
- lyd_find_sibling_val(lyd_node_children(node), iter, NULL, 0, &node);
+ lyd_find_sibling_val(lyd_node_children(node, 0), iter, NULL, 0, &node);
--depth;
}
@@ -922,11 +922,11 @@
LY_LIST_FOR(first, node) {
/* validate all children recursively */
- LY_CHECK_RET(lyd_validate_final_r(lyd_node_children(node), node->schema, NULL, val_opts));
+ LY_CHECK_RET(lyd_validate_final_r(lyd_node_children(node, 0), node->schema, NULL, val_opts));
/* set default for containers */
if ((node->schema->nodetype == LYS_CONTAINER) && !(node->schema->flags & LYS_PRESENCE)) {
- LY_LIST_FOR(lyd_node_children(node), next) {
+ LY_LIST_FOR(lyd_node_children(node, 0), next) {
if (!(next->flags & LYD_DEFAULT)) {
break;
}
@@ -1178,7 +1178,7 @@
}
/* move tree_iter */
- tree_iter = lyd_node_children(match);
+ tree_iter = lyd_node_children(match, 0);
/* move depth */
--cur_depth;
@@ -1250,7 +1250,7 @@
LY_CHECK_GOTO(ret = lyd_validate_must(op, val_opts), cleanup);
/* final validation of all the descendants */
- LY_CHECK_GOTO(ret = lyd_validate_final_r(lyd_node_children(op), op->schema, NULL, val_opts), cleanup);
+ LY_CHECK_GOTO(ret = lyd_validate_final_r(lyd_node_children(op, 0), op->schema, NULL, val_opts), cleanup);
cleanup:
/* restore operation tree */
diff --git a/src/xpath.c b/src/xpath.c
index 39c7365..1a13f1f 100644
--- a/src/xpath.c
+++ b/src/xpath.c
@@ -192,7 +192,7 @@
&& (((struct lyd_node_inner *)item->node)->child->schema->nodetype == LYS_LEAF)) {
LOGDBG(LY_LDGXPATH, "\t%d (pos %u): ELEM %s (1st child val: %s)", i + 1, item->pos,
item->node->schema->name,
- (str = (char *)lyd_value2str((struct lyd_node_term *)lyd_node_children(item->node), &dynamic)));
+ (str = (char *)lyd_value2str((struct lyd_node_term *)lyd_node_children(item->node, 0), &dynamic)));
if (dynamic) {
free(str);
}
@@ -362,7 +362,7 @@
strcpy(*str + (*used - 1), "\n");
++(*used);
- for (child = lyd_node_children(node); child; child = child->next) {
+ for (child = lyd_node_children(node, 0); child; child = child->next) {
rc = cast_string_recursive(child, 0, root_type, indent + 1, str, used, size);
LY_CHECK_RET(rc);
}
@@ -1322,7 +1322,7 @@
if (elem->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA)) {
next = NULL;
} else {
- next = lyd_node_children(elem);
+ next = lyd_node_children(elem, 0);
}
if (!next) {
skip_children:
@@ -5437,16 +5437,15 @@
for (i = 0; i < set->used; ) {
replaced = 0;
- siblings = NULL;
if ((set->val.nodes[i].type == LYXP_NODE_ROOT_CONFIG) || (set->val.nodes[i].type == LYXP_NODE_ROOT)) {
assert(!set->val.nodes[i].node);
/* search in all the trees */
siblings = set->tree;
- } else if (!(set->val.nodes[i].node->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA))) {
+ } else {
/* search in children */
- siblings = lyd_node_children(set->val.nodes[i].node);
+ siblings = lyd_node_children(set->val.nodes[i].node, 0);
}
for (sub = siblings; sub; sub = sub->next) {
@@ -5527,7 +5526,7 @@
siblings = set->tree;
} else if (set->val.nodes[i].type == LYXP_NODE_ELEM) {
/* search in children */
- siblings = lyd_node_children(set->val.nodes[i].node);
+ siblings = lyd_node_children(set->val.nodes[i].node, 0);
}
/* find the node using hashes */
@@ -5716,7 +5715,7 @@
/* TREE DFS NEXT ELEM */
/* select element for the next run - children first */
- next = lyd_node_children(elem);
+ next = lyd_node_children(elem, 0);
if (!next) {
skip_children:
/* no children, so try siblings, but only if it's not the start,
@@ -6063,7 +6062,7 @@
}
/* add all the children of this node */
- first = lyd_node_children(parent);
+ first = lyd_node_children(parent, 0);
break;
default:
LOGINT_RET(parent->schema->module->ctx);