plugins types FEATURE xpath1.0 LYB value support
diff --git a/src/plugins_types.h b/src/plugins_types.h
index fc2110f..191faf5 100644
--- a/src/plugins_types.h
+++ b/src/plugins_types.h
@@ -960,35 +960,30 @@
  */
 
 /**
- * @brief Validate, canonize and store value of the ietf-yang-types xpath1.0 type.
- * Implementation of the ::lyplg_type_store_clb.
+ * @brief Implementation of ::lyplg_type_store_clb for the ietf-yang-types xpath1.0 type.
  */
 LY_ERR lyplg_type_store_xpath10(const struct ly_ctx *ctx, const struct lysc_type *type, const void *value, size_t value_len,
         uint32_t options, LY_VALUE_FORMAT format, void *prefix_data, uint32_t hints, const struct lysc_node *ctx_node,
         struct lyd_value *storage, struct lys_glob_unres *unres, struct ly_err_item **err);
 
 /**
- * @brief Comparison callback checking the xpath1.0 value.
- * Implementation of the ::lyplg_type_compare_clb.
+ * @brief Implementation of ::lyplg_type_compare_clb for the ietf-yang-types xpath1.0 type.
  */
 LY_ERR lyplg_type_compare_xpath10(const struct lyd_value *val1, const struct lyd_value *val2);
 
 /**
- * @brief Printer callback printing the xpath1.0 value.
- * Implementation of the ::lyplg_type_print_clb.
+ * @brief Implementation of ::lyplg_type_print_clb for the ietf-yang-types xpath1.0 type.
  */
 const void *lyplg_type_print_xpath10(const struct ly_ctx *ctx, const struct lyd_value *value, LY_VALUE_FORMAT format,
         void *prefix_data, ly_bool *dynamic, size_t *value_len);
 
 /**
- * @brief Duplication callback of the xpath1.0 values.
- * Implementation of the ::lyplg_type_dup_clb.
+ * @brief Implementation of ::lyplg_type_dup_clb for the ietf-yang-types xpath1.0 type.
  */
 LY_ERR lyplg_type_dup_xpath10(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup);
 
 /**
- * @brief Free value of the derived xpath1.0 types.
- * Implementation of the ::lyplg_type_free_clb.
+ * @brief Implementation of ::lyplg_type_free_clb for the ietf-yang-types xpath1.0 type.
  */
 void lyplg_type_free_xpath10(const struct ly_ctx *ctx, struct lyd_value *value);
 
diff --git a/src/plugins_types/xpath1.0.c b/src/plugins_types/xpath1.0.c
index 38e7731..f1a94c3 100644
--- a/src/plugins_types/xpath1.0.c
+++ b/src/plugins_types/xpath1.0.c
@@ -12,8 +12,6 @@
  *     https://opensource.org/licenses/BSD-3-Clause
  */
 
-#define _GNU_SOURCE
-
 #include "plugins_types.h"
 
 #include <assert.h>
