blob: e3a090baa5ea2c457292e6387c6b0ffe9fc02373 [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
Michal Vaskoa6669ba2020-08-06 16:14:26 +020032struct lyd_node *
33lys_getnext_data(const struct lyd_node *last, const struct lyd_node *sibling, const struct lysc_node **slast,
34 const struct lysc_node *parent, const struct lysc_module *module)
35{
36 const struct lysc_node *siter = NULL;
37 struct lyd_node *match = NULL;
38
39 assert(parent || module);
40 assert(!last || (slast && *slast));
41
42 if (slast) {
43 siter = *slast;
44 }
45
46 if (last && last->next && (last->next->schema == siter)) {
47 /* return next data instance */
48 return last->next;
49 }
50
51 /* find next schema node data instance */
52 while ((siter = lys_getnext(siter, parent, module, 0))) {
53 if (!lyd_find_sibling_val(sibling, siter, NULL, 0, &match)) {
54 break;
55 }
56 }
57
58 if (slast) {
59 *slast = siter;
60 }
61 return match;
62}
63
Radek Krejcie7b95092019-05-15 11:03:07 +020064struct lyd_node **
65lyd_node_children_p(struct lyd_node *node)
66{
67 assert(node);
Michal Vasko52927e22020-03-16 17:26:14 +010068
69 if (!node->schema) {
70 return &((struct lyd_node_opaq *)node)->child;
71 } else {
72 switch (node->schema->nodetype) {
73 case LYS_CONTAINER:
74 case LYS_LIST:
Michal Vasko1bf09392020-03-27 12:38:10 +010075 case LYS_RPC:
Michal Vasko52927e22020-03-16 17:26:14 +010076 case LYS_ACTION:
77 case LYS_NOTIF:
78 return &((struct lyd_node_inner *)node)->child;
79 default:
80 return NULL;
81 }
Radek Krejcie7b95092019-05-15 11:03:07 +020082 }
83}
84
Radek Krejcidae0ee82020-05-06 16:53:24 +020085API struct lyd_node *
Michal Vasko5bfd4be2020-06-23 13:26:19 +020086lyd_node_children(const struct lyd_node *node, int options)
Radek Krejcie7b95092019-05-15 11:03:07 +020087{
Michal Vasko5bfd4be2020-06-23 13:26:19 +020088 struct lyd_node **children, *child;
Radek Krejcie7b95092019-05-15 11:03:07 +020089
90 if (!node) {
91 return NULL;
92 }
93
Michal Vasko5bfd4be2020-06-23 13:26:19 +020094 children = lyd_node_children_p((struct lyd_node *)node);
Radek Krejcie7b95092019-05-15 11:03:07 +020095 if (children) {
Michal Vasko5bfd4be2020-06-23 13:26:19 +020096 child = *children;
97 if (options & LYD_CHILDREN_SKIP_KEYS) {
Michal Vasko04091642020-06-29 11:50:14 +020098 while (child && child->schema && (child->schema->flags & LYS_KEY)) {
Michal Vasko5bfd4be2020-06-23 13:26:19 +020099 child = child->next;
100 }
101 }
102 return child;
Radek Krejcie7b95092019-05-15 11:03:07 +0200103 } else {
104 return NULL;
105 }
106}
Michal Vasko9b368d32020-02-14 13:53:31 +0100107
Michal Vaskoc193ce92020-03-06 11:04:48 +0100108API const struct lys_module *
109lyd_owner_module(const struct lyd_node *node)
Michal Vasko9b368d32020-02-14 13:53:31 +0100110{
111 const struct lysc_node *schema;
112
Michal Vasko52927e22020-03-16 17:26:14 +0100113 if (!node || !node->schema) {
Michal Vaskoc193ce92020-03-06 11:04:48 +0100114 return NULL;
115 }
Michal Vasko9b368d32020-02-14 13:53:31 +0100116
117 for (schema = node->schema; schema->parent; schema = schema->parent);
118 return schema->module;
119}
Michal Vaskob1b5c262020-03-05 14:29:47 +0100120
121const struct lys_module *
Michal Vasko26e80012020-07-08 10:55:46 +0200122lyd_mod_next_module(struct lyd_node *tree, const struct lys_module *module, const struct ly_ctx *ctx, uint32_t *i,
123 struct lyd_node **first)
Michal Vaskob1b5c262020-03-05 14:29:47 +0100124{
125 struct lyd_node *iter;
126 const struct lys_module *mod;
127
128 /* get the next module */
Michal Vasko26e80012020-07-08 10:55:46 +0200129 if (module) {
130 if (*i) {
Michal Vaskob1b5c262020-03-05 14:29:47 +0100131 mod = NULL;
Michal Vasko26e80012020-07-08 10:55:46 +0200132 } else {
133 mod = module;
134 ++(*i);
Michal Vaskob1b5c262020-03-05 14:29:47 +0100135 }
136 } else {
137 do {
138 mod = ly_ctx_get_module_iter(ctx, i);
139 } while (mod && !mod->implemented);
140 }
141
142 /* find its data */
143 *first = NULL;
144 if (mod) {
145 LY_LIST_FOR(tree, iter) {
Michal Vaskoc193ce92020-03-06 11:04:48 +0100146 if (lyd_owner_module(iter) == mod) {
Michal Vaskob1b5c262020-03-05 14:29:47 +0100147 *first = iter;
148 break;
149 }
150 }
151 }
152
153 return mod;
154}
155
156const struct lys_module *
157lyd_data_next_module(struct lyd_node **next, struct lyd_node **first)
158{
159 const struct lys_module *mod;
160
161 if (!*next) {
162 /* all data traversed */
163 *first = NULL;
164 return NULL;
165 }
166
167 *first = *next;
168
169 /* prepare next */
Michal Vaskoc193ce92020-03-06 11:04:48 +0100170 mod = lyd_owner_module(*next);
Michal Vaskob1b5c262020-03-05 14:29:47 +0100171 LY_LIST_FOR(*next, *next) {
Michal Vaskoc193ce92020-03-06 11:04:48 +0100172 if (lyd_owner_module(*next) != mod) {
Michal Vaskob1b5c262020-03-05 14:29:47 +0100173 break;
174 }
175 }
176
177 return mod;
178}
Michal Vasko9f96a052020-03-10 09:41:45 +0100179
180LY_ERR
181lyd_parse_check_keys(struct lyd_node *node)
182{
183 const struct lysc_node *skey = NULL;
184 const struct lyd_node *key;
185
186 assert(node->schema->nodetype == LYS_LIST);
187
Michal Vasko5bfd4be2020-06-23 13:26:19 +0200188 key = lyd_node_children(node, 0);
Michal Vasko9f96a052020-03-10 09:41:45 +0100189 while ((skey = lys_getnext(skey, node->schema, NULL, 0)) && (skey->flags & LYS_KEY)) {
190 if (!key || (key->schema != skey)) {
Michal Vaskob7be7a82020-08-20 09:09:04 +0200191 LOGVAL(LYD_CTX(node), LY_VLOG_LYD, node, LY_VCODE_NOKEY, skey->name);
Michal Vasko9f96a052020-03-10 09:41:45 +0100192 return LY_EVALID;
193 }
194
195 key = key->next;
196 }
197
198 return LY_SUCCESS;
199}
Michal Vasko60ea6352020-06-29 13:39:39 +0200200
201void
202lyd_parse_set_data_flags(struct lyd_node *node, struct ly_set *when_check, struct lyd_meta **meta, int options)
203{
204 struct lyd_meta *meta2, *prev_meta = NULL;
205
206 if (!(node->schema->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)) && node->schema->when) {
Radek Krejci7931b192020-06-25 17:05:03 +0200207 if (options & LYD_PARSE_TRUSTED) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200208 /* just set it to true */
209 node->flags |= LYD_WHEN_TRUE;
210 } else {
211 /* remember we need to evaluate this node's when */
212 ly_set_add(when_check, node, LY_SET_OPT_USEASLIST);
213 }
214 }
215
Radek Krejci7931b192020-06-25 17:05:03 +0200216 if (options & LYD_PARSE_TRUSTED) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200217 /* node is valid */
218 node->flags &= ~LYD_NEW;
219 }
220
221 LY_LIST_FOR(*meta, meta2) {
222 if (!strcmp(meta2->name, "default") && !strcmp(meta2->annotation->module->name, "ietf-netconf-with-defaults")
223 && meta2->value.boolean) {
224 /* node is default according to the metadata */
225 node->flags |= LYD_DEFAULT;
226
227 /* delete the metadata */
228 if (prev_meta) {
229 prev_meta->next = meta2->next;
230 } else {
231 *meta = (*meta)->next;
232 }
Michal Vasko3a41dff2020-07-15 14:30:28 +0200233 lyd_free_meta_single(meta2);
Michal Vasko60ea6352020-06-29 13:39:39 +0200234 break;
235 }
236
237 prev_meta = meta2;
238 }
239}
240
Michal Vaskoc0004272020-08-06 08:32:34 +0200241API LY_ERR
Michal Vasko61551fa2020-07-09 15:45:45 +0200242lyd_any_copy_value(struct lyd_node *trg, const union lyd_any_value *value, LYD_ANYDATA_VALUETYPE value_type)
243{
244 struct lyd_node_any *t;
245 int len;
246
247 assert(trg->schema->nodetype & LYS_ANYDATA);
248
249 t = (struct lyd_node_any *)trg;
250
251 /* free trg */
252 switch (t->value_type) {
253 case LYD_ANYDATA_DATATREE:
254 lyd_free_all(t->value.tree);
255 break;
256 case LYD_ANYDATA_STRING:
257 case LYD_ANYDATA_XML:
258 case LYD_ANYDATA_JSON:
Michal Vaskob7be7a82020-08-20 09:09:04 +0200259 FREE_STRING(LYD_CTX(trg), t->value.str);
Michal Vasko61551fa2020-07-09 15:45:45 +0200260 break;
261 case LYD_ANYDATA_LYB:
262 free(t->value.mem);
263 break;
264 }
265 t->value.str = NULL;
266
267 if (!value) {
268 /* only free value in this case */
269 return LY_SUCCESS;
270 }
271
272 /* copy src */
273 t->value_type = value_type;
274 switch (value_type) {
275 case LYD_ANYDATA_DATATREE:
276 if (value->tree) {
Michal Vasko3a41dff2020-07-15 14:30:28 +0200277 LY_CHECK_RET(lyd_dup_siblings(value->tree, NULL, LYD_DUP_RECURSIVE, &t->value.tree));
Michal Vasko61551fa2020-07-09 15:45:45 +0200278 }
279 break;
280 case LYD_ANYDATA_STRING:
281 case LYD_ANYDATA_XML:
282 case LYD_ANYDATA_JSON:
283 if (value->str) {
Michal Vaskob7be7a82020-08-20 09:09:04 +0200284 t->value.str = lydict_insert(LYD_CTX(trg), value->str, 0);
Michal Vasko61551fa2020-07-09 15:45:45 +0200285 }
286 break;
287 case LYD_ANYDATA_LYB:
288 if (value->mem) {
289 len = lyd_lyb_data_length(value->mem);
Radek Krejci82fa8d42020-07-11 22:00:59 +0200290 LY_CHECK_RET(len == -1, LY_EINVAL);
Michal Vasko61551fa2020-07-09 15:45:45 +0200291 t->value.mem = malloc(len);
Michal Vaskob7be7a82020-08-20 09:09:04 +0200292 LY_CHECK_ERR_RET(!t->value.mem, LOGMEM(LYD_CTX(trg)), LY_EMEM);
Michal Vasko61551fa2020-07-09 15:45:45 +0200293 memcpy(t->value.mem, value->mem, len);
294 }
295 break;
296 }
297
298 return LY_SUCCESS;
299}
300
Michal Vasko60ea6352020-06-29 13:39:39 +0200301LYB_HASH
302lyb_hash(struct lysc_node *sibling, uint8_t collision_id)
303{
304 const struct lys_module *mod;
305 int ext_len;
306 uint32_t full_hash;
307 LYB_HASH hash;
308
309 if ((collision_id < LYS_NODE_HASH_COUNT) && sibling->hash[collision_id]) {
310 return sibling->hash[collision_id];
311 }
312
313 mod = sibling->module;
314
315 full_hash = dict_hash_multi(0, mod->name, strlen(mod->name));
316 full_hash = dict_hash_multi(full_hash, sibling->name, strlen(sibling->name));
317 if (collision_id) {
318 if (collision_id > strlen(mod->name)) {
319 /* fine, we will not hash more bytes, just use more bits from the hash than previously */
320 ext_len = strlen(mod->name);
321 } else {
322 /* use one more byte from the module name than before */
323 ext_len = collision_id;
324 }
325 full_hash = dict_hash_multi(full_hash, mod->name, ext_len);
326 }
327 full_hash = dict_hash_multi(full_hash, NULL, 0);
328
329 /* use the shortened hash */
330 hash = full_hash & (LYB_HASH_MASK >> collision_id);
331 /* add colision identificator */
332 hash |= LYB_HASH_COLLISION_ID >> collision_id;
333
334 /* save this hash */
335 if (collision_id < LYS_NODE_HASH_COUNT) {
336 sibling->hash[collision_id] = hash;
337 }
338
339 return hash;
340}
341
342int
343lyb_has_schema_model(const struct lysc_node *sibling, const struct lys_module **models)
344{
Michal Vaskofd69e1d2020-07-03 11:57:17 +0200345 LY_ARRAY_COUNT_TYPE u;
Michal Vasko60ea6352020-06-29 13:39:39 +0200346
347 LY_ARRAY_FOR(models, u) {
348 if (sibling->module == models[u]) {
349 return 1;
350 }
351 }
352
353 return 0;
354}