blob: 798f2380a759dbf011bcdca13022b277f8527f6b [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 *
Radek Krejcie7b95092019-05-15 11:03:07 +020048lyd_node_children(const struct lyd_node *node)
49{
50 struct lyd_node **children;
51
52 if (!node) {
53 return NULL;
54 }
55
56 children = lyd_node_children_p((struct lyd_node*)node);
57 if (children) {
58 return *children;
59 } else {
60 return NULL;
61 }
62}
Michal Vasko9b368d32020-02-14 13:53:31 +010063
Michal Vaskoc193ce92020-03-06 11:04:48 +010064API const struct lys_module *
65lyd_owner_module(const struct lyd_node *node)
Michal Vasko9b368d32020-02-14 13:53:31 +010066{
67 const struct lysc_node *schema;
68
Michal Vasko52927e22020-03-16 17:26:14 +010069 if (!node || !node->schema) {
Michal Vaskoc193ce92020-03-06 11:04:48 +010070 return NULL;
71 }
Michal Vasko9b368d32020-02-14 13:53:31 +010072
73 for (schema = node->schema; schema->parent; schema = schema->parent);
74 return schema->module;
75}
Michal Vaskob1b5c262020-03-05 14:29:47 +010076
77const struct lys_module *
78lyd_mod_next_module(struct lyd_node *tree, const struct lys_module **modules, int mod_count, const struct ly_ctx *ctx,
79 uint32_t *i, struct lyd_node **first)
80{
81 struct lyd_node *iter;
82 const struct lys_module *mod;
83
84 /* get the next module */
85 if (modules && mod_count) {
86 if (*i < (unsigned)mod_count) {
87 mod = modules[(*i)++];
88 } else {
89 mod = NULL;
90 }
91 } else {
92 do {
93 mod = ly_ctx_get_module_iter(ctx, i);
94 } while (mod && !mod->implemented);
95 }
96
97 /* find its data */
98 *first = NULL;
99 if (mod) {
100 LY_LIST_FOR(tree, iter) {
Michal Vaskoc193ce92020-03-06 11:04:48 +0100101 if (lyd_owner_module(iter) == mod) {
Michal Vaskob1b5c262020-03-05 14:29:47 +0100102 *first = iter;
103 break;
104 }
105 }
106 }
107
108 return mod;
109}
110
111const struct lys_module *
112lyd_data_next_module(struct lyd_node **next, struct lyd_node **first)
113{
114 const struct lys_module *mod;
115
116 if (!*next) {
117 /* all data traversed */
118 *first = NULL;
119 return NULL;
120 }
121
122 *first = *next;
123
124 /* prepare next */
Michal Vaskoc193ce92020-03-06 11:04:48 +0100125 mod = lyd_owner_module(*next);
Michal Vaskob1b5c262020-03-05 14:29:47 +0100126 LY_LIST_FOR(*next, *next) {
Michal Vaskoc193ce92020-03-06 11:04:48 +0100127 if (lyd_owner_module(*next) != mod) {
Michal Vaskob1b5c262020-03-05 14:29:47 +0100128 break;
129 }
130 }
131
132 return mod;
133}
Michal Vasko9f96a052020-03-10 09:41:45 +0100134
135LY_ERR
136lyd_parse_check_keys(struct lyd_node *node)
137{
138 const struct lysc_node *skey = NULL;
139 const struct lyd_node *key;
140
141 assert(node->schema->nodetype == LYS_LIST);
142
143 key = lyd_node_children(node);
144 while ((skey = lys_getnext(skey, node->schema, NULL, 0)) && (skey->flags & LYS_KEY)) {
145 if (!key || (key->schema != skey)) {
146 LOGVAL(node->schema->module->ctx, LY_VLOG_LYD, node, LY_VCODE_NOKEY, skey->name);
147 return LY_EVALID;
148 }
149
150 key = key->next;
151 }
152
153 return LY_SUCCESS;
154}