<commit_before>/**
 * @file libyang.h
 * @author <NAME> <<EMAIL>>
 * @brief The main libyang public header.
 *
 * 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_LIBYANG_H_
#define LY_LIBYANG_H_

#include <stdio.h>

#include "tree_schema.h"
#include "tree_data.h"
#include "xml.h"
#include "dict.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
 * @page howto How To ...
 *
 * - @subpage howtocontext
 * - @subpage howtoschemas
 * - @subpage howtodata
 * - @subpage howtologger
 */

/** @page howtocontext Context
 *
 * The context concept allows callers to work in environments with different sets of YANG schemas.
 *
 * The first step in libyang is to create a new context using ly_ctx_new(). It returns a handler
 * used in the following work.
 *
 * When creating a new context, search dir can be specified (NULL is accepted) to provide directory
 * where libyang will automatically search for schemas being imported or included. The search path
 * can be later changed via ly_ctx_set_searchdir() function. Before exploring the specified search
 * dir, libyang tries to get imported and included schemas from the current working directory first.
 *
 * Schemas are added into the context using [parser functions](@ref parsers) - lys_parse() or lys_read().
 * Note, that parser functions for schemas have \b lys_ prefix while instance data parser functions have
 * \b lyd_ prefix.
 *
 * Context can hold multiple revisons of the same schema.
 *
 * Context holds all modules and their submodules internally. The list of available module names is
 * provided via ly_ctx_get_module_names() functions. Similarly, caller can get also a list of submodules
 * names of a specific module using ly_ctx_get_submodule_names() function. The returned names can be
 * subsequently used to get the (sub)module structures using ly_ctx_get_module() and ly_ctx_get_submodule().
 *
 * Modules held by a context cannot be removed one after one. The only way how to \em change modules in the
 * context is to create a new context and remove the old one. To remove a context, there is ly_ctx_destroy()
 * function.
 *
 * \note API for this group of functions is available in the [context module](@ref context).
 *
 */

/**
 * @page howtoschemas Schemas
 *
 * Schema is an internal libyang's representation of a YANG data model. Each schema is connected with
 * its [context](@ref howtocontext) and loaded using [parser functions](@ref parsers). It means, that
 * the schema cannot be created (nor changed) programatically. In libyang, schemas are used only to
 * access data model definitions.
 *
 * \note There are many functions to access information from the schema trees. Details are available in
 * the [Schema Tree module](@ref schematree).
 *
 * YANG Features Manipulation
 * --------------------------
 *
 * The group of functions prefixed by \b lys_features_ are used to access and manipulate with the schema's
 * features.
 *
 * The first two functions are used to access information about the features in the schema.
 * lys_features_list() provides list of all features defined in the specific schema and its
 * submodules. Optionally, it can also provides information about the state of all features.
 * Alternatively, caller can use lys_features_state() function to get state of one specific
 * feature.
 *
 * The remaining two functions, lys_features_enable() and lys_features_disable(), are used
 * to enable and disable the specific feature. By default, when the module is loaded by libyang
 * parser, all features are disabled.
 *
 * Note, that feature's state can affect some of the output formats (e.g. Tree format).
 *
 */

/**
 * @page howtodata Data Instances
 *
 */

/**
 *
 * @page howtologger Logger
 *
 * There are 4 verbosity levels defined as ::LY_LOG_LEVEL. The level can be
 * changed by the ly_verb() function. By default, the verbosity level is
 * set to #LY_LLERR value.
 *
 * In case the logger has an error message (LY_LLERR) to print, also an error
 * code is recorded in extern ly_errno variable. Possible values are of type
 * ::LY_ERR.
 *
 * \note API for this group of functions is available in the [logger module](@ref logger).
 */

/**
 * @defgroup context Context
 * @{
 *
 * Structures and functions to manipulate with the libyang "containers". The \em context concept allows callers
 * to work in environments with different sets of YANG schemas. More detailed information can be found at
 * @ref howtocontext page.
 */

/**
 * @brief libyang context handler.
 */
struct ly_ctx;

