blob: b30dd98405220639664297cde36f07a7608c8763 [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:
32 return &((struct lyd_node_inner*)node)->child;
33 default:
34 return NULL;
35 }
36}
37
38API const struct lyd_node *
39lyd_node_children(const struct lyd_node *node)
40{
41 struct lyd_node **children;
42
43 if (!node) {
44 return NULL;
45 }
46
47 children = lyd_node_children_p((struct lyd_node*)node);
48 if (children) {
49 return *children;
50 } else {
51 return NULL;
52 }
53}
54
55LY_ERR
56lyd_parse_check_options(struct ly_ctx *ctx, int options, const char *func)
57{
58 int x = options & LYD_OPT_TYPEMASK;
59
60 /* LYD_OPT_WHENAUTODEL can be used only with LYD_OPT_DATA or LYD_OPT_CONFIG */
61 if (options & LYD_OPT_WHENAUTODEL) {
62 if ((x == LYD_OPT_EDIT) || (x == LYD_OPT_NOTIF_FILTER)) {
63 LOGERR(ctx, LY_EINVAL, "%s: Invalid options 0x%x (LYD_OPT_DATA_WHENAUTODEL can be used only with LYD_OPT_DATA or LYD_OPT_CONFIG)",
64 func, options);
65 return LY_EINVAL;
66 }
67 }
68
69 if (options & (LYD_OPT_DATA_ADD_YANGLIB | LYD_OPT_DATA_NO_YANGLIB)) {
70 if (x != LYD_OPT_DATA) {
71 LOGERR(ctx, LY_EINVAL, "%s: Invalid options 0x%x (LYD_OPT_DATA_*_YANGLIB can be used only with LYD_OPT_DATA)",
72 func, options);
73 return LY_EINVAL;
74 }
75 }
76
77 /* "is power of 2" algorithm, with 0 exception */
78 if (x && !(x && !(x & (x - 1)))) {
79 LOGERR(ctx, LY_EINVAL, "%s: Invalid options 0x%x (multiple data type flags set).", func, options);
80 return LY_EINVAL;
81 }
82
83 return LY_SUCCESS;
84}
85
86LY_ERR
Radek Krejciaca74032019-06-04 08:53:06 +020087lyd_value_parse(struct lyd_node_term *node, const char *value, size_t value_len, int dynamic,
Radek Krejcie553e6d2019-06-07 15:33:18 +020088 ly_type_resolve_prefix get_prefix, void *parser, struct lyd_node **trees)
Radek Krejcie7b95092019-05-15 11:03:07 +020089{
Radek Krejcie553e6d2019-06-07 15:33:18 +020090 LY_ERR ret = LY_SUCCESS, rc;
Radek Krejcie7b95092019-05-15 11:03:07 +020091 struct ly_err_item *err = NULL;
92 struct ly_ctx *ctx;
93 struct lysc_type *type;
Radek Krejci51cddef2019-05-20 15:40:27 +020094 void *priv = NULL;
Radek Krejcie553e6d2019-06-07 15:33:18 +020095 int options = LY_TYPE_OPTS_VALIDATE | LY_TYPE_OPTS_CANONIZE | LY_TYPE_OPTS_STORE |
96 (dynamic ? LY_TYPE_OPTS_DYNAMIC : 0) | (trees ? 0 : LY_TYPE_OPTS_INCOMPLETE_DATA);
Radek Krejcie7b95092019-05-15 11:03:07 +020097 assert(node);
98
99 ctx = node->schema->module->ctx;
100 type = ((struct lysc_node_leaf*)node->schema)->type;
101 if (type->plugin->validate) {
Radek Krejcie553e6d2019-06-07 15:33:18 +0200102 rc = type->plugin->validate(ctx, type, value, value_len, options,
103 get_prefix, parser, (struct lyd_node*)node, trees,
104 &node->value.canonized, &err, &priv);
105 if (rc == LY_EINCOMPLETE) {
106 ret = rc;
107 /* continue with storing, just remember what to return if storing is ok */
108 } else if (rc) {
109 ret = rc;
110 if (err) {
111 ly_err_print(err);
112 LOGVAL(ctx, LY_VLOG_STR, err->path, err->vecode, err->msg);
113 ly_err_free(err);
114 }
Radek Krejci51cddef2019-05-20 15:40:27 +0200115 goto error;
Radek Krejcie7b95092019-05-15 11:03:07 +0200116 }
Radek Krejci5819f7c2019-05-31 14:53:29 +0200117 } else if (dynamic) {
118 node->value.canonized = lydict_insert_zc(ctx, (char*)value);
119 } else {
Radek Krejcie7b95092019-05-15 11:03:07 +0200120 node->value.canonized = lydict_insert(ctx, value, value_len);
121 }
122
Radek Krejci5819f7c2019-05-31 14:53:29 +0200123 if (type->plugin->store) {
Radek Krejcie553e6d2019-06-07 15:33:18 +0200124 rc = type->plugin->store(ctx, type, options, &node->value, &err, &priv);
125 if (rc) {
126 ret = rc;
127 if (err) {
128 ly_err_print(err);
129 LOGVAL(ctx, LY_VLOG_STR, err->path, err->vecode, err->msg);
130 ly_err_free(err);
131 }
Radek Krejci51cddef2019-05-20 15:40:27 +0200132 goto error;
133 }
134 }
135
136error:
Radek Krejcie7b95092019-05-15 11:03:07 +0200137 return ret;
138}
139