Skip to content

Commit 2f58b41

Browse files
committed
tree data UPDATE remove value_type from any nodes
1 parent 0e0d9fd commit 2f58b41

19 files changed

+249
-412
lines changed

doc/transition_4_5.dox

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@
44
* There are few non-backwards-compatible changes that should not affect the majority of users. These include an
55
* **updated canonical value** of *date-and-time* value in an unknown timezone. Also, there were minor changes in a few
66
* public structures. These include changing the type of the `parent` member of ::lyd_node or
7-
* removing the `lyd_anydata_value` union. Both these changes made the data node structures more unified and
8-
* user-friendly.
7+
* removing the `lyd_anydata_value` union and `value_type` member of `struct lyd_node_any`. Both these changes made the
8+
* data node structures more unified and user-friendly. Anyxml and anydata nodes now have either a data tree or string
9+
* value, with string values having hints that aid in correctly printing and preserving the values.
910
*
1011
* To mention all the significant changes, the binary **LYB format was improved** and now fully supports 2 variants.
1112
* The default one is optimized for performance and has fairly lenient restrictions on the context parsing these data.

src/diff.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1890,7 +1890,7 @@ lyd_diff_apply_r(struct lyd_node **first_node, struct lyd_node *parent_node, con
18901890
} else {
18911891
struct lyd_node_any *any = (struct lyd_node_any *)diff_node;
18921892

1893-
LY_CHECK_RET(lyd_any_copy_value(match, any->child ? any->child : (void *)any->value, any->value_type));
1893+
LY_CHECK_RET(lyd_any_copy_value(match, any->child, any->value, any->hints));
18941894
}
18951895