/**
 * @brief Create libyang context
 *
 * Context is used to hold all information about schemas. Usually, the application is supposed
 * to work with a single context in which libyang is holding all schemas (and other internal
 * information) according to which the data trees will be processed and validated. So, the schema
 * trees are tightly connected with the specific context and they are held by the context internally
 * - caller does not need to keep pointers to the schemas returned by lys_parse(), context knows
 * about them. The data trees created with lyd_parse() are still connected with the specific context,
 * but they are not internally held by the context. The data tree just points and lean on some data
 * held by the context (schema tree, string dictionary, etc.). Therefore, in case of data trees, caller
 * is supposed to keep pointers returned by the lyd_parse() and manage the data tree on its own. This
 * also affects the number of instances of both tree types. While you can have only one instance of
 * specific schema connected with a single context, number of data tree instances is not connected.
 *
 * @param[in] search_dir Directory where libyang will search for the imported or included modules
 * and submodules. If no such directory is available, NULL is accepted.
 *
 * @return Pointer to the created libyang context, NULL in case of error.
 */
struct ly_ctx *ly_ctx_new(const char *search_dir);

/**
 * @brief Change the search path in libyang context
 *
 * @param[in] ctx Context to be modified.
 * @param[in] search_dir New search path to replace the current one in ctx.
 */
void ly_ctx_set_searchdir(struct ly_ctx *ctx, const char *search_dir);

/**
 * @brief Get current value of the search path in libyang context
 *
 * @param[in] ctx Context to query.
 * @return Current value of the search path.
 */
const char *ly_ctx_get_searchdir(const struct ly_ctx *ctx);

/**
 * @brief Get data of an internal ietf-yang-library module.
 *
 * @param[in] ctx Context with the modules.
 * @return Root data node corresponding to the model, NULL on error.
 * Caller is responsible for freeing the returned data tree using lyd_free().
 */
struct lyd_node *ly_ctx_info(struct ly_ctx *ctx);

/**
 * @brief Get the names of the loaded modules.
 *
 * @param[in] ctx Context with the modules.
 * @return NULL-terminated array of the module names,
 * NULL on error. The returned array must be freed by the caller, do not free
 * names in the array. Also remember that the names will be freed with freeing
 * the context.
 */
const char **ly_ctx_get_module_names(const struct ly_ctx *ctx);

/**
 * @brief Get the names of the loaded submodules of the specified module.
 *
 * @param[in] ctx Context with the modules.
 * @param[in] module_name Name of the parent module.
 * @return NULL-terminated array of submodule names of the parent module,
 * NULL on error. The returned array must be freed by the caller, do not free
 * names in the array. Also remember that the names will be freed with freeing
 * the context.
 */
const char **ly_ctx_get_submodule_names(const struct ly_ctx *ctx, const char *module_name);

/**
 * @brief Get pointer to the schema tree of the module of the specified name.
 *
 * @param[in] ctx Context to work in.
 * @param[in] name Name of the YANG module to get.
 * @param[in] revision Optional revision date of the YANG module to get. If not specified,
 * the schema in the newest revision is returned if any.
 * @return Pointer to the data model structure, NULL if no schema following the name and
 * revision requirements is present in the context.
 */
const struct lys_module *ly_ctx_get_module(const struct ly_ctx *ctx, const char *name, const char *revision);

/**
 * @brief Try to find the model in the searchpath of \p ctx and load it into it. If custom missing
 * module callback is set, it is used instead.
 *
 * @param[in] ctx Context to add to.
 * @param[in] name Name of the module to load.
 * @param[in] revision Optional revision date of the module. If not specified, it is
 * assumed that there is only one model revision in the searchpath (the first matching file
 * is parsed).
 * @return Pointer to the data model structure, NULL if not found or some error occured.
 */
const struct lys_module *ly_ctx_load_module(struct ly_ctx *ctx, const char *name, const char *revision);

/**
 * @brief Callback for retrieving missing included or imported models in a custom way.
 *
 * @param[in] name Missing module name.
 * @param[in] revision Optional missing module revision.
 * @param[in] user_data User-supplied callback data.
 * @param[out] format Format of the returned module data.
 * @param[out] free_module_data Optional callback for freeing the returned module data. If not set, free() is used.
 * @return Requested module data or NULL on error.
 */
typedef char *(*ly_module_clb)(const char *name, const char *revision, void *user_data, LYS_INFORMAT *format,
                               void (**free_module_data)(char *model_data));

/**
 * @brief Set missing include or import model callback.
 *
 * @param[in] ctx Context that will use this callback.
 * @param[in] clb Callback responsible for returning a missing model.
 * @param[in] user_data Arbitrary data that will always be passed to the callback \p clb.
 */
void ly_ctx_set_module_clb(struct ly_ctx *ctx, ly_module_clb clb, void *user_data);

