blob: 8328ad72053e79a4ffec7c11b7e014e90610bec2 [file] [log] [blame]
Radek Krejcie7b95092019-05-15 11:03:07 +02001/**
2 * @file tree_data_helpers.c
3 * @author Radek Krejci <rkrejci@cesnet.cz>
4 * @brief Parsing and validation helper functions for data trees
5 *
6 * Copyright (c) 2015 - 2018 CESNET, z.s.p.o.
7 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
14#include "common.h"
15
16#include <assert.h>
17#include <stdlib.h>
18
19#include "log.h"
20#include "dict.h"
21#include "plugins_types.h"
22#include "tree_data.h"
23#include "tree_schema.h"
24
25struct lyd_node **
26lyd_node_children_p(struct lyd_node *node)
27{
28 assert(node);
Michal Vasko52927e22020-03-16 17:26:14 +010029
30 if (!node->schema) {
31 return &((struct lyd_node_opaq *)node)->child;
32 } else {
33 switch (node->schema->nodetype) {
34 case LYS_CONTAINER:
35 case LYS_LIST:
36 case LYS_ACTION:
37 case LYS_NOTIF:
38 return &((struct lyd_node_inner *)node)->child;
39 default:
40 return NULL;
41 }
Radek Krejcie7b95092019-05-15 11:03:07 +020042 }
43}
44
45API const struct lyd_node *
46lyd_node_children(const struct lyd_node *node)
47{
48 struct lyd_node **children;
49
50 if (!node) {
51 return NULL;
52 }
53
54 children = lyd_node_children_p((struct lyd_node*)node);
55 if (children) {
56 return *children;
57 } else {
58 return NULL;
59 }
60}
Michal Vasko9b368d32020-02-14 13:53:31 +010061
Michal Vaskoc193ce92020-03-06 11:04:48 +010062API const struct lys_module *
63lyd_owner_module(const struct lyd_node *node)
Michal Vasko9b368d32020-02-14 13:53:31 +010064{
65 const struct lysc_node *schema;
66
Michal Vasko52927e22020-03-16 17:26:14 +010067 if (!node || !node->schema) {
Michal Vaskoc193ce92020-03-06 11:04:48 +010068 return NULL;
69 }
Michal Vasko9b368d32020-02-14 13:53:31 +010070
71 for (schema = node->schema; schema->parent; schema = schema->parent);
72 return schema->module;
73}
Michal Vaskob1b5c262020-03-05 14:29:47 +010074
75const struct lys_module *
76lyd_mod_next_module(struct lyd_node *tree, const struct lys_module **modules, int mod_count, const struct ly_ctx *ctx,
77 uint32_t *i, struct lyd_node **first)
78{
79 struct lyd_node *iter;
80 const struct lys_module *mod;
81
82 /* get the next module */
83 if (modules && mod_count) {
84 if (*i < (unsigned)mod_count) {
85 mod = modules[(*i)++];
86 } else {
87 mod = NULL;
88 }
89 } else {
90 do {
91 mod = ly_ctx_get_module_iter(ctx, i);
92 } while (mod && !mod->implemented);
93 }
94
95 /* find its data */
96 *first = NULL;
97 if (mod) {
98 LY_LIST_FOR(tree, iter) {
Michal Vaskoc193ce92020-03-06 11:04:48 +010099 if (lyd_owner_module(iter) == mod) {
Michal Vaskob1b5c262020-03-05 14:29:47 +0100100 *first = iter;
101 break;
102 }
103 }
104 }
105
106 return mod;
107}
108
109const struct lys_module *
110lyd_data_next_module(struct lyd_node **next, struct lyd_node **first)
111{
112 const struct lys_module *mod;
113
114 if (!*next) {
115 /* all data traversed */
116 *first = NULL;
117 return NULL;
118 }
119
120 *first = *next;
121
122 /* prepare next */
Michal Vaskoc193ce92020-03-06 11:04:48 +0100123 mod = lyd_owner_module(*next);
Michal Vaskob1b5c262020-03-05 14:29:47 +0100124 LY_LIST_FOR(*next, *next) {
Michal Vaskoc193ce92020-03-06 11:04:48 +0100125 if (lyd_owner_module(*next) != mod) {
Michal Vaskob1b5c262020-03-05 14:29:47 +0100126 break;
127 }
128 }
129
130 return mod;
131}
Michal Vasko9f96a052020-03-10 09:41:45 +0100132
133LY_ERR
134lyd_parse_check_keys(struct lyd_node *node)
135{
136 const struct lysc_node *skey = NULL;
137 const struct lyd_node *key;
138
139 assert(node->schema->nodetype == LYS_LIST);
140
141 key = lyd_node_children(node);
142 while ((skey = lys_getnext(skey, node->schema, NULL, 0)) && (skey->flags & LYS_KEY)) {
143 if (!key || (key->schema != skey)) {
144 LOGVAL(node->schema->module->ctx, LY_VLOG_LYD, node, LY_VCODE_NOKEY, skey->name);
145 return LY_EVALID;
146 }
147
148 key = key->next;
149 }
150
151 return LY_SUCCESS;
152}