@@ -31,6 +29,15 @@
 #include "xpath.h"
 
 /**
+ * @page howtoDataLYB LYB Binary Format
+ * @subsection howtoDataLYBTypesXpath10 xpath1.0 (ietf-yang-types)
+ *
+ * | Size (B) | Mandatory | Type | Meaning |
+ * | :------  | :-------: | :--: | :-----: |
+ * | string length | yes | `char *` | string JSON format of the XPath expression |
+ */
+
+/**
  * @brief Stored value structure for xpath1.0
  */
 struct lyd_value_xpath10 {
@@ -199,44 +206,76 @@
 
 API LY_ERR
 lyplg_type_store_xpath10(const struct ly_ctx *ctx, const struct lysc_type *type, const void *value, size_t value_len,
-        uint32_t options, LY_VALUE_FORMAT format, void *prefix_data, uint32_t hints, const struct lysc_node *ctx_node,
-        struct lyd_value *storage, struct lys_glob_unres *unres, struct ly_err_item **err)
+        uint32_t options, LY_VALUE_FORMAT format, void *prefix_data, uint32_t hints,
+        const struct lysc_node *UNUSED(ctx_node), struct lyd_value *storage, struct lys_glob_unres *UNUSED(unres),
+        struct ly_err_item **err)
 {
     LY_ERR ret = LY_SUCCESS;
-    struct lyd_value_xpath10 *xp_val;
-    char *canonical;
+    struct lysc_type_str *type_str = (struct lysc_type_str *)type;
+    struct lyd_value_xpath10 *val;
+    char *canon;
 
-    /* store as a string */
-    ret = lyplg_type_store_string(ctx, type, value, value_len, options, format, prefix_data, hints, ctx_node,
-            storage, unres, err);
-    LY_CHECK_RET(ret);
+    /* clear storage */
+    memset(storage, 0, sizeof *storage);
 
-    xp_val = calloc(1, sizeof *xp_val);
-    LY_CHECK_ERR_GOTO(!xp_val, LOGMEM(ctx); ret = LY_EMEM, cleanup);
-    storage->ptr = xp_val;
+    /* check hints */
+    ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
+    LY_CHECK_GOTO(ret, cleanup);
+
+    /* length restriction of the string */
+    if (type_str->length) {
+        /* value_len is in bytes, but we need number of characters here */
+        ret = lyplg_type_validate_range(LY_TYPE_STRING, type_str->length, ly_utf8len(value, value_len), value, value_len, err);
+        LY_CHECK_GOTO(ret, cleanup);
+    }
+
+    /* pattern restrictions */
+    ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err);
+    LY_CHECK_GOTO(ret, cleanup);
+
+    /* init storage */
+    storage->_canonical = NULL;
+    storage->ptr = NULL;
+    storage->realtype = type;
+
+    /* allocate value */
+    val = calloc(1, sizeof *val);
+    LY_CHECK_ERR_GOTO(!val, LOGMEM(ctx); ret = LY_EMEM, cleanup);
+    storage->ptr = val;
 
     /* store format-specific data and context for later prefix resolution */
-    ret = lyplg_type_prefix_data_new(ctx, storage->_canonical, strlen(storage->_canonical), format, prefix_data,
-            &xp_val->format, &xp_val->prefix_data);
+    ret = lyplg_type_prefix_data_new(ctx, value, value_len, format, prefix_data, &val->format, &val->prefix_data);
     LY_CHECK_GOTO(ret, cleanup);
-    xp_val->ctx = ctx;
+    val->ctx = ctx;
 
     /* parse */
-    ret = lyxp_expr_parse(ctx, storage->_canonical, strlen(storage->_canonical), 1, &xp_val->exp);
+    ret = lyxp_expr_parse(ctx, value, value_len, 1, &val->exp);
     LY_CHECK_GOTO(ret, cleanup);
 
-    if (format != LY_VALUE_JSON) {
-        /* generate canonical (JSON) value */
-        ret = xpath10_print_value(xp_val, LY_VALUE_JSON, NULL, &canonical, err);
+    /* store canonical value */
+    if ((format == LY_VALUE_CANON) || (format == LY_VALUE_JSON) || (format == LY_VALUE_LYB)) {
+        if (options & LYPLG_TYPE_STORE_DYNAMIC) {
+            ret = lydict_insert_zc(ctx, (char *)value, &storage->_canonical);
+            options &= ~LYPLG_TYPE_STORE_DYNAMIC;
+            LY_CHECK_GOTO(ret, cleanup);
+        } else {
+            ret = lydict_insert(ctx, value, value_len, &storage->_canonical);
+            LY_CHECK_GOTO(ret, cleanup);
+        }
+    } else {
+        /* JSON format with prefix is the canonical one */
+        ret = xpath10_print_value(val, LY_VALUE_JSON, NULL, &canon, err);
         LY_CHECK_GOTO(ret, cleanup);
 
-        /* replace the canonical value */
-        lydict_remove(ctx, storage->_canonical);
-        storage->_canonical = NULL;
-        LY_CHECK_GOTO(ret = lydict_insert_zc(ctx, canonical, &storage->_canonical), cleanup);
+        ret = lydict_insert_zc(ctx, canon, &storage->_canonical);
+        LY_CHECK_GOTO(ret, cleanup);
     }
 
 cleanup:
+    if (options & LYPLG_TYPE_STORE_DYNAMIC) {
+        free((void *)value);
+    }
+
     if (ret) {
         lyplg_type_free_xpath10(ctx, storage);
     }
@@ -244,13 +283,13 @@
 }
 
 API const void *