/**
 * @brief Get the custom callback for missing module retrieval.
 *
 * @param[in] ctx Context to read from.
 * @param[in] user_data Optional pointer for getting the user-supplied callbck data.
 * @return Custom user missing module callback or NULL if not set.
 */
ly_module_clb ly_ctx_get_module_clb(const struct ly_ctx *ctx, void **user_data);

/**
 * @brief Get pointer to the schema tree of the module of the specified namespace
 *
 * @param[in] ctx Context to work in.
 * @param[in] ns Namespace of the YANG module to get.
 * @param[in] revision Optional revision date of the YANG module to get. If not specified,
 * the schema in the newest revision is returned if any.
 * @return Pointer to the data model structure, NULL if no schema following the namespace and
 * revision requirements is present in the context.
 */
const struct lys_module *ly_ctx_get_module_by_ns(const struct ly_ctx *ctx, const char *ns, const char *revision);

/**
 * @brief Get submodule from the context's search dir.
 *
 * @param[in] module Parent (belongs-to) module.
 * @param[in] name Name of the YANG submodule to get.
 * @param[in] revision Optional revision date of the YANG submodule to get. If
 * not specified, the newest revision is returned (TODO).
 * @return Pointer to the data model structure.
 */
const struct lys_submodule *ly_ctx_get_submodule(const struct lys_module *module, const char *name,
                                                 const char *revision);

/**
 * @brief Get schema node according to the given absolute schema node identifier.
 *
 * Prefix (module name) must be used in two cases. Firstly, the first node MUST
 * have a prefix, which is treated as the current module. Secondly, every other
 * node MUST have a prefix if its module differs from the current module.
 * Here are some examples:
 *
 * /ietf-netconf-monitoring:get-schema/input/identifier
 * /ietf-interfaces:interfaces/interface/ietf-ip:ipv4/ietf-ip:address/ietf-ip:ip
 *
 * @param[in] ctx Context to work in.
 * @param[in] nodeid Absolute schema node identifier.
 * @return Resolved schema node or NULL.
 */
const struct lys_node *ly_ctx_get_node(const struct ly_ctx *ctx, const char *nodeid);

/**
 * @brief Free all internal structures of the specified context.
 *
 * The function should be used before terminating the application to destroy
 * and free all structures internally used by libyang. If the caller uses
 * multiple contexts, the function should be called for each used context.
 *
 * All instance data are supposed to be freed before destroying the context.
 * Data models are destroyed automatically as part of ly_ctx_destroy() call.
 *
 * @param[in] ctx libyang context to destroy
 */
void ly_ctx_destroy(struct ly_ctx *ctx);

/**@} context */

/**
 * @defgroup parsers Parsers
 * @{
 *
 * Parsers allows to read schema and data trees from a specific format.
 *
 * For schemas, the following formats are supported:
 * - YANG
 *
 *   Basic YANG schemas format described in [RFC 6020](http://tools.ietf.org/html/rfc6020).
 *   Currently, only YANG 1.0 is supported.
 *
 *   \todo YANG input is not yet implemented
 *
 * - YIN
 *
 *   Alternative XML-based format to YANG. The details can be found in
 *   [RFC 6020](http://tools.ietf.org/html/rfc6020#section-11).
 *
 * For data instances, the following formats are supported:
 * - \todo TBD
 *
 */

/**
 * @brief Load a schema into the specified context.
 *
 * LY_IN_YANG (YANG) format is not yet supported.
 *
 * @param[in] ctx libyang context where to process the data model.
 * @param[in] data The string containing the dumped data model in the specified
 * format.
 * @param[in] format Format of the input data (YANG or YIN).
 * @return Pointer to the data model structure or NULL on error.
 */
const struct lys_module *lys_parse_data(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format);

/**
 * @brief Load a schema into the specified context from a file.
 *
 * LY_IN_YANG (YANG) format is not yet supported.
 *
 * @param[in] ctx libyang context where to process the data model.
 * @param[in] path Path to the file with the model in the specified format.
 * @param[in] format Format of the input data (YANG or YIN).
 * @return Pointer to the data model structure or NULL on error.
 */
const struct lys_module *lys_parse_path(struct ly_ctx *ctx, const char *path, LYS_INFORMAT format);

/**
 * @brief Read a schema from file descriptor into the specified context.
 *
 * LY_IN_YANG (YANG) format is not yet supported.
 *
 * \note Current implementation supports only reading data from standard (disk) file, not from sockets, pipes, etc.
 *
 * @param[in] ctx libyang context where to process the data model.
 * @param[in] fd File descriptor of a regular file (e.g. sockets are not supported) containing the schema
 *            in the specified format.
 * @param[in] format Format of the input data (YANG or YIN).
 * @return Pointer to the data model structure or NULL on error.
 */
