blob: cb2cb1f987f570eeb974a0764e99629c66335f05 [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>
18
Radek Krejci535ea9f2020-05-29 16:01:05 +020019#include "common.h"
20#include "context.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020021#include "log.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020022#include "tree.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020023#include "tree_data.h"
24#include "tree_schema.h"
25
26struct lyd_node **
27lyd_node_children_p(struct lyd_node *node)
28{
29 assert(node);
Michal Vasko52927e22020-03-16 17:26:14 +010030
31 if (!node->schema) {
32 return &((struct lyd_node_opaq *)node)->child;
33 } else {
34 switch (node->schema->nodetype) {
35 case LYS_CONTAINER:
36 case LYS_LIST:
Michal Vasko1bf09392020-03-27 12:38:10 +010037 case LYS_RPC:
Michal Vasko52927e22020-03-16 17:26:14 +010038 case LYS_ACTION:
39 case LYS_NOTIF:
40 return &((struct lyd_node_inner *)node)->child;
41 default:
42 return NULL;
43 }
Radek Krejcie7b95092019-05-15 11:03:07 +020044 }
45}
46
Radek Krejcidae0ee82020-05-06 16:53:24 +020047API struct lyd_node *
Michal Vasko5bfd4be2020-06-23 13:26:19 +020048lyd_node_children(const struct lyd_node *node, int options)
Radek Krejcie7b95092019-05-15 11:03:07 +020049{
Michal Vasko5bfd4be2020-06-23 13:26:19 +020050 struct lyd_node **children, *child;
Radek Krejcie7b95092019-05-15 11:03:07 +020051
52 if (!node) {
53 return NULL;
54 }
55
Michal Vasko5bfd4be2020-06-23 13:26:19 +020056 children = lyd_node_children_p((struct lyd_node *)node);
Radek Krejcie7b95092019-05-15 11:03:07 +020057 if (children) {
Michal Vasko5bfd4be2020-06-23 13:26:19 +020058 child = *children;
59 if (options & LYD_CHILDREN_SKIP_KEYS) {
Michal Vasko04091642020-06-29 11:50:14 +020060 while (child && child->schema && (child->schema->flags & LYS_KEY)) {
Michal Vasko5bfd4be2020-06-23 13:26:19 +020061 child = child->next;
62 }
63 }
64 return child;
Radek Krejcie7b95092019-05-15 11:03:07 +020065 } else {
66 return NULL;
67 }
68}
Michal Vasko9b368d32020-02-14 13:53:31 +010069
Michal Vaskoc193ce92020-03-06 11:04:48 +010070API const struct lys_module *
71lyd_owner_module(const struct lyd_node *node)
Michal Vasko9b368d32020-02-14 13:53:31 +010072{
73 const struct lysc_node *schema;
74
Michal Vasko52927e22020-03-16 17:26:14 +010075 if (!node || !node->schema) {
Michal Vaskoc193ce92020-03-06 11:04:48 +010076 return NULL;
77 }
Michal Vasko9b368d32020-02-14 13:53:31 +010078
79 for (schema = node->schema; schema->parent; schema = schema->parent);
80 return schema->module;
81}
Michal Vaskob1b5c262020-03-05 14:29:47 +010082
83const struct lys_module *
84lyd_mod_next_module(struct lyd_node *tree, const struct lys_module **modules, int mod_count, const struct ly_ctx *ctx,
85 uint32_t *i, struct lyd_node **first)
86{
87 struct lyd_node *iter;
88 const struct lys_module *mod;
89
90 /* get the next module */
91 if (modules && mod_count) {
92 if (*i < (unsigned)mod_count) {
93 mod = modules[(*i)++];
94 } else {
95 mod = NULL;
96 }
97 } else {
98 do {
99 mod = ly_ctx_get_module_iter(ctx, i);
100 } while (mod && !mod->implemented);
101 }
102
103 /* find its data */
104 *first = NULL;
105 if (mod) {
106 LY_LIST_FOR(tree, iter) {
Michal Vaskoc193ce92020-03-06 11:04:48 +0100107 if (lyd_owner_module(iter) == mod) {
Michal Vaskob1b5c262020-03-05 14:29:47 +0100108 *first = iter;
109 break;
110 }
111 }
112 }
113
114 return mod;
115}
116
117const struct lys_module *
118lyd_data_next_module(struct lyd_node **next, struct lyd_node **first)
119{
120 const struct lys_module *mod;
121
122 if (!*next) {
123 /* all data traversed */
124 *first = NULL;
125 return NULL;
126 }
127
128 *first = *next;
129
130 /* prepare next */
Michal Vaskoc193ce92020-03-06 11:04:48 +0100131 mod = lyd_owner_module(*next);
Michal Vaskob1b5c262020-03-05 14:29:47 +0100132 LY_LIST_FOR(*next, *next) {
Michal Vaskoc193ce92020-03-06 11:04:48 +0100133 if (lyd_owner_module(*next) != mod) {
Michal Vaskob1b5c262020-03-05 14:29:47 +0100134 break;
135 }
136 }
137
138 return mod;
139}
Michal Vasko9f96a052020-03-10 09:41:45 +0100140
141LY_ERR
142lyd_parse_check_keys(struct lyd_node *node)
143{
144 const struct lysc_node *skey = NULL;
145 const struct lyd_node *key;
146
147 assert(node->schema->nodetype == LYS_LIST);
148
Michal Vasko5bfd4be2020-06-23 13:26:19 +0200149 key = lyd_node_children(node, 0);
Michal Vasko9f96a052020-03-10 09:41:45 +0100150 while ((skey = lys_getnext(skey, node->schema, NULL, 0)) && (skey->flags & LYS_KEY)) {
151 if (!key || (key->schema != skey)) {
152 LOGVAL(node->schema->module->ctx, LY_VLOG_LYD, node, LY_VCODE_NOKEY, skey->name);
153 return LY_EVALID;
154 }
155
156 key = key->next;
157 }
158
159 return LY_SUCCESS;
160}