ly_ctx_destroy(ly_native_ctx, NULL);
}
+
+const struct lyd_node *yang_dnode_get_parent(const struct lyd_node *dnode,
+ const char *name)
+{
+ const struct lyd_node *orig_dnode = dnode;
+
+ while (orig_dnode) {
+ switch (orig_dnode->schema->nodetype) {
+ case LYS_LIST:
+ case LYS_CONTAINER:
+ if (!strcmp(orig_dnode->schema->name, name))
+ return orig_dnode;
+ break;
+ default:
+ break;
+ }
+
+ orig_dnode = orig_dnode->parent;
+ }
+
+ return NULL;
+}
+
+/* API to check if the given node is last node in the list */
+static bool yang_is_last_list_dnode(const struct lyd_node *dnode)
+{
+ return (((dnode->next == NULL)
+ || (dnode->next
+ && (strcmp(dnode->next->schema->name, dnode->schema->name)
+ != 0)))
+ && dnode->prev
+ && ((dnode->prev == dnode)
+ || (strcmp(dnode->prev->schema->name, dnode->schema->name)
+ != 0)));
+}
+
+/* API to check if the given node is last node in the data tree level */
+static bool yang_is_last_level_dnode(const struct lyd_node *dnode)
+{
+ const struct lyd_node *parent;
+ const struct lys_node_list *snode;
+ const struct lyd_node *key_leaf;
+ uint8_t keys_size;
+
+ switch (dnode->schema->nodetype) {
+ case LYS_LIST:
+ assert(dnode->parent);
+ parent = dnode->parent;
+ snode = (struct lys_node_list *)parent->schema;
+ key_leaf = dnode->prev;
+ for (keys_size = 1; keys_size < snode->keys_size; keys_size++)
+ key_leaf = key_leaf->prev;
+ if (key_leaf->prev == dnode)
+ return true;
+ break;
+ case LYS_CONTAINER:
+ return true;
+ default:
+ break;
+ }
+
+ return false;
+}
+
+
+const struct lyd_node *
+yang_get_subtree_with_no_sibling(const struct lyd_node *dnode)
+{
+ bool parent = true;
+ const struct lyd_node *node;
+ const struct lys_node_container *snode;
+
+ node = dnode;
+ if (node->schema->nodetype != LYS_LIST)
+ return node;
+
+ while (parent) {
+ switch (node->schema->nodetype) {
+ case LYS_CONTAINER:
+ snode = (struct lys_node_container *)node->schema;
+ if ((!snode->presence)
+ && yang_is_last_level_dnode(node)) {
+ if (node->parent
+ && (node->parent->schema->module
+ == dnode->schema->module))
+ node = node->parent;
+ else
+ parent = false;
+ } else
+ parent = false;
+ break;
+ case LYS_LIST:
+ if (yang_is_last_list_dnode(node)
+ && yang_is_last_level_dnode(node)) {
+ if (node->parent
+ && (node->parent->schema->module
+ == dnode->schema->module))
+ node = node->parent;
+ else
+ parent = false;
+ } else
+ parent = false;
+ break;
+ default:
+ parent = false;
+ break;
+ }
+ }
+ return node;
+}
+
+uint32_t yang_get_list_pos(const struct lyd_node *node)
+{
+ return lyd_list_pos(node);
+}
+
+uint32_t yang_get_list_elements_count(const struct lyd_node *node)
+{
+ unsigned int count;
+ struct lys_node *schema;
+
+ if (!node
+ || ((node->schema->nodetype != LYS_LIST)
+ && (node->schema->nodetype != LYS_LEAFLIST))) {
+ return 0;
+ }
+
+ schema = node->schema;
+ count = 0;
+ do {
+ if (node->schema == schema)
+ ++count;
+ node = node->next;
+ } while (node);
+ return count;
+}
+
+
+const struct lyd_node *yang_dnode_get_child(const struct lyd_node *dnode)
+{
+ if (dnode)
+ return dnode->child;
+ return NULL;
+}
#endif
/* Maximum XPath length. */
-#define XPATH_MAXLEN 512
+#define XPATH_MAXLEN 1024
/* Maximum list key length. */
#define LIST_MAXKEYS 8
*/
extern void yang_terminate(void);
+/*
+ * API to return the parent dnode having a given schema-node name
+ * Use case: One has to access the parent dnode's private pointer
+ * for a given child node.
+ * For that there is a need to find parent dnode first.
+ *
+ * dnode The starting node to work on
+ *
+ * name The name of container/list schema-node
+ *
+ * Returns The dnode matched with the given name
+ */
+extern const struct lyd_node *
+yang_dnode_get_parent(const struct lyd_node *dnode, const char *name);
+
+
+/*
+ * In some cases there is a need to auto delete the parent nodes
+ * if the given node is last in the list.
+ * It tries to delete all the parents in a given tree in a given module.
+ * The use case is with static routes and route maps
+ * example : ip route 1.1.1.1/32 ens33
+ * ip route 1.1.1.1/32 ens34
+ * After this no ip route 1.1.1.1/32 ens34 came, now staticd
+ * has to find out upto which level it has to delete the dnodes.
+ * For this case it has to send delete nexthop
+ * After this no ip route 1.1.1.1/32 ens33 came, now staticd has to
+ * clear nexthop, path and route nodes.
+ * The same scheme is required for routemaps also
+ * dnode The starting node to work on
+ *
+ * Returns The final parent node selected for deletion
+ */
+extern const struct lyd_node *
+yang_get_subtree_with_no_sibling(const struct lyd_node *dnode);
+
+/* To get the relative position of a node in list */
+extern uint32_t yang_get_list_pos(const struct lyd_node *node);
+
+/* To get the number of elements in a list
+ *
+ * dnode : The head of list
+ * Returns : The number of dnodes present in the list
+ */
+extern uint32_t yang_get_list_elements_count(const struct lyd_node *node);
+
+
+/* To get the immediate child of a dnode */
+const struct lyd_node *yang_dnode_get_child(const struct lyd_node *dnode);
+
+
#ifdef __cplusplus
}
#endif