const struct lys_module *lys_parse_fd(struct ly_ctx *ctx, int fd, LYS_INFORMAT format);

/**
 * @defgroup parseroptions Data parser options
 * @ingroup parsers
 *
 * Various options to change the data tree parsers behavior.
 *
 * By default, parser silently ignores the data without a matching node in schema trees. If the caller want to stop
 * parsing in case of presence of unknown data, the #LYD_OPT_STRICT can be used. The strict mode is useful for
 * NETCONF servers, since NETCONF clients should always send data according to the capabilities announced by the server.
 * On the other hand, the default non-strict mode is useful for clients receiving data from NETCONF server since
 * clients are not required to understand everything the server does. Of course, the optimal strategy is to use
 * filtering to get only the required data.
 *
 * The #LYD_OPT_DESTRUCT option is used to optimize memory consumption profile of the parser in case the input
 * data are no more needed after the parser function call. It continuously free the input data whenever it is
 * processed for the output. This option is applicable only in case the input data are in the XML tree format.
 *
 * Parser also expects that the provided data are complete and performs data validation according to all
 * implemented YANG rules. This can be problem in case of representing NETCONF's subtree filter data,
 * edit-config's data or the received data (after get or get-config request) where a filter was applied - such data
 * do not represent a complete data set and different validation rules can fail. Therefore there are other options
 * to make parser to accept such a data.
 *
 * @{
 */
#define LYD_OPT_STRICT    0x01  /**< instead of silent ignoring data without schema definition, raise an error.
                                     Having an unknown element of the known namespace is always an error. */
#define LYD_OPT_DESTRUCT  0x02  /**< safe consumed memory and free the processed XML data continuously. On the
                                     other hand, it takes some more time. This option is applicable only with
                                     lyd_parse_xml() and lyd_parse_output_xml() functions. */
#define LYD_OPT_EDIT      0x04  /**< make validation to accept NETCONF edit-config's content:
                                     - mandatory nodes can be omitted
                                     - leafrefs and instance-identifier are not resolved
                                     - status data are not allowed */
#define LYD_OPT_FILTER    0x08  /**< make validation to accept NETCONF subtree filter data:
                                     - leafs/leaf-lists with no data are allowed (even not allowed e.g. by length restriction)
                                     - multiple instances of container/leaf/.. are allowed
                                     - list's keys/unique nodes are not required
                                     - mandatory nodes can be omitted
                                     - leafrefs and instance-identifier are not resolved
                                     - data from different choice's branches are allowed */
#define LYD_OPT_GETCONFIG 0x10  /**< make validation to accept get-config's result data even with applied filter:
                                     - mandatory nodes can be omitted
                                     - leafrefs and instance-identifier are not resolved
                                     - list's keys/unique nodes are not required (so duplication is not checked)
                                     - status data are not allowed */
#define LYD_OPT_GET       0x20  /**< make validation to accept get's result data even with applied filter:
                                     - same as for #LYD_OPT_GETCONFIG but the status data are allowed */
#define LYD_OPT_OBSOLETE  0x40  /**< By default, using obsolete statements (status set to obsolete) just generates
                                     a warning, but the processing continues. With this flag, using such a statement
                                     raises an error. */
#define LYD_OPT_NOSIBLINGS 0x80 /**< Parse only the XML tree with the provided (in case of lyd_parse_*_xml() functions)
                                     or the first (in case of other lyd_parse_*() functions) root element. By default,
                                     the parser processes all top-level elements. This option applies only to XML
                                     input data. */

/**
 * @}
 */

/**
 * @brief Parse (and validate according to appropriate schema from the given context) data.
 *
 * In case of LY_XML format, the data string is parsed completely. It means that when it contains
 * a non well-formed XML with multiple root elements, all those sibling XML trees are parsed. The
 * returned data node is a root of the first tree with other trees connected via the next pointer.
 * This behavior can be changed by #LYD_OPT_NOSIBLINGS option.
 *
 * @param[in] ctx Context to connect with the data tree being built here.
 * @param[in] data Serialized data in the specified format.<commit_msg>docs BUGFIX small improvement of macro description<commit_after>/**
 * @file libyang.h
 * @author <NAME> <<EMAIL>>
 * @brief The main libyang public header.
 *
 * 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_LIBYANG_H_
#define LY_LIBYANG_H_

#include <stdio.h>

#include "tree_schema.h"
#include "tree_data.h"
#include "xml.h"
#include "dict.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
 * @page howto How To ...
 *
 * - @subpage howtocontext
 * - @subpage howtoschemas
 * - @subpage howtodata
 * - @subpage howtologger
 */

