data type CHANGE clarify and simplify information about lyd_value's type
diff --git a/src/plugins_types.c b/src/plugins_types.c
index 7445972..62e3498 100644
--- a/src/plugins_types.c
+++ b/src/plugins_types.c
@@ -50,7 +50,7 @@
* Implementation of the ly_type_free_clb.
*/
static void
-ly_type_free_canonical(struct ly_ctx *ctx, struct lysc_type *UNUSED(type), struct lyd_value *value)
+ly_type_free_canonical(struct ly_ctx *ctx, struct lyd_value *value)
{
lydict_remove(ctx, value->canonized);
value->canonized = NULL;
@@ -901,12 +901,12 @@
* Implementation of the ly_type_free_clb.
*/
static void
-ly_type_free_bits(struct ly_ctx *ctx, struct lysc_type *type, struct lyd_value *value)
+ly_type_free_bits(struct ly_ctx *ctx, struct lyd_value *value)
{
LY_ARRAY_FREE(value->bits_items);
value->bits_items = NULL;
- ly_type_free_canonical(ctx, type, value);
+ ly_type_free_canonical(ctx, value);
}
@@ -1347,7 +1347,7 @@
pred->value = calloc(1, sizeof *pred->value);
type = ((struct lysc_node_leaf*)key)->type;
- pred->value->plugin = type->plugin;
+ pred->value->realtype = type;
ret = type->plugin->store(ctx, type, val, val_len, options, ly_type_stored_prefixes_clb, prefixes, format, key, NULL,
pred->value, NULL, &err);
if (ret == LY_EINCOMPLETE) {
@@ -1438,7 +1438,7 @@
asprintf(&errmsg, "Invalid instance-identifier \"%s\" value - required instance not found.",
"TODO");
/* we have to clean up the storage */
- type->plugin->free(ctx, type, storage);
+ type->plugin->free(ctx, storage);
goto error;
}
@@ -1811,12 +1811,12 @@
* Implementation of the ly_type_free_clb.
*/
static void
-ly_type_free_instanceid(struct ly_ctx *ctx, struct lysc_type *type, struct lyd_value *value)
+ly_type_free_instanceid(struct ly_ctx *ctx, struct lyd_value *value)
{
lyd_value_free_path(ctx, value->target);
value->target = NULL;
- ly_type_free_canonical(ctx, type, value);
+ ly_type_free_canonical(ctx, value);
}
/**
@@ -1848,7 +1848,7 @@
storage_dummy = 1;
}
/* rewrite leafref plugin stored in the storage by default */
- storage->plugin = type_lr->realtype->plugin;
+ storage->realtype = type_lr->realtype;
/* check value according to the real type of the leafref target */
ret = type_lr->realtype->plugin->store(ctx, type_lr->realtype, value, value_len, options,
@@ -2010,7 +2010,7 @@
} while (*token != ']');
/* compare key and the value */
- if (key->value.plugin->compare(&key->value, &((struct lyd_node_term*)value)->value)) {
+ if (key->value.realtype->plugin->compare(&key->value, &((struct lyd_node_term*)value)->value)) {
/* nodes does not match, try another instance */
next_instance:
token = first_pred;
@@ -2048,7 +2048,7 @@
}
if (storage_dummy) {
- storage->plugin->free(ctx, type_lr->realtype, storage);
+ storage->realtype->plugin->free(ctx, storage);
free(storage);
}
return ret;
@@ -2058,7 +2058,7 @@
*err = ly_err_new(LY_LLERR, LY_EVALID, LYVE_RESTRICTION, errmsg, NULL, NULL);
}
if (storage_dummy) {
- storage->plugin->free(ctx, type_lr->realtype, storage);
+ storage->realtype->plugin->free(ctx, storage);
free(storage);
}
return LY_EVALID;
@@ -2073,7 +2073,7 @@
static LY_ERR
ly_type_compare_leafref(const struct lyd_value *val1, const struct lyd_value *val2)
{
- return val1->plugin->compare(val1, val2);
+ return val1->realtype->plugin->compare(val1, val2);
}
/**
@@ -2082,11 +2082,9 @@
* Implementation of the ly_type_free_clb.
*/
static void
-ly_type_free_leafref(struct ly_ctx *ctx, struct lysc_type *type, struct lyd_value *value)
+ly_type_free_leafref(struct ly_ctx *ctx, struct lyd_value *value)
{
- struct lysc_type *realtype = ((struct lysc_type_leafref*)type)->realtype;
-
- realtype->plugin->free(ctx, realtype, value);
+ value->realtype->plugin->free(ctx, value);
}
/**
@@ -2113,12 +2111,24 @@
* about the second call to avoid rewriting the canonized value */
secondcall = 1;
- /* get u of the used type to call the store callback second time, if it fails
- * we are continuing with another type in row, anyway now we should have the data */
- LY_ARRAY_FOR(type_u->types, u) {
- if (type_u->types[u] == subvalue->type) {
- goto search_subtype;
- }
+ /* call the callback second time */
+ ret = subvalue->value->realtype->plugin->store(ctx, subvalue->value->realtype, value, value_len,
+ options & ~(LY_TYPE_OPTS_CANONIZE | LY_TYPE_OPTS_DYNAMIC),
+ ly_type_stored_prefixes_clb, subvalue->prefixes, format,
+ context_node, trees, subvalue->value, NULL, err);
+ if (ret) {
+ /* second call failed, we have to try another subtype of the union.
+ * Unfortunately, since the realtype can change (e.g. in leafref), we are not able to detect
+ * which of the subtype's were tried the last time, so we have to try all of them.
+ * We also have to remove the LY_TYPE_OPTS_SECOND_CALL flag since the callbacks will be now
+ * called for the first time.
+ * In the second call we should have all the data instances, so the LY_EINCOMPLETE should not
+ * happen again.
+ */
+ options = options & ~LY_TYPE_OPTS_SECOND_CALL;
+ ly_err_free(*err);
+ *err = NULL;
+ goto search_subtype;
}
} else {
/* prepare subvalue storage */
@@ -2128,12 +2138,10 @@
/* store prefixes for later use */
subvalue->prefixes = ly_type_get_prefixes(ctx, value, value_len, get_prefix, parser);
+search_subtype:
/* use the first usable sybtype to store the value */
LY_ARRAY_FOR(type_u->types, u) {
- subvalue->value->plugin = type_u->types[u]->plugin;
- subvalue->type = type_u->types[u];
-
-search_subtype:
+ subvalue->value->realtype = type_u->types[u];
ret = type_u->types[u]->plugin->store(ctx, type_u->types[u], value, value_len, options & ~(LY_TYPE_OPTS_CANONIZE | LY_TYPE_OPTS_DYNAMIC),
ly_type_stored_prefixes_clb, subvalue->prefixes, format,
context_node, trees, subvalue->value, NULL, err);
@@ -2141,21 +2149,14 @@
/* success (or not yet complete) */
break;
}
-
- if (options & LY_TYPE_OPTS_SECOND_CALL) {
- /* if started as LY_TYPE_OPTS_SECOND_CALL, we need it just for a single call of the
- * store callback, because if it fails, another store callback is called for the first time */
- options = options & ~LY_TYPE_OPTS_SECOND_CALL;
- }
- if (*err) {
- ly_err_free(*err);
- *err = NULL;
- }
+ ly_err_free(*err);
+ *err = NULL;
}
- }
- if (u == LY_ARRAY_SIZE(type_u->types)) {
- asprintf(&errmsg, "Invalid union value \"%.*s\" - no matching subtype found.", (int)value_len, value);
- goto error;
+
+ if (u == LY_ARRAY_SIZE(type_u->types)) {
+ asprintf(&errmsg, "Invalid union value \"%.*s\" - no matching subtype found.", (int)value_len, value);
+ goto error;
+ }
}
/* success */
@@ -2199,7 +2200,7 @@
free(subvalue->value);
free(subvalue);
if ((options & LY_TYPE_OPTS_SECOND_CALL) && (options & LY_TYPE_OPTS_STORE)) {
- subvalue = NULL;
+ storage->subvalue = NULL;
}
return LY_EVALID;
@@ -2213,10 +2214,10 @@
static LY_ERR
ly_type_compare_union(const struct lyd_value *val1, const struct lyd_value *val2)
{
- if (val1->subvalue->type != val2->subvalue->type) {
+ if (val1->realtype != val2->realtype) {
return LY_EVALID;
}
- return val1->subvalue->type->plugin->compare(val1->subvalue->value, val2->subvalue->value);
+ return val1->realtype->plugin->compare(val1->subvalue->value, val2->subvalue->value);
}
/**
@@ -2225,13 +2226,13 @@
* Implementation of the ly_type_free_clb.
*/
static void
-ly_type_free_union(struct ly_ctx *ctx, struct lysc_type *type, struct lyd_value *value)
+ly_type_free_union(struct ly_ctx *ctx, struct lyd_value *value)
{
unsigned int u;
if (value->subvalue) {
if (value->subvalue->value) {
- value->subvalue->value->plugin->free(ctx, value->subvalue->type, value->subvalue->value);
+ value->subvalue->value->realtype->plugin->free(ctx, value->subvalue->value);
LY_ARRAY_FOR(value->subvalue->prefixes, u) {
lydict_remove(ctx, value->subvalue->prefixes[u].prefix);
}
@@ -2241,10 +2242,12 @@
free(value->subvalue);
value->subvalue = NULL;
}
- ly_type_free_canonical(ctx, type, value);
+ ly_type_free_canonical(ctx, value);
}
-
+/**
+ * @brief Set of type plugins for YANG built-in types
+ */
struct lysc_type_plugin ly_builtin_type_plugins[LY_DATA_TYPE_COUNT] = {
{0}, /* LY_TYPE_UNKNOWN */
{.type = LY_TYPE_BINARY, .store = ly_type_store_binary, .compare = ly_type_compare_canonical, .free = ly_type_free_canonical},
@@ -2267,4 +2270,3 @@
{.type = LY_TYPE_INT32, .store = ly_type_store_int, .compare = ly_type_compare_canonical, .free = ly_type_free_canonical},
{.type = LY_TYPE_INT64, .store = ly_type_store_int, .compare = ly_type_compare_canonical, .free = ly_type_free_canonical},
};
-
diff --git a/src/plugins_types.h b/src/plugins_types.h
index 4b13f1f..a4b243f 100644
--- a/src/plugins_types.h
+++ b/src/plugins_types.h
@@ -137,10 +137,9 @@
* Note that this callback is responsible also for freeing the canonized member in the @p value.
*
* @param[in] ctx libyang ctx to enable correct manipulation with values that are in the dictionary.
- * @param[in] type Type of the stored value.
* @param[in,out] value Value structure to free the data stored there by the plugin's ly_type_store_clb() callback
*/
-typedef void (*ly_type_free_clb)(struct ly_ctx *ctx, struct lysc_type *type, struct lyd_value *value);
+typedef void (*ly_type_free_clb)(struct ly_ctx *ctx, struct lyd_value *value);
/**
* @brief Hold type-specific functions for various operations with the data values.
diff --git a/src/tree_data.c b/src/tree_data.c
index c9ef10f..19a3549 100644
--- a/src/tree_data.c
+++ b/src/tree_data.c
@@ -163,7 +163,9 @@
ctx = node->schema->module->ctx;
type = ((struct lysc_node_leaf*)node->schema)->type;
- node->value.plugin = type->plugin;
+ if (!second) {
+ node->value.realtype = type;
+ }
rc = type->plugin->store(ctx, type, value, value_len, options, get_prefix, parser, format,
trees ? (void*)node : (void*)node->schema, trees,
&node->value, NULL, &err);
@@ -286,7 +288,7 @@
}
cleanup:
- type->plugin->free(ctx, type, &data);
+ type->plugin->free(ctx, &data);
return ret;
}
diff --git a/src/tree_data.h b/src/tree_data.h
index 242ffa1..96e0e81 100644
--- a/src/tree_data.h
+++ b/src/tree_data.h
@@ -183,7 +183,6 @@
const char *prefix; /**< prefix string used in the canonized string to identify the mod of the YANG schema */
const struct lys_module *mod; /**< YANG schema module identified by the prefix string */
} *prefixes; /**< list of mappings between prefix in canonized value to a YANG schema ([sized array](@ref sizedarrays)) */
- struct lysc_type *type;
struct lyd_value *value;
} *subvalue;
@@ -213,10 +212,13 @@
}; /**< The union is just a list of shorthands to possible values stored by a type's plugin. libyang works only with the canonized string,
this specific data type storage is just to simplify use of the values by the libyang users. */
- struct lysc_type_plugin *plugin; /**< pointer to the type plugin which stored the data. This pointer can differ from the pointer
- in the lysc_type structure since the plugin itself can use other plugins for storing data.
- Speaking about built-in types, this is the case of leafref which stores data as its target type.
- Similarly union types stores the currently used type plugin in its internal lyd_value structure. */
+ struct lysc_type *realtype; /**< pointer to the real type of the data stored in the value structure. This type can differ from the type
+ in the schema node of the data node since the type's store plugin can use other types/plugins for
+ storing data. Speaking about built-in types, this is the case of leafref which stores data as its
+ target type. In contrast, union type also use its subtype's callbacks, but inside an internal data
+ lyd_value::subvalue structure, so here is the pointer to the union type.
+ In general, this type is used to get free callback for this lyd_value structure, so it must reflect
+ the type used to store data directly in the same lyd_value instance. */
};
/**
diff --git a/src/tree_data_free.c b/src/tree_data_free.c
index 36a11a0..80653d8 100644
--- a/src/tree_data_free.c
+++ b/src/tree_data_free.c
@@ -33,8 +33,7 @@
LY_ARRAY_FOR(path, u) {
LY_ARRAY_FOR(path[u].predicates, v) {
if (path[u].predicates[v].type > 0) {
- struct lysc_type *t = ((struct lysc_node_leaf*)path[u].predicates[v].key)->type;
- t->plugin->free(ctx, t, path[u].predicates[v].value);
+ ((struct lysc_node_leaf*)path[u].predicates[v].key)->type->plugin->free(ctx, path[u].predicates[v].value);
free(path[u].predicates[v].value);
}
}
@@ -186,8 +185,7 @@
}
#endif
} else if (node->schema->nodetype & LYD_NODE_TERM) {
- struct lysc_type *type = ((struct lysc_node_leaf*)node->schema)->type;
- type->plugin->free(ctx, type, &((struct lyd_node_term*)node)->value);
+ ((struct lysc_node_leaf*)node->schema)->type->plugin->free(ctx, &((struct lyd_node_term*)node)->value);
}
/* free the node's attributes */