blob: 755166766f551bd6114b4fb3a764f6a77f22aa2f [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 */
Radek Krejcie7b95092019-05-15 11:03:07 +020014
15#include <assert.h>
Radek Krejci535ea9f2020-05-29 16:01:05 +020016#include <stdint.h>
Radek Krejcie7b95092019-05-15 11:03:07 +020017#include <stdlib.h>
Radek Krejciad97c5f2020-06-30 09:19:28 +020018#include <string.h>
Radek Krejcie7b95092019-05-15 11:03:07 +020019
Radek Krejci535ea9f2020-05-29 16:01:05 +020020#include "common.h"
21#include "context.h"
Radek Krejciad97c5f2020-06-30 09:19:28 +020022#include "hash_table.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020023#include "log.h"
Radek Krejciad97c5f2020-06-30 09:19:28 +020024#include "lyb.h"
Radek Krejci7931b192020-06-25 17:05:03 +020025#include "parser_data.h"
Radek Krejciad97c5f2020-06-30 09:19:28 +020026#include "set.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020027#include "tree.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020028#include "tree_data.h"
Michal Vasko60ea6352020-06-29 13:39:39 +020029#include "tree_data_internal.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020030#include "tree_schema.h"
31
32struct lyd_node **
33lyd_node_children_p(struct lyd_node *node)
34{
35 assert(node);
Michal Vasko52927e22020-03-16 17:26:14 +010036
37 if (!node->schema) {
38 return &((struct lyd_node_opaq *)node)->child;
39 } else {
40 switch (node->schema->nodetype) {
41 case LYS_CONTAINER:
42 case LYS_LIST:
Michal Vasko1bf09392020-03-27 12:38:10 +010043 case LYS_RPC:
Michal Vasko52927e22020-03-16 17:26:14 +010044 case LYS_ACTION:
45 case LYS_NOTIF:
46 return &((struct lyd_node_inner *)node)->child;
47 default:
48 return NULL;
49 }
Radek Krejcie7b95092019-05-15 11:03:07 +020050 }
51}
52
Radek Krejcidae0ee82020-05-06 16:53:24 +020053API struct lyd_node *
Michal Vasko5bfd4be2020-06-23 13:26:19 +020054lyd_node_children(const struct lyd_node *node, int options)
Radek Krejcie7b95092019-05-15 11:03:07 +020055{
Michal Vasko5bfd4be2020-06-23 13:26:19 +020056 struct lyd_node **children, *child;
Radek Krejcie7b95092019-05-15 11:03:07 +020057
58 if (!node) {
59 return NULL;
60 }
61
Michal Vasko5bfd4be2020-06-23 13:26:19 +020062 children = lyd_node_children_p((struct lyd_node *)node);
Radek Krejcie7b95092019-05-15 11:03:07 +020063 if (children) {
Michal Vasko5bfd4be2020-06-23 13:26:19 +020064 child = *children;
65 if (options & LYD_CHILDREN_SKIP_KEYS) {
Michal Vasko04091642020-06-29 11:50:14 +020066 while (child && child->schema && (child->schema->flags & LYS_KEY)) {
Michal Vasko5bfd4be2020-06-23 13:26:19 +020067 child = child->next;
68 }
69 }
70 return child;
Radek Krejcie7b95092019-05-15 11:03:07 +020071 } else {
72 return NULL;
73 }
74}
Michal Vasko9b368d32020-02-14 13:53:31 +010075
Michal Vaskoc193ce92020-03-06 11:04:48 +010076API const struct lys_module *
77lyd_owner_module(const struct lyd_node *node)
Michal Vasko9b368d32020-02-14 13:53:31 +010078{
79 const struct lysc_node *schema;
80
Michal Vasko52927e22020-03-16 17:26:14 +010081 if (!node || !node->schema) {
Michal Vaskoc193ce92020-03-06 11:04:48 +010082 return NULL;
83 }
Michal Vasko9b368d32020-02-14 13:53:31 +010084
85 for (schema = node->schema; schema->parent; schema = schema->parent);
86 return schema->module;
87}
Michal Vaskob1b5c262020-03-05 14:29:47 +010088
89const struct lys_module *
Michal Vasko26e80012020-07-08 10:55:46 +020090lyd_mod_next_module(struct lyd_node *tree, const struct lys_module *module, const struct ly_ctx *ctx, uint32_t *i,
91 struct lyd_node **first)
Michal Vaskob1b5c262020-03-05 14:29:47 +010092{
93 struct lyd_node *iter;
94 const struct lys_module *mod;
95
96 /* get the next module */
Michal Vasko26e80012020-07-08 10:55:46 +020097 if (module) {
98 if (*i) {
Michal Vaskob1b5c262020-03-05 14:29:47 +010099 mod = NULL;
Michal Vasko26e80012020-07-08 10:55:46 +0200100 } else {
101 mod = module;
102 ++(*i);
Michal Vaskob1b5c262020-03-05 14:29:47 +0100103 }
104 } else {
105 do {
106 mod = ly_ctx_get_module_iter(ctx, i);
107 } while (mod && !mod->implemented);
108 }
109
110 /* find its data */
111 *first = NULL;
112 if (mod) {
113 LY_LIST_FOR(tree, iter) {
Michal Vaskoc193ce92020-03-06 11:04:48 +0100114 if (lyd_owner_module(iter) == mod) {
Michal Vaskob1b5c262020-03-05 14:29:47 +0100115 *first = iter;
116 break;
117 }
118 }
119 }
120
121 return mod;
122}
123
124const struct lys_module *
125lyd_data_next_module(struct lyd_node **next, struct lyd_node **first)
126{
127 const struct lys_module *mod;
128
129 if (!*next) {
130 /* all data traversed */
131 *first = NULL;
132 return NULL;
133 }
134
135 *first = *next;
136
137 /* prepare next */
Michal Vaskoc193ce92020-03-06 11:04:48 +0100138 mod = lyd_owner_module(*next);
Michal Vaskob1b5c262020-03-05 14:29:47 +0100139 LY_LIST_FOR(*next, *next) {
Michal Vaskoc193ce92020-03-06 11:04:48 +0100140 if (lyd_owner_module(*next) != mod) {
Michal Vaskob1b5c262020-03-05 14:29:47 +0100141 break;
142 }
143 }
144
145 return mod;
146}
Michal Vasko9f96a052020-03-10 09:41:45 +0100147
148LY_ERR
149lyd_parse_check_keys(struct lyd_node *node)
150{
151 const struct lysc_node *skey = NULL;
152 const struct lyd_node *key;
153
154 assert(node->schema->nodetype == LYS_LIST);
155
Michal Vasko5bfd4be2020-06-23 13:26:19 +0200156 key = lyd_node_children(node, 0);
Michal Vasko9f96a052020-03-10 09:41:45 +0100157 while ((skey = lys_getnext(skey, node->schema, NULL, 0)) && (skey->flags & LYS_KEY)) {
158 if (!key || (key->schema != skey)) {
159 LOGVAL(node->schema->module->ctx, LY_VLOG_LYD, node, LY_VCODE_NOKEY, skey->name);
160 return LY_EVALID;
161 }
162
163 key = key->next;
164 }
165
166 return LY_SUCCESS;
167}
Michal Vasko60ea6352020-06-29 13:39:39 +0200168
169void
170lyd_parse_set_data_flags(struct lyd_node *node, struct ly_set *when_check, struct lyd_meta **meta, int options)
171{
172 struct lyd_meta *meta2, *prev_meta = NULL;
173
174 if (!(node->schema->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)) && node->schema->when) {
Radek Krejci7931b192020-06-25 17:05:03 +0200175 if (options & LYD_PARSE_TRUSTED) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200176 /* just set it to true */
177 node->flags |= LYD_WHEN_TRUE;
178 } else {
179 /* remember we need to evaluate this node's when */
180 ly_set_add(when_check, node, LY_SET_OPT_USEASLIST);
181 }
182 }
183
Radek Krejci7931b192020-06-25 17:05:03 +0200184 if (options & LYD_PARSE_TRUSTED) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200185 /* node is valid */
186 node->flags &= ~LYD_NEW;
187 }
188
189 LY_LIST_FOR(*meta, meta2) {
190 if (!strcmp(meta2->name, "default") && !strcmp(meta2->annotation->module->name, "ietf-netconf-with-defaults")
191 && meta2->value.boolean) {
192 /* node is default according to the metadata */
193 node->flags |= LYD_DEFAULT;
194
195 /* delete the metadata */
196 if (prev_meta) {
197 prev_meta->next = meta2->next;
198 } else {
199 *meta = (*meta)->next;
200 }
Michal Vasko3a41dff2020-07-15 14:30:28 +0200201 lyd_free_meta_single(meta2);
Michal Vasko60ea6352020-06-29 13:39:39 +0200202 break;
203 }
204
205 prev_meta = meta2;
206 }
207}
208
Michal Vasko61551fa2020-07-09 15:45:45 +0200209LY_ERR
210lyd_any_copy_value(struct lyd_node *trg, const union lyd_any_value *value, LYD_ANYDATA_VALUETYPE value_type)
211{
212 struct lyd_node_any *t;
213 int len;
214
215 assert(trg->schema->nodetype & LYS_ANYDATA);
216
217 t = (struct lyd_node_any *)trg;
218
219 /* free trg */
220 switch (t->value_type) {
221 case LYD_ANYDATA_DATATREE:
222 lyd_free_all(t->value.tree);
223 break;
224 case LYD_ANYDATA_STRING:
225 case LYD_ANYDATA_XML:
226 case LYD_ANYDATA_JSON:
227 FREE_STRING(LYD_NODE_CTX(trg), t->value.str);
228 break;
229 case LYD_ANYDATA_LYB:
230 free(t->value.mem);
231 break;
232 }
233 t->value.str = NULL;
234
235 if (!value) {
236 /* only free value in this case */
237 return LY_SUCCESS;
238 }
239
240 /* copy src */
241 t->value_type = value_type;
242 switch (value_type) {
243 case LYD_ANYDATA_DATATREE:
244 if (value->tree) {
Michal Vasko3a41dff2020-07-15 14:30:28 +0200245 LY_CHECK_RET(lyd_dup_siblings(value->tree, NULL, LYD_DUP_RECURSIVE, &t->value.tree));
Michal Vasko61551fa2020-07-09 15:45:45 +0200246 }
247 break;
248 case LYD_ANYDATA_STRING:
249 case LYD_ANYDATA_XML:
250 case LYD_ANYDATA_JSON:
251 if (value->str) {
252 t->value.str = lydict_insert(LYD_NODE_CTX(trg), value->str, 0);
253 }
254 break;
255 case LYD_ANYDATA_LYB:
256 if (value->mem) {
257 len = lyd_lyb_data_length(value->mem);
Radek Krejci82fa8d42020-07-11 22:00:59 +0200258 LY_CHECK_RET(len == -1, LY_EINVAL);
Michal Vasko61551fa2020-07-09 15:45:45 +0200259 t->value.mem = malloc(len);
260 LY_CHECK_ERR_RET(!t->value.mem, LOGMEM(LYD_NODE_CTX(trg)), LY_EMEM);
261 memcpy(t->value.mem, value->mem, len);
262 }
263 break;
264 }
265
266 return LY_SUCCESS;
267}
268
Michal Vasko60ea6352020-06-29 13:39:39 +0200269LYB_HASH
270lyb_hash(struct lysc_node *sibling, uint8_t collision_id)
271{
272 const struct lys_module *mod;
273 int ext_len;
274 uint32_t full_hash;
275 LYB_HASH hash;
276
277 if ((collision_id < LYS_NODE_HASH_COUNT) && sibling->hash[collision_id]) {
278 return sibling->hash[collision_id];
279 }
280
281 mod = sibling->module;
282
283 full_hash = dict_hash_multi(0, mod->name, strlen(mod->name));
284 full_hash = dict_hash_multi(full_hash, sibling->name, strlen(sibling->name));
285 if (collision_id) {
286 if (collision_id > strlen(mod->name)) {
287 /* fine, we will not hash more bytes, just use more bits from the hash than previously */
288 ext_len = strlen(mod->name);
289 } else {
290 /* use one more byte from the module name than before */
291 ext_len = collision_id;
292 }
293 full_hash = dict_hash_multi(full_hash, mod->name, ext_len);
294 }
295 full_hash = dict_hash_multi(full_hash, NULL, 0);
296
297 /* use the shortened hash */
298 hash = full_hash & (LYB_HASH_MASK >> collision_id);
299 /* add colision identificator */
300 hash |= LYB_HASH_COLLISION_ID >> collision_id;
301
302 /* save this hash */
303 if (collision_id < LYS_NODE_HASH_COUNT) {
304 sibling->hash[collision_id] = hash;
305 }
306
307 return hash;
308}
309
310int
311lyb_has_schema_model(const struct lysc_node *sibling, const struct lys_module **models)
312{
Michal Vaskofd69e1d2020-07-03 11:57:17 +0200313 LY_ARRAY_COUNT_TYPE u;
Michal Vasko60ea6352020-06-29 13:39:39 +0200314
315 LY_ARRAY_FOR(models, u) {
316 if (sibling->module == models[u]) {
317 return 1;
318 }
319 }
320
321 return 0;
322}