/** @page howtocontext Context
 *
 * The context concept allows callers to work in environments with different sets of YANG schemas.
 *
 * The first step in libyang is to create a new context using ly_ctx_new(). It returns a handler
 * used in the following work.
 *
 * When creating a new context, search dir can be specified (NULL is accepted) to provide directory
 * where libyang will automatically search for schemas being imported or included. The search path
 * can be later changed via ly_ctx_set_searchdir() function. Before exploring the specified search
 * dir, libyang tries to get imported and included schemas from the current working directory first.
 *
 * Schemas are added into the context using [parser functions](@ref parsers) - lys_parse() or lys_read().
 * Note, that parser functions for schemas have \b lys_ prefix while instance data parser functions have
 * \b lyd_ prefix.
 *
 * Context can hold multiple revisons of the same schema.
 *
 * Context holds all modules and their submodules internally. The list of available module names is
 * provided via ly_ctx_get_module_names() functions. Similarly, caller can get also a list of submodules
 * names of a specific module using ly_ctx_get_submodule_names() function. The returned names can be
 * subsequently used to get the (sub)module structures using ly_ctx_get_module() and ly_ctx_get_submodule().
 *
 * Modules held by a context cannot be removed one after one. The only way how to \em change modules in the
 * context is to create a new context and remove the old one. To remove a context, there is ly_ctx_destroy()
 * function.
 *
 * \note API for this group of functions is available in the [context module](@ref context).
 *
 */

/**
 * @page howtoschemas Schemas
 *
 * Schema is an internal libyang's representation of a YANG data model. Each schema is connected with
 * its [context](@ref howtocontext) and loaded using [parser functions](@ref parsers). It means, that
 * the schema cannot be created (nor changed) programatically. In libyang, schemas are used only to
 * access data model definitions.
 *
 * \note There are many functions to access information from the schema trees. Details are available in
 * the [Schema Tree module](@ref schematree).
 *
 * YANG Features Manipulation
 * --------------------------
 *
 * The group of functions prefixed by \b lys_features_ are used to access and manipulate with the schema's
 * features.
 *
 * The first two functions are used to access information about the features in the schema.
 * lys_features_list() provides list of all features defined in the specific schema and its
 * submodules. Optionally, it can also provides information about the state of all features.
 * Alternatively, caller can use lys_features_state() function to get state of one specific
 * feature.
 *
 * The remaining two functions, lys_features_enable() and lys_features_disable(), are used
 * to enable and disable the specific feature. By default, when the module is loaded by libyang
 * parser, all features are disabled.
 *
 * Note, that feature's state can affect some of the output formats (e.g. Tree format).
 *
 */

/**
 * @page howtodata Data Instances
 *
 */

/**
 *
 * @page howtologger Logger
 *
 * There are 4 verbosity levels defined as ::LY_LOG_LEVEL. The level can be
 * changed by the ly_verb() function. By default, the verbosity level is
 * set to #LY_LLERR value.
 *
 * In case the logger has an error message (LY_LLERR) to print, also an error
 * code is recorded in extern ly_errno variable. Possible values are of type
 * ::LY_ERR.
 *
 * \note API for this group of functions is available in the [logger module](@ref logger).
 */

/**
 * @defgroup context Context
 * @{
 *
 * Structures and functions to manipulate with the libyang "containers". The \em context concept allows callers
 * to work in environments with different sets of YANG schemas. More detailed information can be found at
 * @ref howtocontext page.
 */

/**
 * @brief libyang context handler.
 */
struct ly_ctx;

/**
 * @brief Create libyang context
 *
 * Context is used to hold all information about schemas. Usually, the application is supposed
 * to work with a single context in which libyang is holding all schemas (and other internal
 * information) according to which the data trees will be processed and validated. So, the schema
 * trees are tightly connected with the specific context and they are held by the context internally
 * - caller does not need to keep pointers to the schemas returned by lys_parse(), context knows
 * about them. The data trees created with lyd_parse() are still connected with the specific context,
 * but they are not internally held by the context. The data tree just points and lean on some data
 * held by the context (schema tree, string dictionary, etc.). Therefore, in case of data trees, caller
 * is supposed to keep pointers returned by the lyd_parse() and manage the data tree on its own. This
 * also affects the number of instances of both tree types. While you can have only one instance of
 * specific schema connected with a single context, number of data tree instances is not connected.
 *
 * @param[in] search_dir Directory where libyang will search for the imported or included modules
 * and submodules. If no such directory is available, NULL is accepted.
 *
 * @return Pointer to the created libyang context, NULL in case of error.
 */
