blob: 7ecec94f60c52d52586cc6feb0b85d01d0078a69 [file] [log] [blame]
/**
* @file tree_internal.h
* @author Radek Krejci <rkrejci@cesnet.cz>
* @brief libyang internal functions for manipulating with the data model and
* data trees.
*
* Copyright (c) 2015 CESNET, z.s.p.o.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name of the Company nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*/
#ifndef LY_TREE_INTERNAL_H_
#define LY_TREE_INTERNAL_H_
#include "tree.h"
/**
* @brief Internal list of built-in types
*/
struct ly_types {
LY_DATA_TYPE type;
struct lys_tpdf *def;
};
extern struct ly_types ly_types[LY_DATA_TYPE_COUNT];
/**
* @brief Unresolved leafref or instance-identifier in DATA
*/
struct unres_data {
uint8_t is_leafref;
struct lyd_node *dnode;
struct unres_data *next;
#ifndef NDEBUG
uint32_t line;
#endif
};
/**
* @brief Type of an unresolved item in a SCHEMA
*/
enum UNRES_ITEM {
UNRES_RESOLVED, /* a resolved item */
UNRES_IDENT, /* unresolved derived identities */
UNRES_TYPE_IDENTREF, /* check identityref value */
UNRES_TYPE_LEAFREF, /* check leafref value */
UNRES_TYPE_DER, /* unresolved derived type */
UNRES_IFFEAT, /* unresolved if-feature */
UNRES_USES, /* unresolved uses grouping (refines and augments in it are resolved as well) */
UNRES_TYPE_DFLT, /* validate default type value */
UNRES_CHOICE_DFLT, /* check choice default case */
UNRES_LIST_KEYS, /* list keys */
UNRES_LIST_UNIQ, /* list uniques */
UNRES_WHEN, /* check when */
UNRES_MUST /* check must */
};
/**
* @brief Unresolved items in a SCHEMA
*/
struct unres_schema {
void **item; /* array of pointers, each is determined by the type (one of lys_* structures) */
enum UNRES_ITEM *type; /* array of unres types */
void **str_snode; /* array of pointers, each is determined by the type (a string, a lys_node *, or NULL) */
#ifndef NDEBUG
uint32_t *line; /* array of lines for each unres item */
#endif
uint32_t count; /* count of unres items */
};
/**
* @brief Create submodule structure by reading data from memory.
*
* @param[in] module Schema tree where to connect the submodule, belongs-to value must match.
* @param[in] data String containing the submodule specification in the given \p format.
* @param[in] format Format of the data to read.
* @param[in] implement Flag to distinguish implemented and just imported (sub)modules.
* @return Created submodule structure or NULL in case of error.
*/
struct lys_submodule *lys_submodule_parse(struct lys_module *module, const char *data, LYS_INFORMAT format, int implement);
/**
* @brief Create submodule structure by reading data from file descriptor.
*
* \note Current implementation supports only reading data from standard (disk) file, not from sockets, pipes, etc.
*
* @param[in] module Schema tree where to connect the submodule, belongs-to value must match.
* @param[in] fd Standard file descriptor of the file containing the submodule specification in the given \p format.
* @param[in] format Format of the data to read.
* @param[in] implement Flag to distinguish implemented and just imported (sub)modules.
* @return Created submodule structure or NULL in case of error.
*/
struct lys_submodule *lys_submodule_read(struct lys_module *module, int fd, LYS_INFORMAT format, int implement);
/**
* @brief Free the submodule structure
*
* @param[in] submodule The structure to free. Do not use the pointer after calling this function.
*/
void lys_submodule_free(struct lys_submodule *submodule);
/**
* @brief Add child schema tree node at the end of the parent's child list.
*
* If the child is connected somewhere (has a parent), it is completely
* unlinked and none of the following conditions applies.
* If the child has prev sibling(s), they are ignored (child is added at the
* end of the child list).
* If the child has next sibling(s), all of them are connected with the parent.
*
* @param[in] parent Parent node where the \p child will be added.
* @param[in] module Module where the \p child will be added if the \p parent
* parameter is NULL (case of top-level elements). The parameter does not change
* the module of the \p child element. If the \p parent parameter is present,
* the \p module parameter is ignored.
* @param[in] child The schema tree node to be added.
* @return 0 on success, nonzero else
*/
int lys_node_addchild(struct lys_node *parent, struct lys_module *module, struct lys_node *child);
/**
* @brief Check that the \p node being connected into the \p parent has a unique name (identifier).
*
* Function is performed also as part of lys_node_addchild().
*
* @param[in] node The schema tree node to be checked.
* @param[in] parent Parent node where the \p child is supposed to be added.
* @param[in] module Module where the \p child is supposed to be added if the \p parent
* parameter is NULL (case of top-level elements). The parameter does not change
* the module of the \p child element. If the \p parent parameter is present,
* the \p module parameter is ignored.
* @return 0 on success, nonzero else
*/
int
lys_check_id(struct lys_node *node, struct lys_node *parent, struct lys_module *module);
/**
* @brief Create a copy of the specified schema tree \p node
*
* @param[in] module Target module for the duplicated node.
* @param[in] node Schema tree node to be duplicated.
* @param[in] flags Config flag to be inherited in case the origin node does not specify config flag
* @param[in] nacm NACM flags to be inherited from the parent
* @param[in] recursive 1 if all children are supposed to be also duplicated.
* @param[in] unres TODO provide description
* @return Created copy of the provided schema \p node.
*/
struct lys_node *lys_node_dup(struct lys_module *module, struct lys_node *node, uint8_t flags, uint8_t nacm,
int recursive, struct unres_schema *unres);
/**
* @brief Free the schema tree restriction (must, ...) structure content
*
* @param[in] ctx libyang context where the schema of the restriction is used.
* @param[in] restr The restriction structure to free. The function actually frees only
* the content of the structure, so after using this function, caller is supposed to
* use free(restr). It is done to free the content of structures being allocated as
* part of array, in that case the free() is used on the whole array.
*/
void lys_restr_free(struct ly_ctx *ctx, struct lys_restr *restr);
/**
* @brief Free the schema tree type structure content
*
* @param[in] ctx libyang context where the schema of the type is used.
* @param[in] restr The type structure to free. The function actually frees only
* the content of the structure, so after using this function, caller is supposed to
* use free(type). It is done to free the content of structures being allocated as
* part of array, in that case the free() is used on the whole array.
*/
void lys_type_free(struct ly_ctx *ctx, struct lys_type *type);
/**
* @brief Unlink the schema node from the tree.
*
* @param[in] node Schema tree node to unlink.
*/
void lys_node_unlink(struct lys_node *node);
/**
* @brief Free the schema node structure, includes unlinking it from the tree
*
* @param[in] node Schema tree node to free. Do not use the pointer after calling this function.
*/
void lys_node_free(struct lys_node *node);
/**
* @brief Free (and unlink it from the context) the specified schema.
*
* It is dangerous to call this function on schemas already placed into the context's
* list of modules - there can be many references from other modules and data instances.
*
* @param[in] module Data model to free.
*/
void lys_free(struct lys_module *module);
/**
* @brief Search for a mandatory element in the given schema tree subtree
*
* Besides the mandatory statements, also min-elements and max-elements constraints in
* lists and leaf-list are checked.
*
* @param[in] start Root node for the searching subtree. Expecting that the root elementa
* exists and has already all child instances resolved. Note that the root itself is not
* checked since it must be present.
* @return The first mandatory element definition not present in the data, NULL if
* there is no such element in the root's subtree.
*/
struct lys_node *ly_check_mandatory(struct lyd_node *start);
#endif /* LY_TREE_INTERNAL_H_ */