data tree REFACTOR make dup-inst handling generic
... and not specific for diff.
diff --git a/src/tree_data_helpers.c b/src/tree_data_helpers.c
index 89afee3..bb4b734 100644
--- a/src/tree_data_helpers.c
+++ b/src/tree_data_helpers.c
@@ -37,6 +37,76 @@
#include "validation.h"
#include "xml.h"
+/**
+ * @brief Find an entry in duplicate instance cache for an instance. Create it if it does not exist.
+ *
+ * @param[in] first_inst Instance of the cache entry.
+ * @param[in,out] dup_inst_cache Duplicate instance cache.
+ * @return Instance cache entry.
+ */
+static struct lyd_dup_inst *
+lyd_dup_inst_get(const struct lyd_node *first_inst, struct lyd_dup_inst **dup_inst_cache)
+{
+ struct lyd_dup_inst *item;
+ LY_ARRAY_COUNT_TYPE u;
+
+ LY_ARRAY_FOR(*dup_inst_cache, u) {
+ if ((*dup_inst_cache)[u].inst_set->dnodes[0] == first_inst) {
+ return &(*dup_inst_cache)[u];
+ }
+ }
+
+ /* it was not added yet, add it now */
+ LY_ARRAY_NEW_RET(LYD_CTX(first_inst), *dup_inst_cache, item, NULL);
+
+ return item;
+}
+
+LY_ERR
+lyd_dup_inst_next(struct lyd_node **inst, const struct lyd_node *siblings, struct lyd_dup_inst **dup_inst_cache)
+{
+ struct lyd_dup_inst *dup_inst;
+
+ if (!*inst || !lysc_is_dup_inst_list((*inst)->schema)) {
+ /* no match or not dup-inst list, inst is unchanged */
+ return LY_SUCCESS;
+ }
+
+ /* there can be more exact same instances and we must make sure we do not match a single node more times */
+ dup_inst = lyd_dup_inst_get(*inst, dup_inst_cache);
+ LY_CHECK_ERR_RET(!dup_inst, LOGMEM(LYD_CTX(siblings)), LY_EMEM);
+
+ if (!dup_inst->used) {
+ /* we did not cache these instances yet, do so */
+ lyd_find_sibling_dup_inst_set(siblings, *inst, &dup_inst->inst_set);
+ assert(dup_inst->inst_set->count && (dup_inst->inst_set->dnodes[0] == *inst));
+ }
+
+ if (dup_inst->used == dup_inst->inst_set->count) {
+ /* we have used all the instances */
+ *inst = NULL;
+ } else {
+ assert(dup_inst->used < dup_inst->inst_set->count);
+
+ /* use another instance */
+ *inst = dup_inst->inst_set->dnodes[dup_inst->used];
+ ++dup_inst->used;
+ }
+
+ return LY_SUCCESS;
+}
+
+void
+lyd_dup_inst_free(struct lyd_dup_inst *dup_inst)
+{
+ LY_ARRAY_COUNT_TYPE u;
+
+ LY_ARRAY_FOR(dup_inst, u) {
+ ly_set_free(dup_inst[u].inst_set, NULL);
+ }
+ LY_ARRAY_FREE(dup_inst);
+}
+
struct lyd_node *
lys_getnext_data(const struct lyd_node *last, const struct lyd_node *sibling, const struct lysc_node **slast,
const struct lysc_node *parent, const struct lysc_module *module)