data tree FEATURE support for lists with duplicate instances
Changes mainly in diff processing.
Refs #1483
diff --git a/src/validation.c b/src/validation.c
index 27d5371..86d47d8 100644
--- a/src/validation.c
+++ b/src/validation.c
@@ -3,7 +3,7 @@
* @author Michal Vasko <mvasko@cesnet.cz>
* @brief Validation
*
- * Copyright (c) 2019 CESNET, z.s.p.o.
+ * Copyright (c) 2019 - 2021 CESNET, z.s.p.o.
*
* This source code is licensed under BSD 3-Clause License (the "License").
* You may not use this file except in compliance with the License.
@@ -12,6 +12,7 @@
* https://opensource.org/licenses/BSD-3-Clause
*/
#define _POSIX_C_SOURCE 200809L /* strdup */
+#define _GNU_SOURCE /* asprintf */
#include "validation.h"
@@ -46,41 +47,58 @@
LY_ERR ret = LY_SUCCESS;
struct lyd_node *new_diff = NULL;
const struct lyd_node *prev_inst;
- char *key = NULL, *value = NULL;
+ char *key = NULL, *value = NULL, *position = NULL;
size_t buflen = 0, bufused = 0;
+ uint32_t pos;
assert((op == LYD_DIFF_OP_DELETE) || (op == LYD_DIFF_OP_CREATE));
if ((op == LYD_DIFF_OP_CREATE) && lysc_is_userordered(node->schema)) {
- if (node->prev->next && (node->prev->schema == node->schema)) {
- prev_inst = node->prev;
- } else {
- /* first instance */
- prev_inst = NULL;
- }
+ if (lysc_is_dup_inst_list(node->schema)) {
+ pos = lyd_list_pos(node);
- if (node->schema->nodetype == LYS_LIST) {
- /* generate key meta */
- if (prev_inst) {
- LY_CHECK_GOTO(ret = lyd_path_list_predicate(prev_inst, &key, &buflen, &bufused, 0), cleanup);
+ /* generate position meta */
+ if (pos > 1) {
+ if (asprintf(&position, "%" PRIu32, pos - 1) == -1) {
+ LOGMEM(LYD_CTX(node));
+ ret = LY_EMEM;
+ goto cleanup;
+ }
} else {
- key = strdup("");
- LY_CHECK_ERR_GOTO(!key, LOGMEM(LYD_CTX(node)); ret = LY_EMEM, cleanup);
+ position = strdup("");
+ LY_CHECK_ERR_GOTO(!position, LOGMEM(LYD_CTX(node)); ret = LY_EMEM, cleanup);
}
} else {
- /* generate value meta */
- if (prev_inst) {
- value = strdup(LYD_CANON_VALUE(prev_inst));
- LY_CHECK_ERR_GOTO(!value, LOGMEM(LYD_CTX(node)); ret = LY_EMEM, cleanup);
+ if (node->prev->next && (node->prev->schema == node->schema)) {
+ prev_inst = node->prev;
} else {
- value = strdup("");
- LY_CHECK_ERR_GOTO(!value, LOGMEM(LYD_CTX(node)); ret = LY_EMEM, cleanup);
+ /* first instance */
+ prev_inst = NULL;
+ }
+
+ if (node->schema->nodetype == LYS_LIST) {
+ /* generate key meta */
+ if (prev_inst) {
+ LY_CHECK_GOTO(ret = lyd_path_list_predicate(prev_inst, &key, &buflen, &bufused, 0), cleanup);
+ } else {
+ key = strdup("");
+ LY_CHECK_ERR_GOTO(!key, LOGMEM(LYD_CTX(node)); ret = LY_EMEM, cleanup);
+ }
+ } else {
+ /* generate value meta */
+ if (prev_inst) {
+ value = strdup(LYD_CANON_VALUE(prev_inst));
+ LY_CHECK_ERR_GOTO(!value, LOGMEM(LYD_CTX(node)); ret = LY_EMEM, cleanup);
+ } else {
+ value = strdup("");
+ LY_CHECK_ERR_GOTO(!value, LOGMEM(LYD_CTX(node)); ret = LY_EMEM, cleanup);
+ }
}
}
}
/* create new diff tree */
- LY_CHECK_GOTO(ret = lyd_diff_add(node, op, NULL, NULL, key, value, NULL, &new_diff), cleanup);
+ LY_CHECK_GOTO(ret = lyd_diff_add(node, op, NULL, NULL, key, value, position, NULL, NULL, &new_diff), cleanup);
/* merge into existing diff */
ret = lyd_diff_merge_all(diff, new_diff, 0);
@@ -89,6 +107,7 @@
lyd_free_tree(new_diff);
free(key);
free(value);
+ free(position);
return ret;
}
@@ -370,8 +389,7 @@
assert(node->flags & LYD_NEW);
/* key-less list or non-configuration leaf-list */
- if (((node->schema->nodetype == LYS_LIST) && (node->schema->flags & LYS_KEYLESS)) ||
- ((node->schema->nodetype == LYS_LEAFLIST) && !(node->schema->flags & LYS_CONFIG_W))) {
+ if (lysc_is_dup_inst_list(node->schema)) {
/* duplicate instances allowed */
return LY_SUCCESS;
}