plugins types FEATURE instance-identifier LYB value support
diff --git a/src/plugins_types.h b/src/plugins_types.h
index 5a67905..b8981af 100644
--- a/src/plugins_types.h
+++ b/src/plugins_types.h
@@ -770,42 +770,36 @@
*/
/**
- * @brief Validate and store value of the YANG built-in instance-identifier type.
- * Implementation of the ::lyplg_type_store_clb.
+ * @brief Implementation of ::lyplg_type_store_clb for the built-in instance-identifier type.
*/
LY_ERR lyplg_type_store_instanceid(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 instance-identifier value.
- * Implementation of the ::lyplg_type_compare_clb.
- */
-LY_ERR lyplg_type_compare_instanceid(const struct lyd_value *val1, const struct lyd_value *val2);
-
-/**
- * @brief Printer callback printing the instance-identifier value.
- * Implementation of the ::lyplg_type_print_clb.
- */
-const void *lyplg_type_print_instanceid(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 instance-identifier values.
- * Implementation of the ::lyplg_type_dup_clb.
- */
-LY_ERR lyplg_type_dup_instanceid(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup);
-
-/**
- * @brief Validate value of the YANG built-in instance-identifier type.
- * Implementation of the ::lyplg_type_validate_clb.
+ * @brief Implementation of ::lyplg_type_validate_clb for the built-in instance-identifier type.
*/
LY_ERR lyplg_type_validate_instanceid(const struct ly_ctx *ctx, const struct lysc_type *type, const struct lyd_node *ctx_node,
const struct lyd_node *tree, struct lyd_value *storage, struct ly_err_item **err);
/**
- * @brief Free value of the YANG built-in instance-identifier types.
- * Implementation of the ::lyplg_type_free_clb.
+ * @brief Implementation of ::lyplg_type_compare_clb for the built-in instance-identifier type.
+ */
+LY_ERR lyplg_type_compare_instanceid(const struct lyd_value *val1, const struct lyd_value *val2);
+
+/**
+ * @brief Implementation of ::lyplg_type_print_clb for the built-in instance-identifier type.
+ */
+const void *lyplg_type_print_instanceid(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 Implementation of ::lyplg_type_dup_clb for the built-in instance-identifier type.
+ */
+LY_ERR lyplg_type_dup_instanceid(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup);
+
+/**
+ * @brief Implementation of ::lyplg_type_free_clb for the built-in instance-identifier type.
*/
void lyplg_type_free_instanceid(const struct ly_ctx *ctx, struct lyd_value *value);
diff --git a/src/plugins_types/instanceid.c b/src/plugins_types/instanceid.c
index ced2bac..c7aa720 100644
--- a/src/plugins_types/instanceid.c
+++ b/src/plugins_types/instanceid.c
@@ -12,8 +12,6 @@
* https://opensource.org/licenses/BSD-3-Clause
*/
-#define _GNU_SOURCE
-
#include "plugins_types.h"
#include <assert.h>
@@ -31,137 +29,119 @@
#include "path.h"
#include "plugins_internal.h" /* LY_TYPE_*_STR */
-API const void *
-lyplg_type_print_instanceid(const struct ly_ctx *ctx, const struct lyd_value *value, LY_VALUE_FORMAT format,
- void *prefix_data, ly_bool *dynamic, size_t *value_len)
+/**
+ * @page howtoDataLYB LYB Binary Format
+ * @subsection howtoDataLYBTypesInstanceIdentifier instance-identifier (built-in)
+ *
+ * | Size (B) | Mandatory | Type | Meaning |
+ * | :------ | :-------: | :--: | :-----: |
+ * | string length | yes | `char *` | string JSON format of the instance-identifier |
+ */
+
+/**
+ * @brief Convert compiled path (instance-identifier) into string.
+ *
+ * @param[in] path Compiled path.
+ * @param[in] format Value format.
+ * @param[in] prefix_data Format-specific data for resolving prefixes.
+ * @param[out] str Printed instance-identifier.
+ * @return LY_ERR value.
+ */
+static LY_ERR
+instanceid_path2str(const struct ly_path *path, LY_VALUE_FORMAT format, void *prefix_data, char **str)
{
+ LY_ERR ret = LY_SUCCESS;
LY_ARRAY_COUNT_TYPE u, v;
- char *result = NULL;
+ char *result = NULL, quot;
+ const struct lys_module *mod = NULL;
+ ly_bool inherit_prefix, d;
+ const char *strval;
- if (!value->target) {
- /* value was not fully processed */
- return NULL;
- }
-
- if ((format == LY_VALUE_XML) || (format == LY_VALUE_SCHEMA)) {
+ switch (format) {
+ case LY_VALUE_XML:
+ case LY_VALUE_SCHEMA:
+ case LY_VALUE_SCHEMA_RESOLVED:
/* everything is prefixed */
- LY_ARRAY_FOR(value->target, u) {
- ly_strcat(&result, "/%s:%s", lyplg_type_get_prefix(value->target[u].node->module, format, prefix_data),
- value->target[u].node->name);
- LY_ARRAY_FOR(value->target[u].predicates, v) {
- struct ly_path_predicate *pred = &value->target[u].predicates[v];
+ inherit_prefix = 0;
+ break;
+ case LY_VALUE_CANON:
+ case LY_VALUE_JSON:
+ case LY_VALUE_LYB:
+ /* the same prefix is inherited and skipped */
+ inherit_prefix = 1;
+ break;
+ }
- switch (value->target[u].pred_type) {
- case LY_PATH_PREDTYPE_NONE:
- break;
- case LY_PATH_PREDTYPE_POSITION:
- /* position predicate */
- ly_strcat(&result, "[%" PRIu64 "]", pred->position);
- break;
- case LY_PATH_PREDTYPE_LIST: {
- /* key-predicate */
- ly_bool d = 0;
- const char *str = pred->value.realtype->plugin->print(ctx, &pred->value, format, prefix_data, &d, NULL);
- char quot = '\'';
- if (strchr(str, quot)) {
- quot = '"';
- }
- ly_strcat(&result, "[%s:%s=%c%s%c]", lyplg_type_get_prefix(pred->key->module, format, prefix_data),
- pred->key->name, quot, str, quot);
- if (d) {
- free((char *)str);
- }
- break;
- }
- case LY_PATH_PREDTYPE_LEAFLIST: {
- /* leaf-list-predicate */
- ly_bool d = 0;
- const char *str = pred->value.realtype->plugin->print(ctx, &pred->value, format, prefix_data, &d, NULL);
- char quot = '\'';
- if (strchr(str, quot)) {
- quot = '"';
- }
- ly_strcat(&result, "[.=%c%s%c]", quot, str, quot);
- if (d) {
- free((char *)str);
- }
- break;
- }
- }
- }
+ LY_ARRAY_FOR(path, u) {
+ /* new node */
+ if (!inherit_prefix || (mod != path[u].node->module)) {
+ mod = path[u].node->module;
+ ret = ly_strcat(&result, "/%s:%s", lyplg_type_get_prefix(mod, format, prefix_data), path[u].node->name);
+ } else {
+ ret = ly_strcat(&result, "/%s", path[u].node->name);
}
+ LY_CHECK_GOTO(ret, cleanup);
- *dynamic = 1;
- } else if ((format == LY_VALUE_CANON) || (format == LY_VALUE_JSON) || (format == LY_VALUE_LYB)) {
- /* generate canonical, only the first node or the node changing module is prefixed */
- if (!value->_canonical) {
- struct lys_module *mod = NULL;
- LY_ARRAY_FOR(value->target, u) {
- if (mod != value->target[u].node->module) {
- mod = value->target[u].node->module;
- ly_strcat(&result, "/%s:%s", lyplg_type_get_prefix(mod, format, prefix_data), value->target[u].node->name);
+ /* node predicates */
+ LY_ARRAY_FOR(path[u].predicates, v) {
+ struct ly_path_predicate *pred = &path[u].predicates[v];
+
+ switch (path[u].pred_type) {
+ case LY_PATH_PREDTYPE_NONE:
+ break;
+ case LY_PATH_PREDTYPE_POSITION:
+ /* position predicate */
+ ret = ly_strcat(&result, "[%" PRIu64 "]", pred->position);
+ break;
+ case LY_PATH_PREDTYPE_LIST:
+ /* key-predicate */
+ strval = pred->value.realtype->plugin->print(path[u].node->module->ctx, &pred->value, format, prefix_data,
+ &d, NULL);
+
+ /* default quote */
+ quot = '\'';
+ if (strchr(strval, quot)) {
+ quot = '"';
+ }
+ if (inherit_prefix) {
+ /* always the same prefix as the parent */
+ ret = ly_strcat(&result, "[%s=%c%s%c]", pred->key->name, quot, strval, quot);
} else {
- ly_strcat(&result, "/%s", value->target[u].node->name);
+ ret = ly_strcat(&result, "[%s:%s=%c%s%c]", lyplg_type_get_prefix(pred->key->module, format, prefix_data),
+ pred->key->name, quot, strval, quot);
}
- LY_ARRAY_FOR(value->target[u].predicates, v) {
- struct ly_path_predicate *pred = &value->target[u].predicates[v];
+ if (d) {
+ free((char *)strval);
+ }
+ break;
+ case LY_PATH_PREDTYPE_LEAFLIST:
+ /* leaf-list-predicate */
+ strval = pred->value.realtype->plugin->print(path[u].node->module->ctx, &pred->value, format, prefix_data,
+ &d, NULL);
- switch (value->target[u].pred_type) {
- case LY_PATH_PREDTYPE_NONE:
- break;
- case LY_PATH_PREDTYPE_POSITION:
- /* position predicate */
- ly_strcat(&result, "[%" PRIu64 "]", pred->position);
- break;
- case LY_PATH_PREDTYPE_LIST: {
- /* key-predicate */
- ly_bool d = 0;
- const char *str = pred->value.realtype->plugin->print(ctx, &pred->value, format, prefix_data, &d, NULL);
- char quot = '\'';
- if (strchr(str, quot)) {
- quot = '"';
- }
- ly_strcat(&result, "[%s=%c%s%c]", pred->key->name, quot, str, quot);
- if (d) {
- free((char *)str);
- }
- break;
- }
- case LY_PATH_PREDTYPE_LEAFLIST: {
- /* leaf-list-predicate */
- ly_bool d = 0;
- const char *str = pred->value.realtype->plugin->print(ctx, &pred->value, format, prefix_data, &d, NULL);
- char quot = '\'';
- if (strchr(str, quot)) {
- quot = '"';
- }
- ly_strcat(&result, "[.=%c%s%c]", quot, str, quot);
- if (d) {
- free((char *)str);
- }
- break;
- }
- }
+ /* default quote */
+ quot = '\'';
+ if (strchr(strval, quot)) {
+ quot = '"';
}
+ ret = ly_strcat(&result, "[.=%c%s%c]", quot, strval, quot);
+ if (d) {
+ free((char *)strval);
+ }
+ break;
}
- lydict_insert_zc(ctx, result, (const char **)&value->_canonical);
+ LY_CHECK_GOTO(ret, cleanup);
}
+ }
- /* use canonical */
- result = (char *)value->_canonical;
- if (dynamic) {
- *dynamic = 0;
- }
+cleanup:
+ if (ret) {
+ free(result);
} else {
- /* not supported format */
- return NULL;
+ *str = result;
}
-
- if (value_len) {
- *value_len = strlen(result);
- }
- return result;
+ return ret;
}
API LY_ERR
@@ -171,37 +151,54 @@
{
LY_ERR ret = LY_SUCCESS;
struct lysc_type_instanceid *type_inst = (struct lysc_type_instanceid *)type;
- struct ly_path *path = NULL;
+ struct ly_path *path;
+ char *canon;
- /* init */
- *err = NULL;
+ /* clear storage */
+ memset(storage, 0, sizeof *storage);
/* check hints */
ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
- LY_CHECK_GOTO(ret != LY_SUCCESS, cleanup_value);
+ LY_CHECK_GOTO(ret, cleanup);
- LY_CHECK_GOTO(ret = lyplg_type_lypath_new(ctx, value, value_len, options, format, prefix_data, ctx_node,
- unres, &path, err), cleanup);
+ /* compile instance-identifier into path */
+ ret = lyplg_type_lypath_new(ctx, value, value_len, options, format, prefix_data, ctx_node,
+ unres, &path, err);
+ LY_CHECK_GOTO(ret, cleanup);
- /* store resolved schema path and init storage */
+ /* init storage */
storage->_canonical = NULL;
storage->target = path;
- path = NULL;
storage->realtype = type;
- /* generate canonical value */
- lyplg_type_print_instanceid(ctx, storage, LY_VALUE_CANON, NULL, NULL, NULL);
+ /* store canonical value */
+ if (format == LY_VALUE_CANON) {
+ 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 = instanceid_path2str(path, LY_VALUE_JSON, NULL, &canon);
+ LY_CHECK_GOTO(ret, cleanup);
- /* cleanup */
-cleanup:
- lyplg_type_lypath_free(ctx, path);
-
-cleanup_value:
- if (options & LYPLG_TYPE_STORE_DYNAMIC) {
- free((char *)value);
+ ret = lydict_insert_zc(ctx, canon, &storage->_canonical);
+ LY_CHECK_GOTO(ret, cleanup);
}
- if ((ret == LY_SUCCESS) && type_inst->require_instance) {
+cleanup:
+ if (options & LYPLG_TYPE_STORE_DYNAMIC) {
+ free((void *)value);
+ }
+
+ if (ret) {
+ lyplg_type_free_instanceid(ctx, storage);
+ }
+ if (!ret && type_inst->require_instance) {
/* needs to be resolved */
return LY_EINCOMPLETE;
} else {
@@ -225,14 +222,12 @@
}
/* find the target in data */
- if (!(ret = ly_path_eval(storage->target, tree, NULL))) {
- return LY_SUCCESS;
+ if ((ret = ly_path_eval(storage->target, tree, NULL))) {
+ const char *value = lyplg_type_print_instanceid(ctx, storage, LY_VALUE_CANON, NULL, NULL, NULL);
+ return ly_err_new(err, ret, LYVE_DATA, NULL, NULL, LY_ERRMSG_NOINST, value);
}
- /* error */
- const char *value = storage->realtype->plugin->print(ctx, storage, LY_VALUE_CANON, NULL, NULL, NULL);
-
- return ly_err_new(err, ret, LYVE_DATA, NULL, NULL, LY_ERRMSG_NOINST, value);
+ return LY_SUCCESS;
}
API LY_ERR
@@ -246,7 +241,7 @@
if (val1 == val2) {
return LY_SUCCESS;
- } else if (!val1->target || !val2->target || (LY_ARRAY_COUNT(val1->target) != LY_ARRAY_COUNT(val2->target))) {
+ } else if (LY_ARRAY_COUNT(val1->target) != LY_ARRAY_COUNT(val2->target)) {
return LY_ENOT;
}
@@ -274,7 +269,8 @@
break;
case LY_PATH_PREDTYPE_LIST:
/* key-predicate */
- if ((pred1->key != pred2->key) || ((struct lysc_node_leaf *)pred1->key)->type->plugin->compare(&pred1->value, &pred2->value)) {
+ if ((pred1->key != pred2->key) ||
+ ((struct lysc_node_leaf *)pred1->key)->type->plugin->compare(&pred1->value, &pred2->value)) {
return LY_ENOT;
}
break;
@@ -291,20 +287,61 @@
return LY_SUCCESS;
}
+API const void *
+lyplg_type_print_instanceid(const struct ly_ctx *UNUSED(ctx), const struct lyd_value *value, LY_VALUE_FORMAT format,
+ void *prefix_data, ly_bool *dynamic, size_t *value_len)
+{
+ char *ret;
+
+ if ((format == LY_VALUE_CANON) || (format == LY_VALUE_JSON) || (format == LY_VALUE_LYB)) {
+ if (dynamic) {
+ *dynamic = 0;
+ }
+ if (value_len) {
+ *value_len = strlen(value->_canonical);
+ }
+ return value->_canonical;
+ }
+
+ /* print the value in the specific format */
+ if (instanceid_path2str(value->target, format, prefix_data, &ret)) {
+ return NULL;
+ }
+ *dynamic = 1;
+ if (value_len) {
+ *value_len = strlen(ret);
+ }
+ return ret;
+}
+
API LY_ERR
lyplg_type_dup_instanceid(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup)
{
- LY_CHECK_RET(lydict_insert(ctx, original->_canonical, strlen(original->_canonical), &dup->_canonical));
+ LY_ERR ret;
+
+ memset(dup, 0, sizeof *dup);
+
+ /* canonical value */
+ ret = lydict_insert(ctx, original->_canonical, ly_strlen(original->_canonical), &dup->_canonical);
+ LY_CHECK_GOTO(ret, error);
+
+ /* copy path */
+ ret = ly_path_dup(ctx, original->target, &dup->target);
+ LY_CHECK_GOTO(ret, error);
+
dup->realtype = original->realtype;
- return ly_path_dup(ctx, original->target, &dup->target);
+ return LY_SUCCESS;
+
+error:
+ lyplg_type_free_instanceid(ctx, dup);
+ return ret;
}
API void
lyplg_type_free_instanceid(const struct ly_ctx *ctx, struct lyd_value *value)
{
+ lydict_remove(ctx, value->_canonical);
ly_path_free(ctx, value->target);
- value->target = NULL;
- lyplg_type_free_simple(ctx, value);
}
/**