Merge remote-tracking branch 'upstream/libyang2' into libyang2
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 346527b..199cdee 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -211,6 +211,7 @@
src/parser_xml.c
src/printer_data.c
src/printer_xml.c
+ src/printer_json.c
src/tree_schema.c
src/tree_schema_free.c
src/tree_schema_compile.c
diff --git a/src/common.h b/src/common.h
index f0f70e4..dc23869 100644
--- a/src/common.h
+++ b/src/common.h
@@ -433,6 +433,14 @@
const char **value, size_t *value_len, const char **errmsg);
/**
+ * @brief ly_clb_get_prefix implementation for JSON. For its simplicity, this implementation is used
+ * internally for various purposes.
+ *
+ * Implemented in printer_json.c
+ */
+const char *json_print_get_prefix(const struct lys_module *mod, void *private);
+
+/**
* @brief mmap(2) wrapper to map input files into memory to unify parsing.
*
* The address space is allocate only for reading.
diff --git a/src/parser_xml.c b/src/parser_xml.c
index fcd9681..48ddf73 100644
--- a/src/parser_xml.c
+++ b/src/parser_xml.c
@@ -323,6 +323,14 @@
/* calculate the hash and insert it into parent (list with keys is handled when its keys are inserted) */
lyd_hash(cur);
lyd_insert_hash(cur);
+
+ /* if we have empty non-presence container, we keep it, but mark it as default */
+ if (cur->schema->nodetype == LYS_CONTAINER && !((struct lyd_node_inner*)cur)->child &&
+ !cur->attr && !(((struct lysc_node_container*)cur->schema)->flags & LYS_PRESENCE)) {
+ cur->flags |= LYD_DEFAULT;
+ }
+
+ /* TODO context validation */
}
cleanup:
diff --git a/src/plugins_types.c b/src/plugins_types.c
index df706a5..15386ad 100644
--- a/src/plugins_types.c
+++ b/src/plugins_types.c
@@ -50,14 +50,11 @@
* Implementation of the ly_type_print_clb.
*/
static const char *
-ly_type_print_canonical(const struct lyd_value *value, LYD_FORMAT UNUSED(format), int prefixes, int *dynamic)
+ly_type_print_canonical(const struct lyd_value *value, LYD_FORMAT UNUSED(format),
+ ly_clb_get_prefix UNUSED(get_prefix), void *UNUSED(printer), int *dynamic)
{
*dynamic = 0;
- if (prefixes) {
- return "";
- } else {
- return (char*)value->canonized;
- }
+ return (char*)value->canonized;
}
/**
@@ -120,7 +117,7 @@
}
API struct lyd_value_prefix *
-ly_type_get_prefixes(struct ly_ctx *ctx, const char *value, size_t value_len, ly_clb_resolve_prefix get_prefix, void *parser)
+ly_type_get_prefixes(struct ly_ctx *ctx, const char *value, size_t value_len, ly_clb_resolve_prefix resolve_prefix, void *parser)
{
LY_ERR ret;
unsigned int c;
@@ -150,7 +147,7 @@
}
}
if (!mod) {
- mod = get_prefix(ctx, start, len, parser);
+ mod = resolve_prefix(ctx, start, len, parser);
if (mod) {
LY_ARRAY_NEW_GOTO(ctx, prefixes, p, ret, error);
p->mod = mod;
@@ -439,7 +436,7 @@
*/
static LY_ERR
ly_type_store_int(struct ly_ctx *ctx, struct lysc_type *type, const char *value, size_t value_len, int options,
- ly_clb_resolve_prefix UNUSED(get_prefix), void *UNUSED(parser), LYD_FORMAT UNUSED(format),
+ ly_clb_resolve_prefix UNUSED(resolve_prefix), void *UNUSED(parser), LYD_FORMAT UNUSED(format),
const void *UNUSED(context_node), const struct lyd_node **UNUSED(trees),
struct lyd_value *storage, const char **canonized, struct ly_err_item **err)
{
@@ -513,7 +510,7 @@
*/
static LY_ERR
ly_type_store_uint(struct ly_ctx *ctx, struct lysc_type *type, const char *value, size_t value_len, int options,
- ly_clb_resolve_prefix UNUSED(get_prefix), void *UNUSED(parser), LYD_FORMAT UNUSED(format),
+ ly_clb_resolve_prefix UNUSED(resolve_prefix), void *UNUSED(parser), LYD_FORMAT UNUSED(format),
const void *UNUSED(context_node), const struct lyd_node **UNUSED(trees),
struct lyd_value *storage, const char **canonized, struct ly_err_item **err)
{
@@ -586,7 +583,7 @@
*/
static LY_ERR
ly_type_store_decimal64(struct ly_ctx *ctx, struct lysc_type *type, const char *value, size_t value_len, int options,
- ly_clb_resolve_prefix UNUSED(get_prefix), void *UNUSED(parser), LYD_FORMAT UNUSED(format),
+ ly_clb_resolve_prefix UNUSED(resolve_prefix), void *UNUSED(parser), LYD_FORMAT UNUSED(format),
const void *UNUSED(context_node), const struct lyd_node **UNUSED(trees),
struct lyd_value *storage, const char **canonized, struct ly_err_item **err)
{
@@ -669,7 +666,7 @@
*/
static LY_ERR
ly_type_store_binary(struct ly_ctx *ctx, struct lysc_type *type, const char *value, size_t value_len, int options,
- ly_clb_resolve_prefix UNUSED(get_prefix), void *UNUSED(parser), LYD_FORMAT UNUSED(format),
+ ly_clb_resolve_prefix UNUSED(resolve_prefix), void *UNUSED(parser), LYD_FORMAT UNUSED(format),
const void *UNUSED(context_node), const struct lyd_node **UNUSED(trees),
struct lyd_value *storage, const char **canonized, struct ly_err_item **err)
{
@@ -772,7 +769,7 @@
*/
static LY_ERR
ly_type_store_string(struct ly_ctx *ctx, struct lysc_type *type, const char *value, size_t value_len, int options,
- ly_clb_resolve_prefix UNUSED(get_prefix), void *UNUSED(parser), LYD_FORMAT UNUSED(format),
+ ly_clb_resolve_prefix UNUSED(resolve_prefix), void *UNUSED(parser), LYD_FORMAT UNUSED(format),
const void *UNUSED(context_node), const struct lyd_node **UNUSED(trees),
struct lyd_value *storage, const char **canonized, struct ly_err_item **err)
{
@@ -815,7 +812,7 @@
*/
static LY_ERR
ly_type_store_bits(struct ly_ctx *ctx, struct lysc_type *type, const char *value, size_t value_len, int options,
- ly_clb_resolve_prefix UNUSED(get_prefix), void *UNUSED(parser), LYD_FORMAT UNUSED(format),
+ ly_clb_resolve_prefix UNUSED(resolve_prefix), void *UNUSED(parser), LYD_FORMAT UNUSED(format),
const void *UNUSED(context_node), const struct lyd_node **UNUSED(trees),
struct lyd_value *storage, const char **canonized, struct ly_err_item **err)
{
@@ -1001,7 +998,7 @@
*/
static LY_ERR
ly_type_store_enum(struct ly_ctx *ctx, struct lysc_type *type, const char *value, size_t value_len, int options,
- ly_clb_resolve_prefix UNUSED(get_prefix), void *UNUSED(parser), LYD_FORMAT UNUSED(format),
+ ly_clb_resolve_prefix UNUSED(resolve_prefix), void *UNUSED(parser), LYD_FORMAT UNUSED(format),
const void *UNUSED(context_node), const struct lyd_node **UNUSED(trees),
struct lyd_value *storage, const char **canonized, struct ly_err_item **err)
{
@@ -1080,7 +1077,7 @@
*/
static LY_ERR
ly_type_store_boolean(struct ly_ctx *ctx, struct lysc_type *UNUSED(type), const char *value, size_t value_len, int options,
- ly_clb_resolve_prefix UNUSED(get_prefix), void *UNUSED(parser), LYD_FORMAT UNUSED(format),
+ ly_clb_resolve_prefix UNUSED(resolve_prefix), void *UNUSED(parser), LYD_FORMAT UNUSED(format),
const void *UNUSED(context_node), const struct lyd_node **UNUSED(trees),
struct lyd_value *storage, const char **canonized, struct ly_err_item **err)
{
@@ -1128,7 +1125,7 @@
*/
static LY_ERR
ly_type_store_empty(struct ly_ctx *ctx, struct lysc_type *UNUSED(type), const char *value, size_t value_len, int options,
- ly_clb_resolve_prefix UNUSED(get_prefix), void *UNUSED(parser), LYD_FORMAT UNUSED(format),
+ ly_clb_resolve_prefix UNUSED(resolve_prefix), void *UNUSED(parser), LYD_FORMAT UNUSED(format),
const void *UNUSED(context_node), const struct lyd_node **UNUSED(trees),
struct lyd_value *storage, const char **canonized, struct ly_err_item **err)
{
@@ -1185,7 +1182,7 @@
*/
static LY_ERR
ly_type_store_identityref(struct ly_ctx *ctx, struct lysc_type *type, const char *value, size_t value_len, int options,
- ly_clb_resolve_prefix get_prefix, void *parser, LYD_FORMAT UNUSED(format),
+ ly_clb_resolve_prefix resolve_prefix, void *parser, LYD_FORMAT UNUSED(format),
const void *UNUSED(context_node), const struct lyd_node **UNUSED(trees),
struct lyd_value *storage, const char **canonized, struct ly_err_item **err)
{
@@ -1217,7 +1214,7 @@
goto error;
}
- mod = get_prefix(ctx, prefix, prefix_len, parser);
+ mod = resolve_prefix(ctx, prefix, prefix_len, parser);
if (!mod) {
asprintf(&errmsg, "Invalid identityref \"%.*s\" value - unable to map prefix to YANG schema.", (int)value_len, value);
goto error;
@@ -1290,28 +1287,14 @@
* Implementation of the ly_type_print_clb.
*/
static const char *
-ly_type_print_identityref(const struct lyd_value *value, LYD_FORMAT format, int prefixes, int *dynamic)
+ly_type_print_identityref(const struct lyd_value *value, LYD_FORMAT UNUSED(format), ly_clb_get_prefix get_prefix, void *printer, int *dynamic)
{
char *result = NULL;
- if (prefixes) {
- if (format == LYD_XML) {
- *dynamic = 1;
- asprintf(&result, "xmlns:%s=\"%s\"", value->ident->module->prefix, value->ident->module->ns);
- return result;
- } else {
- *dynamic = 0;
- return "";
- }
- } else {
- *dynamic = 1;
- if (format == LYD_XML) {
- asprintf(&result, "%s:%s", value->ident->module->prefix, value->ident->name);
- } else {
- asprintf(&result, "%s:%s", value->ident->module->name, value->ident->name);
- }
- return result;
- }
+ *dynamic = 1;
+ asprintf(&result, "%s:%s", get_prefix(value->ident->module, printer), value->ident->name);
+
+ return result;
}
/* @brief Duplication callback of the identityref values.
@@ -1541,7 +1524,7 @@
*/
static LY_ERR
ly_type_store_instanceid(struct ly_ctx *ctx, struct lysc_type *type, const char *value, size_t value_len, int options,
- ly_clb_resolve_prefix get_prefix, void *parser, LYD_FORMAT format,
+ ly_clb_resolve_prefix resolve_prefix, void *parser, LYD_FORMAT format,
const void *UNUSED(context_node), const struct lyd_node **trees,
struct lyd_value *storage, const char **canonized, struct ly_err_item **err)
{
@@ -1568,9 +1551,10 @@
/* the second run, the first one ended with LY_EINCOMPLETE, but we have prepared the target structure */
if (!lyd_target(storage->target, trees)) {
- /* TODO print instance-identifier */
+ /* in error message we print the JSON format of the instance-identifier - in case of XML, it is not possible
+ * to get the exactly same string as original, JSON is less demanding and still well readable/understandable. */
int dynamic = 0;
- const char *id = storage->realtype->plugin->print(storage, format, 0, &dynamic);
+ const char *id = storage->realtype->plugin->print(storage, LYD_JSON, json_print_get_prefix, NULL, &dynamic);
asprintf(&errmsg, "Invalid instance-identifier \"%s\" value - required instance not found.", id);
if (dynamic) {
free((char*)id);
@@ -1583,7 +1567,7 @@
return LY_SUCCESS;
} else {
/* first run without prepared target, we will need all the prefixes used in the instance-identifier value */
- prefixes = ly_type_get_prefixes(ctx, value, value_len, get_prefix, parser);
+ prefixes = ly_type_get_prefixes(ctx, value, value_len, resolve_prefix, parser);
}
if (value[0] != '/') {
@@ -1683,7 +1667,7 @@
if (node_d) {
while (node_d) {
- if (!lyd_value_compare((const struct lyd_node_term*)key_d, val, val_len, get_prefix, parser, format, trees)) {
+ if (!lyd_value_compare((const struct lyd_node_term*)key_d, val, val_len, resolve_prefix, parser, format, trees)) {
/* match */
break;
}
@@ -1711,7 +1695,7 @@
}
} else {
/* check value to the type */
- if (lys_value_validate(NULL, key_s, val, val_len, get_prefix, parser, format)) {
+ if (lys_value_validate(NULL, key_s, val, val_len, resolve_prefix, parser, format)) {
asprintf(&errmsg, "Invalid instance-identifier \"%.*s\" value - key-predicate \"%.*s\"'s key value is invalid.",
(int)value_len, value, (int)(token - pred_start), pred_start);
goto error;
@@ -1758,7 +1742,7 @@
if (key_d) {
while (key_d) {
- if (!lyd_value_compare((const struct lyd_node_term*)key_d, val, val_len, get_prefix, parser, format, trees)) {
+ if (!lyd_value_compare((const struct lyd_node_term*)key_d, val, val_len, resolve_prefix, parser, format, trees)) {
/* match */
break;
}
@@ -1772,7 +1756,7 @@
}
} else {
/* check value to the type */
- if (lys_value_validate(NULL, key_s, val, val_len, get_prefix, parser, format)) {
+ if (lys_value_validate(NULL, key_s, val, val_len, resolve_prefix, parser, format)) {
asprintf(&errmsg, "Invalid instance-identifier \"%.*s\" value - leaf-list-predicate \"%.*s\"'s value is invalid.",
(int)value_len, value, (int)(token - pred_start), pred_start);
goto error;
@@ -1943,152 +1927,91 @@
return LY_SUCCESS;
}
-static void
-ly_type_print_prefixes_mod(char **str, struct ly_set *printed, struct lys_module *mod)
-{
- unsigned int u = printed->count;
- if (ly_set_add(printed, mod, 0) == (int)u) {
- /* newly added module - print it */
- asprintf(str, "%s%sxmlns:%s=\"%s\"", *str ? *str : "", *str ? " " : "", mod->prefix, mod->ns);
- }
-}
-
/**
* @brief Printer callback printing the instance-identifier value.
*
* Implementation of the ly_type_print_clb.
*/
static const char *
-ly_type_print_instanceid(const struct lyd_value *value, LYD_FORMAT format, int prefixes, int *dynamic)
+ly_type_print_instanceid(const struct lyd_value *value, LYD_FORMAT format, ly_clb_get_prefix get_prefix, void *printer, int *dynamic)
{
unsigned int u, v;
char *result = NULL;
- if (prefixes) {
- /* print namespace definition -only for XML, it does not make sense in JSON */
- if (format == LYD_XML) {
- struct ly_set printed_prefixes = {0};
-
- LY_ARRAY_FOR(value->target, u) {
- ly_type_print_prefixes_mod(&result, &printed_prefixes, value->target[u].node->module);
- LY_ARRAY_FOR(value->target[u].predicates, v) {
- struct lyd_value_path_predicate *pred = &value->target[u].predicates[v];
- if (pred->type) {
- /* non-position predicate with a value
- * (key is of the same namespace as the list, so we don't need to handle its prefix) */
- int d = 0;
- char *token, *s = (char*)pred->value->realtype->plugin->print(pred->value, LYD_XML, 1, &d);
- if (s && s[0]) {
- char *start = s;
- if (!d) {
- start = s = strdup(s);
- }
- while ((token = strsep(&s, " "))) {
- unsigned int i;
- char *equal;
- equal = strchr(token, '=');
- /* check if we already have such a prefix */
- for (i = 0; i < printed_prefixes.count; i++) {
- /* equal points to =\"namespace\" and we need to compare just the namespace without quotation */
- size_t len = strlen(equal) - 3;
- size_t len_ns = strlen(((struct lys_module *)printed_prefixes.objs[i])->ns);
- if (len == len_ns && !strncmp(((struct lys_module *)printed_prefixes.objs[i])->ns, equal + 2, len)) {
- /* match, do not print this namespace definition */
- break;
- }
- }
- if (i == printed_prefixes.count) {
- /* not yet printed namespace */
- ly_strcat(&result, "%s%s", result ? " " : "", token);
- }
- }
- free(start);
- }
+ if (format == LYD_XML) {
+ /* everything is prefixed */
+ LY_ARRAY_FOR(value->target, u) {
+ ly_strcat(&result, "/%s:%s", get_prefix(value->target[u].node->module, printer), value->target[u].node->name);
+ LY_ARRAY_FOR(value->target[u].predicates, v) {
+ struct lyd_value_path_predicate *pred = &value->target[u].predicates[v];
+ if (pred->type == 0) {
+ /* position predicate */
+ ly_strcat(&result, "[%"PRIu64"]", pred->position);
+ } else if (pred->type == 1) {
+ /* key-predicate */
+ int d = 0;
+ const char *value = pred->value->realtype->plugin->print(pred->value, format, get_prefix, printer, &d);
+ char quot = '\'';
+ if (strchr(value, quot)) {
+ quot = '"';
+ }
+ ly_strcat(&result, "[%s:%s=%c%s%c]", get_prefix(pred->key->module, printer), pred->key->name, quot, value, quot);
+ if (d) {
+ free((char*)value);
+ }
+ } else if (pred->type == 2) {
+ /* leaf-list-predicate */
+ int d = 0;
+ const char *value = pred->value->realtype->plugin->print(pred->value, format, get_prefix, printer, &d);
+ char quot = '\'';
+ if (strchr(value, quot)) {
+ quot = '"';
+ }
+ ly_strcat(&result, "[.=%c%s%c]", quot, value, quot);
+ if (d) {
+ free((char*)value);
}
}
}
- ly_set_erase(&printed_prefixes, NULL);
- } else { /* JSON */
- *dynamic = 0;
- return "";
}
- } else {
- /* print value */
- if (format == LYD_XML) {
- /* everything is prefixed */
- LY_ARRAY_FOR(value->target, u) {
- ly_strcat(&result, "/%s:%s", value->target[u].node->module->prefix, value->target[u].node->name);
- LY_ARRAY_FOR(value->target[u].predicates, v) {
- struct lyd_value_path_predicate *pred = &value->target[u].predicates[v];
- if (pred->type == 0) {
- /* position predicate */
- ly_strcat(&result, "[%"PRIu64"]", pred->position);
- } else if (pred->type == 1) {
- /* key-predicate */
- int d = 0;
- const char *value = pred->value->realtype->plugin->print(pred->value, format, 0, &d);
- char quot = '\'';
- if (strchr(value, quot)) {
- quot = '"';
- }
- ly_strcat(&result, "[%s:%s=%c%s%c]", pred->key->module->prefix, pred->key->name, quot, value, quot);
- if (d) {
- free((char*)value);
- }
- } else if (pred->type == 2) {
- /* leaf-list-predicate */
- int d = 0;
- const char *value = pred->value->realtype->plugin->print(pred->value, format, 0, &d);
- char quot = '\'';
- if (strchr(value, quot)) {
- quot = '"';
- }
- ly_strcat(&result, "[.=%c%s%c]", quot, value, quot);
- if (d) {
- free((char*)value);
- }
- }
- }
+ } else { /* LYD_JSON */
+ /* only the first node or the node changing module is prefixed */
+ 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", get_prefix(mod, printer), value->target[u].node->name);
+ } else {
+ ly_strcat(&result, "/%s", value->target[u].node->name);
}
- } else { /* LYD_JSON */
- /* only the first node or the node changing module is prefixed */
- 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", mod->name, value->target[u].node->name);
- } else {
- ly_strcat(&result, "/%s", value->target[u].node->name);
- }
- LY_ARRAY_FOR(value->target[u].predicates, v) {
- struct lyd_value_path_predicate *pred = &value->target[u].predicates[v];
- if (pred->type == 0) {
- /* position predicate */
- ly_strcat(&result, "[%"PRIu64"]", pred->position);
- } else if (pred->type == 1) {
- /* key-predicate */
- int d = 0;
- const char *value = pred->value->realtype->plugin->print(pred->value, format, 0, &d);
- char quot = '\'';
- if (strchr(value, quot)) {
- quot = '"';
- }
- ly_strcat(&result, "[%s=%c%s%c]", pred->key->name, quot, value, quot);
- if (d) {
- free((char*)value);
- }
- } else if (pred->type == 2) {
- /* leaf-list-predicate */
- int d = 0;
- const char *value = pred->value->realtype->plugin->print(pred->value, format, 0, &d);
- char quot = '\'';
- if (strchr(value, quot)) {
- quot = '"';
- }
- ly_strcat(&result, "[.=%c%s%c]", quot, value, quot);
- if (d) {
- free((char*)value);
- }
+ LY_ARRAY_FOR(value->target[u].predicates, v) {
+ struct lyd_value_path_predicate *pred = &value->target[u].predicates[v];
+ if (pred->type == 0) {
+ /* position predicate */
+ ly_strcat(&result, "[%"PRIu64"]", pred->position);
+ } else if (pred->type == 1) {
+ /* key-predicate */
+ int d = 0;
+ const char *value = pred->value->realtype->plugin->print(pred->value, format, get_prefix, printer, &d);
+ char quot = '\'';
+ if (strchr(value, quot)) {
+ quot = '"';
+ }
+ ly_strcat(&result, "[%s=%c%s%c]", pred->key->name, quot, value, quot);
+ if (d) {
+ free((char*)value);
+ }
+ } else if (pred->type == 2) {
+ /* leaf-list-predicate */
+ int d = 0;
+ const char *value = pred->value->realtype->plugin->print(pred->value, format, get_prefix, printer, &d);
+ char quot = '\'';
+ if (strchr(value, quot)) {
+ quot = '"';
+ }
+ ly_strcat(&result, "[.=%c%s%c]", quot, value, quot);
+ if (d) {
+ free((char*)value);
}
}
}
@@ -2162,7 +2085,7 @@
*/
static LY_ERR
ly_type_store_leafref(struct ly_ctx *ctx, struct lysc_type *type, const char *value, size_t value_len, int options,
- ly_clb_resolve_prefix get_prefix, void *parser, LYD_FORMAT format,
+ ly_clb_resolve_prefix resolve_prefix, void *parser, LYD_FORMAT format,
const void *context_node, const struct lyd_node **trees,
struct lyd_value *storage, const char **canonized, struct ly_err_item **err)
{
@@ -2188,7 +2111,7 @@
/* 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,
- get_prefix, parser, format, context_node, trees,
+ resolve_prefix, parser, format, context_node, trees,
storage, canonized, err);
if (ret != LY_SUCCESS && ret != LY_EINCOMPLETE) {
return ret;
@@ -2418,9 +2341,9 @@
* Implementation of the ly_type_print_clb.
*/
static const char *
-ly_type_print_leafref(const struct lyd_value *value, LYD_FORMAT format, int prefixes, int *dynamic)
+ly_type_print_leafref(const struct lyd_value *value, LYD_FORMAT format, ly_clb_get_prefix get_prefix, void *printer, int *dynamic)
{
- return value->realtype->plugin->print(value, format, prefixes, dynamic);
+ return value->realtype->plugin->print(value, format, get_prefix, printer, dynamic);
}
/* @brief Duplication callback of the leafref values.
@@ -2451,7 +2374,7 @@
*/
static LY_ERR
ly_type_store_union(struct ly_ctx *ctx, struct lysc_type *type, const char *value, size_t value_len, int options,
- ly_clb_resolve_prefix get_prefix, void *parser, LYD_FORMAT format,
+ ly_clb_resolve_prefix resolve_prefix, void *parser, LYD_FORMAT format,
const void *context_node, const struct lyd_node **trees,
struct lyd_value *storage, const char **canonized, struct ly_err_item **err)
{
@@ -2493,7 +2416,7 @@
subvalue->value = calloc(1, sizeof *subvalue->value);
/* store prefixes for later use */
- subvalue->prefixes = ly_type_get_prefixes(ctx, value, value_len, get_prefix, parser);
+ subvalue->prefixes = ly_type_get_prefixes(ctx, value, value_len, resolve_prefix, parser);
search_subtype:
/* use the first usable sybtype to store the value */
@@ -2583,31 +2506,9 @@
* Implementation of the ly_type_print_clb.
*/
static const char *
-ly_type_print_union(const struct lyd_value *value, LYD_FORMAT format, int prefixes, int *dynamic)
+ly_type_print_union(const struct lyd_value *value, LYD_FORMAT format, ly_clb_get_prefix get_prefix, void *printer, int *dynamic)
{
- unsigned int u;
- char *result = NULL;
-
- if (prefixes) {
- if (format == LYD_XML) {
- LY_ARRAY_FOR(value->subvalue->prefixes, u) {
- ly_strcat(&result, "%sxmlns:%s=\"%s\"", result ? " " : "",
- value->subvalue->prefixes[u].prefix, value->subvalue->prefixes[u].mod->ns);
- }
- if (result) {
- *dynamic = 1;
- return result;
- } else {
- *dynamic = 0;
- return "";
- }
- } else {
- *dynamic = 0;
- return "";
- }
- } else {
- return ly_type_print_canonical(value, format, 0, dynamic);
- }
+ return ly_type_print_canonical(value, format, get_prefix, printer, dynamic);
}
/* @brief Duplication callback of the union values.
diff --git a/src/plugins_types.h b/src/plugins_types.h
index 49f624f..5023b1b 100644
--- a/src/plugins_types.h
+++ b/src/plugins_types.h
@@ -94,8 +94,8 @@
* @param[in] value_len Length of the given \p value.
* @param[in] options [Type plugin options ](@ref plugintypeopts).
*
- * @param[in] get_prefix Parser-specific getter to resolve prefixes used in the value strings.
- * @param[in] parser Parser's data for @p get_prefix
+ * @param[in] resolve_prefix Parser-specific callback to resolve prefixes used in the value strings.
+ * @param[in] parser Parser's data for @p resolve_prefix
* @param[in] format Input format of the data.
* @param[in] context_node The @p value's node for the case that the require-instance restriction is supposed to be resolved. This argument is of
* lys_node (in case LY_TYPE_OPTS_INCOMPLETE_DATA set in @p options) or lyd_node structure.
@@ -115,7 +115,7 @@
* @return LY_ERR value if an error occurred and the value could not be canonized following the type's rules.
*/
typedef LY_ERR (*ly_type_store_clb)(struct ly_ctx *ctx, struct lysc_type *type, const char *value, size_t value_len, int options,
- ly_clb_resolve_prefix get_prefix, void *parser, LYD_FORMAT format,
+ ly_clb_resolve_prefix resolve_prefix, void *parser, LYD_FORMAT format,
const void *context_node, const struct lyd_node **trees,
struct lyd_value *storage, const char **canonized, struct ly_err_item **err);
@@ -137,15 +137,15 @@
* @param[in] value Value to print.
* @param[in] format Format in which the data are supposed to be printed.
* Only 2 formats are currently implemented: LYD_XML and LYD_JSON.
- * @param[in] prefixes Flag to get printed prefix/namespace string instead of the value itself.
- * Since JSON uses YANG module names as prefixes, this option make sense only with LYD_XML @p format.
+ * @param[in] get_prefix Callback to get prefix to use when printing objects supposed to be prefixed.
+ * @param[in] printer Private data for the @p get_prefix callback.
* @param[out] dynamic Flag if the returned string is dynamically allocated. In such a case the caller is responsible
* for freeing it.
* @return String with the value of @p value in specified @p format. According to the returned @p dynamic flag, caller
* can be responsible for freeing allocated memory.
* @return NULL in case of error.
*/
-typedef const char *(*ly_type_print_clb)(const struct lyd_value *value, LYD_FORMAT format, int prefixes, int *dynamic);
+typedef const char *(*ly_type_print_clb)(const struct lyd_value *value, LYD_FORMAT format, ly_clb_get_prefix get_prefix, void *printer, int *dynamic);
/**
* @brief Callback to duplicate data in data structure. Note that callback is even responsible for duplicating lyd_value::canonized.
diff --git a/src/printer_json.c b/src/printer_json.c
new file mode 100644
index 0000000..1ef4309
--- /dev/null
+++ b/src/printer_json.c
@@ -0,0 +1,39 @@
+/**
+ * @file printer_xml.c
+ * @author Michal Vasko <mvasko@cesnet.cz>
+ * @author Radek Krejci <rkrejci@cesnet.cz>
+ * @brief XML printer for libyang data structure
+ *
+ * Copyright (c) 2015 - 2019 CESNET, z.s.p.o.
+ *
+ * This source code is licensed under BSD 3-Clause License (the "License").
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ */
+
+#include "common.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "log.h"
+#include "plugins_types.h"
+#include "printer_data.h"
+#include "printer_internal.h"
+#include "tree.h"
+#include "tree_data.h"
+#include "tree_schema.h"
+
+/**
+ * @brief JSON mapping of YANG modules to prefixes in values.
+ *
+ * Implementation of ly_clb_get_prefix.
+ */
+const char *
+json_print_get_prefix(const struct lys_module *mod, void *UNUSED(private))
+{
+ return mod->name;
+}
+
diff --git a/src/printer_xml.c b/src/printer_xml.c
index 813d032..8d2dd01 100644
--- a/src/printer_xml.c
+++ b/src/printer_xml.c
@@ -334,6 +334,20 @@
static LY_ERR xml_print_node(struct xmlpr_ctx *ctx, const struct lyd_node *node);
/**
+ * @brief XML mapping of YANG modules to prefixes in values.
+ *
+ * Implementation of ly_clb_get_prefix
+ */
+static const char *
+xml_print_get_prefix(const struct lys_module *mod, void *private)
+{
+ struct ly_set *ns_list = (struct ly_set*)private;
+
+ ly_set_add(ns_list, (void*)mod, 0);
+ return mod->prefix;
+}
+
+/**
* @brief Print XML element representing lyd_node_term.
*
* @param[in] ctx XML printer context.
@@ -344,18 +358,28 @@
xml_print_term(struct xmlpr_ctx *ctx, const struct lyd_node_term *node)
{
LY_CHECK_RET(xml_print_node_open(ctx, (struct lyd_node *)node));
+ struct ly_set ns_list = {0};
+ unsigned int u;
+ int dynamic;
+ const char *value = node->value.realtype->plugin->print(&node->value, LYD_XML, xml_print_get_prefix, &ns_list, &dynamic);
- if (((struct lysc_node_leaf*)node->schema)->type->plugin->flags & LY_TYPE_FLAG_PREFIXES) {
- /* TODO get prefixes from the value and print namespaces */
+ /* print namespaces connected with the values's prefixes */
+ for (u = 0; u < ns_list.count; ++u) {
+ const struct lys_module *mod = (const struct lys_module*)ns_list.objs[u];
+ ly_print(ctx->out, "%sxmlns:%s=\"%s\"", u ? " " : "", mod->prefix, mod->ns);
}
+ ly_set_erase(&ns_list, NULL);
- if (!node->value.canonized || !node->value.canonized[0]) {
+ if (!value || !value[0]) {
ly_print(ctx->out, "/>%s", LEVEL ? "\n" : "");
} else {
ly_print(ctx->out, ">");
- lyxml_dump_text(ctx->out, node->value.canonized, 0);
+ lyxml_dump_text(ctx->out, value, 0);
ly_print(ctx->out, "</%s>%s", node->schema->name, LEVEL ? "\n" : "");
}
+ if (dynamic) {
+ free((void*)value);
+ }
return LY_SUCCESS;
}
diff --git a/src/printer_yang.c b/src/printer_yang.c
index 42fcb14..a54c30f 100755
--- a/src/printer_yang.c
+++ b/src/printer_yang.c
@@ -26,6 +26,7 @@
#include "tree.h"
#include "tree_schema.h"
#include "tree_schema_internal.h"
+#include "plugins_types.h"
#include "xpath.h"
/**
@@ -900,6 +901,19 @@
}
static void
+yprc_dflt_value(struct ypr_ctx *ctx, const struct lyd_value *value, struct lysc_ext_instance *exts)
+{
+ int dynamic;
+ const char *str;
+
+ str = value->realtype->plugin->print(value, LYD_JSON, json_print_get_prefix, NULL, &dynamic);
+ ypr_substmt(ctx, LYEXT_SUBSTMT_DEFAULT, 0, str, exts);
+ if (dynamic) {
+ free((void*)str);
+ }
+}
+
+static void
yprc_type(struct ypr_ctx *ctx, const struct lysc_type *type)
{
unsigned int u;
@@ -911,7 +925,7 @@
yprc_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, type->exts, &flag, 0);
if (type->dflt) {
ypr_open(ctx->out, &flag);
- ypr_substmt(ctx, LYEXT_SUBSTMT_DEFAULT, 0, type->dflt, type->exts);
+ yprc_dflt_value(ctx, type->dflt, type->exts);
}
switch(type->basetype) {
@@ -1539,7 +1553,10 @@
LY_ARRAY_FOR(leaf->musts, u) {
yprc_must(ctx, &leaf->musts[u], NULL);
}
- ypr_substmt(ctx, LYEXT_SUBSTMT_DEFAULT, 0, leaf->dflt, leaf->exts);
+
+ if (leaf->dflt) {
+ yprc_dflt_value(ctx, leaf->dflt, leaf->exts);
+ }
yprc_node_common2(ctx, node, NULL);
@@ -1603,7 +1620,7 @@
yprc_must(ctx, &llist->musts[u], NULL);
}
LY_ARRAY_FOR(llist->dflts, u) {
- ypr_substmt(ctx, LYEXT_SUBSTMT_DEFAULT, u, llist->dflts[u], llist->exts);
+ yprc_dflt_value(ctx, llist->dflts[u], llist->exts);
}
ypr_config(ctx, node->flags, node->exts, NULL);
diff --git a/src/tree.h b/src/tree.h
index 5210ce2..d0a9ced 100644
--- a/src/tree.h
+++ b/src/tree.h
@@ -157,10 +157,12 @@
extern const char* ly_data_type2str[LY_DATA_TYPE_COUNT];
/**
- * @brief Callback provided by the data parsers to type plugins to resolve (format-specific) mapping between prefixes used in the value strings
- * to the YANG schemas.
+ * @brief Callback provided by the data/schema parsers to type plugins to resolve (format-specific) mapping between prefixes used
+ * in the value strings to the YANG schemas.
*
- * XML uses XML namespaces, JSON uses schema names as prefixes.
+ * Reverse function to ly_clb_get_prefix.
+ *
+ * XML uses XML namespaces, JSON uses schema names as prefixes, YIN/YANG uses prefixes of the imports.
*
* @param[in] ctx libyang context to find the schema.
* @param[in] prefix Prefix found in the value string
@@ -170,6 +172,20 @@
*/
typedef const struct lys_module *(*ly_clb_resolve_prefix)(struct ly_ctx *ctx, const char *prefix, size_t prefix_len, void *private);
+/**
+ * @brief Callback provided by the data/schema printers to type plugins to resolve (format-specific) mapping between YANG module of a data object
+ * to prefixes used in the value strings.
+ *
+ * Reverse function to ly_clb_resolve_prefix.
+ *
+ * XML uses XML namespaces, JSON uses schema names as prefixes, YIN/YANG uses prefixes of the imports.
+ *
+ * @param[in] mod YANG module of the object.
+ * @param[in] private Internal data needed by the callback.
+ * @return String representing prefix for the object of the given YANG module @p mod.
+ */
+typedef const char *(*ly_clb_get_prefix)(const struct lys_module *mod, void *private);
+
/** @} */
#ifdef __cplusplus
diff --git a/src/tree_data_hash.c b/src/tree_data_hash.c
index 2d6913a..7627ce5 100644
--- a/src/tree_data_hash.c
+++ b/src/tree_data_hash.c
@@ -57,7 +57,7 @@
for (iter = list->child; keys_count; --keys_count, iter = iter->next) {
int dynamic = 0;
struct lysc_type *type = ((struct lysc_node_leaf*)iter->schema)->type;
- const char *value = type->plugin->print(&((struct lyd_node_term*)iter)->value, LYD_JSON, 0, &dynamic);
+ const char *value = type->plugin->print(&((struct lyd_node_term*)iter)->value, LYD_JSON, json_print_get_prefix, NULL, &dynamic);
node->hash = dict_hash_multi(node->hash, value, strlen(value));
if (dynamic) {
free((char*)value);
@@ -70,7 +70,8 @@
} else if (node->schema->nodetype == LYS_LEAFLIST) {
struct lyd_node_term *llist = (struct lyd_node_term*)node;
int dynamic = 0;
- const char *value = ((struct lysc_node_leaflist*)node->schema)->type->plugin->print(&llist->value, LYD_JSON, 0, &dynamic);
+ const char *value = ((struct lysc_node_leaflist*)node->schema)->type->plugin->print(&llist->value, LYD_JSON,
+ json_print_get_prefix, NULL, &dynamic);
node->hash = dict_hash_multi(node->hash, value, strlen(value));
if (dynamic) {
free((char*)value);
diff --git a/src/tree_schema.h b/src/tree_schema.h
index a8b2d5f..d032021 100644
--- a/src/tree_schema.h
+++ b/src/tree_schema.h
@@ -980,7 +980,7 @@
struct lysc_type {
struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
- const char *dflt; /**< type's default value if any */
+ struct lyd_value *dflt; /**< type's default value if any */
struct lysc_type_plugin *plugin; /**< type's plugin with built-in as well as user functions to canonize or validate the value of the type */
LY_DATA_TYPE basetype; /**< Base type of the type */
uint32_t refcount; /**< reference counter for type sharing */
@@ -988,7 +988,7 @@
struct lysc_type_num {
struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
- const char *dflt; /**< type's default value if any */
+ struct lyd_value *dflt; /**< type's default value if any */
struct lysc_type_plugin *plugin; /**< type's plugin with built-in as well as user functions to canonize or validate the value of the type */
LY_DATA_TYPE basetype; /**< Base type of the type */
uint32_t refcount; /**< reference counter for type sharing */
@@ -997,7 +997,7 @@
struct lysc_type_dec {
struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
- const char *dflt; /**< type's default value if any */
+ struct lyd_value *dflt; /**< type's default value if any */
struct lysc_type_plugin *plugin; /**< type's plugin with built-in as well as user functions to canonize or validate the value of the type */
LY_DATA_TYPE basetype; /**< Base type of the type */
uint32_t refcount; /**< reference counter for type sharing */
@@ -1007,7 +1007,7 @@
struct lysc_type_str {
struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
- const char *dflt; /**< type's default value if any */
+ struct lyd_value *dflt; /**< type's default value if any */
struct lysc_type_plugin *plugin; /**< type's plugin with built-in as well as user functions to canonize or validate the value of the type */
LY_DATA_TYPE basetype; /**< Base type of the type */
uint32_t refcount; /**< reference counter for type sharing */
@@ -1256,7 +1256,7 @@
struct lysc_type *type; /**< type of the leaf node (mandatory) */
const char *units; /**< units of the leaf's type */
- const char *dflt; /**< default value */
+ struct lyd_value *dflt; /**< default value */
};
struct lysc_node_leaflist {
@@ -1281,7 +1281,7 @@
struct lysc_type *type; /**< type of the leaf node (mandatory) */
const char *units; /**< units of the leaf's type */
- const char **dflts; /**< list of default values ([sized array](@ref sizedarrays)) */
+ struct lyd_value **dflts; /**< list of default values ([sized array](@ref sizedarrays)) */
uint32_t min; /**< min-elements constraint */
uint32_t max; /**< max-elements constraint */
diff --git a/src/tree_schema_compile.c b/src/tree_schema_compile.c
index 8204bf4..d81ac32 100644
--- a/src/tree_schema_compile.c
+++ b/src/tree_schema_compile.c
@@ -404,7 +404,7 @@
LY_CHECK_ERR_RET(!edef, LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
"Extension definition of extension instance \"%s\" not found.", ext_p->name),
LY_EVALID);
- /* TODO plugins */
+ /* TODO extension plugins */
return LY_SUCCESS;
}
@@ -2939,6 +2939,7 @@
struct lysc_type *base = NULL, *prev_type;
struct ly_set tpdf_chain = {0};
const char *dflt = NULL;
+ struct lys_module *dflt_mod = NULL;
(*type) = NULL;
@@ -2965,6 +2966,7 @@
if (!dflt) {
/* inherit default */
dflt = tctx->tpdf->dflt;
+ dflt_mod = tctx->mod->mod;
}
if (dummyloops && (!units || *units) && dflt) {
basetype = ((struct type_context*)tpdf_chain.objs[tpdf_chain.count - 1])->tpdf->type.compiled->basetype;
@@ -3138,8 +3140,20 @@
(*type) = base;
++(*type)->refcount;
}
- if (!(*type)->dflt) {
- DUP_STRING(ctx->ctx, dflt, (*type)->dflt);
+ if (dflt && !(*type)->dflt) {
+ struct ly_err_item *err = NULL;
+ (*type)->dflt = calloc(1, sizeof *(*type)->dflt);
+ (*type)->dflt->realtype = (*type);
+ ret = (*type)->plugin->store(ctx->ctx, (*type), dflt, strlen(dflt),
+ LY_TYPE_OPTS_INCOMPLETE_DATA | LY_TYPE_OPTS_SCHEMA | LY_TYPE_OPTS_STORE,
+ lys_resolve_prefix, (void*)dflt_mod, LYD_XML, NULL, NULL, (*type)->dflt, NULL, &err);
+ if (err) {
+ ly_err_print(err);
+ LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
+ "Invalid type's default value \"%s\" which does not fit the type (%s).", dflt, err->msg);
+ ly_err_free(err);
+ }
+ LY_CHECK_GOTO(ret, cleanup);
}
COMPILE_ARRAY_GOTO(ctx, type_p->exts, (*type)->exts, u, lys_compile_ext, ret, cleanup);
@@ -3431,7 +3445,7 @@
static LY_ERR
lys_compile_node_type(struct lysc_ctx *ctx, struct lysp_node *context_node, struct lysp_type *type_p, struct lysc_node_leaf *leaf)
{
- unsigned int u, v;
+ unsigned int u;
struct lysc_node_leaflist *llist = (struct lysc_node_leaflist*)leaf;
LY_CHECK_RET(lys_compile_type(ctx, context_node, leaf->flags, ctx->mod_def->parsed, leaf->name, type_p, &leaf->type,
@@ -3439,12 +3453,18 @@
if (leaf->nodetype == LYS_LEAFLIST) {
if (llist->type->dflt && !llist->dflts && !llist->min) {
LY_ARRAY_CREATE_RET(ctx->ctx, llist->dflts, 1, LY_EMEM);
- DUP_STRING(ctx->ctx, llist->type->dflt, llist->dflts[0]);
+ llist->dflts[0] = calloc(1, sizeof *llist->dflts[0]);
+ llist->dflts[0]->realtype = llist->type->dflt->realtype;
+ llist->dflts[0]->realtype->plugin->duplicate(ctx->ctx, llist->type->dflt, llist->dflts[0]);
+ llist->dflts[0]->realtype->refcount++;
LY_ARRAY_INCREMENT(llist->dflts);
}
} else {
if (leaf->type->dflt && !leaf->dflt && !(leaf->flags & LYS_MAND_TRUE)) {
- DUP_STRING(ctx->ctx, leaf->type->dflt, leaf->dflt);
+ leaf->dflt = calloc(1, sizeof *leaf->dflt);
+ leaf->dflt->realtype = leaf->type->dflt->realtype;
+ leaf->dflt->realtype->plugin->duplicate(ctx->ctx, leaf->type->dflt, leaf->dflt);
+ leaf->dflt->realtype->refcount++;
}
}
if (leaf->type->basetype == LY_TYPE_LEAFREF) {
@@ -3458,11 +3478,6 @@
}
}
} else if (leaf->type->basetype == LY_TYPE_EMPTY) {
- if (leaf->flags & LYS_SET_DFLT) {
- LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS, "%s of type \"empty\" must not have a default value (%s).",
- leaf->nodetype == LYS_LEAFLIST ? "Leaf-list" : "Leaf", leaf->nodetype == LYS_LEAFLIST ? llist->dflts[0] : leaf->dflt);
- return LY_EVALID;
- }
if (leaf->nodetype == LYS_LEAFLIST && ctx->mod_def->version < LYS_VERSION_1_1) {
LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
"Leaf-list of type \"empty\" is allowed only in YANG 1.1 modules.");
@@ -3470,21 +3485,6 @@
}
}
- if (leaf->nodetype == LYS_LEAFLIST && (llist->flags & LYS_CONFIG_W) && llist->dflts && LY_ARRAY_SIZE(llist->dflts)) {
- /* configuration data values must be unique - so check the default values */
- LY_ARRAY_FOR(llist->dflts, u) {
- for (v = u + 1; v < LY_ARRAY_SIZE(llist->dflts); ++v) {
- if (!strcmp(llist->dflts[u], llist->dflts[v])) {
- LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
- "Configuration leaf-list has multiple defaults of the same value \"%s\".", llist->dflts[v]);
- return LY_EVALID;
- }
- }
- }
- }
-
- /* TODO validate default value according to the type, possibly postpone the check when the leafref target is known */
-
return LY_SUCCESS;
}
@@ -3509,12 +3509,29 @@
leaf->units = lydict_insert(ctx->ctx, leaf_p->units, 0);
leaf->flags |= LYS_SET_UNITS;
}
+
+ /* the dflt member is just filled to avoid getting the default value from the type */
+ leaf->dflt = (void*)leaf_p->dflt;
+ ret = lys_compile_node_type(ctx, node_p, &leaf_p->type, leaf);
+
if (leaf_p->dflt) {
- leaf->dflt = lydict_insert(ctx->ctx, leaf_p->dflt, 0);
+ struct ly_err_item *err = NULL;
+ leaf->dflt = calloc(1, sizeof *leaf->dflt);
+ leaf->dflt->realtype = leaf->type;
+ ret = leaf->type->plugin->store(ctx->ctx, leaf->type, leaf_p->dflt, strlen(leaf_p->dflt),
+ LY_TYPE_OPTS_INCOMPLETE_DATA | LY_TYPE_OPTS_SCHEMA | LY_TYPE_OPTS_STORE,
+ lys_resolve_prefix, (void*)ctx->mod_def, LYD_XML, NULL, NULL, leaf->dflt, NULL, &err);
+ leaf->dflt->realtype->refcount++;
+ if (err) {
+ ly_err_print(err);
+ LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
+ "Invalid leaf's default value \"%s\" which does not fit the type (%s).", leaf_p->dflt, err->msg);
+ ly_err_free(err);
+ }
+ LY_CHECK_GOTO(ret, done);
leaf->flags |= LYS_SET_DFLT;
}
- ret = lys_compile_node_type(ctx, node_p, &leaf_p->type, leaf);
done:
return ret;
@@ -3533,7 +3550,7 @@
{
struct lysp_node_leaflist *llist_p = (struct lysp_node_leaflist*)node_p;
struct lysc_node_leaflist *llist = (struct lysc_node_leaflist*)node;
- unsigned int u;
+ unsigned int u, v;
LY_ERR ret = LY_SUCCESS;
COMPILE_ARRAY_GOTO(ctx, llist_p->musts, llist->musts, u, lys_compile_must, ret, done);
@@ -3542,14 +3559,50 @@
llist->flags |= LYS_SET_UNITS;
}
+ /* the dflts member is just filled to avoid getting the default value from the type */
+ llist->dflts = (void*)llist_p->dflts;
+ ret = lys_compile_node_type(ctx, node_p, &llist_p->type, (struct lysc_node_leaf*)llist);
if (llist_p->dflts) {
+ llist->dflts = NULL; /* reset the temporary llist_p->dflts */
LY_ARRAY_CREATE_GOTO(ctx->ctx, llist->dflts, LY_ARRAY_SIZE(llist_p->dflts), ret, done);
LY_ARRAY_FOR(llist_p->dflts, u) {
- DUP_STRING(ctx->ctx, llist_p->dflts[u], llist->dflts[u]);
+ struct ly_err_item *err = NULL;
LY_ARRAY_INCREMENT(llist->dflts);
+ llist->dflts[u] = calloc(1, sizeof *llist->dflts[u]);
+ llist->dflts[u]->realtype = llist->type;
+ ret = llist->type->plugin->store(ctx->ctx, llist->type, llist_p->dflts[u], strlen(llist_p->dflts[u]),
+ LY_TYPE_OPTS_INCOMPLETE_DATA | LY_TYPE_OPTS_SCHEMA | LY_TYPE_OPTS_STORE,
+ lys_resolve_prefix, (void*)ctx->mod_def, LYD_XML, NULL, NULL, llist->dflts[u], NULL, &err);
+ llist->dflts[u]->realtype->refcount++;
+ if (err) {
+ ly_err_print(err);
+ LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
+ "Invalid leaf-lists's default value \"%s\" which does not fit the type (%s).", llist_p->dflts[u], err->msg);
+ ly_err_free(err);
+ }
+ LY_CHECK_GOTO(ret, done);
}
llist->flags |= LYS_SET_DFLT;
}
+ if ((llist->flags & LYS_CONFIG_W) && llist->dflts && LY_ARRAY_SIZE(llist->dflts)) {
+ /* configuration data values must be unique - so check the default values */
+ LY_ARRAY_FOR(llist->dflts, u) {
+ for (v = u + 1; v < LY_ARRAY_SIZE(llist->dflts); ++v) {
+ if (!llist->type->plugin->compare(llist->dflts[u], llist->dflts[v])) {
+ int dynamic = 0;
+ const char *val = llist->type->plugin->print(llist->dflts[v], LYD_XML, json_print_get_prefix, NULL, &dynamic);
+ LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
+ "Configuration leaf-list has multiple defaults of the same value \"%s\".", val);
+ if (dynamic) {
+ free((char*)val);
+ }
+ return LY_EVALID;
+ }
+ }
+ }
+ }
+
+ /* TODO validate default value according to the type, possibly postpone the check when the leafref target is known */
llist->min = llist_p->min;
if (llist->min) {
@@ -3557,8 +3610,6 @@
}
llist->max = llist_p->max ? llist_p->max : (uint32_t)-1;
- ret = lys_compile_node_type(ctx, node_p, &llist_p->type, (struct lysc_node_leaf*)llist);
-
done:
return ret;
}
@@ -3743,7 +3794,9 @@
/* ignore default values of the key */
if ((*key)->dflt) {
- lydict_remove(ctx->ctx, (*key)->dflt);
+ (*key)->dflt->realtype->plugin->free(ctx->ctx, (*key)->dflt);
+ lysc_type_free(ctx->ctx, (*key)->dflt->realtype);
+ free((*key)->dflt);
(*key)->dflt = NULL;
}
/* mark leaf as key */
@@ -4428,10 +4481,13 @@
"Invalid refine of mandatory - leaf already has \"default\" statement.");
return LY_EVALID;
}
- } else {
+ } else if (((struct lysc_node_leaf*)node)->dflt) {
/* remove the default value taken from the leaf's type */
- FREE_STRING(ctx->ctx, ((struct lysc_node_leaf*)node)->dflt);
- ((struct lysc_node_leaf*)node)->dflt = NULL;
+ struct lysc_node_leaf *leaf = (struct lysc_node_leaf*)node;
+ leaf->dflt->realtype->plugin->free(ctx->ctx, leaf->dflt);
+ lysc_type_free(ctx->ctx, leaf->dflt->realtype);
+ free(leaf->dflt);
+ leaf->dflt = NULL;
}
} else if ((node->nodetype & LYS_CHOICE) && ((struct lysc_node_choice*)node)->dflt) {
if (refine_flag) {
@@ -4453,9 +4509,13 @@
node->flags &= ~LYS_MAND_TRUE;
node->flags |= LYS_MAND_FALSE;
lys_compile_mandatory_parents(node->parent, 0);
- if ((node->nodetype & LYS_LEAF) && !((struct lysc_node_leaf*)node)->dflt) {
+ if ((node->nodetype & LYS_LEAF) && !((struct lysc_node_leaf*)node)->dflt && ((struct lysc_node_leaf*)node)->type->dflt) {
/* get the type's default value if any */
- DUP_STRING(ctx->ctx, ((struct lysc_node_leaf*)node)->type->dflt, ((struct lysc_node_leaf*)node)->dflt);
+ struct lysc_node_leaf *leaf = (struct lysc_node_leaf*)node;
+ leaf->dflt = calloc(1, sizeof *leaf->dflt);
+ leaf->dflt->realtype = leaf->type->dflt->realtype;
+ leaf->dflt->realtype->plugin->duplicate(ctx->ctx, leaf->type->dflt, leaf->dflt);
+ leaf->dflt->realtype->refcount++;
}
}
return LY_SUCCESS;
@@ -4492,7 +4552,7 @@
size_t prefix_len, name_len;
struct lys_module *mod, *mod_old;
struct lysp_refine *rfn;
- LY_ERR ret = LY_EVALID;
+ LY_ERR ret = LY_EVALID, rc;
uint32_t min, max;
uint16_t flags;
struct ly_set refined = {0};
@@ -4684,27 +4744,68 @@
goto cleanup;
}
if (node->nodetype == LYS_LEAF) {
- FREE_STRING(ctx->ctx, ((struct lysc_node_leaf*)node)->dflt);
- DUP_STRING(ctx->ctx, rfn->dflts[0], ((struct lysc_node_leaf*)node)->dflt);
- node->flags |= LYS_SET_DFLT;
- /* TODO check the default value according to type */
+ struct ly_err_item *err = NULL;
+ struct lysc_node_leaf *leaf = (struct lysc_node_leaf*)node;
+ if (leaf->dflt) {
+ /* remove the previous default value */
+ leaf->dflt->realtype->plugin->free(ctx->ctx, leaf->dflt);
+ lysc_type_free(ctx->ctx, leaf->dflt->realtype);
+ } else {
+ /* prepare a new one */
+ leaf->dflt = calloc(1, sizeof *leaf->dflt);
+ leaf->dflt->realtype = leaf->type;
+ }
+ /* parse the new one */
+ rc = leaf->type->plugin->store(ctx->ctx, leaf->type, rfn->dflts[0], strlen(rfn->dflts[0]),
+ LY_TYPE_OPTS_INCOMPLETE_DATA | LY_TYPE_OPTS_SCHEMA | LY_TYPE_OPTS_STORE,
+ lys_resolve_prefix, (void*)ctx->mod_def, LYD_XML, NULL, NULL, leaf->dflt, NULL, &err);
+ leaf->dflt->realtype->refcount++;
+ if (err) {
+ ly_err_print(err);
+ LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
+ "Invalid refine of default - value \"%s\" does not fit the type (%s).", rfn->dflts[0], err->msg);
+ ly_err_free(err);
+ }
+ LY_CHECK_GOTO(rc, cleanup);
+ leaf->flags |= LYS_SET_DFLT;
} else if (node->nodetype == LYS_LEAFLIST) {
+ struct lysc_node_leaflist *llist = (struct lysc_node_leaflist*)node;
+
if (ctx->mod->version < 2) {
LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
"Invalid refine of default in leaf-list - the default statement is allowed only in YANG 1.1 modules.");
goto cleanup;
}
- LY_ARRAY_FOR(((struct lysc_node_leaflist*)node)->dflts, u) {
- lydict_remove(ctx->ctx, ((struct lysc_node_leaflist*)node)->dflts[u]);
+
+ /* remove previous set of default values */
+ LY_ARRAY_FOR(llist->dflts, u) {
+ llist->dflts[u]->realtype->plugin->free(ctx->ctx, llist->dflts[u]);
+ lysc_type_free(ctx->ctx, llist->dflts[u]->realtype);
+ free(llist->dflts[u]);
}
- LY_ARRAY_FREE(((struct lysc_node_leaflist*)node)->dflts);
- ((struct lysc_node_leaflist*)node)->dflts = NULL;
- LY_ARRAY_CREATE_GOTO(ctx->ctx, ((struct lysc_node_leaflist*)node)->dflts, LY_ARRAY_SIZE(rfn->dflts), ret, cleanup);
+ LY_ARRAY_FREE(llist->dflts);
+ llist->dflts = NULL;
+
+ /* create the new set of the default values */
+ LY_ARRAY_CREATE_GOTO(ctx->ctx, llist->dflts, LY_ARRAY_SIZE(rfn->dflts), ret, cleanup);
LY_ARRAY_FOR(rfn->dflts, u) {
- LY_ARRAY_INCREMENT(((struct lysc_node_leaflist*)node)->dflts);
- DUP_STRING(ctx->ctx, rfn->dflts[u], ((struct lysc_node_leaflist*)node)->dflts[u]);
+ struct ly_err_item *err = NULL;
+ LY_ARRAY_INCREMENT(llist->dflts);
+ llist->dflts[u] = calloc(1, sizeof *llist->dflts[u]);
+ llist->dflts[u]->realtype = llist->type;
+ ret = llist->type->plugin->store(ctx->ctx, llist->type, rfn->dflts[u], strlen(rfn->dflts[u]),
+ LY_TYPE_OPTS_INCOMPLETE_DATA | LY_TYPE_OPTS_SCHEMA | LY_TYPE_OPTS_STORE,
+ lys_resolve_prefix, (void*)ctx->mod_def, LYD_XML, NULL, NULL, llist->dflts[u], NULL, &err);
+ llist->dflts[u]->realtype->refcount++;
+ if (err) {
+ ly_err_print(err);
+ LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
+ "Invalid refine of default in leaf-lists - value \"%s\" does not fit the type (%s).", rfn->dflts[u], err->msg);
+ ly_err_free(err);
+ }
+ LY_CHECK_GOTO(ret, cleanup);
}
- /* TODO check the default values according to type */
+ llist->flags |= LYS_SET_DFLT;
} else if (node->nodetype == LYS_CHOICE) {
if (((struct lysc_node_choice*)node)->dflt) {
/* unset LYS_SET_DFLT from the current default case */
@@ -5298,7 +5399,7 @@
LY_ERR
lys_compile_deviations(struct lysc_ctx *ctx, struct lysp_module *mod_p)
{
- LY_ERR ret = LY_EVALID;
+ LY_ERR ret = LY_EVALID, rc;
struct ly_set devs_p = {0};
struct ly_set targets = {0};
struct lysc_node *target; /* target target of the deviation */
@@ -5318,9 +5419,9 @@
uint16_t flags; /* target's flags from lys_resolve_schema_nodeid() */
uint8_t not_supported; /* flag if deviates contains not-supported deviate */
} **devs = NULL;
- int i;
+ int i, changed_type;
size_t prefix_len, name_len;
- const char *prefix, *name, *nodeid;
+ const char *prefix, *name, *nodeid, *dflt;
struct lys_module *mod;
uint32_t min, max;
uint16_t flags;
@@ -5398,11 +5499,23 @@
goto cleanup; \
}
+
#define DEV_CHECK_NONPRESENCE(TYPE, COND, MEMBER, PROPERTY, VALUEMEMBER) \
+ if (((TYPE)devs[u]->target)->MEMBER && (COND)) { \
+ LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE, \
+ "Invalid deviation adding \"%s\" property which already exists (with value \"%s\").", \
+ PROPERTY, ((TYPE)devs[u]->target)->VALUEMEMBER); \
+ goto cleanup; \
+ }
+
+#define DEV_CHECK_NONPRESENCE_VALUE(TYPE, COND, MEMBER, PROPERTY, VALUEMEMBER) \
if (((TYPE)devs[u]->target)->MEMBER && (COND)) { \
+ int dynamic_ = 0; const char *val_; \
+ val_ = ((TYPE)devs[u]->target)->VALUEMEMBER->realtype->plugin->print(((TYPE)devs[u]->target)->VALUEMEMBER, \
+ LYD_XML, lys_get_prefix, ctx->mod_def, &dynamic_); \
LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE, \
- "Invalid deviation adding \"%s\" property which already exists (with value \"%s\").", \
- PROPERTY, ((TYPE)devs[u]->target)->VALUEMEMBER); \
+ "Invalid deviation adding \"%s\" property which already exists (with value \"%s\").", PROPERTY, val_); \
+ if (dynamic_) {free((void*)val_);} \
goto cleanup; \
}
@@ -5427,17 +5540,6 @@
goto cleanup; \
}
-#define DEV_DEL_MEMBER(TYPE, MEMBER_TRG, MEMBER_DEV, DELFUNC, PROPERTY) \
- DEV_CHECK_PRESENCE(TYPE, 0, MEMBER_TRG, "deleting", PROPERTY, d_del->MEMBER_DEV); \
- if (strcmp(((TYPE)devs[u]->target)->MEMBER_TRG, d_del->MEMBER_DEV)) { \
- LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE, \
- "Invalid deviation deleting \"%s\" property \"%s\" which does not match the target's property value \"%s\".", \
- PROPERTY, d_del->MEMBER_DEV, ((TYPE)devs[u]->target)->MEMBER_TRG); \
- goto cleanup; \
- } \
- DELFUNC(ctx->ctx, ((TYPE)devs[u]->target)->MEMBER_TRG); \
- ((TYPE)devs[u]->target)->MEMBER_TRG = NULL;
-
#define DEV_DEL_ARRAY(TYPE, ARRAY_TRG, ARRAY_DEV, VALMEMBER, VALMEMBER_CMP, DELFUNC_DEREF, DELFUNC, PROPERTY) \
DEV_CHECK_PRESENCE(TYPE, 0, ARRAY_TRG, "deleting", PROPERTY, d_del->ARRAY_DEV[0]VALMEMBER); \
LY_ARRAY_FOR(d_del->ARRAY_DEV, x) { \
@@ -5463,6 +5565,13 @@
/* apply deviations */
for (u = 0; u < devs_p.count && devs[u]; ++u) {
+ struct lysc_node_leaf *leaf = (struct lysc_node_leaf*)devs[u]->target;
+ struct lysc_node_leaflist *llist = (struct lysc_node_leaflist*)devs[u]->target;
+ struct ly_err_item *err = NULL;
+
+ dflt = NULL;
+ changed_type = 0;
+
lysc_update_path(ctx, NULL, devs[u]->nodeid);
if (devs[u]->flags & LYSC_OPT_INTERNAL) {
@@ -5588,32 +5697,51 @@
switch (devs[u]->target->nodetype) {
case LYS_LEAF:
DEV_CHECK_CARDINALITY(d_add->dflts, 1, "default");
- DEV_CHECK_NONPRESENCE(struct lysc_node_leaf*, (devs[u]->target->flags & LYS_SET_DFLT), dflt, "default", dflt);
- if (((struct lysc_node_leaf*)devs[u]->target)->dflt) {
+ DEV_CHECK_NONPRESENCE_VALUE(struct lysc_node_leaf*, (devs[u]->target->flags & LYS_SET_DFLT), dflt, "default", dflt);
+ if (leaf->dflt) {
/* first, remove the default value taken from the type */
- lydict_remove(ctx->ctx, ((struct lysc_node_leaf*)devs[u]->target)->dflt);
- ((struct lysc_node_leaf*)devs[u]->target)->dflt = NULL;
+ leaf->dflt->realtype->plugin->free(ctx->ctx, leaf->dflt);
+ lysc_type_free(ctx->ctx, leaf->dflt->realtype);
+ } else {
+ /* prepare new default value storage */
+ leaf->dflt = calloc(1, sizeof *leaf->dflt);
}
- DUP_STRING(ctx->ctx, d_add->dflts[0], ((struct lysc_node_leaf*)devs[u]->target)->dflt);
+ dflt = d_add->dflts[0];
+ /* parsing is done at the end after possible replace of the leaf's type */
+
/* mark the new default values as leaf's own */
devs[u]->target->flags |= LYS_SET_DFLT;
break;
case LYS_LEAFLIST:
- if (((struct lysc_node_leaflist*)devs[u]->target)->dflts && !(devs[u]->target->flags & LYS_SET_DFLT)) {
+ if (llist->dflts && !(devs[u]->target->flags & LYS_SET_DFLT)) {
/* first, remove the default value taken from the type */
- LY_ARRAY_FOR(((struct lysc_node_leaflist*)devs[u]->target)->dflts, x) {
- lydict_remove(ctx->ctx, ((struct lysc_node_leaflist*)devs[u]->target)->dflts[x]);
+ LY_ARRAY_FOR(llist->dflts, x) {
+ llist->dflts[x]->realtype->plugin->free(ctx->ctx, llist->dflts[x]);
+ lysc_type_free(ctx->ctx, llist->dflts[x]->realtype);
+ free(llist->dflts[x]);
}
- LY_ARRAY_FREE(((struct lysc_node_leaflist*)devs[u]->target)->dflts);
- ((struct lysc_node_leaflist*)devs[u]->target)->dflts = NULL;
+ LY_ARRAY_FREE(llist->dflts);
+ llist->dflts = NULL;
}
/* add new default value(s) */
- LY_ARRAY_CREATE_GOTO(ctx->ctx, ((struct lysc_node_leaflist*)devs[u]->target)->dflts,
- LY_ARRAY_SIZE(d_add->dflts), ret, cleanup);
- for (x = y = LY_ARRAY_SIZE(((struct lysc_node_leaflist*)devs[u]->target)->dflts);
+ LY_ARRAY_CREATE_GOTO(ctx->ctx, llist->dflts, LY_ARRAY_SIZE(d_add->dflts), ret, cleanup);
+ for (x = y = LY_ARRAY_SIZE(llist->dflts);
x < LY_ARRAY_SIZE(d_add->dflts) + y; ++x) {
- DUP_STRING(ctx->ctx, d_add->dflts[x - y], ((struct lysc_node_leaflist*)devs[u]->target)->dflts[x]);
- LY_ARRAY_INCREMENT(((struct lysc_node_leaflist*)devs[u]->target)->dflts);
+ LY_ARRAY_INCREMENT(llist->dflts);
+ llist->dflts[x] = calloc(1, sizeof *llist->dflts[x]);
+ llist->dflts[x]->realtype = llist->type;
+ rc = llist->type->plugin->store(ctx->ctx, llist->type, d_add->dflts[x - y], strlen(d_add->dflts[x - y]),
+ LY_TYPE_OPTS_INCOMPLETE_DATA | LY_TYPE_OPTS_SCHEMA | LY_TYPE_OPTS_STORE,
+ lys_resolve_prefix, (void*)ctx->mod_def, LYD_XML, NULL, NULL, llist->dflts[x], NULL, &err);
+ llist->dflts[x]->realtype->refcount++;
+ if (err) {
+ ly_err_print(err);
+ LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
+ "Invalid deviation adding \"default\" property \"%s\" which does not fit the type (%s).",
+ d_add->dflts[x - y], err->msg);
+ ly_err_free(err);
+ }
+ LY_CHECK_GOTO(rc, cleanup);
}
/* mark the new default values as leaf-list's own */
devs[u]->target->flags |= LYS_SET_DFLT;
@@ -5709,7 +5837,15 @@
/* [units-stmt] */
if (d_del->units) {
DEV_CHECK_NODETYPE(LYS_LEAF | LYS_LEAFLIST, "delete", "units");
- DEV_DEL_MEMBER(struct lysc_node_leaf*, units, units, lydict_remove, "units");
+ DEV_CHECK_PRESENCE(struct lysc_node_leaf*, 0, units, "deleting", "units", d_del->units);
+ if (strcmp(((struct lysc_node_leaf*)devs[u]->target)->units, d_del->units)) {
+ LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
+ "Invalid deviation deleting \"units\" property \"%s\" which does not match the target's property value \"%s\".",
+ d_del->units, ((struct lysc_node_leaf*)devs[u]->target)->units);
+ goto cleanup;
+ }
+ lydict_remove(ctx->ctx, ((struct lysc_node_leaf*)devs[u]->target)->units);
+ ((struct lysc_node_leaf*)devs[u]->target)->units = NULL;
}
/* *must-stmt */
@@ -5795,13 +5931,61 @@
DEV_CHECK_PRESENCE(struct lysc_node_leaf*, !(devs[u]->target->flags & LYS_SET_DFLT),
dflt, "deleting", "default", d_del->dflts[0]);
- DEV_DEL_MEMBER(struct lysc_node_leaf*, dflt, dflts[0], lydict_remove, "default");
+ /* check that the values matches */
+ dflt = leaf->dflt->realtype->plugin->print(leaf->dflt, LYD_XML, lys_get_prefix, ctx->mod_def, &i);
+ if (strcmp(dflt, d_del->dflts[0])) {
+ if (i) {
+ free((char*)dflt);
+ }
+ LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
+ "Invalid deviation deleting \"default\" property \"%s\" which does not match the target's property value \"%s\".",
+ d_del->dflts[0], dflt);
+ goto cleanup;
+ }
+ if (i) {
+ free((char*)dflt);
+ }
+ dflt = NULL;
+
+ /* remove the default specification */
+ leaf->dflt->realtype->plugin->free(ctx->ctx, leaf->dflt);
+ lysc_type_free(ctx->ctx, leaf->dflt->realtype);
+ free(leaf->dflt);
+ leaf->dflt = NULL;
devs[u]->target->flags &= ~LYS_SET_DFLT;
break;
case LYS_LEAFLIST:
- DEV_DEL_ARRAY(struct lysc_node_leaflist*, dflts, dflts, , , , lydict_remove, "default");
- if (!((struct lysc_node_leaflist*)devs[u]->target)->dflts) {
- devs[u]->target->flags &= ~LYS_SET_DFLT;
+ DEV_CHECK_PRESENCE(struct lysc_node_leaflist*, 0, dflts, "deleting", "default", d_del->dflts[0]);
+ LY_ARRAY_FOR(d_del->dflts, x) {
+ LY_ARRAY_FOR(llist->dflts, y) {
+ dflt = llist->type->plugin->print(llist->dflts[y], LYD_XML, lys_get_prefix, ctx->mod_def, &i);
+ if (!strcmp(dflt, d_del->dflts[x])) {
+ if (i) {
+ free((char*)dflt);
+ }
+ dflt = NULL;
+ break;
+ }
+ if (i) {
+ free((char*)dflt);
+ }
+ dflt = NULL;
+ }
+ if (y == LY_ARRAY_SIZE(llist->dflts)) {
+ LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE, "Invalid deviation deleting \"default\" property \"%s\" "
+ "which does not match any of the target's property values.", d_del->dflts[x]);
+ goto cleanup;
+ }
+ LY_ARRAY_DECREMENT(llist->dflts);
+ llist->dflts[y]->realtype->plugin->free(ctx->ctx, llist->dflts[y]);
+ lysc_type_free(ctx->ctx, llist->dflts[y]->realtype);
+ free(llist->dflts[y]);
+ memmove(&llist->dflts[y], &llist->dflts[y + 1], (LY_ARRAY_SIZE(llist->dflts) - y) * (sizeof *llist->dflts));
+ }
+ if (!LY_ARRAY_SIZE(llist->dflts)) {
+ LY_ARRAY_FREE(llist->dflts);
+ llist->dflts = NULL;
+ llist->flags &= ~LYS_SET_DFLT;
}
break;
case LYS_CHOICE:
@@ -5853,7 +6037,30 @@
DEV_CHECK_NODETYPE(LYS_LEAF | LYS_LEAFLIST, "replace", "type");
/* type is mandatory, so checking for its presence is not necessary */
lysc_type_free(ctx->ctx, ((struct lysc_node_leaf*)devs[u]->target)->type);
+
+ if (leaf->dflt && !(devs[u]->target->flags & LYS_SET_DFLT)) {
+ /* the target has default from the previous type - remove it */
+ if (devs[u]->target->nodetype == LYS_LEAF) {
+ leaf->dflt->realtype->plugin->free(ctx->ctx, leaf->dflt);
+ lysc_type_free(ctx->ctx, leaf->dflt->realtype);
+ free(leaf->dflt);
+ leaf->dflt = NULL;
+ } else { /* LYS_LEAFLIST */
+ LY_ARRAY_FOR(llist->dflts, x) {
+ llist->dflts[x]->realtype->plugin->free(ctx->ctx, llist->dflts[x]);
+ lysc_type_free(ctx->ctx, llist->dflts[x]->realtype);
+ free(llist->dflts[x]);
+ }
+ LY_ARRAY_FREE(llist->dflts);
+ llist->dflts = NULL;
+ }
+ }
+ if (!leaf->dflt) {
+ /* do not set changed_type after type compilation */
+ changed_type = -1;
+ }
LY_CHECK_GOTO(lys_compile_node_type(ctx, NULL, d_rpl->type, (struct lysc_node_leaf*)devs[u]->target), cleanup);
+ changed_type++;
}
/* [units-stmt] */
@@ -5872,9 +6079,11 @@
case LYS_LEAF:
DEV_CHECK_PRESENCE(struct lysc_node_leaf*, !(devs[u]->target->flags & LYS_SET_DFLT),
dflt, "replacing", "default", d_rpl->dflt);
-
- lydict_remove(ctx->ctx, ((struct lysc_node_leaf*)devs[u]->target)->dflt);
- DUP_STRING(ctx->ctx, d_rpl->dflt, ((struct lysc_node_leaf*)devs[u]->target)->dflt);
+ /* first, remove the default value taken from the type */
+ leaf->dflt->realtype->plugin->free(ctx->ctx, leaf->dflt);
+ lysc_type_free(ctx->ctx, leaf->dflt->realtype);
+ dflt = d_rpl->dflt;
+ /* parsing is done at the end after possible replace of the leaf's type */
break;
case LYS_CHOICE:
DEV_CHECK_PRESENCE(struct lysc_node_choice*, 0, dflt, "replacing", "default", d_rpl->dflt);
@@ -5976,6 +6185,68 @@
goto cleanup;
}
+ if (dflt) {
+ /* parse added/changed default value after possible change of the type */
+ leaf->dflt->realtype = leaf->type;
+ rc = leaf->type->plugin->store(ctx->ctx, leaf->type, dflt, strlen(dflt),
+ LY_TYPE_OPTS_INCOMPLETE_DATA | LY_TYPE_OPTS_SCHEMA | LY_TYPE_OPTS_STORE,
+ lys_resolve_prefix, (void*)ctx->mod_def, LYD_XML, NULL, NULL, leaf->dflt, NULL, &err);
+ leaf->dflt->realtype->refcount++;
+ if (err) {
+ ly_err_print(err);
+ LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
+ "Invalid deviation setting \"default\" property \"%s\" which does not fit the type (%s).", dflt, err->msg);
+ ly_err_free(err);
+ }
+ LY_CHECK_GOTO(rc, cleanup);
+ } else if (changed_type && leaf->dflt) {
+ /* the leaf/leaf-list's type has changed, but there is still a default value for the previous type */
+ int dynamic;
+ if (devs[u]->target->nodetype == LYS_LEAF) {
+ dflt = leaf->dflt->realtype->plugin->print(leaf->dflt, LYD_XML, lys_get_prefix, ctx->mod, &dynamic);
+ leaf->dflt->realtype->plugin->free(ctx->ctx, leaf->dflt);
+ lysc_type_free(ctx->ctx, leaf->dflt->realtype);
+ leaf->dflt->realtype = leaf->type;
+ rc = leaf->type->plugin->store(ctx->ctx, leaf->type, dflt, strlen(dflt),
+ LY_TYPE_OPTS_INCOMPLETE_DATA | LY_TYPE_OPTS_SCHEMA | LY_TYPE_OPTS_STORE,
+ lys_resolve_prefix, (void*)ctx->mod, LYD_XML, NULL, NULL, leaf->dflt, NULL, &err);
+ leaf->dflt->realtype->refcount++;
+ if (err) {
+ ly_err_print(err);
+ LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
+ "Invalid deviation replacing leaf's type - the leaf's default value \"%s\" does not match the type (%s).", dflt, err->msg);
+ ly_err_free(err);
+ }
+ if (dynamic) {
+ free((void*)dflt);
+ }
+ LY_CHECK_GOTO(rc, cleanup);
+ dflt = NULL;
+ } else { /* LYS_LEAFLIST */
+ LY_ARRAY_FOR(llist->dflts, x) {
+ llist->dflts[x]->realtype->plugin->print(llist->dflts[x], LYD_XML, lys_get_prefix, ctx->mod, &dynamic);
+ llist->dflts[x]->realtype->plugin->free(ctx->ctx, llist->dflts[x]);
+ lysc_type_free(ctx->ctx, llist->dflts[x]->realtype);
+ llist->dflts[x]->realtype = llist->type;
+ rc = llist->type->plugin->store(ctx->ctx, llist->type, dflt, strlen(dflt),
+ LY_TYPE_OPTS_INCOMPLETE_DATA | LY_TYPE_OPTS_SCHEMA | LY_TYPE_OPTS_STORE,
+ lys_resolve_prefix, (void*)ctx->mod, LYD_XML, NULL, NULL, llist->dflts[x], NULL, &err);
+ llist->dflts[x]->realtype->refcount++;
+ if (err) {
+ ly_err_print(err);
+ LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
+ "Invalid deviation replacing leaf-list's type - the leaf-list's default value \"%s\" does not match the type (%s).",
+ dflt, err->msg);
+ ly_err_free(err);
+ }
+ if (dynamic) {
+ free((void*)dflt);
+ }
+ LY_CHECK_GOTO(rc, cleanup);
+ }
+ }
+ }
+
/* check mandatory - default compatibility */
if ((devs[u]->target->nodetype & (LYS_LEAF | LYS_LEAFLIST))
&& (devs[u]->target->flags & LYS_SET_DFLT)
@@ -5997,8 +6268,6 @@
goto cleanup;
}
- /* TODO check default value(s) according to the type */
-
lysc_update_path(ctx, NULL, NULL);
}
diff --git a/src/tree_schema_free.c b/src/tree_schema_free.c
index e3fd817..f82f240 100644
--- a/src/tree_schema_free.c
+++ b/src/tree_schema_free.c
@@ -20,6 +20,7 @@
#include "tree.h"
#include "tree_schema.h"
#include "tree_schema_internal.h"
+#include "plugins_types.h"
#include "xpath.h"
void lysp_grp_free(struct ly_ctx *ctx, struct lysp_grp *grp);
@@ -623,7 +624,11 @@
break;
}
FREE_ARRAY(ctx, type->exts, lysc_ext_instance_free);
- FREE_STRING(ctx, type->dflt);
+ if (type->dflt) {
+ type->plugin->free(ctx, type->dflt);
+ lysc_type_free(ctx, type->dflt->realtype);
+ free(type->dflt);
+ }
free(type);
}
@@ -689,7 +694,11 @@
lysc_type_free(ctx, node->type);
}
FREE_STRING(ctx, node->units);
- FREE_STRING(ctx, node->dflt);
+ if (node->dflt) {
+ node->dflt->realtype->plugin->free(ctx, node->dflt);
+ lysc_type_free(ctx, node->dflt->realtype);
+ free(node->dflt);
+ }
}
static void
@@ -703,7 +712,9 @@
}
FREE_STRING(ctx, node->units);
LY_ARRAY_FOR(node->dflts, u) {
- lydict_remove(ctx, node->dflts[u]);
+ node->dflts[u]->realtype->plugin->free(ctx, node->dflts[u]);
+ lysc_type_free(ctx, node->dflts[u]->realtype);
+ free(node->dflts[u]);
}
LY_ARRAY_FREE(node->dflts);
}
diff --git a/src/tree_schema_helpers.c b/src/tree_schema_helpers.c
index ed76616..423e673 100644
--- a/src/tree_schema_helpers.c
+++ b/src/tree_schema_helpers.c
@@ -1628,3 +1628,39 @@
return LY_ARRAY_SIZE(ext);
}
+/**
+ * @brief Schema mapping of YANG modules to prefixes in values.
+ *
+ * Implementation of ly_clb_get_prefix. Inverse function to lys_resolve_prefix.
+ *
+ * In this case the @p mod is searched in the list of imports and the import's prefix
+ * (not the module's itself) prefix is returned.
+ */
+const char *
+lys_get_prefix(const struct lys_module *mod, void *private)
+{
+ struct lys_module *context_mod = (struct lys_module*)private;
+ unsigned int u;
+
+ LY_ARRAY_FOR(context_mod->compiled->imports, u) {
+ if (context_mod->compiled->imports[u].module == mod) {
+ /* match */
+ return mod->compiled->imports[u].prefix;
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * @brief Schema mapping of prefix in values to YANG modules (imports).
+ *
+ * Implementation of ly_clb_resolve_prefix. Inverse function to lys_get_prefix().
+ *
+ * In this case the @p prefix is searched in the list of imports' prefixes (not the prefixes of the imported modules themselves).
+ */
+const struct lys_module *
+lys_resolve_prefix(struct ly_ctx *UNUSED(ctx), const char *prefix, size_t prefix_len, void *private)
+{
+ return lys_module_find_prefix((const struct lys_module*)private, prefix, prefix_len);
+}
diff --git a/src/tree_schema_internal.h b/src/tree_schema_internal.h
index fbd0b6a..53653ba 100644
--- a/src/tree_schema_internal.h
+++ b/src/tree_schema_internal.h
@@ -142,6 +142,33 @@
LY_ERR lysp_check_identifierchar(struct lys_parser_ctx *ctx, unsigned int c, int first, int *prefix);
/**
+ * @brief Internal structure for lys_get_prefix().
+ */
+struct lys_get_prefix_data {
+ const struct lys_module *context_mod;
+ struct ly_set prefixes;
+};
+
+/**
+ * @brief Schema mapping of YANG modules to prefixes in values.
+ *
+ * Implementation of ly_clb_get_prefix. Inverse function to lys_resolve_prefix.
+ *
+ * In this case the @p mod is searched in the list of imports and the import's prefix
+ * (not the module's itself) prefix is returned.
+ */
+const char *lys_get_prefix(const struct lys_module *mod, void *private);
+
+/**
+ * @brief Schema mapping of prefix in values to YANG modules (imports).
+ *
+ * Implementation of ly_clb_resolve_prefix. Inverse function to lys_get_prefix().
+ *
+ * In this case the @p prefix is searched in the list of imports' prefixes (not the prefixes of the imported modules themselves).
+ */
+const struct lys_module *lys_resolve_prefix(struct ly_ctx *ctx, const char *prefix, size_t prefix_len, void *private);
+
+/**
* @brief Check the currently present prefixes in the module for collision with the new one.
*
* @param[in] ctx Context for logging.
diff --git a/tests/features/test_types.c b/tests/features/test_types.c
index 08ad498..94f4832 100644
--- a/tests/features/test_types.c
+++ b/tests/features/test_types.c
@@ -671,19 +671,20 @@
s->func = NULL;
}
+static const char *
+test_get_prefix(const struct lys_module *mod, void *private)
+{
+ (void)mod;
+ return (const char *)private;
+}
+
static void
-test_printed_value(const struct lyd_value *value, const char *expected_prefixes, const char *expected_value, LYD_FORMAT format)
+test_printed_value(const struct lyd_value *value, const char *expected_value, LYD_FORMAT format, const char *prefix)
{
const char *str;
int dynamic;
- assert_non_null(str = value->realtype->plugin->print(value, format, 1, &dynamic));
- assert_string_equal(expected_prefixes, str);
- if (dynamic) {
- free((char*)str);
- }
-
- assert_non_null(str = value->realtype->plugin->print(value, format, 0, &dynamic));
+ assert_non_null(str = value->realtype->plugin->print(value, format, test_get_prefix, (void*)prefix, &dynamic));
assert_string_equal(expected_value, str);
if (dynamic) {
free((char*)str);
@@ -709,7 +710,7 @@
leaf = (struct lyd_node_term*)tree;
assert_null(leaf->value.canonized);
assert_string_equal("gigabit-ethernet", leaf->value.ident->name);
- test_printed_value(&leaf->value, "xmlns:t=\"urn:tests:types\"", "t:gigabit-ethernet", LYD_XML);
+ test_printed_value(&leaf->value, "t:gigabit-ethernet", LYD_XML, "t");
value.realtype = leaf->value.realtype;
assert_int_equal(LY_SUCCESS, value.realtype->plugin->duplicate(s->ctx, &leaf->value, &value));
@@ -724,7 +725,7 @@
assert_string_equal("ident", tree->schema->name);
leaf = (struct lyd_node_term*)tree;
assert_null(leaf->value.canonized);
- test_printed_value(&leaf->value, "xmlns:d=\"urn:tests:defs\"", "d:fast-ethernet", LYD_XML);
+ test_printed_value(&leaf->value, "d:fast-ethernet", LYD_XML, "d");
lyd_free_all(tree);
/* invalid value */
@@ -842,8 +843,8 @@
assert_string_equal("value", leaf->value.target[1].node->name);
assert_null(leaf->value.target[1].predicates);
- test_printed_value(&leaf->value, "xmlns:t=\"urn:tests:types\"", "/t:list_inst[t:id=\"/t:leaflisttarget[.='b']\"]/t:value", LYD_XML);
- test_printed_value(&leaf->value, "", "/types:list_inst[id=\"/types:leaflisttarget[.='b']\"]/value", LYD_JSON);
+ test_printed_value(&leaf->value, "/t:list_inst[t:id=\"/t:leaflisttarget[.='b']\"]/t:value", LYD_XML, "t");
+ test_printed_value(&leaf->value, "/types:list_inst[id=\"/types:leaflisttarget[.='b']\"]/value", LYD_JSON, "types");
value.realtype = leaf->value.realtype;
assert_int_equal(LY_SUCCESS, value.realtype->plugin->duplicate(s->ctx, &leaf->value, &value));
@@ -940,11 +941,13 @@
data = "<cont xmlns=\"urn:tests:types\"/><t:inst xmlns:t=\"urn:tests:types\">/t:cont/t:leaftarget</t:inst>";
assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, 0));
- logbuf_assert("Invalid instance-identifier \"/t:cont/t:leaftarget\" value - required instance not found. /");
+ /* instance-identifier is here in JSON format because it is already in internal representation without original prefixes */
+ logbuf_assert("Invalid instance-identifier \"/types:cont/leaftarget\" value - required instance not found. /");
data = "<t:inst xmlns:t=\"urn:tests:types\">/t:cont/t:leaftarget</t:inst>";
assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, 0));
- logbuf_assert("Invalid instance-identifier \"/t:cont/t:leaftarget\" value - required instance not found. /");
+ /* instance-identifier is here in JSON format because it is already in internal representation without original prefixes */
+ logbuf_assert("Invalid instance-identifier \"/types:cont/leaftarget\" value - required instance not found. /");
data = "<leaflisttarget xmlns=\"urn:tests:types\">x</leaflisttarget><t:inst xmlns:t=\"urn:tests:types\">/t:leaflisttarget[1</t:inst>";
assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, 0));
@@ -969,7 +972,8 @@
data = "<cont xmlns=\"urn:tests:types\"><leaflisttarget>1</leaflisttarget><leaflisttarget>2</leaflisttarget></cont>"
"<t:inst xmlns:t=\"urn:tests:types\">/t:cont/t:leaflisttarget[4]</t:inst>";
assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, 0));
- logbuf_assert("Invalid instance-identifier \"/t:cont/t:leaflisttarget[4]\" value - required instance not found. /");
+ /* instance-identifier is here in JSON format because it is already in internal representation without original prefixes */
+ logbuf_assert("Invalid instance-identifier \"/types:cont/leaflisttarget[4]\" value - required instance not found. /");
data = "<t:inst-noreq xmlns:t=\"urn:tests:types\">/t:cont/t:leaflisttarget[6]</t:inst-noreq>";
assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, 0));
@@ -1000,7 +1004,8 @@
data = "<cont xmlns=\"urn:tests:types\"><leaflisttarget>1</leaflisttarget></cont>"
"<t:inst xmlns:t=\"urn:tests:types\">/t:cont/t:leaflisttarget[.='2']</t:inst>";
assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, 0));
- logbuf_assert("Invalid instance-identifier \"/t:cont/t:leaflisttarget[.='2']\" value - required instance not found. /");
+ /* instance-identifier is here in JSON format because it is already in internal representation without original prefixes */
+ logbuf_assert("Invalid instance-identifier \"/types:cont/leaflisttarget[.='2']\" value - required instance not found. /");
data = "<cont xmlns=\"urn:tests:types\"><leaflisttarget>1</leaflisttarget></cont>"
"<t:inst xmlns:t=\"urn:tests:types\">/t:cont/t:leaflisttarget[.='x']</t:inst>";
@@ -1017,7 +1022,8 @@
data = "<cont xmlns=\"urn:tests:types\"><listtarget><id>1</id><value>x</value></listtarget></cont>"
"<t:inst xmlns:t=\"urn:tests:types\">/t:cont/t:listtarget[t:id='2']</t:inst>";
assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, 0));
- logbuf_assert("Invalid instance-identifier \"/t:cont/t:listtarget[t:id='2']\" value - required instance not found. /");
+ /* instance-identifier is here in JSON format because it is already in internal representation without original prefixes */
+ logbuf_assert("Invalid instance-identifier \"/types:cont/listtarget[id='2']\" value - required instance not found. /");
data = "<leaflisttarget xmlns=\"urn:tests:types\">a</leaflisttarget>"
"<leaflisttarget xmlns=\"urn:tests:types\">b</leaflisttarget>"
@@ -1239,7 +1245,7 @@
assert_int_equal(LY_TYPE_INT8, leaf->value.subvalue->value->realtype->basetype);
assert_int_equal(12, leaf->value.subvalue->value->int8);
- test_printed_value(&leaf->value, "", "12", LYD_XML);
+ test_printed_value(&leaf->value, "12", LYD_XML, NULL);
value.realtype = leaf->value.realtype;
assert_int_equal(LY_SUCCESS, value.realtype->plugin->duplicate(s->ctx, &leaf->value, &value));
@@ -1275,8 +1281,8 @@
assert_int_equal(LY_TYPE_IDENT, leaf->value.subvalue->value->realtype->basetype);
assert_null(leaf->value.subvalue->value->canonized);
- test_printed_value(&leaf->value, "xmlns:x=\"urn:tests:defs\"", "x:fast-ethernet", LYD_XML);
- test_printed_value(leaf->value.subvalue->value, "xmlns:d=\"urn:tests:defs\"", "d:fast-ethernet", LYD_XML);
+ test_printed_value(&leaf->value, "x:fast-ethernet", LYD_XML, "x");
+ test_printed_value(leaf->value.subvalue->value, "d:fast-ethernet", LYD_XML, "d");
value.realtype = leaf->value.realtype;
assert_int_equal(LY_SUCCESS, value.realtype->plugin->duplicate(s->ctx, &leaf->value, &value));
diff --git a/tests/src/test_parser_xml.c b/tests/src/test_parser_xml.c
index 9ade723..fa882c0 100644
--- a/tests/src/test_parser_xml.c
+++ b/tests/src/test_parser_xml.c
@@ -58,6 +58,8 @@
const char *schema_a = "module a {namespace urn:tests:a;prefix a;yang-version 1.1;"
"list l1 { key \"a b\"; leaf a {type string;} leaf b {type string;} leaf c {type string;}}"
"leaf foo { type string;}"
+ "container c { leaf x {type string;}}"
+ "container cp {presence \"container switch\"; leaf y {type string;}}"
"anydata any {config false;} }";
#if ENABLE_LOGGER_CHECKING
@@ -164,12 +166,42 @@
*state = NULL;
}
+static void
+test_container(void **state)
+{
+ *state = test_container;
+
+ const char *data = "<c xmlns=\"urn:tests:a\"/>";
+ struct lyd_node *tree;
+ struct lyd_node_inner *cont;
+
+ assert_int_equal(LY_SUCCESS, lyd_parse_xml(ctx, data, 0, &tree));
+ assert_non_null(tree);
+ assert_int_equal(LYS_CONTAINER, tree->schema->nodetype);
+ assert_string_equal("c", tree->schema->name);
+ cont = (struct lyd_node_inner*)tree;
+ assert_true(cont->flags & LYD_DEFAULT);
+ lyd_free_all(tree);
+
+ data = "<cp xmlns=\"urn:tests:a\"/>";
+ assert_int_equal(LY_SUCCESS, lyd_parse_xml(ctx, data, 0, &tree));
+ assert_non_null(tree);
+ assert_int_equal(LYS_CONTAINER, tree->schema->nodetype);
+ assert_string_equal("cp", tree->schema->name);
+ cont = (struct lyd_node_inner*)tree;
+ assert_false(cont->flags & LYD_DEFAULT);
+ lyd_free_all(tree);
+
+ *state = NULL;
+}
+
int main(void)
{
const struct CMUnitTest tests[] = {
cmocka_unit_test_setup_teardown(test_leaf, setup, teardown),
cmocka_unit_test_setup_teardown(test_anydata, setup, teardown),
cmocka_unit_test_setup_teardown(test_list, setup, teardown),
+ cmocka_unit_test_setup_teardown(test_container, setup, teardown),
};
return cmocka_run_group_tests(tests, NULL, NULL);
diff --git a/tests/src/test_tree_schema_compile.c b/tests/src/test_tree_schema_compile.c
index e5e28ff..d56b274 100644
--- a/tests/src/test_tree_schema_compile.c
+++ b/tests/src/test_tree_schema_compile.c
@@ -23,6 +23,7 @@
#include "../../src/common.h"
#include "../../src/tree_schema_internal.h"
#include "../../src/xpath.h"
+#include "../../src/plugins_types.h"
void lysc_feature_free(struct ly_ctx *ctx, struct lysc_feature *feat);
@@ -480,6 +481,8 @@
struct lys_module *mod;
struct lysc_type *type;
struct lysc_node_leaflist *ll;
+ const char *dflt;
+ int dynamic;
assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIRS, &ctx));
@@ -519,16 +522,19 @@
assert_non_null(mod->compiled);
assert_non_null((ll = (struct lysc_node_leaflist*)mod->compiled->data));
assert_non_null(ll->dflts);
- assert_int_equal(3, ll->type->refcount);
+ assert_int_equal(6, ll->type->refcount); /* 3x type's reference, 3x default value's reference (typedef's default does not reference own type) */
assert_int_equal(2, LY_ARRAY_SIZE(ll->dflts));
- assert_string_equal("1", ll->dflts[0]);
- assert_string_equal("1", ll->dflts[1]);
+ assert_string_equal("1", dflt = ll->dflts[0]->realtype->plugin->print(ll->dflts[0], LYD_XML, NULL, NULL, &dynamic));
+ assert_int_equal(0, dynamic);
+ assert_string_equal("1", dflt = ll->dflts[1]->realtype->plugin->print(ll->dflts[1], LYD_XML, NULL, NULL, &dynamic));
+ assert_int_equal(0, dynamic);
assert_int_equal(LYS_CONFIG_R | LYS_STATUS_CURR | LYS_ORDBY_SYSTEM | LYS_SET_DFLT | LYS_SET_CONFIG, ll->flags);
assert_non_null((ll = (struct lysc_node_leaflist*)mod->compiled->data->next));
assert_non_null(ll->dflts);
- assert_int_equal(3, ll->type->refcount);
+ assert_int_equal(6, ll->type->refcount); /* 3x type's reference, 3x default value's reference */
assert_int_equal(1, LY_ARRAY_SIZE(ll->dflts));
- assert_string_equal("10", ll->dflts[0]);
+ assert_string_equal("10", dflt = ll->dflts[0]->realtype->plugin->print(ll->dflts[0], LYD_XML, NULL, NULL, &dynamic));
+ assert_int_equal(0, dynamic);
assert_int_equal(LYS_CONFIG_W | LYS_STATUS_CURR | LYS_ORDBY_USER, ll->flags);
/* ordered-by is ignored for state data, RPC/action output parameters and notification content */
@@ -555,7 +561,7 @@
logbuf_assert("Leaf-list of type \"empty\" is allowed only in YANG 1.1 modules. /aa:ll");
assert_null(lys_parse_mem(ctx, "module bb {yang-version 1.1;namespace urn:bb;prefix bb;leaf-list ll {type empty; default x;}}", LYS_IN_YANG));
- logbuf_assert("Leaf-list of type \"empty\" must not have a default value (x). /bb:ll");
+ logbuf_assert("Invalid leaf-lists's default value \"x\" which does not fit the type (Invalid empty value \"x\".). /bb:ll");
assert_non_null(mod = lys_parse_mem(ctx, "module cc {yang-version 1.1;namespace urn:cc;prefix cc;"
"leaf-list ll {config false;type string; default one;default two;default one;}}", LYS_IN_YANG));
@@ -2123,7 +2129,7 @@
/* invalid */
assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa;"
"leaf l {type empty; default x;}}", LYS_IN_YANG));
- logbuf_assert("Leaf of type \"empty\" must not have a default value (x). /aa:l");
+ logbuf_assert("Invalid leaf's default value \"x\" which does not fit the type (Invalid empty value \"x\".). /aa:l");
assert_null(lys_parse_mem(ctx, "module bb {namespace urn:bb;prefix bb;typedef mytype {type empty; default x;}"
"leaf l {type mytype;}}", LYS_IN_YANG));
@@ -2222,6 +2228,8 @@
struct ly_ctx *ctx;
struct lys_module *mod;
struct lysc_type *type;
+ struct lysc_node_leaf *leaf;
+ int dynamic;
assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIRS, &ctx));
@@ -2243,44 +2251,54 @@
"leaf l {type mybasetype;}}", LYS_IN_YANG));
type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
assert_non_null(type);
- assert_int_equal(2, type->refcount);
+ assert_int_equal(3, type->refcount); /* 2x type reference, 1x default value's reference (typedf's default does not reference own type)*/
assert_int_equal(LY_TYPE_STRING, type->basetype);
- assert_string_equal("hello", ((struct lysc_node_leaf*)mod->compiled->data)->dflt);
- assert_string_equal("xxx", ((struct lysc_node_leaf*)mod->compiled->data)->units);
+ leaf = (struct lysc_node_leaf*)mod->compiled->data;
+ assert_string_equal("hello", leaf->dflt->realtype->plugin->print(leaf->dflt, LYD_XML, NULL, NULL, &dynamic));
+ assert_int_equal(0, dynamic);
+ assert_string_equal("xxx", leaf->units);
assert_non_null(mod = lys_parse_mem(ctx, "module c {namespace urn:c;prefix c; typedef mybasetype {type string;default hello;units xxx;}"
"leaf l {type mybasetype; default goodbye;units yyy;}}", LYS_IN_YANG));
type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
assert_non_null(type);
- assert_int_equal(2, type->refcount);
+ assert_int_equal(3, type->refcount); /* 2x type reference, 1x default value's reference */
assert_int_equal(LY_TYPE_STRING, type->basetype);
- assert_string_equal("goodbye", ((struct lysc_node_leaf*)mod->compiled->data)->dflt);
- assert_string_equal("yyy", ((struct lysc_node_leaf*)mod->compiled->data)->units);
+ leaf = (struct lysc_node_leaf*)mod->compiled->data;
+ assert_string_equal("goodbye", leaf->dflt->realtype->plugin->print(leaf->dflt, LYD_XML, NULL, NULL, &dynamic));
+ assert_int_equal(0, dynamic);
+ assert_string_equal("yyy", leaf->units);
assert_non_null(mod = lys_parse_mem(ctx, "module d {namespace urn:d;prefix d; typedef mybasetype {type string;default hello;units xxx;}"
"typedef mytype {type mybasetype;}leaf l1 {type mytype; default goodbye;units yyy;}"
"leaf l2 {type mytype;}}", LYS_IN_YANG));
type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
assert_non_null(type);
- assert_int_equal(4, type->refcount);
+ assert_int_equal(6, type->refcount); /* 4x type reference, 2x default value's reference (1 shared compiled type of typedefs which default does not reference own type) */
assert_int_equal(LY_TYPE_STRING, type->basetype);
- assert_string_equal("goodbye", ((struct lysc_node_leaf*)mod->compiled->data)->dflt);
- assert_string_equal("yyy", ((struct lysc_node_leaf*)mod->compiled->data)->units);
+ leaf = (struct lysc_node_leaf*)mod->compiled->data;
+ assert_string_equal("goodbye", leaf->dflt->realtype->plugin->print(leaf->dflt, LYD_XML, NULL, NULL, &dynamic));
+ assert_int_equal(0, dynamic);
+ assert_string_equal("yyy", leaf->units);
type = ((struct lysc_node_leaf*)mod->compiled->data->next)->type;
assert_non_null(type);
- assert_int_equal(4, type->refcount);
+ assert_int_equal(6, type->refcount); /* 4x type reference, 2x default value's reference (1 shared compiled type of typedefs which default does not reference own type) */
assert_int_equal(LY_TYPE_STRING, type->basetype);
- assert_string_equal("hello", ((struct lysc_node_leaf*)mod->compiled->data->next)->dflt);
- assert_string_equal("xxx", ((struct lysc_node_leaf*)mod->compiled->data->next)->units);
+ leaf = (struct lysc_node_leaf*)mod->compiled->data->next;
+ assert_string_equal("hello", leaf->dflt->realtype->plugin->print(leaf->dflt, LYD_XML, NULL, NULL, &dynamic));
+ assert_int_equal(0, dynamic);
+ assert_string_equal("xxx", leaf->units);
assert_non_null(mod = lys_parse_mem(ctx, "module e {namespace urn:e;prefix e; typedef mybasetype {type string;}"
"typedef mytype {type mybasetype; default hello;units xxx;}leaf l {type mytype;}}", LYS_IN_YANG));
type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
assert_non_null(type);
- assert_int_equal(3, type->refcount);
+ assert_int_equal(4, type->refcount); /* 3x type reference, 1x default value's reference (typedef's default does not reference own type) */
assert_int_equal(LY_TYPE_STRING, type->basetype);
- assert_string_equal("hello", ((struct lysc_node_leaf*)mod->compiled->data)->dflt);
- assert_string_equal("xxx", ((struct lysc_node_leaf*)mod->compiled->data)->units);
+ leaf = (struct lysc_node_leaf*)mod->compiled->data;
+ assert_string_equal("hello", leaf->dflt->realtype->plugin->print(leaf->dflt, LYD_XML, NULL, NULL, &dynamic));
+ assert_int_equal(0, dynamic);
+ assert_string_equal("xxx", leaf->units);
/* mandatory leaf does not takes default value from type */
assert_non_null(mod = lys_parse_mem(ctx, "module f {namespace urn:f;prefix f;typedef mytype {type string; default hello;units xxx;}"
@@ -2508,6 +2526,9 @@
struct ly_ctx *ctx;
struct lys_module *mod;
struct lysc_node *parent, *child;
+ struct lysc_node_leaf *leaf;
+ struct lysc_node_leaflist *llist;
+ int dynamic;
assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIRS, &ctx));
@@ -2529,20 +2550,23 @@
assert_non_null((parent = mod->compiled->data));
assert_int_equal(LYS_CONTAINER, parent->nodetype);
assert_string_equal("c", parent->name);
- assert_non_null((child = ((struct lysc_node_container*)parent)->child));
- assert_int_equal(LYS_LEAF, child->nodetype);
- assert_string_equal("l", child->name);
- assert_string_equal("hello", ((struct lysc_node_leaf*)child)->dflt);
- assert_int_equal(LYS_CONFIG_R, child->flags & LYS_CONFIG_MASK);
- assert_non_null(child = child->next);
- assert_int_equal(LYS_LEAFLIST, child->nodetype);
- assert_string_equal("ll", child->name);
- assert_int_equal(2, LY_ARRAY_SIZE(((struct lysc_node_leaflist*)child)->dflts));
- assert_string_equal("hello", ((struct lysc_node_leaflist*)child)->dflts[0]);
- assert_string_equal("world", ((struct lysc_node_leaflist*)child)->dflts[1]);
- assert_int_equal(2, ((struct lysc_node_leaflist*)child)->min);
- assert_int_equal(5, ((struct lysc_node_leaflist*)child)->max);
- assert_non_null(child = child->next);
+ assert_non_null((leaf = (struct lysc_node_leaf*)((struct lysc_node_container*)parent)->child));
+ assert_int_equal(LYS_LEAF, leaf->nodetype);
+ assert_string_equal("l", leaf->name);
+ assert_string_equal("hello", leaf->dflt->realtype->plugin->print(leaf->dflt, LYD_XML, NULL, NULL, &dynamic));
+ assert_int_equal(0, dynamic);
+ assert_int_equal(LYS_CONFIG_R, leaf->flags & LYS_CONFIG_MASK);
+ assert_non_null(llist = (struct lysc_node_leaflist*)leaf->next);
+ assert_int_equal(LYS_LEAFLIST, llist->nodetype);
+ assert_string_equal("ll", llist->name);
+ assert_int_equal(2, LY_ARRAY_SIZE(llist->dflts));
+ assert_string_equal("hello", llist->dflts[0]->realtype->plugin->print(llist->dflts[0], LYD_XML, NULL, NULL, &dynamic));
+ assert_int_equal(0, dynamic);
+ assert_string_equal("world", llist->dflts[1]->realtype->plugin->print(llist->dflts[1], LYD_XML, NULL, NULL, &dynamic));
+ assert_int_equal(0, dynamic);
+ assert_int_equal(2, llist->min);
+ assert_int_equal(5, llist->max);
+ assert_non_null(child = llist->next);
assert_int_equal(LYS_CHOICE, child->nodetype);
assert_string_equal("ch", child->name);
assert_string_equal("b", ((struct lysc_node_choice*)child)->dflt->name);
@@ -2550,16 +2574,17 @@
assert_false(LYS_SET_DFLT & ((struct lysc_node_choice*)child)->cases[0].flags);
assert_non_null(child->iffeatures);
assert_int_equal(1, LY_ARRAY_SIZE(child->iffeatures));
- assert_non_null(child = child->next);
- assert_int_equal(LYS_LEAF, child->nodetype);
- assert_string_equal("x", child->name);
- assert_false(LYS_MAND_TRUE & child->flags);
- assert_string_equal("cheers!", ((struct lysc_node_leaf*)child)->dflt);
- assert_non_null(((struct lysc_node_leaf*)child)->musts);
- assert_int_equal(2, LY_ARRAY_SIZE(((struct lysc_node_leaf*)child)->musts));
- assert_string_equal("refined", child->dsc);
- assert_string_equal("refined", child->ref);
- assert_non_null(child = child->next);
+ assert_non_null(leaf = (struct lysc_node_leaf*)child->next);
+ assert_int_equal(LYS_LEAF, leaf->nodetype);
+ assert_string_equal("x", leaf->name);
+ assert_false(LYS_MAND_TRUE & leaf->flags);
+ assert_string_equal("cheers!", leaf->dflt->realtype->plugin->print(leaf->dflt, LYD_XML, NULL, NULL, &dynamic));
+ assert_int_equal(0, dynamic);
+ assert_non_null(leaf->musts);
+ assert_int_equal(2, LY_ARRAY_SIZE(leaf->musts));
+ assert_string_equal("refined", leaf->dsc);
+ assert_string_equal("refined", leaf->ref);
+ assert_non_null(child = leaf->next);
assert_int_equal(LYS_ANYDATA, child->nodetype);
assert_string_equal("a", child->name);
assert_true(LYS_MAND_TRUE & child->flags);
@@ -2578,11 +2603,12 @@
assert_non_null(mod = lys_parse_mem(ctx, "module b {yang-version 1.1;namespace urn:b;prefix b;import grp {prefix g;}"
"uses g:grp {status deprecated; refine c/x {default hello; mandatory false;}}}", LYS_IN_YANG));
- assert_non_null((child = ((struct lysc_node_container*)mod->compiled->data)->child->prev->prev->prev));
- assert_int_equal(LYS_LEAF, child->nodetype);
- assert_string_equal("x", child->name);
- assert_false(LYS_MAND_TRUE & child->flags);
- assert_string_equal("hello", ((struct lysc_node_leaf*)child)->dflt);
+ assert_non_null((leaf = (struct lysc_node_leaf*)((struct lysc_node_container*)mod->compiled->data)->child->prev->prev->prev));
+ assert_int_equal(LYS_LEAF, leaf->nodetype);
+ assert_string_equal("x", leaf->name);
+ assert_false(LYS_MAND_TRUE & leaf->flags);
+ assert_string_equal("hello", leaf->dflt->realtype->plugin->print(leaf->dflt, LYD_XML, NULL, NULL, &dynamic));
+ assert_int_equal(0, dynamic);
/* invalid */
assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa;import grp {prefix g;}"
@@ -2799,6 +2825,9 @@
struct lys_module *mod;
const struct lysc_node *node;
const struct lysc_node_list *list;
+ const struct lysc_node_leaflist *llist;
+ const struct lysc_node_leaf *leaf;
+ int dynamic;
assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIRS, &ctx));
@@ -2881,16 +2910,20 @@
assert_null(((struct lysc_node_choice*)node)->dflt);
assert_non_null(node = node->next);
assert_null(((struct lysc_node_choice*)node)->dflt);
- assert_non_null(node = node->next);
- assert_null(((struct lysc_node_leaf*)node)->dflt);
- assert_non_null(node = node->next);
- assert_int_equal(1, LY_ARRAY_SIZE(((struct lysc_node_leaflist*)node)->dflts));
- assert_string_equal("hello", ((struct lysc_node_leaflist*)node)->dflts[0]);
- assert_non_null(node = node->next);
- assert_string_equal("nothing", ((struct lysc_node_leaf*)node)->dflt);
- assert_non_null(node = node->next);
- assert_int_equal(1, LY_ARRAY_SIZE(((struct lysc_node_leaflist*)node)->dflts));
- assert_string_equal("nothing", ((struct lysc_node_leaflist*)node)->dflts[0]);
+ assert_non_null(leaf = (struct lysc_node_leaf*)node->next);
+ assert_null(leaf->dflt);
+ assert_non_null(llist = (struct lysc_node_leaflist*)leaf->next);
+ assert_int_equal(1, LY_ARRAY_SIZE(llist->dflts));
+ assert_string_equal("hello", llist->dflts[0]->realtype->plugin->print(llist->dflts[0], LYD_XML, NULL, NULL, &dynamic));
+ assert_int_equal(0, dynamic);
+ assert_non_null(leaf = (struct lysc_node_leaf*)llist->next);
+ assert_string_equal("nothing", leaf->dflt->realtype->plugin->print(leaf->dflt, LYD_XML, NULL, NULL, &dynamic));
+ assert_int_equal(0, dynamic);
+ assert_int_equal(5, leaf->dflt->realtype->refcount); /* 3x type reference, 2x default value reference (typedef's default does not reference own type) */
+ assert_non_null(llist = (struct lysc_node_leaflist*)leaf->next);
+ assert_int_equal(1, LY_ARRAY_SIZE(llist->dflts));
+ assert_string_equal("nothing", llist->dflts[0]->realtype->plugin->print(llist->dflts[0], LYD_XML, NULL, NULL, &dynamic));
+ assert_int_equal(0, dynamic);
assert_non_null(lys_parse_mem(ctx, "module g {yang-version 1.1; namespace urn:g;prefix g;import e {prefix x;}"
"deviation /x:b {deviate add {default x:b;}}"
@@ -2904,21 +2937,30 @@
assert_non_null(node = node->next);
assert_non_null(((struct lysc_node_choice*)node)->dflt);
assert_string_equal("b", ((struct lysc_node_choice*)node)->dflt->name);
- assert_non_null(node = node->next);
- assert_non_null(((struct lysc_node_leaf*)node)->dflt);
- assert_string_equal("bye", ((struct lysc_node_leaf*)node)->dflt);
- assert_non_null(node = node->next);
- assert_int_equal(3, LY_ARRAY_SIZE(((struct lysc_node_leaflist*)node)->dflts));
- assert_string_equal("hello", ((struct lysc_node_leaflist*)node)->dflts[0]);
- assert_string_equal("all", ((struct lysc_node_leaflist*)node)->dflts[1]);
- assert_string_equal("people", ((struct lysc_node_leaflist*)node)->dflts[2]);
- assert_non_null(node = node->next);
- assert_non_null(((struct lysc_node_leaf*)node)->dflt);
- assert_string_equal("hi", ((struct lysc_node_leaf*)node)->dflt);
- assert_non_null(node = node->next);
- assert_int_equal(2, LY_ARRAY_SIZE(((struct lysc_node_leaflist*)node)->dflts));
- assert_string_equal("hi", ((struct lysc_node_leaflist*)node)->dflts[0]);
- assert_string_equal("all", ((struct lysc_node_leaflist*)node)->dflts[1]);
+ assert_non_null(leaf = (struct lysc_node_leaf*)node->next);
+ assert_non_null(leaf->dflt);
+ assert_string_equal("bye", leaf->dflt->realtype->plugin->print(leaf->dflt, LYD_XML, NULL, NULL, &dynamic));
+ assert_int_equal(0, dynamic);
+ assert_non_null(llist = (struct lysc_node_leaflist*)leaf->next);
+ assert_int_equal(3, LY_ARRAY_SIZE(llist->dflts));
+ assert_string_equal("hello", llist->dflts[0]->realtype->plugin->print(llist->dflts[0], LYD_XML, NULL, NULL, &dynamic));
+ assert_int_equal(0, dynamic);
+ assert_string_equal("all", llist->dflts[1]->realtype->plugin->print(llist->dflts[1], LYD_XML, NULL, NULL, &dynamic));
+ assert_int_equal(0, dynamic);
+ assert_string_equal("people", llist->dflts[2]->realtype->plugin->print(llist->dflts[2], LYD_XML, NULL, NULL, &dynamic));
+ assert_int_equal(0, dynamic);
+ assert_non_null(leaf = (struct lysc_node_leaf*)llist->next);
+ assert_non_null(leaf->dflt);
+ assert_string_equal("hi", leaf->dflt->realtype->plugin->print(leaf->dflt, LYD_XML, NULL, NULL, &dynamic));
+ assert_int_equal(0, dynamic);
+ assert_int_equal(6, leaf->dflt->realtype->refcount); /* 3x type reference, 3x default value reference
+ - previous type's default values were replaced by node's default values where d2 now has 2 default values */
+ assert_non_null(llist = (struct lysc_node_leaflist*)leaf->next);
+ assert_int_equal(2, LY_ARRAY_SIZE(llist->dflts));
+ assert_string_equal("hi", llist->dflts[0]->realtype->plugin->print(llist->dflts[0], LYD_XML, NULL, NULL, &dynamic));
+ assert_int_equal(0, dynamic);
+ assert_string_equal("all", llist->dflts[1]->realtype->plugin->print(llist->dflts[1], LYD_XML, NULL, NULL, &dynamic));
+ assert_int_equal(0, dynamic);
assert_non_null(lys_parse_mem(ctx, "module h {yang-version 1.1; namespace urn:h;prefix h;import e {prefix x;}"
"deviation /x:b {deviate replace {default x:a;}}"
@@ -2929,9 +2971,10 @@
assert_non_null(node = node->next);
assert_non_null(((struct lysc_node_choice*)node)->dflt);
assert_string_equal("a", ((struct lysc_node_choice*)node)->dflt->name);
- assert_non_null(node = node->next);
- assert_non_null(((struct lysc_node_leaf*)node)->dflt);
- assert_string_equal("hello", ((struct lysc_node_leaf*)node)->dflt);
+ assert_non_null(leaf = (struct lysc_node_leaf*)node->next);
+ assert_non_null(leaf->dflt);
+ assert_string_equal("hello", leaf->dflt->realtype->plugin->print(leaf->dflt, LYD_XML, NULL, NULL, &dynamic));
+ assert_int_equal(0, dynamic);
ly_ctx_set_module_imp_clb(ctx, test_imp_clb, "module i {namespace urn:i;prefix i;"
"list l1 {key a; leaf a {type string;} leaf b {type string;} leaf c {type string;}}"
@@ -3044,15 +3087,19 @@
"leaf a {type string; default 10;} leaf-list b {type string;}"
"deviation /a {deviate replace {type mytype;}}"
"deviation /b {deviate replace {type mytype;}}}", LYS_IN_YANG));
- assert_non_null(node = mod->compiled->data);
- assert_string_equal("a", node->name);
- assert_int_equal(LY_TYPE_INT8, ((struct lysc_node_leaf*)node)->type->basetype);
- assert_string_equal("10", ((struct lysc_node_leaf*)node)->dflt);
- assert_non_null(node = node->next);
- assert_string_equal("b", node->name);
- assert_int_equal(LY_TYPE_INT8, ((struct lysc_node_leaflist*)node)->type->basetype);
- assert_int_equal(1, LY_ARRAY_SIZE(((struct lysc_node_leaflist*)node)->dflts));
- assert_string_equal("1", ((struct lysc_node_leaflist*)node)->dflts[0]);
+ assert_non_null(leaf = (struct lysc_node_leaf*)mod->compiled->data);
+ assert_string_equal("a", leaf->name);
+ assert_int_equal(LY_TYPE_INT8, leaf->type->basetype);
+ assert_string_equal("10", leaf->dflt->realtype->plugin->print(leaf->dflt, LYD_XML, NULL, NULL, &dynamic));
+ assert_int_equal(0, dynamic);
+ assert_int_equal(10, leaf->dflt->uint8);
+ assert_non_null(llist = (struct lysc_node_leaflist*)leaf->next);
+ assert_string_equal("b", llist->name);
+ assert_int_equal(LY_TYPE_INT8, llist->type->basetype);
+ assert_int_equal(1, LY_ARRAY_SIZE(llist->dflts));
+ assert_string_equal("1", llist->dflts[0]->realtype->plugin->print(llist->dflts[0], LYD_XML, NULL, NULL, &dynamic));
+ assert_int_equal(0, dynamic);
+ assert_int_equal(1, llist->dflts[0]->uint8);
assert_null(lys_parse_mem(ctx, "module aa1 {namespace urn:aa1;prefix aa1;import a {prefix a;}"
"deviation /a:top/a:z {deviate not-supported;}}", LYS_IN_YANG));