struct ly_ctx *ly_ctx_new(const char *search_dir);

/**
 * @brief Change the search path in libyang context
 *
 * @param[in] ctx Context to be modified.
 * @param[in] search_dir New search path to replace the current one in ctx.
 */
void ly_ctx_set_searchdir(struct ly_ctx *ctx, const char *search_dir);

/**
 * @brief Get current value of the search path in libyang context
 *
 * @param[in] ctx Context to query.
 * @return Current value of the search path.
 */
const char *ly_ctx_get_searchdir(const struct ly_ctx *ctx);

/**
 * @brief Get data of an internal ietf-yang-library module.
 *
 * @param[in] ctx Context with the modules.
 * @return Root data node corresponding to the model, NULL on error.
 * Caller is responsible for freeing the returned data tree using lyd_free().
 */
struct lyd_node *ly_ctx_info(struct ly_ctx *ctx);

/**
 * @brief Get the names of the loaded modules.
 *
 * @param[in] ctx Context with the modules.
 * @return NULL-terminated array of the module names,
 * NULL on error. The returned array must be freed by the caller, do not free
 * names in the array. Also remember that the names will be freed with freeing
 * the context.
 */
const char **ly_ctx_get_module_names(const struct ly_ctx *ctx);

/**
 * @brief Get the names of the loaded submodules of the specified module.
 *
 * @param[in] ctx Context with the modules.
 * @param[in] module_name Name of the parent module.
 * @return NULL-terminated array of submodule names of the parent module,
 * NULL on error. The returned array must be freed by the caller, do not free
 * names in the array. Also remember that the names will be freed with freeing
 * the context.
 */
const char **ly_ctx_get_submodule_names(const struct ly_ctx *ctx, const char *module_name);

/**
 * @brief Get pointer to the schema tree of the module of the specified name.
 *
 * @param[in] ctx Context to work in.
 * @param[in] name Name of the YANG module to get.
 * @param[in] revision Optional revision date of the YANG module to get. If not specified,
 * the schema in the newest revision is returned if any.
 * @return Pointer to the data model structure, NULL if no schema following the name and
 * revision requirements is present in the context.
 */
const struct lys_module *ly_ctx_get_module(const struct ly_ctx *ctx, const char *name, const char *revision);

/**
 * @brief Try to find the model in the searchpath of \p ctx and load it into it. If custom missing
 * module callback is set, it is used instead.
 *
 * @param[in] ctx Context to add to.
 * @param[in] name Name of the module to load.
 * @param[in] revision Optional revision date of the module. If not specified, it is
 * assumed that there is only one model revision in the searchpath (the first matching file
 * is parsed).
 * @return Pointer to the data model structure, NULL if not found or some error occured.
 */
const struct lys_module *ly_ctx_load_module(struct ly_ctx *ctx, const char *name, const char *revision);

/**
 * @brief Callback for retrieving missing included or imported models in a custom way.
 *
 * @param[in] name Missing module name.
 * @param[in] revision Optional missing module revision.
 * @param[in] user_data User-supplied callback data.
 * @param[out] format Format of the returned module data.
 * @param[out] free_module_data Optional callback for freeing the returned module data. If not set, free() is used.
 * @return Requested module data or NULL on error.
 */
typedef char *(*ly_module_clb)(const char *name, const char *revision, void *user_data, LYS_INFORMAT *format,
                               void (**free_module_data)(char *model_data));

/**
 * @brief Set missing include or import model callback.
 *
 * @param[in] ctx Context that will use this callback.
 * @param[in] clb Callback responsible for returning a missing model.
 * @param[in] user_data Arbitrary data that will always be passed to the callback \p clb.
 */
void ly_ctx_set_module_clb(struct ly_ctx *ctx, ly_module_clb clb, void *user_data);

/**
 * @brief Get the custom callback for missing module retrieval.
 *
 * @param[in] ctx Context to read from.
 * @param[in] user_data Optional pointer for getting the user-supplied callbck data.
 * @return Custom user missing module callback or NULL if not set.
 */
