blob: 90f5736d8c4d5f450880c21611796777d3e96f99 [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);
29 switch (node->schema->nodetype) {
30 case LYS_CONTAINER:
31 case LYS_LIST:
Radek Krejci26a5dfb2019-07-26 14:51:06 +020032 case LYS_ACTION:
33 case LYS_NOTIF:
Radek Krejcie7b95092019-05-15 11:03:07 +020034 return &((struct lyd_node_inner*)node)->child;
35 default:
36 return NULL;
37 }
38}
39
40API const struct lyd_node *
41lyd_node_children(const struct lyd_node *node)
42{
43 struct lyd_node **children;
44
45 if (!node) {
46 return NULL;
47 }
48
49 children = lyd_node_children_p((struct lyd_node*)node);
50 if (children) {
51 return *children;
52 } else {
53 return NULL;
54 }
55}
Michal Vasko9b368d32020-02-14 13:53:31 +010056
Michal Vaskoc193ce92020-03-06 11:04:48 +010057API const struct lys_module *
58lyd_owner_module(const struct lyd_node *node)
Michal Vasko9b368d32020-02-14 13:53:31 +010059{
60 const struct lysc_node *schema;
61
Michal Vaskoc193ce92020-03-06 11:04:48 +010062 if (!node) {
63 return NULL;
64 }
Michal Vasko9b368d32020-02-14 13:53:31 +010065
66 for (schema = node->schema; schema->parent; schema = schema->parent);
67 return schema->module;
68}
Michal Vaskob1b5c262020-03-05 14:29:47 +010069
70const struct lys_module *
71lyd_mod_next_module(struct lyd_node *tree, const struct lys_module **modules, int mod_count, const struct ly_ctx *ctx,
72 uint32_t *i, struct lyd_node **first)
73{
74 struct lyd_node *iter;
75 const struct lys_module *mod;
76
77 /* get the next module */
78 if (modules && mod_count) {
79 if (*i < (unsigned)mod_count) {
80 mod = modules[(*i)++];
81 } else {
82 mod = NULL;
83 }
84 } else {
85 do {
86 mod = ly_ctx_get_module_iter(ctx, i);
87 } while (mod && !mod->implemented);
88 }
89
90 /* find its data */
91 *first = NULL;
92 if (mod) {
93 LY_LIST_FOR(tree, iter) {
Michal Vaskoc193ce92020-03-06 11:04:48 +010094 if (lyd_owner_module(iter) == mod) {
Michal Vaskob1b5c262020-03-05 14:29:47 +010095 *first = iter;
96 break;
97 }
98 }
99 }
100
101 return mod;
102}
103
104const struct lys_module *
105lyd_data_next_module(struct lyd_node **next, struct lyd_node **first)
106{
107 const struct lys_module *mod;
108
109 if (!*next) {
110 /* all data traversed */
111 *first = NULL;
112 return NULL;
113 }
114
115 *first = *next;
116
117 /* prepare next */
Michal Vaskoc193ce92020-03-06 11:04:48 +0100118 mod = lyd_owner_module(*next);
Michal Vaskob1b5c262020-03-05 14:29:47 +0100119 LY_LIST_FOR(*next, *next) {
Michal Vaskoc193ce92020-03-06 11:04:48 +0100120 if (lyd_owner_module(*next) != mod) {
Michal Vaskob1b5c262020-03-05 14:29:47 +0100121 break;
122 }
123 }
124
125 return mod;
126}
Michal Vasko9f96a052020-03-10 09:41:45 +0100127
128LY_ERR
129lyd_parse_check_keys(struct lyd_node *node)
130{
131 const struct lysc_node *skey = NULL;
132 const struct lyd_node *key;
133
134 assert(node->schema->nodetype == LYS_LIST);
135
136 key = lyd_node_children(node);
137 while ((skey = lys_getnext(skey, node->schema, NULL, 0)) && (skey->flags & LYS_KEY)) {
138 if (!key || (key->schema != skey)) {
139 LOGVAL(node->schema->module->ctx, LY_VLOG_LYD, node, LY_VCODE_NOKEY, skey->name);
140 return LY_EVALID;
141 }
142
143 key = key->next;
144 }
145
146 return LY_SUCCESS;
147}