Revert "REVERT to version 0.2.55."
This reverts commit a5835e9bb0a9a958f6e6a2c871acc5b16158f16d.
Conflicts:
CMakeLists.txt
src/resolve.c
src/tree_schema.c
diff --git a/src/common.h b/src/common.h
index 41e3c1f..cb09fec 100644
--- a/src/common.h
+++ b/src/common.h
@@ -99,8 +99,8 @@
LYE_ENUM_WS,
LYE_BITS_DUPVAL,
LYE_BITS_DUPNAME,
- LYE_INPREF,
- LYE_INPREF_LEN,
+ LYE_INMOD,
+ LYE_INMOD_LEN,
LYE_KEY_NLEAF,
LYE_KEY_TYPE,
LYE_KEY_CONFIG,
@@ -165,7 +165,7 @@
* correcting theit ref_count -> do not touch them. Prefixes of
* the namespaces are import prefixes of the modules. Output
* parameters are optional, but either all 3 are set or none
- * of them is. Logs directly.
+ * of them are. Logs directly.
*
* @param[in] module Module with imports to use.
* @param[in] expr JSON expression.
diff --git a/src/log.c b/src/log.c
index 77ff9b5..9321194 100644
--- a/src/log.c
+++ b/src/log.c
@@ -78,8 +78,8 @@
/* LYE_ENUM_WS */ "The enum name \"%s\" includes invalid leading or trailing whitespaces.",
/* LYE_BITS_DUPVAL */ "The position \"%d\" of \"%s\" bits has already been used to another named bit.",
/* LYE_BITS_DUPNAME */ "The bit name \"%s\" has already been assigned to another bit.",
-/* LYE_INPREF */ "Prefix in \"%s\" refers to an unknown module.",
-/* LYE_INPREF_LEN */ "Prefix \"%.*s\" refers to an unknown module.",
+/* LYE_INMOD */ "Module name in \"%s\" refers to an unknown module.",
+/* LYE_INMOD_LEN */ "Module name \"%.*s\" refers to an unknown module.",
/* LYE_KEY_NLEAF */ "Key \"%s\" is not a leaf.",
/* LYE_KEY_TYPE */ "Key \"%s\" must not be the built-in type \"empty\".",
/* LYE_KEY_CONFIG */ "The \"config\" value of the \"%s\" key differs from its list config value.",
diff --git a/src/parser.c b/src/parser.c
index 3248879..b08a7fc 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -590,7 +590,11 @@
if (!strcmp(node->value_str, "true")) {
node->value.bool = 1;
- } /* else false, so keep it zero */
+ } else if (strcmp(node->value_str, "false")) {
+ LOGVAL(LYE_INVAL, line, node->value_str, node->schema->name);
+ return EXIT_FAILURE;
+ }
+ /* else stays 0 */
break;
case LY_TYPE_DEC64:
diff --git a/src/parser_yin.c b/src/parser_yin.c
index 5ea60f1..28e14e7 100644
--- a/src/parser_yin.c
+++ b/src/parser_yin.c
@@ -466,7 +466,7 @@
struct unres_schema *unres)
{
#define REGEX_ERR_LEN 128
- const char *value, *delim, *name, *err_ptr;
+ const char *value, *name, *err_ptr;
struct lyxml_elem *next, *node;
struct lys_restr **restr;
struct lys_type_bit bit;
@@ -476,17 +476,15 @@
int64_t p, p_;
GETVAL(value, yin, "name");
-
- delim = strchr(value, ':');
- if (delim) {
- type->prefix = lydict_insert(module->ctx, value, delim - value);
- delim++;
- value += delim-value;
+ value = transform_expr_xml2json(module->ctx, value, yin, 1);
+ if (!value) {
+ goto error;
}
+ type->module_name = value;
- rc = resolve_superior_type(value, type->prefix, module, parent, &type->der);
+ rc = resolve_superior_type(value, type->module_name, module, parent, &type->der);
if (rc == -1) {
- LOGVAL(LYE_INPREF, LOGLINE(yin), type->prefix);
+ LOGVAL(LYE_INMOD, LOGLINE(yin), type->module_name);
goto error;
} else if (rc == EXIT_FAILURE) {
/* HACK for unres */
@@ -924,7 +922,11 @@
}
GETVAL(value, node, "value");
- type->info.lref.path = lydict_insert(module->ctx, value, 0);
+ /* store in the JSON format */
+ type->info.lref.path = transform_expr_xml2json(module->ctx, value, node, 1);
+ if (!type->info.lref.path) {
+ goto error;
+ }
if (unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent, LOGLINE(yin)) == -1) {
goto error;
}
diff --git a/src/printer_info.c b/src/printer_info.c
index 01e30df..5ec0f7c 100644
--- a/src/printer_info.c
+++ b/src/printer_info.c
@@ -395,8 +395,8 @@
}
ly_print(out, "%-*s", INDENT_LEN, "Superior: ");
if (type->der) {
- if (type->prefix) {
- ly_print(out, "%s:", type->prefix);
+ if (type->module_name) {
+ ly_print(out, "%s:", type->module_name);
}
ly_print(out, "%s\n", type->der->name);
} else {
diff --git a/src/printer_tree.c b/src/printer_tree.c
index 6947593..aa2dc0a 100644
--- a/src/printer_tree.c
+++ b/src/printer_tree.c
@@ -178,8 +178,8 @@
{
if ((type->base == LY_TYPE_LEAFREF) && !type->der->module) {
ly_print(out, "-> %s", type->info.lref.path);
- } else if (type->prefix) {
- ly_print(out, "%s:%s", type->prefix, type->der->name);
+ } else if (type->module_name) {
+ ly_print(out, "%s:%s", type->module_name, type->der->name);
} else {
ly_print(out, "%s", type->der->name);
}
diff --git a/src/printer_yang.c b/src/printer_yang.c
index 09a56b7..6e413ff 100644
--- a/src/printer_yang.c
+++ b/src/printer_yang.c
@@ -236,9 +236,12 @@
yang_print_type(struct lyout *out, int level, struct lys_module *module, struct lys_type *type)
{
int i;
+ const char *str;
- if (type->prefix) {
- ly_print(out, "%*stype %s:%s {\n", LEVEL, INDENT, type->prefix, type->der->name);
+ if (type->module_name) {
+ str = transform_expr_json2xml(module, type->module_name, NULL, NULL, NULL);
+ ly_print(out, "%*stype %s:%s {\n", LEVEL, INDENT, str, type->der->name);
+ lydict_remove(module->ctx, str);
} else {
ly_print(out, "%*stype %s {\n", LEVEL, INDENT, type->der->name);
}
@@ -309,7 +312,9 @@
}
break;
case LY_TYPE_LEAFREF:
- ly_print(out, "%*spath \"%s\";\n", LEVEL, INDENT, type->info.lref.path);
+ str = transform_expr_json2xml(module, type->info.lref.path, NULL, NULL, NULL);
+ ly_print(out, "%*spath \"%s\";\n", LEVEL, INDENT, str);
+ lydict_remove(module->ctx, str);
break;
case LY_TYPE_STRING:
if (type->info.str.length) {
diff --git a/src/resolve.c b/src/resolve.c
index 778a09b..ad2070a 100644
--- a/src/resolve.c
+++ b/src/resolve.c
@@ -31,6 +31,7 @@
#include "resolve.h"
#include "common.h"
#include "xpath.h"
+#include "parser.h"
#include "dict_private.h"
#include "tree_internal.h"
@@ -1259,22 +1260,22 @@
* @brief Resolve a typedef. Does not log.
*
* @param[in] name Typedef name.
- * @param[in] prefix Typedef name prefix.
- * @param[in] module The main module.
- * @param[in] parent The parent of the resolved type definition.
+ * @param[in] mod_name Typedef name module name.
+ * @param[in] module Main module.
+ * @param[in] parent Parent of the resolved type definition.
* @param[out] ret Pointer to the resolved typedef. Can be NULL.
*
* @return EXIT_SUCCESS on success, EXIT_FAILURE on forward reference, -1 on error.
*/
int
-resolve_superior_type(const char *name, const char *prefix, struct lys_module *module, struct lys_node *parent,
+resolve_superior_type(const char *name, const char *mod_name, struct lys_module *module, struct lys_node *parent,
struct lys_tpdf **ret)
{
int i, j;
struct lys_tpdf *tpdf;
int tpdf_size;
- if (!prefix) {
+ if (!mod_name) {
/* no prefix, try built-in types */
for (i = 1; i < LY_DATA_TYPE_COUNT; i++) {
if (!strcmp(ly_types[i].def->name, name)) {
@@ -1285,13 +1286,13 @@
}
}
} else {
- if (!strcmp(prefix, module->prefix)) {
+ if (!strcmp(mod_name, module->name)) {
/* prefix refers to the current module, ignore it */
- prefix = NULL;
+ mod_name = NULL;
}
}
- if (!prefix && parent) {
+ if (!mod_name && parent) {
/* search in local typedefs */
while (parent) {
switch (parent->nodetype) {
@@ -1342,9 +1343,9 @@
parent = parent->parent;
}
- } else if (prefix) {
+ } else if (mod_name) {
/* get module where to search */
- module = resolve_prefixed_module(module, prefix, strlen(prefix));
+ module = ly_ctx_get_module(module->ctx, mod_name, NULL);
if (!module) {
return -1;
}
@@ -1375,14 +1376,81 @@
return EXIT_FAILURE;
}
-/* logs directly */
+/**
+ * @brief Check the default \p value of the \p type. Logs directly.
+ *
+ * @param[in] type Type definition to use.
+ * @param[in] value Default value to check.
+ * @param[in] first Whether this is the first resolution try. Affects logging.
+ * @param[in] line Line in the input file.
+ *
+ * @return EXIT_SUCCESS on success, EXIT_FAILURE on forward reference, -1 on error.
+ */
static int
-check_default(struct lys_type *type, const char *value)
+check_default(struct lys_type *type, const char *value, int first, uint32_t line)
{
- /* TODO - RFC 6020, sec. 7.3.4 */
- (void)type;
- (void)value;
- return EXIT_SUCCESS;
+ struct lyd_node_leaf_list node;
+ struct lys_type *iter;
+ int ret = EXIT_SUCCESS, found;
+
+ /* dummy leaf */
+ node.value_str = value;
+ node.value_type = type->base;
+ node.schema = calloc(1, sizeof *node.schema);
+ node.schema->name = strdup("default");
+
+ if (type->base == LY_TYPE_UNION) {
+ found = 0;
+ iter = lyp_get_next_union_type(type, NULL, &found);
+ while (iter) {
+ node.value_type = iter->base;
+
+ /* special case with too much effort required and almost no added value */
+ if ((iter->base == LY_TYPE_IDENT) || (iter->base == LY_TYPE_INST)) {
+ LOGVAL(LYE_SPEC, line,
+ "Union with \"instance-identifier\" or \"identityref\" and a default value is not supported!");
+ ret = -1;
+ goto finish;
+ }
+
+ if (!lyp_parse_value(&node, iter, 1, NULL, UINT_MAX)) {
+ break;
+ }
+
+ found = 0;
+ iter = lyp_get_next_union_type(type, iter, &found);
+ }
+
+ if (!iter) {
+ if (!first) {
+ LOGVAL(LYE_INVAL, line, node.value_str, "default");
+ }
+ ret = EXIT_FAILURE;
+ goto finish;
+ }
+
+ } else if (type->base == LY_TYPE_LEAFREF) {
+ if (!type->info.lref.target) {
+ ret = EXIT_FAILURE;
+ goto finish;
+ }
+ ret = check_default(&type->info.lref.target->type, value, first, line);
+
+ } else if ((type->base == LY_TYPE_INST) || (type->base == LY_TYPE_IDENT)) {
+ /* it was converted to JSON format before, nothing else sensible we can do */
+
+ } else {
+ ret = lyp_parse_value(&node, type, 1, NULL, (first ? UINT_MAX : line));
+ }
+
+finish:
+ if (node.value_type == LY_TYPE_BITS) {
+ free(node.value.bit);
+ }
+ free((char *)node.schema->name);
+ free(node.schema);
+
+ return ret;
}
/**
@@ -1555,7 +1623,7 @@
if (prefix) {
module = resolve_prefixed_module(uses->module, prefix, pref_len);
if (!module) {
- LOGVAL(LYE_INPREF_LEN, line, pref_len, prefix);
+ LOGVAL(LYE_INMOD_LEN, line, pref_len, prefix);
return -1;
}
start = module->data;
@@ -1609,7 +1677,7 @@
module = resolve_prefixed_module(module, prefix, pref_len);
if (!module) {
/* identity refers unknown data model */
- LOGVAL(LYE_INPREF_LEN, line, pref_len, prefix);
+ LOGVAL(LYE_INMOD_LEN, line, pref_len, prefix);
return -1;
}
} else {
@@ -1644,135 +1712,6 @@
}
/**
- * @brief Resolve (find) a valid sibling. Does not log.
- *
- * Valid child means a schema pointer to a node that is part of
- * the data meaning uses are skipped. Includes module comparison
- * (can handle augments). Module is adjusted based on the prefix.
- * Includes are also searched if siblings are top-level nodes.
- *
- * @param[in] mod Main module. Prefix is considered to be from this module.
- * @param[in] siblings Siblings to consider. They are first adjusted to
- * point to the first sibling.
- * @param[in] prefix Node prefix.
- * @param[in] pref_len Node prefix length.
- * @param[in] name Node name.
- * @param[in] nam_len Node name length.
- * @param[in] type ORed desired type of the node. 0 means any type.
- * Returns only schema data nodes (no uses, grouping, augment, choice, case).
- * @param[out] ret Pointer to the node of the desired type. Can be NULL.
- *
- * @return EXIT_SUCCESS on success, EXIT_FAILURE on forward reference, -1 on error.
- */
-int
-resolve_sibling(struct lys_module *mod, struct lys_node *siblings, const char *prefix, int pref_len, const char *name,
- int nam_len, LYS_NODE type, struct lys_node **ret)
-{
- struct lys_node *node, *old_siblings = NULL;
- struct lys_module *prefix_mod, *cur_mod;
- int in_submod;
-
- assert(siblings && name);
- assert(!(type & LYS_USES));
-
- /* find the beginning */
- while (siblings->prev->next) {
- siblings = siblings->prev;
- }
-
- /* fill the name length in case the caller is so indifferent */
- if (!nam_len) {
- nam_len = strlen(name);
- }
-
- /* we start with the module itself, submodules come later */
- in_submod = 0;
-
- /* set prefix_mod correctly */
- if (prefix) {
- prefix_mod = resolve_prefixed_module(mod, prefix, pref_len);
- if (!prefix_mod) {
- return -1;
- }
- cur_mod = prefix_mod;
- /* it is not our module */
- if (cur_mod != mod) {
- old_siblings = siblings;
- siblings = cur_mod->data;
- }
- } else {
- if (mod) {
- prefix_mod = mod;
- } else {
- prefix_mod = siblings->module;
- }
- if (prefix_mod->type) {
- prefix_mod = ((struct lys_submodule *)prefix_mod)->belongsto;
- }
- cur_mod = prefix_mod;
- }
-
- while (1) {
- /* try to find the node */
- node = NULL;
- while ((node = lys_getnext(node, siblings->parent, cur_mod, 0))) {
- if (!type || (node->nodetype & type)) {
- /* module check */
- if (!node->module->type) {
- if (cur_mod != node->module) {
- continue;
- }
- } else {
- /* both are submodules */
- if (cur_mod->type) {
- if (cur_mod != node->module) {
- continue;
- }
- } else {
- if (cur_mod != ((struct lys_submodule *)node->module)->belongsto) {
- continue;
- }
- }
- }
-
- /* direct name check */
- if (node->name == name || (!strncmp(node->name, name, nam_len) && !node->name[nam_len])) {
- if (ret) {
- *ret = node;
- }
- return EXIT_SUCCESS;
- }
- }
- }
-
- /* The original siblings may be valid,
- * it's a special case when we're looking
- * for a node from augment.
- */
- if (old_siblings) {
- siblings = old_siblings;
- old_siblings = NULL;
- continue;
- }
-
- /* we're not top-level, search ended */
- if (siblings->parent) {
- break;
- }
-
- /* let's try the submodules */
- if (in_submod == prefix_mod->inc_size) {
- break;
- }
- cur_mod = (struct lys_module *)prefix_mod->inc[in_submod].submodule;
- siblings = cur_mod->data;
- ++in_submod;
- }
-
- return EXIT_FAILURE;
-}
-
-/**
* @brief Resolve (find) a schema node based on a schema-nodeid. Does not log.
*
* node_type - LYS_AUGMENT (searches also RPCs and notifications)
@@ -2344,7 +2283,7 @@
path += i;
/* source (must be leaf) */
- rc = resolve_sibling(mod, source_node->child, sour_pref, sour_pref_len, source, sour_len, LYS_LEAF, &src_node);
+ rc = lys_getsibling(mod, source_node->child, sour_pref, sour_pref_len, source, sour_len, LYS_LEAF, &src_node);
if (rc) {
if ((rc == -1) || !first) {
LOGVAL(LYE_NORESOLV, line, path-parsed);
@@ -2372,7 +2311,7 @@
}
}
while (1) {
- rc = resolve_sibling(mod, dst_node->child, dest_pref, dest_pref_len, dest, dest_len,
+ rc = lys_getsibling(mod, dst_node->child, dest_pref, dest_pref_len, dest, dest_len,
LYS_CONTAINER | LYS_LIST | LYS_LEAF, &dst_node);
if (rc) {
if ((rc == -1) || !first) {
@@ -2481,7 +2420,7 @@
node = node->child;
}
- rc = resolve_sibling(mod, node, prefix, pref_len, name, nam_len, LYS_ANY & (~LYS_USES), &node);
+ rc = lys_getsibling(mod, node, prefix, pref_len, name, nam_len, 0, &node);
if (rc) {
if ((rc == -1) || !first) {
LOGVAL(LYE_NORESOLV, line, path);
@@ -3094,7 +3033,7 @@
module = resolve_prefixed_module(module, basename, prefix_len);
if (!module) {
/* identity refers unknown data model */
- LOGVAL(LYE_INPREF, line, basename);
+ LOGVAL(LYE_INMOD, line, basename);
return -1;
}
} else {
@@ -3273,7 +3212,7 @@
len = strlen(keys_str);
}
- rc = resolve_sibling(mod, list->child, NULL, 0, keys_str, len, LYS_LEAF, (struct lys_node **)&list->keys[i]);
+ rc = lys_getsibling(mod, list->child, NULL, 0, keys_str, len, LYS_LEAF, (struct lys_node **)&list->keys[i]);
if (rc) {
if ((rc == -1) || !first) {
LOGVAL(LYE_INRESOLV, line, "list keys", keys_str);
@@ -3551,9 +3490,9 @@
stype = item;
/* HACK type->der is temporarily its parent */
- rc = resolve_superior_type(base_name, stype->prefix, mod, (struct lys_node *)stype->der, &stype->der);
+ rc = resolve_superior_type(base_name, stype->module_name, mod, (struct lys_node *)stype->der, &stype->der);
if (rc == -1) {
- LOGVAL(LYE_INPREF, line, stype->prefix);
+ LOGVAL(LYE_INMOD, line, stype->module_name);
} else if (!rc) {
stype->base = stype->der->type.base;
}
@@ -3574,7 +3513,7 @@
base_name = str_snode;
stype = item;
- rc = check_default(stype, base_name);
+ rc = check_default(stype, base_name, first, line);
/* do not remove base_name (dflt), it's in a typedef */
has_str = 0;
break;
diff --git a/src/resolve.h b/src/resolve.h
index 710996a..1eb768a 100644
--- a/src/resolve.h
+++ b/src/resolve.h
@@ -107,9 +107,6 @@
int resolve_unique(struct lys_node *parent, const char *uniq_str, struct lys_unique *uniq_s, int first, uint32_t line);
-int resolve_sibling(struct lys_module *mod, struct lys_node *siblings, const char *prefix, int pref_len,
- const char *name, int nam_len, LYS_NODE type, struct lys_node **ret);
-
int resolve_schema_nodeid(const char *id, struct lys_node *start, struct lys_module *mod,
LYS_NODE node_type, struct lys_node **ret);
diff --git a/src/tree_data.c b/src/tree_data.c
index b17067b..b89d433 100644
--- a/src/tree_data.c
+++ b/src/tree_data.c
@@ -85,7 +85,7 @@
siblings = parent->schema->child;
}
- if (resolve_sibling(module, siblings, NULL, 0, name, strlen(name), LYS_CONTAINER | LYS_LIST | LYS_NOTIF | LYS_RPC,
+ if (lys_getsibling(module, siblings, NULL, 0, name, strlen(name), LYS_CONTAINER | LYS_LIST | LYS_NOTIF | LYS_RPC,
&snode) || !snode) {
return NULL;
}
@@ -131,7 +131,7 @@
siblings = parent->schema->child;
}
- if (resolve_sibling(module, siblings, NULL, 0, name, strlen(name), LYS_LEAFLIST | LYS_LEAF, &snode)
+ if (lys_getsibling(module, siblings, NULL, 0, name, strlen(name), LYS_LEAFLIST | LYS_LEAF, &snode)
|| !snode) {
return NULL;
}
@@ -341,7 +341,7 @@
siblings = parent->schema->child;
}
- if (resolve_sibling(module, siblings, NULL, 0, name, strlen(name), LYS_LEAFLIST | LYS_LEAF, &snode)
+ if (lys_getsibling(module, siblings, NULL, 0, name, strlen(name), LYS_LEAFLIST | LYS_LEAF, &snode)
|| !snode) {
ly_errno = LY_EINVAL;
return NULL;
@@ -416,7 +416,7 @@
ctx = parent->schema->module->ctx;
}
- if (resolve_sibling(module, siblings, NULL, 0, name, strlen(name), LYS_ANYXML, &snode)
+ if (lys_getsibling(module, siblings, NULL, 0, name, strlen(name), LYS_ANYXML, &snode)
|| !snode) {
return NULL;
}
diff --git a/src/tree_data.h b/src/tree_data.h
index b387719..606724e 100644
--- a/src/tree_data.h
+++ b/src/tree_data.h
@@ -205,6 +205,7 @@
* @param[in] module Module with the node being created.
* @param[in] name Schema node name of the new data node. The node can be #LYS_CONTAINER, #LYS_LIST,
* #LYS_INPUT, #LYS_OUTPUT, #LYS_NOTIF, or #LYS_RPC.
+ * @return New node, NULL on error.
*/
struct lyd_node *lyd_new(struct lyd_node *parent, struct lys_module *module, const char *name);
@@ -217,6 +218,7 @@
* @param[in] type Type of the value provided in the \p value parameter. Cannot be #LY_TYPE_DER, #LY_TYPE_UNION,
* or #LY_TYPE_INST.
* @param[in] value Value of the node being created. Can be NULL only if \p type is #LY_TYPE_EMPTY.
+ * @return New node, NULL on error.
*/
struct lyd_node *lyd_new_leaf_val(struct lyd_node *parent, struct lys_module *module, const char *name,
LY_DATA_TYPE type, lyd_val value);
@@ -234,6 +236,7 @@
* #LY_TYPE_UNION in this case.
* @param[in] val_str String form of the value of the node being created. Can be NULL only if \p type is
* #LY_TYPE_EMPTY.
+ * @return New node, NULL on error.
*/
struct lyd_node *lyd_new_leaf_str(struct lyd_node *parent, struct lys_module *module, const char *name,
LY_DATA_TYPE type, const char *val_str);
@@ -245,6 +248,7 @@
* @param[in] module Module with the node being created.
* @param[in] name Schema node name of the new data node.
* @param[in] val_xml Value of the node being created. Must be a well-formed XML.
+ * @return New node, NULL on error.
*/
struct lyd_node *lyd_new_anyxml(struct lyd_node *parent, struct lys_module *module, const char *name,
const char *val_xml);
diff --git a/src/tree_internal.h b/src/tree_internal.h
index 51fd2b6..231a16e 100644
--- a/src/tree_internal.h
+++ b/src/tree_internal.h
@@ -123,29 +123,6 @@
int lys_node_addchild(struct lys_node *parent, struct lys_module *module, struct lys_node *child);
/**
- * @brief Get next schema tree (sibling) node element that can be instanciated in a data tree.
- *
- * lys_getnext() is supposed to be called sequentially. In the first call, the \p last parameter is usually NULL
- * and function starts returning i) the first \p parent child or ii) the first top level element of the \p module.
- * Consequent calls suppose to provide the previously returned node as the \p last parameter and still the same
- * \p parent and \p module parameters.
- *
- * The function does not traverse via RPCs and Notifications.
- *
- * @param[in] last Previously returned schema tree node, or NULL in case of the first call.
- * @param[in] parent Parent of the subtree where the function starts processing
- * @param[in] module In case of iterating on top level elements, the \p parent is NULL and module must be specified.
- * @param[in] option 1 to include the choice schema nodes into the result set.
- * @return Next schema tree node that can be instanciated in a data tree, NULL in case there is no such element
- */
-struct lys_node *lys_getnext(struct lys_node *last, struct lys_node *parent, struct lys_module *module, int options);
-
-/**
- * @brief option for lys_getnext() to allow returning the choice nodes.
- */
-#define LYS_GETNEXT_WITHCHOICE 0x01
-
-/**
* @brief Find a valid grouping definition relative to a node.
*
* Valid definition means a sibling of \p start or a sibling of any of \p start 's parents.
@@ -265,6 +242,29 @@
struct lyd_node *lyd_attr_parent(struct lyd_node *root, struct lyd_attr *attr);
/**
+ * @brief Find a specific sibling. Does not log.
+ *
+ * Includes module comparison (can handle augments). Module is adjusted
+ * based on the \p mod_name. Includes are also searched if siblings are
+ * top-level nodes.
+ *
+ * @param[in] mod Main module. Prefix is considered to be from this module.
+ * @param[in] siblings Siblings to consider. They are first adjusted to
+ * point to the first sibling.
+ * @param[in] mod_name Module name.
+ * @param[in] mod_name_len Module name length.
+ * @param[in] name Node name.
+ * @param[in] nam_len Node name length.
+ * @param[in] type ORed desired type of the node. 0 means any type.
+ * Does not return groupings, uses, and augments (but returns augment nodes).
+ * @param[out] ret Pointer to the node of the desired type. Can be NULL.
+ *
+ * @return EXIT_SUCCESS on success, EXIT_FAILURE on forward reference, -1 on error.
+ */
+int lys_getsibling(struct lys_module *mod, struct lys_node *siblings, const char *mod_name, int mod_name_len,
+ const char *name, int nam_len, LYS_NODE type, struct lys_node **ret);
+
+/**
* @brief Compare 2 data nodes if they are the same from the YANG point of view.
*
* - containers are the same if they are defined by the same schema tree node
diff --git a/src/tree_schema.c b/src/tree_schema.c
index 51e2cd3..4645fef 100644
--- a/src/tree_schema.c
+++ b/src/tree_schema.c
@@ -85,7 +85,118 @@
goto check;
}
-struct lys_node *
+int
+lys_getsibling(struct lys_module *mod, struct lys_node *siblings, const char *mod_name, int mod_name_len,
+ const char *name, int nam_len, LYS_NODE type, struct lys_node **ret)
+{
+ struct lys_node *node, *old_siblings = NULL;
+ struct lys_module *prefix_mod, *cur_mod;
+ int in_submod;
+ char *module_name;
+
+ assert(siblings && name);
+ assert(!(type & (LYS_AUGMENT | LYS_USES | LYS_GROUPING)));
+
+ /* find the beginning */
+ while (siblings->prev->next) {
+ siblings = siblings->prev;
+ }
+
+ /* fill the name length in case the caller is so indifferent */
+ if (!nam_len) {
+ nam_len = strlen(name);
+ }
+
+ /* we start with the module itself, submodules come later */
+ in_submod = 0;
+
+ /* set prefix_mod correctly */
+ if (mod_name) {
+ module_name = strndup(mod_name, mod_name_len);
+ prefix_mod = ly_ctx_get_module(siblings->module->ctx, module_name, NULL);
+ free(module_name);
+ if (!prefix_mod) {
+ return -1;
+ }
+ cur_mod = prefix_mod;
+ /* it is not our module */
+ if (cur_mod != mod) {
+ old_siblings = siblings;
+ siblings = cur_mod->data;
+ }
+ } else {
+ if (mod) {
+ prefix_mod = mod;
+ } else {
+ prefix_mod = siblings->module;
+ }
+ if (prefix_mod->type) {
+ prefix_mod = ((struct lys_submodule *)prefix_mod)->belongsto;
+ }
+ cur_mod = prefix_mod;
+ }
+
+ while (1) {
+ /* try to find the node */
+ node = NULL;
+ while ((node = lys_getnext(node, siblings->parent, cur_mod, LYS_GETNEXT_WITHCHOICE | LYS_GETNEXT_WITHCASE))) {
+ if (!type || (node->nodetype & type)) {
+ /* module check */
+ if (!node->module->type) {
+ if (cur_mod != node->module) {
+ continue;
+ }
+ } else {
+ /* both are submodules */
+ if (cur_mod->type) {
+ if (cur_mod != node->module) {
+ continue;
+ }
+ } else {
+ if (cur_mod != ((struct lys_submodule *)node->module)->belongsto) {
+ continue;
+ }
+ }
+ }
+
+ /* direct name check */
+ if ((node->name == name) || (!strncmp(node->name, name, nam_len) && !node->name[nam_len])) {
+ if (ret) {
+ *ret = node;
+ }
+ return EXIT_SUCCESS;
+ }
+ }
+ }
+
+ /* The original siblings may be valid,
+ * it's a special case when we're looking
+ * for a node from an augment.
+ */
+ if (old_siblings) {
+ siblings = old_siblings;
+ old_siblings = NULL;
+ continue;
+ }
+
+ /* we're not top-level, search ended */
+ if (siblings->parent) {
+ break;
+ }
+
+ /* let's try the submodules */
+ if (in_submod == prefix_mod->inc_size) {
+ break;
+ }
+ cur_mod = (struct lys_module *)prefix_mod->inc[in_submod].submodule;
+ siblings = cur_mod->data;
+ ++in_submod;
+ }
+
+ return EXIT_FAILURE;
+}
+
+API struct lys_node *
lys_getnext(struct lys_node *last, struct lys_node *parent, struct lys_module *module, int options)
{
struct lys_node *next;
@@ -123,10 +234,14 @@
}
switch (next->nodetype) {
- case LYS_USES:
case LYS_CASE:
+ if (options & LYS_GETNEXT_WITHCASE) {
+ return next;
+ }
+ /* fallthrough */
case LYS_INPUT:
case LYS_OUTPUT:
+ case LYS_USES:
/* go into */
next = next->child;
goto repeat;
@@ -1035,7 +1150,7 @@
{
int i;
- new->prefix = lydict_insert(mod->ctx, old->prefix, 0);
+ new->module_name = lydict_insert(mod->ctx, old->module_name, 0);
new->base = old->base;
new->der = old->der;
@@ -1165,7 +1280,7 @@
return;
}
- lydict_remove(ctx, type->prefix);
+ lydict_remove(ctx, type->module_name);
switch (type->base) {
case LY_TYPE_BINARY:
@@ -2074,7 +2189,7 @@
}
if (choice_orig->dflt) {
- rc = resolve_sibling(choice->module, choice->child, NULL, 0, choice_orig->dflt->name, 0, LYS_ANYXML
+ rc = lys_getsibling(choice->module, choice->child, NULL, 0, choice_orig->dflt->name, 0, LYS_ANYXML
| LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST
| LYS_LIST, &choice->dflt);
if (rc) {
@@ -2149,8 +2264,8 @@
/* we managed to resolve it before, resolve it again manually */
if (list_orig->keys[0]) {
for (i = 0; i < list->keys_size; ++i) {
- rc = resolve_sibling(list->module, list->child, NULL, 0, list_orig->keys[i]->name, 0, LYS_LEAF,
- (struct lys_node **)&list->keys[i]);
+ rc = lys_getsibling(list->module, list->child, NULL, 0, list_orig->keys[i]->name, 0, LYS_LEAF,
+ (struct lys_node **)&list->keys[i]);
if (rc) {
if (rc == EXIT_FAILURE) {
LOGINT;
diff --git a/src/tree_schema.h b/src/tree_schema.h
index 7fdeb40..41abd66 100644
--- a/src/tree_schema.h
+++ b/src/tree_schema.h
@@ -357,7 +357,7 @@
* @brief YANG type structure providing information from the schema
*/
struct lys_type {
- const char *prefix; /**< prefix for the type referenced in der pointer*/
+ const char *module_name; /**< module name of the type referenced in der pointer*/
LY_DATA_TYPE base; /**< base type */
struct lys_tpdf *der; /**< pointer to the superior typedef. If NULL,
structure provides information about one of the built-in types */
@@ -1292,6 +1292,29 @@
struct lys_feature *lys_is_disabled(struct lys_node *node, int recursive);
/**
+ * @brief Get next schema tree (sibling) node element that can be instanciated in a data tree. Returned node can
+ * be from an augment.
+ *
+ * lys_getnext() is supposed to be called sequentially. In the first call, the \p last parameter is usually NULL
+ * and function starts returning i) the first \p parent child or ii) the first top level element of the \p module.
+ * Consequent calls suppose to provide the previously returned node as the \p last parameter and still the same
+ * \p parent and \p module parameters.
+ *
+ * @param[in] last Previously returned schema tree node, or NULL in case of the first call.
+ * @param[in] parent Parent of the subtree where the function starts processing
+ * @param[in] module In case of iterating on top level elements, the \p parent is NULL and module must be specified.
+ * @param[in] options 1 for including choice, 2 for case schema nodes in the result set.
+ * @return Next schema tree node that can be instanciated in a data tree, NULL in case there is no such element
+ */
+struct lys_node *lys_getnext(struct lys_node *last, struct lys_node *parent, struct lys_module *module, int options);
+
+/**
+ * @brief options for lys_getnext() to allow returning choice and case nodes.
+ */
+#define LYS_GETNEXT_WITHCHOICE 0x01
+#define LYS_GETNEXT_WITHCASE 0x02
+
+/**
* @brief Return parent node in the schema tree.
*
* In case of augmenting node, it returns the target tree node where the augmenting