ly_module_clb ly_ctx_get_module_clb(const struct ly_ctx *ctx, void **user_data);

/**
 * @brief Get pointer to the schema tree of the module of the specified namespace
 *
 * @param[in] ctx Context to work in.
 * @param[in] ns Namespace of the YANG module to get.
 * @param[in] revision Optional revision date of the YANG module to get. If not specified,
 * the schema in the newest revision is returned if any.
 * @return Pointer to the data model structure, NULL if no schema following the namespace and
 * revision requirements is present in the context.
 */
const struct lys_module *ly_ctx_get_module_by_ns(const struct ly_ctx *ctx, const char *ns, const char *revision);

/**
 * @brief Get submodule from the context's search dir.
 *
 * @param[in] module Parent (belongs-to) module.
 * @param[in] name Name of the YANG submodule to get.
 * @param[in] revision Optional revision date of the YANG submodule to get. If
 * not specified, the newest revision is returned (TODO).
 * @return Pointer to the data model structure.
 */
const struct lys_submodule *ly_ctx_get_submodule(const struct lys_module *module, const char *name,
                                                 const char *revision);

/**
 * @brief Get schema node according to the given absolute schema node identifier.
 *
 * Prefix (module name) must be used in two cases. Firstly, the first node MUST
 * have a prefix, which is treated as the current module. Secondly, every other
 * node MUST have a prefix if its module differs from the current module.
 * Here are some examples:
 *
 * /ietf-netconf-monitoring:get-schema/input/identifier
 * /ietf-interfaces:interfaces/interface/ietf-ip:ipv4/ietf-ip:address/ietf-ip:ip
 *
 * @param[in] ctx Context to work in.
 * @param[in] nodeid Absolute schema node identifier.
 * @return Resolved schema node or NULL.
 */
const struct lys_node *ly_ctx_get_node(const struct ly_ctx *ctx, const char *nodeid);

/**
 * @brief Free all internal structures of the specified context.
 *
 * The function should be used before terminating the application to destroy
 * and free all structures internally used by libyang. If the caller uses
 * multiple contexts, the function should be called for each used context.
 *
 * All instance data are supposed to be freed before destroying the context.
 * Data models are destroyed automatically as part of ly_ctx_destroy() call.
 *
 * @param[in] ctx libyang context to destroy
 */
void ly_ctx_destroy(struct ly_ctx *ctx);

/**@} context */

/**
 * @defgroup parsers Parsers
 * @{
 *
 * Parsers allows to read schema and data trees from a specific format.
 *
 * For schemas, the following formats are supported:
 * - YANG
 *
 *   Basic YANG schemas format described in [RFC 6020](http://tools.ietf.org/html/rfc6020).
 *   Currently, only YANG 1.0 is supported.
 *
 *   \todo YANG input is not yet implemented
 *
 * - YIN
 *
 *   Alternative XML-based format to YANG. The details can be found in
 *   [RFC 6020](http://tools.ietf.org/html/rfc6020#section-11).
 *
 * For data instances, the following formats are supported:
 * - \todo TBD
 *
 */

/**
 * @brief Load a schema into the specified context.
 *
 * LY_IN_YANG (YANG) format is not yet supported.
 *
 * @param[in] ctx libyang context where to process the data model.
 * @param[in] data The string containing the dumped data model in the specified
 * format.
 * @param[in] format Format of the input data (YANG or YIN).
 * @return Pointer to the data model structure or NULL on error.
 */
const struct lys_module *lys_parse_data(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format);

/**
 * @brief Load a schema into the specified context from a file.
 *
 * LY_IN_YANG (YANG) format is not yet supported.
 *
 * @param[in] ctx libyang context where to process the data model.
 * @param[in] path Path to the file with the model in the specified format.
 * @param[in] format Format of the input data (YANG or YIN).
 * @return Pointer to the data model structure or NULL on error.
 */
const struct lys_module *lys_parse_path(struct ly_ctx *ctx, const char *path, LYS_INFORMAT format);

/**
 * @brief Read a schema from file descriptor into the specified context.
 *
 * LY_IN_YANG (YANG) format is not yet supported.
 *
 * \note Current implementation supports only reading data from standard (disk) file, not from sockets, pipes, etc.
 *
 * @param[in] ctx libyang context where to process the data model.
 * @param[in] fd File descriptor of a regular file (e.g. sockets are not supported) containing the schema
 *            in the specified format.
 * @param[in] format Format of the input data (YANG or YIN).
 * @return Pointer to the data model structure or NULL on error.
 */
