data tree FEATURE dup and find for metadata
diff --git a/src/tree_data.c b/src/tree_data.c
index 3d9789c..21b8573 100644
--- a/src/tree_data.c
+++ b/src/tree_data.c
@@ -2093,7 +2093,15 @@
dup->schema = node->schema;
dup->prev = dup;
- /* TODO duplicate attributes, implement LYD_DUP_NO_ATTR */
+ /* duplicate metadata */
+ if (!(options & LYD_DUP_NO_META)) {
+ LY_LIST_FOR(node->meta, meta) {
+ if (!lyd_dup_meta(meta, dup)) {
+ ret = LY_EINT;
+ goto error;
+ }
+ }
+ }
/* nodetype-specific work */
if (!dup->schema) {
@@ -2183,7 +2191,6 @@
API struct lyd_node *
lyd_dup(const struct lyd_node *node, struct lyd_node_inner *parent, int options)
{
- struct ly_ctx *ctx;
const struct lyd_node *orig; /* original node to be duplicated */
struct lyd_node *first = NULL; /* the first duplicated node, this is returned */
struct lyd_node *top = NULL; /* the most higher created node */
@@ -2191,7 +2198,6 @@
int keyless_parent_list = 0;
LY_CHECK_ARG_RET(NULL, node, NULL);
- ctx = node->schema->module->ctx;
if (options & LYD_DUP_WITH_PARENTS) {
struct lyd_node_inner *orig_parent, *iter;
@@ -2238,7 +2244,8 @@
}
if (repeat && parent) {
/* given parent and created parents chain actually do not interconnect */
- LOGERR(ctx, LY_EINVAL, "Invalid argument parent (%s()) - does not interconnect with the created node's parents chain.", __func__);
+ LOGERR(LYD_NODE_CTX(node), LY_EINVAL,
+ "Invalid argument parent (%s()) - does not interconnect with the created node's parents chain.", __func__);
goto error;
}
} else {
@@ -2271,6 +2278,35 @@
return NULL;
}
+API struct lyd_meta *
+lyd_dup_meta(const struct lyd_meta *meta, struct lyd_node *node)
+{
+ LY_ERR ret;
+ struct lyd_meta *mt, *last;
+
+ LY_CHECK_ARG_RET(NULL, meta, node, NULL);
+
+ /* create a copy */
+ mt = calloc(1, sizeof *mt);
+ LY_CHECK_ERR_RET(!mt, LOGMEM(LYD_NODE_CTX(node)), NULL);
+ mt->parent = node;
+ mt->annotation = meta->annotation;
+ mt->value.realtype = meta->value.realtype;
+ ret = mt->value.realtype->plugin->duplicate(LYD_NODE_CTX(node), &meta->value, &mt->value);
+ LY_CHECK_ERR_RET(ret, LOGERR(LYD_NODE_CTX(node), LY_EINT, "Value duplication failed."), NULL);
+ mt->name = lydict_insert(LYD_NODE_CTX(node), meta->name, 0);
+
+ /* insert as the last attribute */
+ if (node->meta) {
+ for (last = node->meta; last->next; last = last->next);
+ last->next = mt;
+ } else {
+ node->meta = mt;
+ }
+
+ return mt;
+}
+
/**
* @brief Merge a source sibling into target siblings.
*
@@ -2632,6 +2668,49 @@
return buffer;
}
+API struct lyd_meta *
+lyd_find_meta(const struct lyd_meta *first, const struct lys_module *module, const char *name)
+{
+ struct lyd_meta *ret = NULL;
+ const struct ly_ctx *ctx;
+ const char *prefix, *tmp;
+ char *str;
+ size_t pref_len, name_len;
+
+ LY_CHECK_ARG_RET(NULL, module || strchr(name, ':'), name, NULL);
+
+ if (!first) {
+ return NULL;
+ }
+
+ ctx = first->annotation->module->ctx;
+
+ /* 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 NULL;
+ }
+
+ /* find the module */
+ if (prefix) {
+ str = strndup(prefix, pref_len);
+ module = ly_ctx_get_module_latest(ctx, str);
+ free(str);
+ LY_CHECK_ERR_RET(!module, LOGERR(ctx, LY_EINVAL, "Module \"%.*s\" not found.", pref_len, prefix), NULL);
+ }
+
+ /* find the metadata */
+ LY_LIST_FOR(first, first) {
+ if ((first->annotation->module == module) && !strcmp(first->name, name)) {
+ ret = (struct lyd_meta *)first;
+ break;
+ }
+ }
+
+ return ret;
+}
+
LY_ERR
lyd_find_sibling_next2(const struct lyd_node *first, const struct lysc_node *schema, const char *key_or_value,
size_t val_len, struct lyd_node **match)
diff --git a/src/tree_data.h b/src/tree_data.h
index 4d70a76..f58b523 100644
--- a/src/tree_data.h
+++ b/src/tree_data.h
@@ -895,6 +895,16 @@
struct lyd_node *lyd_dup(const struct lyd_node *node, struct lyd_node_inner *parent, int options);
/**
+ * @brief Create a copy of the metadata.
+ *
+ * @param[in] meta Metadata to copy.
+ * @param[in] node Node where to append the new metadata.
+ * @return Created metadata copy,
+ * @return NULL on error.
+ */
+struct lyd_meta *lyd_dup_meta(const struct lyd_meta *meta, struct lyd_node *node);
+
+/**
* @defgroup mergeoptions Data merge options.
* @ingroup datatree
*
@@ -1055,6 +1065,17 @@
char *lyd_path(const struct lyd_node *node, LYD_PATH_TYPE pathtype, char *buffer, size_t buflen);
/**
+ * @brief Find a specific metadata.
+ *
+ * @param[in] first First metadata to consider.
+ * @param[in] module Module of the metadata definition, may be NULL if @p name includes a prefix.
+ * @param[in] name Name of the metadata to find, may not include a prefix (module name) if @p module is set.
+ * @return Found metadata,
+ * @return NULL if not found.
+ */
+struct lyd_meta *lyd_find_meta(const struct lyd_meta *first, const struct lys_module *module, const char *name);
+
+/**
* @brief Find the node, in the list, satisfying the given restrictions.
* Does **not** use hashes - should not be used unless necessary for best performance.
*
@@ -1080,7 +1101,7 @@
* Note that any explicit values (leaf, leaf-list or list key values) will be canonized first
* before comparison. But values that do not have a canonical value are expected to be in the
* JSON format!
- * @param[in] val_len Optional length of @p key_or_value in case it is not 0-terminated string.
+ * @param[in] val_len Optional length of @p key_or_value in case it is not a 0-terminated string.
* @param[out] match Found data node.
* @return LY_SUCCESS on success, @p match set.
* @return LY_ENOTFOUND if not found, @p match set to NULL.