Skip to content

Commit 9c27159

Browse files
committed
parsers UPDATE connect nodes right after creation
So that when checking for nested extension data, the parent is connected to its parents. Additional schema-mount test added.
1 parent 820d68b commit 9c27159

7 files changed

Lines changed: 220 additions & 145 deletions

File tree

src/parser_common.c

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* @author Michal Vasko <mvasko@cesnet.cz>
44
* @brief libyang common parser functions.
55
*
6-
* Copyright (c) 2015 - 2025 CESNET, z.s.p.o.
6+
* Copyright (c) 2015 - 2026 CESNET, z.s.p.o.
77
*
88
* This source code is licensed under BSD 3-Clause License (the "License").
99
* You may not use this file except in compliance with the License.
@@ -381,7 +381,7 @@ lyd_parser_check_keys(struct lyd_node *node)
381381

382382
LY_ERR
383383
lyd_parser_set_data_flags(struct lyd_node *node, struct lyd_meta **meta, struct lyd_ctx *lydctx,
384-
struct lysc_ext_instance *ext)
384+
const struct lysc_ext_instance *ext)
385385
{
386386
struct lyd_meta *meta2, *prev_meta = NULL, *next_meta = NULL;
387387
struct lyd_ctx_ext_val *ext_val;
@@ -434,7 +434,7 @@ lyd_parser_set_data_flags(struct lyd_node *node, struct lyd_meta **meta, struct
434434
/* rememeber for validation */
435435
ext_val = malloc(sizeof *ext_val);
436436
LY_CHECK_ERR_RET(!ext_val, LOGMEM(LYD_CTX(node)), LY_EMEM);
437-
ext_val->ext = ext;
437+
ext_val->ext = (struct lysc_ext_instance *)ext;
438438
ext_val->sibling = node;
439439
LY_CHECK_RET(ly_set_add(&lydctx->ext_val, ext_val, 1, NULL));
440440
}
@@ -473,6 +473,65 @@ lyd_parser_validate_new_implicit(struct lyd_ctx *lydctx, struct lyd_node *node)
473473
return rc;
474474
}
475475

476+
void
477+
lyd_parser_node_free(struct lyd_node **first_p, struct lyd_node **node)
478+
{
479+
if (*node && (*node)->schema && ((*node)->schema->flags & LYS_KEY)) {
480+
/* no not free keys */
481+
return;
482+
}
483+
484+
if (*first_p && !(*first_p)->parent && (*first_p == *node)) {
485+
*first_p = (*first_p)->next;
486+
}
487+
488+
lyd_free_tree(*node);
489+
*node = NULL;
490+
}
491+
492+
LY_ERR
493+
lyd_parser_node_insert(const struct lysc_ext_instance *ext, struct lyd_node *parent, struct lyd_node **first_p,
494+
struct lyd_node *insert_anchor, uint32_t parse_opts, struct lyd_node *node)
495+
{
496+
const struct lysc_node *skey = NULL;
497+
const struct lyd_node *key;
498+
499+
if (!node || node->parent || (node->prev != node) || (first_p && (*first_p == node))) {
500+
/* no node or already inserted */
501+
return LY_SUCCESS;
502+
}
503+
504+
if (node->schema && (node->schema->nodetype == LYS_LIST)) {
505+
/* check the node has all the keys first */
506+
key = lyd_child(node);
507+
while ((skey = lys_getnext(skey, node->schema, NULL, 0)) && (skey->flags & LYS_KEY)) {
508+
if (!key || (key->schema != skey)) {
509+
/* missing key(s) */
510+
return LY_SUCCESS;
511+
}
512+
513+
key = key->next;
514+
}
515+
}
516+
517+
/* insert */
518+
if (insert_anchor) {
519+
lyd_insert_after(insert_anchor, node);
520+
} else if (ext) {
521+
LY_CHECK_RET(lyplg_ext_insert(parent, node));
522+
} else {
523+
lyd_insert_node(parent, first_p, node,
524+
parse_opts & LYD_PARSE_ORDERED ? LYD_INSERT_NODE_LAST : LYD_INSERT_NODE_DEFAULT);
525+
}
526+
527+
/* adjust the first sibling pointer */
528+
while (!parent && (*first_p)->prev->next) {
529+
*first_p = (*first_p)->prev;
530+
}
531+
532+
return LY_SUCCESS;
533+
}
534+
476535
LY_ERR
477536
lys_parser_fill_filepath(struct ly_ctx *ctx, struct ly_in *in, const char **filepath)
478537
{

src/parser_internal.h

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* @author Michal Vasko <mvasko@cesnet.cz>
55
* @brief Internal structures and functions for libyang parsers
66
*
7-
* Copyright (c) 2020 - 2023 CESNET, z.s.p.o.
7+
* Copyright (c) 2020 - 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.
@@ -440,7 +440,7 @@ LY_ERR lyd_parser_check_keys(struct lyd_node *node);
440440
* @return LY_ERR value.
441441
*/
442442
LY_ERR lyd_parser_set_data_flags(struct lyd_node *node, struct lyd_meta **meta, struct lyd_ctx *lydctx,
443-
struct lysc_ext_instance *ext);
443+
const struct lysc_ext_instance *ext);
444444

445445
/**
446446
* @brief Validate a new parsed data node and add its implicit children.
@@ -451,6 +451,28 @@ LY_ERR lyd_parser_set_data_flags(struct lyd_node *node, struct lyd_meta **meta,
451451
*/
452452
LY_ERR lyd_parser_validate_new_implicit(struct lyd_ctx *lydctx, struct lyd_node *node);
453453

454+
/**
455+
* @brief Free safely a parsed node.
456+
*
457+
* @param[in,out] first_p Pointer to the first sibling on a level.
458+
* @param[in,out] node Node to free, is zeroed.
459+
*/
460+
void lyd_parser_node_free(struct lyd_node **first_p, struct lyd_node **node);
461+
462+
/**
463+
* @brief Insert a parsed node.
464+
*
465+
* @param[in] ext Extension instance if @p node was parsed for one.
466+
* @param[in] parent Data node parent, if any.
467+
* @param[in,out] first_p First sibling on the level, if any.
468+
* @param[in] insert_anchor Optional insert anchor to use.
469+
* @param[in] parse_opts Parser options.
470+
* @param[in] node Node to insert.
471+
* @return LY_ERR value.
472+
*/
473+
LY_ERR lyd_parser_node_insert(const struct lysc_ext_instance *ext, struct lyd_node *parent, struct lyd_node **first_p,
474+
struct lyd_node *insert_anchor, uint32_t parse_opts, struct lyd_node *node);
475+
454476
/**
455477
* @brief Parse an instance extension statement.
456478
*

0 commit comments

Comments
 (0)