const struct lys_module *lys_parse_fd(struct ly_ctx *ctx, int fd, LYS_INFORMAT format);

/**
 * @defgroup parseroptions Data parser options
 * @ingroup parsers
 *
 * Various options to change the data tree parsers behavior.
 *
 * By default, parser silently ignores the data without a matching node in schema trees. If the caller want to stop
 * parsing in case of presence of unknown data, the #LYD_OPT_STRICT can be used. The strict mode is useful for
 * NETCONF servers, since NETCONF clients should always send data according to the capabilities announced by the server.
 * On the other hand, the default non-strict mode is useful for clients receiving data from NETCONF server since
 * clients are not required to understand everything the server does. Of course, the optimal strategy is to use
 * filtering to get only the required data.
 *
 * The #LYD_OPT_DESTRUCT option is used to optimize memory consumption profile of the parser in case the input
 * data are no more needed after the parser function call. It continuously free the input data whenever it is
 * processed for the output. This option is applicable only in case the input data are in the XML tree format.
 *
 * Parser also expects that the provided data are complete and performs data validation according to all
 * implemented YANG rules. This can be problem in case of representing NETCONF's subtree filter data,
 * edit-config's data or the received data (after get or get-config request) where a filter was applied - such data
 * do not represent a complete data set and different validation rules can fail. Therefore there are other options
 * to make parser to accept such a data.
 *
 * @{
 */
#define LYD_OPT_STRICT    0x01  /**< instead of silent ignoring data without schema definition, raise an error.
                                     Having an unknown element of the known namespace is always an error. */
#define LYD_OPT_DESTRUCT  0x02  /**< safe consumed memory and free the processed XML data continuously. On the
                                     other hand, it takes some more time. This option is applicable only with
                                     lyd_parse_xml() and lyd_parse_output_xml() functions. */
#define LYD_OPT_EDIT      0x04  /**< make validation to accept NETCONF edit-config's content:
                                     - mandatory nodes can be omitted
                                     - leafrefs and instance-identifier are not resolved
                                     - status data are not allowed */
#define LYD_OPT_FILTER    0x08  /**< make validation to accept NETCONF subtree filter data:
                                     - leafs/leaf-lists with no data are allowed (even not allowed e.g. by length restriction)
                                     - multiple instances of container/leaf/.. are allowed
                                     - list's keys/unique nodes are not required
                                     - mandatory nodes can be omitted
                                     - leafrefs and instance-identifier are not resolved
                                     - data from different choice's branches are allowed */
#define LYD_OPT_GETCONFIG 0x10  /**< make validation to accept get-config's result data even with applied filter:
                                     - mandatory nodes can be omitted
                                     - leafrefs and instance-identifier are not resolved
                                     - list's keys/unique nodes are not required (so duplication is not checked)
                                     - status data are not allowed */
#define LYD_OPT_GET       0x20  /**< make validation to accept get's result data even with applied filter:
                                     - same as for #LYD_OPT_GETCONFIG but the status data are allowed */
#define LYD_OPT_OBSOLETE  0x40  /**< By default, using obsolete statements (status set to obsolete) just generates
                                     a warning, but the processing continues. With this flag, using such a statement
                                     raises an error. */
#define LYD_OPT_NOSIBLINGS 0x80 /**< Parse only the XML tree from the provided pointer (in case of lyd_parse_*_xml()
                                     functions) or the first (in case of other lyd_parse_*() functions) root element
                                     in the data. By default, the parser processes all top-level elements. This option
                                     applies only to XML input data. */

/**
 * @}
 */

/**
 * @brief Parse (and validate according to appropriate schema from the given context) data.
 *
 * In case of LY_XML format, the data string is parsed completely. It means that when it contains
 * a non well-formed XML with multiple root elements, all those sibling XML trees are parsed. The
 * returned data node is a root of the first tree with other trees connected via the next pointer.
 * This behavior can be changed by #LYD_OPT_NOSIBLINGS option.
 *
 * @param[in] ctx Context to connect with the data tree being built here.
 * @param[in] data Serialized data in the specified format.
{'fraction_non_alphanumeric': 0.06998673580127819, 'fraction_numerical': 0.0025563728445677078, 'mean_word_length': 3.2481303145169553, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 8}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 53, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6560262', 'n_tokens_mistral': 11018, 'n_tokens_neox': 10702, 'n_words': 5501}