18961896
/* with flags */
@@ -2278,7 +2278,7 @@ lyd_diff_merge_replace(struct lyd_node *diff_match, enum lyd_diff_op cur_op, con
22782278

22792279
/* modify the node value */
22802280
any = (struct lyd_node_any *)src_diff;
2281-
LY_CHECK_RET(lyd_any_copy_value(diff_match, any->child ? any->child : (void *)any->value, any->value_type));
2281+
LY_CHECK_RET(lyd_any_copy_value(diff_match, any->child, any->value, any->hints));
22822282
break;
22832283
default:
22842284
LOGINT_RET(LYD_CTX(src_diff));
@@ -3051,7 +3051,7 @@ lyd_diff_reverse_value(struct lyd_node *node, const struct lys_module *mod)
30513051
if (node->schema->nodetype == LYS_LEAF) {
30523052
LY_CHECK_GOTO(ret = lyd_change_term(node, val1), cleanup);
30533053
} else {
3054-
LY_CHECK_GOTO(ret = lyd_any_copy_value(node, val1, LYD_ANYDATA_STRING), cleanup);
3054+
LY_CHECK_GOTO(ret = lyd_any_copy_value(node, NULL, val1, 0), cleanup);
30553055
}
30563056
node->flags = flags;
30573057
LY_CHECK_GOTO(ret = lyd_change_meta(meta, val2), cleanup);

src/parser_json.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1247,7 +1247,7 @@ lydjson_parse_any(struct lyd_json_ctx *lydctx, const struct lysc_node *snode, co
12471247
switch (*status) {
12481248
case LYJSON_OBJECT:
12491249
/* create empty node */
1250-
r = lyd_create_any(snode, NULL, LYD_ANYDATA_DATATREE, 1, 0, node);
1250+
r = lyd_create_any(snode, NULL, NULL, 0, 1, 0, node);
12511251
LY_CHECK_ERR_GOTO(r, rc = r, cleanup);
12521252
break;
12531253
case LYJSON_ARRAY:
@@ -1267,20 +1267,21 @@ lydjson_parse_any(struct lyd_json_ctx *lydctx, const struct lysc_node *snode, co
12671267
rc = LY_EMEM;
12681268
goto cleanup;
12691269
}
1270-
r = lyd_create_any(snode, val, LYD_ANYDATA_JSON, 1, 0, node);
1270+
r = lyd_create_any(snode, NULL, val, LYD_NODEHINT_LIST | LYD_NODEHINT_LEAFLIST, 1, 0, node);
12711271
LY_CHECK_ERR_GOTO(r, rc = r, cleanup);
12721272
val = NULL;
12731273
break;
12741274
case LYJSON_STRING:
12751275
/* string value */
12761276
if (lydctx->jsonctx->dynamic) {
1277-
LY_CHECK_GOTO(rc = lyd_create_any(snode, lydctx->jsonctx->value, LYD_ANYDATA_STRING, 1, 0, node), cleanup);
1277+
LY_CHECK_GOTO(rc = lyd_create_any(snode, NULL, lydctx->jsonctx->value,
1278+
LYD_VALHINT_STRING | LYD_VALHINT_NUM64, 1, 0, node), cleanup);
12781279
lydctx->jsonctx->dynamic = 0;
12791280
} else {
12801281
val = strndup(lydctx->jsonctx->value, lydctx->jsonctx->value_len);
12811282
LY_CHECK_ERR_GOTO(!val, LOGMEM(lydctx->jsonctx->ctx); rc = LY_EMEM, cleanup);
12821283

1283-
r = lyd_create_any(snode, val, LYD_ANYDATA_STRING, 1, 0, node);
1284+
r = lyd_create_any(snode, NULL, val, LYD_VALHINT_STRING | LYD_VALHINT_NUM64, 1, 0, node);
12841285
LY_CHECK_ERR_GOTO(r, rc = r, cleanup);
12851286
val = NULL;
12861287
}
@@ -1293,13 +1294,13 @@ lydjson_parse_any(struct lyd_json_ctx *lydctx, const struct lysc_node *snode, co
12931294
val = strndup(lydctx->jsonctx->value, lydctx->jsonctx->value_len);
12941295
LY_CHECK_ERR_GOTO(!val, LOGMEM(lydctx->jsonctx->ctx); rc = LY_EMEM, cleanup);
12951296

1296-
r = lyd_create_any(snode, val, LYD_ANYDATA_JSON, 1, 0, node);
1297+
r = lyd_create_any(snode, NULL, val, (*status == LYJSON_NUMBER) ? LYD_VALHINT_DECNUM : LYD_VALHINT_BOOLEAN, 1, 0, node);
12971298
LY_CHECK_ERR_GOTO(r, rc = r, cleanup);
12981299
val = NULL;
12991300
break;
13001301
case LYJSON_NULL:
13011302
/* no value */
1302-
r = lyd_create_any(snode, NULL, LYD_ANYDATA_JSON, 1, 0, node);
1303+
r = lyd_create_any(snode, NULL, NULL, LYD_VALHINT_EMPTY, 1, 0, node);
13031304
LY_CHECK_ERR_GOTO(r, rc = r, cleanup);
13041305
break;
13051306
default:

src/parser_lyb.c

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1282,9 +1282,8 @@ lyb_parse_node_any(struct lyd_lyb_ctx *lybctx, struct lyd_node *parent, const st
12821282
LY_ERR rc = LY_SUCCESS;
12831283
struct lyd_node *node = NULL, *tree = NULL;
12841284
struct lyd_meta *meta = NULL;
1285-
LYD_ANYDATA_VALUETYPE value_type = 0;
12861285
char *value = NULL;
1287-
uint32_t flags = 0, prev_parse_opts, prev_int_opts;
1286+
uint32_t flags = 0, value_type = 0, prev_parse_opts, prev_int_opts;
12881287
const struct ly_ctx *ctx = lybctx->parse_ctx->ctx;
12891288

12901289
/* read necessary basic data */
@@ -1295,8 +1294,7 @@ lyb_parse_node_any(struct lyd_lyb_ctx *lybctx, struct lyd_node *parent, const st
12951294
lyb_read_count((uint32_t *)&value_type, lybctx->parse_ctx);
12961295

12971296
/* create the node */
1298-
switch (value_type) {
1299-
case LYD_ANYDATA_DATATREE:
1297+
if (value_type == 0) {
13001298
/* backup original options and use specific ones */
13011299
prev_parse_opts = lybctx->parse_opts;
13021300
prev_int_opts = lybctx->int_opts;
@@ -1310,23 +1308,19 @@ lyb_parse_node_any(struct lyd_lyb_ctx *lybctx, struct lyd_node *parent, const st
13101308
LY_CHECK_GOTO(rc, cleanup);
13111309

13121310
/* use the data tree value */
1313-
rc = lyd_create_any(snode, tree, value_type, 1, 0, &node);
1311+
rc = lyd_create_any(snode, tree, NULL, 0, 1, 0, &node);
13141312
LY_CHECK_GOTO(rc, cleanup);
13151313
tree = NULL;
1316-
break;
1317-
case LYD_ANYDATA_STRING:
1318-
case LYD_ANYDATA_XML:
1319-
case LYD_ANYDATA_JSON:
1314+
} else if (value_type == 1) {
13201315
/* string value */
13211316
rc = lyb_read_string(&value, lybctx->parse_ctx);
13221317
LY_CHECK_GOTO(rc, cleanup);
13231318

13241319
/* use the string value */
1325-
rc = lyd_create_any(snode, value, value_type, 1, 0, &node);
1320+
rc = lyd_create_any(snode, NULL, value, 0, 1, 0, &node);
13261321
LY_CHECK_GOTO(rc, cleanup);
13271322
value = NULL;
1328-
break;
1329-
default:
1323+
} else {
13301324
LOGINT(ctx);
13311325
rc = LY_EINT;
13321326
goto cleanup;

src/parser_xml.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -934,7 +934,7 @@ lydxml_subtree_any(struct lyd_xml_ctx *lydctx, const struct lysc_node *snode, co
934934

935935
if (xmlctx->ws_only) {
936936
/* create empty node first */
937-
r = lyd_create_any(snode, NULL, LYD_ANYDATA_DATATREE, 1, 0, node);
937+
r = lyd_create_any(snode, NULL, NULL, 0, 1, 0, node);
938938
LY_CHECK_ERR_GOTO(r, rc = r, cleanup);
939939
datatree_val = 1;
940940
} else {
@@ -943,7 +943,7 @@ lydxml_subtree_any(struct lyd_xml_ctx *lydctx, const struct lysc_node *snode, co
943943
LY_CHECK_ERR_GOTO(!val, LOGMEM(xmlctx->ctx); rc = LY_EMEM, cleanup);
944944

945945
/* create node */
946-
r = lyd_create_any(snode, val, LYD_ANYDATA_STRING, 1, 1, node);
946+
r = lyd_create_any(snode, NULL, val, 0, 1, 1, node);
947947
LY_CHECK_ERR_GOTO(r, rc = r, cleanup);
948948
val = NULL;
949949
}

src/printer_json.c

Lines changed: 14 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* @author Michal Vasko <mvasko@cesnet.cz>
55
* @brief JSON printer for libyang data structure
66
*
7-
* Copyright (c) 2015 - 2023 CESNET, z.s.p.o.
7+
* Copyright (c) 2015 - 2026 CESNET, z.s.p.o.
88
*
99
* This source code is licensed under BSD 3-Clause License (the "License").
1010
* You may not use this file except in compliance with the License.
@@ -617,12 +617,11 @@ json_print_any_content(struct jsonpr_ctx *pctx, struct lyd_node_any *any)
617617

618618
assert(any->schema->nodetype & LYD_NODE_ANY);
619619

620-
if ((any->schema->nodetype == LYS_ANYDATA) && (any->value_type != LYD_ANYDATA_DATATREE)) {
620+
if ((any->schema->nodetype == LYS_ANYDATA) && any->value) {
621621
LOGINT_RET(pctx->ctx);
622622
}
623623

624-
switch (any->value_type) {
625-
case LYD_ANYDATA_DATATREE:
624+
if (any->child) {
626625
/* print as an object */
627626
ly_print_(pctx->out, "{%s", DO_FORMAT ? "\n" : "");
628627
LEVEL_INC;
@@ -646,34 +645,22 @@ json_print_any_content(struct jsonpr_ctx *pctx, struct lyd_node_any *any)
646645
} else {
647646
ly_print_(pctx->out, "}");
648647
}
649-
break;
650-
case LYD_ANYDATA_JSON:
651-
if (!any->value) {
652-
/* no content */
653-
if (any->schema->nodetype == LYS_ANYXML) {
654-
ly_print_(pctx->out, "null");
655-
} else {
656-
ly_print_(pctx->out, "{}");
657-
}
658-
} else {
659-
/* print without escaping special characters */
648+
} else if (any->value) {
649+
if (any->hints & (LYD_VALHINT_DECNUM | LYD_VALHINT_BOOLEAN | LYD_NODEHINT_LIST | LYD_NODEHINT_LEAFLIST)) {
650+
/* print directly as JSON data */
660651
ly_print_(pctx->out, "%s", any->value);
661-
}
662-
break;
663-
case LYD_ANYDATA_STRING:
664-
case LYD_ANYDATA_XML:
665-
if (!any->value) {
666-
/* no content */
667-
if (any->schema->nodetype == LYS_ANYXML) {
668-
ly_print_(pctx->out, "null");
669-
} else {
670-
ly_print_(pctx->out, "{}");
671-
}
672652
} else {
673653
/* print as a string */
674654
json_print_string(pctx->out, any->value);
675655
}
676-
break;
656+
} else {
657+
/* no content */
658+
if (any->hints & LYD_VALHINT_EMPTY) {
659+
assert(any->schema->nodetype != LYS_ANYDATA);
660+
ly_print_(pctx->out, "null");
661+
} else {
662+
ly_print_(pctx->out, "{}");
663+
}
677664
}
678665

679666
return LY_SUCCESS;

src/printer_lyb.c

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1183,32 +1183,25 @@ static LY_ERR
11831183
lyb_print_node_any(struct lyd_node_any *anydata, struct lyd_lyb_ctx *lybctx)
11841184
{
11851185
LY_ERR rc = LY_SUCCESS;
1186+
uint32_t value_type;
11861187

1187-
if ((anydata->schema->nodetype == LYS_ANYDATA) && (anydata->value_type != LYD_ANYDATA_DATATREE)) {
1188+
if ((anydata->schema->nodetype == LYS_ANYDATA) && anydata->value) {
11881189
LOGINT_RET(lybctx->print_ctx->ctx);
11891190
}
11901191

11911192
/* write necessary basic data */
11921193
LY_CHECK_RET(lyb_print_node_header((struct lyd_node *)anydata, lybctx));
11931194

11941195
/* write anydata value type */
1195-
LY_CHECK_GOTO(rc = lyb_write_count(anydata->value_type, lybctx->print_ctx), cleanup);
1196+
value_type = (anydata->value ? 1 : 0);
1197+
LY_CHECK_GOTO(rc = lyb_write_count(value_type, lybctx->print_ctx), cleanup);
11961198

1197-
switch (anydata->value_type) {
1198-
case LYD_ANYDATA_DATATREE:
1199-
/* print LYB siblings */
1200-
LY_CHECK_GOTO(rc = lyb_print_siblings(anydata->child, 0, lybctx), cleanup);
1201-
break;
1202-
case LYD_ANYDATA_STRING:
1203-
case LYD_ANYDATA_XML:
1204-
case LYD_ANYDATA_JSON:
1199+
if (anydata->value) {
12051200
/* string value */
12061201
LY_CHECK_GOTO(rc = lyb_write_string(anydata->value, 0, lybctx->print_ctx), cleanup);
1207-
break;
1208-
default:
1209-
LOGINT(lybctx->print_ctx->ctx);
1210-
rc = LY_EINT;
1211-
goto cleanup;
1202+
} else {
1203+
/* print LYB siblings, even empty */
1204+
LY_CHECK_GOTO(rc = lyb_print_siblings(anydata->child, 0, lybctx), cleanup);
12121205
}
12131206

12141207
cleanup:

src/printer_xml.c

Lines changed: 24 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -440,59 +440,39 @@ xml_print_anydata(struct xmlpr_ctx *pctx, const struct lyd_node_any *node)
440440
uint32_t prev_opts;
441441
LY_ERR ret;
442442

443-
if ((node->schema->nodetype == LYS_ANYDATA) && (node->value_type != LYD_ANYDATA_DATATREE)) {
443+
if ((node->schema->nodetype == LYS_ANYDATA) && node->value) {
444444
LOGINT_RET(pctx->ctx);
445445
}
446446

447447
xml_print_node_open(pctx, &node->node);
448448

449-
if (!any->child && !any->value) {
450-
/* no content */
451-
no_content:
452-
ly_print_(pctx->out, "/>%s", DO_FORMAT ? "\n" : "");
453-
return LY_SUCCESS;
454-
} else {
455-
switch (any->value_type) {
456-
case LYD_ANYDATA_DATATREE:
457-
/* close opening tag and print data */
458-
prev_opts = pctx->options;
459-
pctx->options &= ~LYD_PRINT_SIBLINGS;
460-
LEVEL_INC;
461-
462-
ly_print_(pctx->out, ">%s", DO_FORMAT ? "\n" : "");
463-
LY_LIST_FOR(any->child, iter) {
464-
ret = xml_print_node(pctx, iter);
465-
LY_CHECK_ERR_RET(ret, LEVEL_DEC, ret);
466-
}
449+
if (any->child) {
450+
/* close opening tag and print data */
451+
prev_opts = pctx->options;
452+
pctx->options &= ~LYD_PRINT_SIBLINGS;
453+
LEVEL_INC;
467454

468-
LEVEL_DEC;
469-
pctx->options = prev_opts;
470-
break;
471-
case LYD_ANYDATA_STRING:
472-
case LYD_ANYDATA_JSON:
473-
/* escape XML-sensitive characters */
474-
if (!any->value[0]) {
475-
goto no_content;
476-
}
477-
/* close opening tag and print data */
478-
ly_print_(pctx->out, ">");
479-
lyxml_dump_text(pctx->out, any->value, 0);
480-
break;
481-
case LYD_ANYDATA_XML:
482-
/* print without escaping special characters */
483-
if (!any->value[0]) {
484-
goto no_content;
485-
}
486-
ly_print_(pctx->out, ">%s", any->value);
487-
break;
455+
ly_print_(pctx->out, ">%s", DO_FORMAT ? "\n" : "");
456+
LY_LIST_FOR(any->child, iter) {
457+
ret = xml_print_node(pctx, iter);
458+
LY_CHECK_ERR_RET(ret, LEVEL_DEC, ret);
488459
}
489460

461+
LEVEL_DEC;
462+
pctx->options = prev_opts;
463+
490464
/* closing tag */
491-
if (any->value_type == LYD_ANYDATA_DATATREE) {
492-
ly_print_(pctx->out, "%*s</%s>%s", INDENT, node->schema->name, DO_FORMAT ? "\n" : "");
493-
} else {
494-
ly_print_(pctx->out, "</%s>%s", node->schema->name, DO_FORMAT ? "\n" : "");
495-
}
465+
ly_print_(pctx->out, "%*s</%s>%s", INDENT, node->schema->name, DO_FORMAT ? "\n" : "");
466+
} else if (any->value && any->value[0]) {
467+
/* close opening tag and print data, escape XML-sensitive characters */
468+
ly_print_(pctx->out, ">");
469+
lyxml_dump_text(pctx->out, any->value, 0);
470+
471+
/* closing tag */
472+
ly_print_(pctx->out, "</%s>%s", node->schema->name, DO_FORMAT ? "\n" : "");
473+
} else {
474+
/* no content, close */
475+
ly_print_(pctx->out, "/>%s", DO_FORMAT ? "\n" : "");
496476
}
497477

498478
return LY_SUCCESS;

0 commit comments

Comments
 (0)