data tree FEATURE initial implementation of YANG data support
diff --git a/src/tree_data_helpers.c b/src/tree_data_helpers.c
new file mode 100644
index 0000000..fc4bf1c
--- /dev/null
+++ b/src/tree_data_helpers.c
@@ -0,0 +1,111 @@
+/**
+ * @file tree_data_helpers.c
+ * @author Radek Krejci <rkrejci@cesnet.cz>
+ * @brief Parsing and validation helper functions for data trees
+ *
+ * Copyright (c) 2015 - 2018 CESNET, z.s.p.o.
+ *
+ * This source code is licensed under BSD 3-Clause License (the "License").
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ */
+#include "common.h"
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include "log.h"
+#include "dict.h"
+#include "plugins_types.h"
+#include "tree_data.h"
+#include "tree_schema.h"
+
+struct lyd_node **
+lyd_node_children_p(struct lyd_node *node)
+{
+ assert(node);
+ switch (node->schema->nodetype) {
+ case LYS_CONTAINER:
+ case LYS_LIST:
+ return &((struct lyd_node_inner*)node)->child;
+ default:
+ return NULL;
+ }
+}
+
+API const struct lyd_node *
+lyd_node_children(const struct lyd_node *node)
+{
+ struct lyd_node **children;
+
+ if (!node) {
+ return NULL;
+ }
+
+ children = lyd_node_children_p((struct lyd_node*)node);
+ if (children) {
+ return *children;
+ } else {
+ return NULL;
+ }
+}
+
+LY_ERR
+lyd_parse_check_options(struct ly_ctx *ctx, int options, const char *func)
+{
+ int x = options & LYD_OPT_TYPEMASK;
+
+ /* LYD_OPT_WHENAUTODEL can be used only with LYD_OPT_DATA or LYD_OPT_CONFIG */
+ if (options & LYD_OPT_WHENAUTODEL) {
+ if ((x == LYD_OPT_EDIT) || (x == LYD_OPT_NOTIF_FILTER)) {
+ 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)",
+ func, options);
+ return LY_EINVAL;
+ }
+ }
+
+ if (options & (LYD_OPT_DATA_ADD_YANGLIB | LYD_OPT_DATA_NO_YANGLIB)) {
+ if (x != LYD_OPT_DATA) {
+ LOGERR(ctx, LY_EINVAL, "%s: Invalid options 0x%x (LYD_OPT_DATA_*_YANGLIB can be used only with LYD_OPT_DATA)",
+ func, options);
+ return LY_EINVAL;
+ }
+ }
+
+ /* "is power of 2" algorithm, with 0 exception */
+ if (x && !(x && !(x & (x - 1)))) {
+ LOGERR(ctx, LY_EINVAL, "%s: Invalid options 0x%x (multiple data type flags set).", func, options);
+ return LY_EINVAL;
+ }
+
+ return LY_SUCCESS;
+}
+
+LY_ERR
+lyd_value_validate(struct lyd_node_term *node, const char *value, size_t value_len, int options)
+{
+ LY_ERR ret = LY_SUCCESS;
+ struct ly_err_item *err = NULL;
+ struct ly_ctx *ctx;
+ struct lysc_type *type;
+
+ assert(node);
+
+ ctx = node->schema->module->ctx;
+ type = ((struct lysc_node_leaf*)node->schema)->type;
+ if (type->plugin->validate) {
+ ret = type->plugin->validate(ctx, type, value, value_len, options, &node->value.canonized, &err);
+ if (ret) {
+ ly_err_print(err);
+ LOGVAL(ctx, LY_VLOG_STR, err->path, err->vecode, err->msg);
+ ly_err_free(err);
+ }
+ } else if (options & LY_TYPE_VALIDATE_CANONIZE) {
+ node->value.canonized = lydict_insert(ctx, value, value_len);
+ }
+
+ return ret;
+}
+