diff options
Diffstat (limited to 'src/tree_data.h')
-rw-r--r-- | src/tree_data.h | 222 |
1 files changed, 165 insertions, 57 deletions
diff --git a/src/tree_data.h b/src/tree_data.h index ff98f60..4d87fba 100644 --- a/src/tree_data.h +++ b/src/tree_data.h @@ -822,7 +822,7 @@ struct lyd_node_inner { }; /**< common part corresponding to ::lyd_node */ struct lyd_node *child; /**< pointer to the first child node. */ - struct hash_table *children_ht; /**< hash table with all the direct children (except keys for a list, lists without keys) */ + struct ly_ht *children_ht; /**< hash table with all the direct children (except keys for a list, lists without keys) */ #define LYD_HT_MIN_ITEMS 4 /**< minimal number of children to create ::lyd_node_inner.children_ht hash table. */ }; @@ -1004,15 +1004,7 @@ struct lyd_node_opaq { * @return Pointer to the parent node of the @p node. * @return NULL in case of the top-level node or if the @p node is NULL itself. */ -static inline struct lyd_node * -lyd_parent(const struct lyd_node *node) -{ - if (!node || !node->parent) { - return NULL; - } - - return &node->parent->node; -} +LIBYANG_API_DECL struct lyd_node *lyd_parent(const struct lyd_node *node); /** * @brief Get the child pointer of a generic data node. @@ -1024,29 +1016,7 @@ lyd_parent(const struct lyd_node *node) * @param[in] node Node to use. * @return Pointer to the first child node (if any) of the @p node. */ -static inline struct lyd_node * -lyd_child(const struct lyd_node *node) -{ - if (!node) { - return NULL; - } - - if (!node->schema) { - /* opaq node */ - return ((const struct lyd_node_opaq *)node)->child; - } - - switch (node->schema->nodetype) { - case LYS_CONTAINER: - case LYS_LIST: - case LYS_RPC: - case LYS_ACTION: - case LYS_NOTIF: - return ((const struct lyd_node_inner *)node)->child; - default: - return NULL; - } -} +LIBYANG_API_DECL struct lyd_node *lyd_child(const struct lyd_node *node); /** * @brief Get the child pointer of a generic data node but skip its keys in case it is ::LYS_LIST. @@ -1072,6 +1042,14 @@ LIBYANG_API_DECL struct lyd_node *lyd_child_no_keys(const struct lyd_node *node) LIBYANG_API_DECL const struct lys_module *lyd_owner_module(const struct lyd_node *node); /** + * @brief Get the module of a node. Useful mainly for opaque nodes. + * + * @param[in] node Node to examine. + * @return Module of the node. + */ +LIBYANG_API_DECL const struct lys_module *lyd_node_module(const struct lyd_node *node); + +/** * @brief Check whether a node value equals to its default one. * * @param[in] node Term node to test. @@ -1133,23 +1111,7 @@ LIBYANG_API_DECL const char *lyd_value_get_canonical(const struct ly_ctx *ctx, c * @param[in] node Data node to use. * @return Canonical value. */ -static inline const char * -lyd_get_value(const struct lyd_node *node) -{ - if (!node) { - return NULL; - } - - if (!node->schema) { - return ((const struct lyd_node_opaq *)node)->value; - } else if (node->schema->nodetype & LYD_NODE_TERM) { - const struct lyd_value *value = &((const struct lyd_node_term *)node)->value; - - return value->_canonical ? value->_canonical : lyd_value_get_canonical(LYD_CTX(node), value); - } - - return NULL; -} +LIBYANG_API_DECL const char *lyd_get_value(const struct lyd_node *node); /** * @brief Get anydata string value. @@ -1172,6 +1134,14 @@ LIBYANG_API_DECL LY_ERR lyd_any_copy_value(struct lyd_node *trg, const union lyd LYD_ANYDATA_VALUETYPE value_type); /** + * @brief Get schema node of a data node. Useful especially for opaque nodes. + * + * @param[in] node Data node to use. + * @return Schema node represented by data @p node, NULL if there is none. + */ +LIBYANG_API_DECL const struct lysc_node *lyd_node_schema(const struct lyd_node *node); + +/** * @brief Create a new inner node in the data tree. * * To create list, use ::lyd_new_list() or ::lyd_new_list2(). @@ -1287,6 +1257,57 @@ LIBYANG_API_DECL LY_ERR lyd_new_list2(struct lyd_node *parent, const struct lys_ const char *keys, ly_bool output, struct lyd_node **node); /** + * @brief Create a new list node in the data tree. + * + * @param[in] parent Parent node for the node being created. NULL in case of creating a top level element. + * @param[in] module Module of the node being created. If NULL, @p parent module will be used. + * @param[in] name Schema node name of the new data node. The node must be #LYS_LIST. + * @param[in] format Format of key values. + * @param[in] key_values Ordered key string values of the new list instance, all must be set. + * @param[in] value_lengths Array of lengths of each @p key_values, may be NULL if @p key_values are 0-terminated strings. + * @param[in] output Flag in case the @p parent is RPC/Action. If value is 0, the input's data nodes of the RPC/Action are + * taken into consideration. Otherwise, the output's data node is going to be created. + * @param[out] node Optional created node. + * @return LY_ERR value. + */ +LIBYANG_API_DECL LY_ERR lyd_new_list3(struct lyd_node *parent, const struct lys_module *module, const char *name, + const char **key_values, uint32_t *value_lengths, ly_bool output, struct lyd_node **node); + +/** + * @brief Create a new list node in the data tree. + * + * @param[in] parent Parent node for the node being created. NULL in case of creating a top level element. + * @param[in] module Module of the node being created. If NULL, @p parent module will be used. + * @param[in] name Schema node name of the new data node. The node must be #LYS_LIST. + * @param[in] format Format of key values. + * @param[in] key_values Ordered key binary (LYB) values of the new list instance, all must be set. + * @param[in] value_lengths Array of lengths of each @p key_values. + * @param[in] output Flag in case the @p parent is RPC/Action. If value is 0, the input's data nodes of the RPC/Action are + * taken into consideration. Otherwise, the output's data node is going to be created. + * @param[out] node Optional created node. + * @return LY_ERR value. + */ +LIBYANG_API_DECL LY_ERR lyd_new_list3_bin(struct lyd_node *parent, const struct lys_module *module, const char *name, + const void **key_values, uint32_t *value_lengths, ly_bool output, struct lyd_node **node); + +/** + * @brief Create a new list node in the data tree. + * + * @param[in] parent Parent node for the node being created. NULL in case of creating a top level element. + * @param[in] module Module of the node being created. If NULL, @p parent module will be used. + * @param[in] name Schema node name of the new data node. The node must be #LYS_LIST. + * @param[in] format Format of key values. + * @param[in] key_values Ordered key canonical values of the new list instance, all must be set. + * @param[in] value_lengths Array of lengths of each @p key_values, may be NULL if @p key_values are 0-terminated strings. + * @param[in] output Flag in case the @p parent is RPC/Action. If value is 0, the input's data nodes of the RPC/Action are + * taken into consideration. Otherwise, the output's data node is going to be created. + * @param[out] node Optional created node. + * @return LY_ERR value. + */ +LIBYANG_API_DECL LY_ERR lyd_new_list3_canon(struct lyd_node *parent, const struct lys_module *module, const char *name, + const char **key_values, uint32_t *value_lengths, ly_bool output, struct lyd_node **node); + +/** * @brief Create a new term node in the data tree. * * To create a top-level term node defined in an extension instance, use ::lyd_new_ext_term(). @@ -1506,6 +1527,7 @@ LIBYANG_API_DECL LY_ERR lyd_new_attr2(struct lyd_node *parent, const char *modul #define LYD_NEW_PATH_CANON_VALUE 0x10 /**< Interpret the provided leaf/leaf-list @p value as being in the canonical (or JSON if no defined) ::LY_VALUE_CANON format. If it is not, it may lead to unexpected behavior. */ +#define LYD_NEW_PATH_WITH_OPAQ 0x20 /**< Consider opaque nodes normally when searching for existing nodes. */ /** @} pathoptions */ @@ -1519,7 +1541,8 @@ LIBYANG_API_DECL LY_ERR lyd_new_attr2(struct lyd_node *parent, const char *modul * Also, if a leaf-list is being created and both a predicate is defined in @p path * and @p value is set, the predicate is preferred. * - * For key-less lists and non-configuration leaf-lists, positional predicates should be used (indices starting from 1). + * For key-less lists, positional predicates must be used (indices starting from 1). For non-configuration leaf-lists + * either positional predicate can be used or leaf-list predicate, when an instance is always created at the end. * If no predicate is used for these nodes, they are always created. * * @param[in] parent Data parent to add to/modify, can be NULL. Note that in case a first top-level sibling is used, @@ -1531,7 +1554,11 @@ LIBYANG_API_DECL LY_ERR lyd_new_attr2(struct lyd_node *parent, const char *modul * For other node types, it should be NULL. * @param[in] options Bitmask of options, see @ref pathoptions. * @param[out] node Optional first created node. - * @return LY_ERR value. + * @return LY_SUCCESS on success. + * @return LY_EEXIST if the final node to create exists (unless ::LYD_NEW_PATH_UPDATE is used). + * @return LY_EINVAL on invalid arguments including invalid @p path. + * @return LY_EVALID on invalid @p value. + * @return LY_ERR on other errors. */ LIBYANG_API_DECL LY_ERR lyd_new_path(struct lyd_node *parent, const struct ly_ctx *ctx, const char *path, const char *value, uint32_t options, struct lyd_node **node); @@ -1554,7 +1581,11 @@ LIBYANG_API_DECL LY_ERR lyd_new_path(struct lyd_node *parent, const struct ly_ct * @param[in] options Bitmask of options, see @ref pathoptions. * @param[out] new_parent Optional first parent node created. If only one node was created, equals to @p new_node. * @param[out] new_node Optional last node created. - * @return LY_ERR value. + * @return LY_SUCCESS on success. + * @return LY_EEXIST if the final node to create exists (unless ::LYD_NEW_PATH_UPDATE is used). + * @return LY_EINVAL on invalid arguments including invalid @p path. + * @return LY_EVALID on invalid @p value. + * @return LY_ERR on other errors. */ LIBYANG_API_DECL LY_ERR lyd_new_path2(struct lyd_node *parent, const struct ly_ctx *ctx, const char *path, const void *value, size_t value_len, LYD_ANYDATA_VALUETYPE value_type, uint32_t options, struct lyd_node **new_parent, @@ -1576,7 +1607,11 @@ LIBYANG_API_DECL LY_ERR lyd_new_path2(struct lyd_node *parent, const struct ly_c * @param[in] value Value of the new leaf/leaf-list. For other node types, it should be NULL. * @param[in] options Bitmask of options, see @ref pathoptions. * @param[out] node Optional first created node. - * @return LY_ERR value. + * @return LY_SUCCESS on success. + * @return LY_EEXIST if the final node to create exists (unless ::LYD_NEW_PATH_UPDATE is used). + * @return LY_EINVAL on invalid arguments including invalid @p path. + * @return LY_EVALID on invalid @p value. + * @return LY_ERR on other errors. */ LIBYANG_API_DECL LY_ERR lyd_new_ext_path(struct lyd_node *parent, const struct lysc_ext_instance *ext, const char *path, const void *value, uint32_t options, struct lyd_node **node); @@ -1662,7 +1697,7 @@ LIBYANG_API_DECL LY_ERR lyd_change_term(struct lyd_node *term, const char *val_s * is always cleared. * * @param[in] term Term node to change. - * @param[in] value New value to set in binary format, see @ref howtoDataLYB. + * @param[in] value New value to set in binary format (usually a pointer), see @ref howtoDataLYB. * @param[in] value_len Length of @p value. * @return LY_SUCCESS if value was changed, * @return LY_EEXIST if value was the same and only the default flag was cleared, @@ -1927,6 +1962,8 @@ LIBYANG_API_DECL LY_ERR lyd_compare_meta(const struct lyd_meta *meta1, const str #define LYD_DUP_WITH_FLAGS 0x08 /**< Also copy any data node flags. That will cause the duplicated data to preserve its validation/default node state. */ #define LYD_DUP_NO_EXT 0x10 /**< Do not duplicate nodes with the ::LYD_EXT flag (nested extension instance data). */ +#define LYD_DUP_WITH_PRIV 0x20 /**< Also copy data node private pointer. Only the pointer is copied, it still points + to the same data. */ /** @} dupoptions */ @@ -2131,7 +2168,7 @@ LIBYANG_API_DECL LY_ERR lyd_merge_module(struct lyd_node **target, const struct * @param[in] first First data tree. * @param[in] second Second data tree. * @param[in] options Bitmask of options flags, see @ref diffoptions. - * @param[out] diff Generated diff. + * @param[out] diff Generated diff, NULL if there are no differences. * @return LY_SUCCESS on success, * @return LY_ERR on error. */ @@ -2146,7 +2183,7 @@ LIBYANG_API_DECL LY_ERR lyd_diff_tree(const struct lyd_node *first, const struct * @param[in] first First data tree. * @param[in] second Second data tree. * @param[in] options Bitmask of options flags, see @ref diffoptions. - * @param[out] diff Generated diff. + * @param[out] diff Generated diff, NULL if there are no differences. * @return LY_SUCCESS on success, * @return LY_ERR on error. */ @@ -2302,6 +2339,10 @@ typedef enum { /** * @brief Generate path of the given node in the requested format. * + * The path is constructed based on the parent node(s) of this node. When run on a node which is disconnected + * from its parent(s), this function might yield unexpected results such as `/example:b` instead of the expected + * `/example:a/b`. + * * @param[in] node Data path of this node will be generated. * @param[in] pathtype Format of the path to generate. * @param[in,out] buffer Prepared buffer of the @p buflen length to store the generated path. @@ -2419,6 +2460,8 @@ LIBYANG_API_DECL void lyxp_vars_free(struct lyxp_var *vars); * `leaf-list[.=...]`, these instances are found using hashes with constant (*O(1)*) complexity * (unless they are defined in top-level). Other predicates can still follow the aforementioned ones. * + * Opaque nodes are part of the evaluation. + * * @param[in] ctx_node XPath context node. * @param[in] xpath [XPath](@ref howtoXPath) to select in JSON format. It must evaluate into a node set. * @param[out] set Set of found data nodes. In case the result is a number, a string, or a boolean, @@ -2527,11 +2570,61 @@ LIBYANG_API_DECL LY_ERR lyd_eval_xpath3(const struct lyd_node *ctx_node, const s const char *xpath, LY_VALUE_FORMAT format, void *prefix_data, const struct lyxp_var *vars, ly_bool *result); /** + * @brief XPath result type. + */ +typedef enum { + LY_XPATH_NODE_SET, /**< XPath node set */ + LY_XPATH_STRING, /**< XPath string */ + LY_XPATH_NUMBER, /**< XPath number */ + LY_XPATH_BOOLEAN /**< XPath boolean */ +} LY_XPATH_TYPE; + +/** + * @brief Evaluate an XPath on data and return the result or convert it first to an expected result type. + * + * Either all return type parameters @p node_set, @p string, @p number, and @p boolean with @p ret_type + * are provided or exactly one of @p node_set, @p string, @p number, and @p boolean is provided with @p ret_type + * being obvious and hence optional. + * + * @param[in] ctx_node XPath context node, NULL for the root node. + * @param[in] tree Data tree to evaluate on. + * @param[in] cur_mod Current module of @p xpath, needed for some kinds of @p format. + * @param[in] xpath [XPath](@ref howtoXPath) to select. + * @param[in] format Format of any prefixes in @p xpath. + * @param[in] prefix_data Format-specific prefix data. + * @param[in] vars Optional [sized array](@ref sizedarrays) of XPath variables. + * @param[out] ret_type XPath type of the result selecting which of @p node_set, @p string, @p number, and @p boolean to use. + * @param[out] node_set XPath node set result. + * @param[out] string XPath string result. + * @param[out] number XPath number result. + * @param[out] boolean XPath boolean result. + * @return LY_SUCCESS on success. + * @return LY_ERR value on error. + */ +LIBYANG_API_DECL LY_ERR lyd_eval_xpath4(const struct lyd_node *ctx_node, const struct lyd_node *tree, + const struct lys_module *cur_mod, const char *xpath, LY_VALUE_FORMAT format, void *prefix_data, + const struct lyxp_var *vars, LY_XPATH_TYPE *ret_type, struct ly_set **node_set, char **string, + long double *number, ly_bool *boolean); + +/** + * @brief Evaluate an XPath on data and free all the nodes except the subtrees selected by the expression. + * + * @param[in,out] tree Data tree to evaluate on and trim. + * @param[in] xpath [XPath](@ref howtoXPath) to select in JSON format. + * @param[in] vars Optional [sized array](@ref sizedarrays) of XPath variables. + * @return LY_SUCCESS on success. + * @return LY_ERR value on error. + */ +LIBYANG_API_DEF LY_ERR lyd_trim_xpath(struct lyd_node **tree, const char *xpath, const struct lyxp_var *vars); + +/** * @brief Search in given data for a node uniquely identified by a path. * * Always works in constant (*O(1)*) complexity. To be exact, it is *O(n)* where *n* is the depth * of the path used. * + * Opaque nodes are NEVER found/traversed. + * * @param[in] ctx_node Path context node. * @param[in] path [Path](@ref howtoXPath) to find. * @param[in] output Whether to search in RPC/action output nodes or in input nodes. @@ -2557,6 +2650,21 @@ LIBYANG_API_DECL LY_ERR lyd_find_path(const struct lyd_node *ctx_node, const cha LIBYANG_API_DECL LY_ERR lyd_find_target(const struct ly_path *path, const struct lyd_node *tree, struct lyd_node **match); /** + * @brief Get current timezone (including DST setting) UTC (GMT) time offset in seconds. + * + * @return Timezone shift in seconds. + */ +LIBYANG_API_DECL int ly_time_tz_offset(void); + +/** + * @brief Get UTC (GMT) timezone offset in seconds at a specific timestamp (including DST setting). + * + * @param[in] time Timestamp to get the offset at. + * @return Timezone shift in seconds. + */ +LIBYANG_API_DECL int ly_time_tz_offset_at(time_t time); + +/** * @brief Convert date-and-time from string to UNIX timestamp and fractions of a second. * * @param[in] value Valid string date-and-time value. |