dict NEW efficient dict_dup finction
diff --git a/src/dict.c b/src/dict.c
index a880696..ba574c8 100644
--- a/src/dict.c
+++ b/src/dict.c
@@ -264,3 +264,49 @@
 
     return result;
 }
+
+static LY_ERR
+dict_dup(const struct ly_ctx *ctx, char *value, const char **str_p)
+{
+    LY_ERR ret = LY_SUCCESS;
+    struct ly_dict_rec *match = NULL, rec;
+    uint32_t hash;
+
+    /* set new callback to only compare memory addresses */
+    lyht_value_equal_cb prev = lyht_set_cb(ctx->dict.hash_tab, lydict_resize_val_eq);
+
+    LOGDBG(LY_LDGDICT, "duplicating %s", value);
+    hash = lyht_hash(value, strlen(value));
+    rec.value = value;
+
+    ret = lyht_find(ctx->dict.hash_tab, (void *)&rec, hash, (void **)&match);
+    if (ret == LY_SUCCESS) {
+        /* record found, increase refcount */
+        match->refcount++;
+        *str_p = match->value;
+    }
+
+    /* restore callback */
+    lyht_set_cb(ctx->dict.hash_tab, prev);
+
+    return ret;
+}
+
+LIBYANG_API_DEF LY_ERR
+lydict_dup(const struct ly_ctx *ctx, const char *value, const char **str_p)
+{
+    LY_ERR result;
+
+    LY_CHECK_ARG_RET(ctx, ctx, str_p, LY_EINVAL);
+
+    if (!value) {
+        *str_p = NULL;
+        return LY_SUCCESS;
+    }
+
+    pthread_mutex_lock((pthread_mutex_t *)&ctx->dict.lock);
+    result = dict_dup(ctx, (char *)value, str_p);
+    pthread_mutex_unlock((pthread_mutex_t *)&ctx->dict.lock);
+
+    return result;
+}
diff --git a/src/dict.h b/src/dict.h
index cf897e7..bc8cac1 100644
--- a/src/dict.h
+++ b/src/dict.h
@@ -113,6 +113,18 @@
  */
 LIBYANG_API_DECL LY_ERR lydict_remove(const struct ly_ctx *ctx, const char *value);
 
+/**
+ * @brief Duplicate string in dictionary. Only a reference counter is incremented.
+ *
+ * @param[in] ctx libyang context handler
+ * @param[in] value NULL-terminated string to be duplicated in the dictionary (reference counter is incremented).
+ * @param[out] str_p Optional parameter to get pointer to the string corresponding to the @p value and stored in dictionary.
+ * @return LY_SUCCESS in case the string already exists in the dictionary.
+ * @return LY_ENOTFOUND in case the string was not found.
+ * @return LY_ERR on other errors
+ */
+LIBYANG_API_DECL LY_ERR lydict_dup(const struct ly_ctx *ctx, const char *value, const char **str_p);
+
 /** @} dict */
 
 #ifdef __cplusplus
diff --git a/src/plugins_types.c b/src/plugins_types.c
index 8305691..b3ffc3e 100644
--- a/src/plugins_types.c
+++ b/src/plugins_types.c
@@ -352,10 +352,16 @@
 LIBYANG_API_DEF LY_ERR
 lyplg_type_dup_simple(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup)
 {
-    memset(dup, 0, sizeof *dup);
-    LY_CHECK_RET(lydict_insert(ctx, original->_canonical, 0, &dup->_canonical));
+    LY_ERR r;
+
+    if ((r = lydict_dup(ctx, original->_canonical, &dup->_canonical))) {
+        /* in case of error NULL the values so that freeing does not fail */
+        memset(dup, 0, sizeof *dup);
+        return r;
+    }
     memcpy(dup->fixed_mem, original->fixed_mem, sizeof dup->fixed_mem);
     dup->realtype = original->realtype;
+
     return LY_SUCCESS;
 }