summaryrefslogtreecommitdiff
path: root/lib/yang.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/yang.c')
-rw-r--r--lib/yang.c156
1 files changed, 129 insertions, 27 deletions
diff --git a/lib/yang.c b/lib/yang.c
index 131d89cdfa..18d2ac58d3 100644
--- a/lib/yang.c
+++ b/lib/yang.c
@@ -6,6 +6,7 @@
#include <zebra.h>
+#include "darr.h"
#include "log.h"
#include "lib_errors.h"
#include "yang.h"
@@ -363,33 +364,10 @@ unsigned int yang_snode_num_keys(const struct lysc_node *snode)
return count;
}
-void yang_dnode_get_path(const struct lyd_node *dnode, char *xpath,
- size_t xpath_len)
-{
- lyd_path(dnode, LYD_PATH_STD, xpath, xpath_len);
-}
-
-const char *yang_dnode_get_schema_name(const struct lyd_node *dnode,
- const char *xpath_fmt, ...)
+char *yang_dnode_get_path(const struct lyd_node *dnode, char *xpath,
+ size_t xpath_len)
{
- if (xpath_fmt) {
- va_list ap;
- char xpath[XPATH_MAXLEN];
-
- va_start(ap, xpath_fmt);
- vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap);
- va_end(ap);
-
- dnode = yang_dnode_get(dnode, xpath);
- if (!dnode) {
- flog_err(EC_LIB_YANG_DNODE_NOT_FOUND,
- "%s: couldn't find %s", __func__, xpath);
- zlog_backtrace(LOG_ERR);
- abort();
- }
- }
-
- return dnode->schema->name;
+ return lyd_path(dnode, LYD_PATH_STD, xpath, xpath_len);
}
struct lyd_node *yang_dnode_get(const struct lyd_node *dnode, const char *xpath)
@@ -673,6 +651,37 @@ static void ly_log_cb(LY_LOG_LEVEL level, const char *msg, const char *path)
zlog(priority, "libyang: %s", msg);
}
+static ssize_t yang_print_darr(void *arg, const void *buf, size_t count)
+{
+ uint8_t *dst = darr_append_n(*(uint8_t **)arg, count);
+
+ memcpy(dst, buf, count);
+ return count;
+}
+
+LY_ERR yang_print_tree_append(uint8_t **darr, const struct lyd_node *root,
+ LYD_FORMAT format, uint32_t options)
+{
+ LY_ERR err;
+
+ err = lyd_print_clb(yang_print_darr, darr, root, format, options);
+ if (err)
+ zlog_err("Failed to save yang tree: %s", ly_last_errmsg());
+ else if (format != LYD_LYB)
+ *darr_append(*darr) = 0;
+ return err;
+}
+
+uint8_t *yang_print_tree(const struct lyd_node *root, LYD_FORMAT format,
+ uint32_t options)
+{
+ uint8_t *darr = NULL;
+
+ if (yang_print_tree_append(&darr, root, format, options))
+ return NULL;
+ return darr;
+}
+
const char *yang_print_errors(struct ly_ctx *ly_ctx, char *buf, size_t buf_len)
{
struct ly_err_item *ei;
@@ -713,6 +722,7 @@ struct ly_ctx *yang_ctx_new_setup(bool embedded_modules, bool explicit_compile)
{
struct ly_ctx *ctx = NULL;
const char *yang_models_path = YANG_MODELS_PATH;
+ uint options;
LY_ERR err;
if (access(yang_models_path, R_OK | X_OK)) {
@@ -726,7 +736,7 @@ struct ly_ctx *yang_ctx_new_setup(bool embedded_modules, bool explicit_compile)
YANG_MODELS_PATH);
}
- uint options = LY_CTX_NO_YANGLIBRARY | LY_CTX_DISABLE_SEARCHDIR_CWD;
+ options = LY_CTX_NO_YANGLIBRARY | LY_CTX_DISABLE_SEARCHDIR_CWD;
if (explicit_compile)
options |= LY_CTX_EXPLICIT_COMPILE;
err = ly_ctx_new(yang_models_path, options, &ctx);
@@ -917,3 +927,95 @@ uint32_t yang_get_list_elements_count(const struct lyd_node *node)
} while (node);
return count;
}
+
+int yang_get_key_preds(char *s, const struct lysc_node *snode,
+ struct yang_list_keys *keys, ssize_t space)
+{
+ const struct lysc_node_leaf *skey;
+ ssize_t len2, len = 0;
+ ssize_t i = 0;
+
+ LY_FOR_KEYS (snode, skey) {
+ assert(i < keys->num);
+ len2 = snprintf(s + len, space - len, "[%s='%s']", skey->name,
+ keys->key[i]);
+ if (len2 > space - len)
+ len = space;
+ else
+ len += len2;
+ i++;
+ }
+
+ assert(i == keys->num);
+ return i;
+}
+
+int yang_get_node_keys(struct lyd_node *node, struct yang_list_keys *keys)
+{
+ struct lyd_node *child = lyd_child(node);
+
+ keys->num = 0;
+ for (; child && lysc_is_key(child->schema); child = child->next) {
+ const char *value = lyd_get_value(child);
+
+ if (!value)
+ return NB_ERR;
+ strlcpy(keys->key[keys->num], value,
+ sizeof(keys->key[keys->num]));
+ keys->num++;
+ }
+ return NB_OK;
+}
+
+LY_ERR yang_lyd_new_list(struct lyd_node_inner *parent,
+ const struct lysc_node *snode,
+ const struct yang_list_keys *list_keys,
+ struct lyd_node_inner **node)
+{
+ struct lyd_node *pnode = &parent->node;
+ struct lyd_node **nodepp = (struct lyd_node **)node;
+ const char(*keys)[LIST_MAXKEYLEN] = list_keys->key;
+
+ /*
+ * When
+ * https://github.com/CESNET/libyang/commit/2c1e327c7c2dd3ba12d466a4ebcf62c1c44116c4
+ * is released in libyang we should add a configure.ac check for the
+ * lyd_new_list3 function and use it here.
+ */
+ switch (list_keys->num) {
+ case 0:
+ return lyd_new_list(pnode, snode->module, snode->name, false,
+ nodepp);
+ case 1:
+ return lyd_new_list(pnode, snode->module, snode->name, false,
+ nodepp, keys[0]);
+ case 2:
+ return lyd_new_list(pnode, snode->module, snode->name, false,
+ nodepp, keys[0], keys[1]);
+ case 3:
+ return lyd_new_list(pnode, snode->module, snode->name, false,
+ nodepp, keys[0], keys[1], keys[2]);
+ case 4:
+ return lyd_new_list(pnode, snode->module, snode->name, false,
+ nodepp, keys[0], keys[1], keys[2], keys[3]);
+ case 5:
+ return lyd_new_list(pnode, snode->module, snode->name, false,
+ nodepp, keys[0], keys[1], keys[2], keys[3],
+ keys[4]);
+ case 6:
+ return lyd_new_list(pnode, snode->module, snode->name, false,
+ nodepp, keys[0], keys[1], keys[2], keys[3],
+ keys[4], keys[5]);
+ case 7:
+ return lyd_new_list(pnode, snode->module, snode->name, false,
+ nodepp, keys[0], keys[1], keys[2], keys[3],
+ keys[4], keys[5], keys[6]);
+ case 8:
+ return lyd_new_list(pnode, snode->module, snode->name, false,
+ nodepp, keys[0], keys[1], keys[2], keys[3],
+ keys[4], keys[5], keys[6], keys[7]);
+ }
+ _Static_assert(LIST_MAXKEYS == 8, "max key mismatch in switch unroll");
+ /*NOTREACHED*/
+ return LY_EINVAL;
+}