blob: fef80100f00c03b417fc55e667649065e6b880ee [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:
Michal Vasko1bf09392020-03-27 12:38:10 +010036 case LYS_RPC:
Michal Vasko52927e22020-03-16 17:26:14 +010037 case LYS_ACTION:
38 case LYS_NOTIF:
39 return &((struct lyd_node_inner *)node)->child;
40 default:
41 return NULL;
42 }
Radek Krejcie7b95092019-05-15 11:03:07 +020043 }
44}
45
Radek Krejcidae0ee82020-05-06 16:53:24 +020046API struct lyd_node *
Radek Krejcie7b95092019-05-15 11:03:07 +020047lyd_node_children(const struct lyd_node *node)
48{
49 struct lyd_node **children;
50
51 if (!node) {
52 return NULL;
53 }
54
55 children = lyd_node_children_p((struct lyd_node*)node);
56 if (children) {
57 return *children;
58 } else {
59 return NULL;
60 }
61}
Michal Vasko9b368d32020-02-14 13:53:31 +010062
Michal Vaskoc193ce92020-03-06 11:04:48 +010063API const struct lys_module *
64lyd_owner_module(const struct lyd_node *node)
Michal Vasko9b368d32020-02-14 13:53:31 +010065{
66 const struct lysc_node *schema;
67
Michal Vasko52927e22020-03-16 17:26:14 +010068 if (!node || !node->schema) {
Michal Vaskoc193ce92020-03-06 11:04:48 +010069 return NULL;
70 }
Michal Vasko9b368d32020-02-14 13:53:31 +010071
72 for (schema = node->schema; schema->parent; schema = schema->parent);
73 return schema->module;
74}
Michal Vaskob1b5c262020-03-05 14:29:47 +010075
76const struct lys_module *
77lyd_mod_next_module(struct lyd_node *tree, const struct lys_module **modules, int mod_count, const struct ly_ctx *ctx,
78 uint32_t *i, struct lyd_node **first)
79{
80 struct lyd_node *iter;
81 const struct lys_module *mod;
82
83 /* get the next module */
84 if (modules && mod_count) {
85 if (*i < (unsigned)mod_count) {
86 mod = modules[(*i)++];
87 } else {
88 mod = NULL;
89 }
90 } else {
91 do {
92 mod = ly_ctx_get_module_iter(ctx, i);
93 } while (mod && !mod->implemented);
94 }
95
96 /* find its data */
97 *first = NULL;
98 if (mod) {
99 LY_LIST_FOR(tree, iter) {
Michal Vaskoc193ce92020-03-06 11:04:48 +0100100 if (lyd_owner_module(iter) == mod) {
Michal Vaskob1b5c262020-03-05 14:29:47 +0100101 *first = iter;
102 break;
103 }
104 }
105 }
106
107 return mod;
108}
109
110const struct lys_module *
111lyd_data_next_module(struct lyd_node **next, struct lyd_node **first)
112{
113 const struct lys_module *mod;
114
115 if (!*next) {
116 /* all data traversed */
117 *first = NULL;
118 return NULL;
119 }
120
121 *first = *next;
122
123 /* prepare next */
Michal Vaskoc193ce92020-03-06 11:04:48 +0100124 mod = lyd_owner_module(*next);
Michal Vaskob1b5c262020-03-05 14:29:47 +0100125 LY_LIST_FOR(*next, *next) {
Michal Vaskoc193ce92020-03-06 11:04:48 +0100126 if (lyd_owner_module(*next) != mod) {
Michal Vaskob1b5c262020-03-05 14:29:47 +0100127 break;
128 }
129 }
130
131 return mod;
132}
Michal Vasko9f96a052020-03-10 09:41:45 +0100133
134LY_ERR
135lyd_parse_check_keys(struct lyd_node *node)
136{
137 const struct lysc_node *skey = NULL;
138 const struct lyd_node *key;
139
140 assert(node->schema->nodetype == LYS_LIST);
141
142 key = lyd_node_children(node);
143 while ((skey = lys_getnext(skey, node->schema, NULL, 0)) && (skey->flags & LYS_KEY)) {
144 if (!key || (key->schema != skey)) {
145 LOGVAL(node->schema->module->ctx, LY_VLOG_LYD, node, LY_VCODE_NOKEY, skey->name);
146 return LY_EVALID;
147 }
148
149 key = key->next;
150 }
151
152 return LY_SUCCESS;
153}