-lyplg_type_print_xpath10(const struct ly_ctx *UNUSED(ctx), const struct lyd_value *value, LY_VALUE_FORMAT format,
+lyplg_type_print_xpath10(const struct ly_ctx *ctx, const struct lyd_value *value, LY_VALUE_FORMAT format,
         void *prefix_data, ly_bool *dynamic, size_t *value_len)
 {
-    char *str_value;
+    char *ret;
     struct ly_err_item *err = NULL;
 
-    if ((format == LY_VALUE_CANON) || (format == LY_VALUE_JSON)) {
+    if ((format == LY_VALUE_CANON) || (format == LY_VALUE_JSON) || (format == LY_VALUE_LYB)) {
         /* canonical */
         if (dynamic) {
             *dynamic = 0;
@@ -261,42 +300,45 @@
         return value->_canonical;
     }
 
-    if (xpath10_print_value(value->ptr, format, prefix_data, &str_value, &err)) {
+    /* print in the specific format */
+    if (xpath10_print_value(value->ptr, format, prefix_data, &ret, &err)) {
         if (err) {
-            LOGVAL_ERRITEM(NULL, err);
+            LOGVAL_ERRITEM(ctx, err);
             ly_err_free(err);
         }
-        *dynamic = 0;
         return NULL;
     }
 
     *dynamic = 1;
-    return str_value;
+    if (value_len) {
+        *value_len = strlen(ret);
+    }
+    return ret;
 }
 
 API LY_ERR
 lyplg_type_dup_xpath10(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup)
 {
     LY_ERR ret = LY_SUCCESS;
-    struct lyd_value_xpath10 *xp_val;
-    const struct lyd_value_xpath10 *xp_val_orig = original->ptr;
+    struct lyd_value_xpath10 *orig_val = original->ptr, *dup_val;
 
+    /* init dup value */
     memset(dup, 0, sizeof *dup);
     dup->realtype = original->realtype;
 
-    ret = lydict_insert(ctx, original->_canonical, 0, &dup->_canonical);
+    ret = lydict_insert(ctx, original->_canonical, ly_strlen(original->_canonical), &dup->_canonical);
     LY_CHECK_GOTO(ret, cleanup);
 
-    xp_val = calloc(1, sizeof *xp_val);
-    LY_CHECK_ERR_GOTO(!xp_val, LOGMEM(ctx); ret = LY_EMEM, cleanup);
-    xp_val->ctx = ctx;
-    dup->ptr = xp_val;
+    dup_val = calloc(1, sizeof *dup_val);
+    LY_CHECK_ERR_GOTO(!dup_val, LOGMEM(ctx); ret = LY_EMEM, cleanup);
+    dup_val->ctx = ctx;
+    dup->ptr = dup_val;
 
-    ret = lyxp_expr_dup(ctx, xp_val_orig->exp, &xp_val->exp);
+    ret = lyxp_expr_dup(ctx, orig_val->exp, &dup_val->exp);
     LY_CHECK_GOTO(ret, cleanup);
 
-    xp_val->format = xp_val_orig->format;
-    ret = lyplg_type_prefix_data_dup(ctx, xp_val_orig->format, xp_val_orig->prefix_data, &xp_val->prefix_data);
+    dup_val->format = orig_val->format;
+    ret = lyplg_type_prefix_data_dup(ctx, orig_val->format, orig_val->prefix_data, &dup_val->prefix_data);
     LY_CHECK_GOTO(ret, cleanup);
 
 cleanup:
@@ -309,14 +351,14 @@
 API void
 lyplg_type_free_xpath10(const struct ly_ctx *ctx, struct lyd_value *value)
 {
-    struct lyd_value_xpath10 *xp_val = value->ptr;
+    struct lyd_value_xpath10 *val = value->ptr;
 
     lydict_remove(ctx, value->_canonical);
-    if (xp_val) {
-        lyxp_expr_free(ctx, xp_val->exp);
-        lyplg_type_prefix_data_free(xp_val->format, xp_val->prefix_data);
+    if (val) {
+        lyxp_expr_free(ctx, val->exp);
+        lyplg_type_prefix_data_free(val->format, val->prefix_data);
 
-        free(xp_val);
+        free(val);
     }
 }