blob: a6f14638055d0d5647545c89f13db24ddef10158 [file] [log] [blame]
Radek Krejcie7b95092019-05-15 11:03:07 +02001/**
2 * @file tree.h
3 * @author Radek Krejci <rkrejci@cesnet.cz>
Radek Krejci8678fa42020-08-18 16:07:28 +02004 * @brief libyang generic macros and functions to work with YANG schema or data trees.
Radek Krejcie7b95092019-05-15 11:03:07 +02005 *
6 * Copyright (c) 2019 CESNET, z.s.p.o.
7 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
14
15#ifndef LY_TREE_H_
16#define LY_TREE_H_
17
Michal Vaskoae867c72020-10-07 08:54:27 +020018#include <inttypes.h>
Radek Krejci7eb54ba2020-05-18 16:30:04 +020019
Michal Vasko9f96a052020-03-10 09:41:45 +010020#include "tree_data.h"
21
Radek Krejcie7b95092019-05-15 11:03:07 +020022#ifdef __cplusplus
23extern "C" {
24#endif
25
26/**
Radek Krejci8678fa42020-08-18 16:07:28 +020027 * @page howtoXPath XPath Addressing
28 *
29 * Internally, XPath evaluation is performed on __when__ and __must__ conditions in the schema. For that almost
30 * a full [XPath 1.0](http://www.w3.org/TR/1999/REC-xpath-19991116/) evaluator was implemented.
31 * In YANG models you can also find paths identifying __augment__ targets, __leafref__ targets, and trivial paths in
32 * __choice default__ and __unique__ statements argument. The exact format of all those paths can be found in the
33 * relevant RFCs. Further will only be discussed paths that are used directly in libyang API functions.
34 *
35 * XPath
36 * =====
37 *
38 * Generally, any xpath argument expects an expression similar to _when_ or _must_ as the same evaluator is used. As for
39 * the format of any prefixes, the standardized JSON ([RFC 7951](https://tools.ietf.org/html/rfc7951#section-6.11))
40 * was used. Summarized, xpath follows these conventions:
41 * - full XPath can be used, but only data nodes (node sets) will always be returned,
42 * - as per the specification, prefixes are actually __module names__,
43 * - also in the specification, for _absolute_ paths, the first (leftmost) node _MUST_ have a prefix,
44 * - for _relative_ paths, you specify the __context node__, which then acts as a parent for the first node in the path,
45 * - nodes always inherit their module (prefix) from their __parent node__ so whenever a node is from a different
46 * module than its parent, it _MUST_ have a prefix,
47 * - nodes from the same module as their __parent__ _MUST NOT_ have a prefix,
48 * - note that non-data nodes/schema-only node (choice, case, uses, input, output) are skipped and _MUST_ not be
49 * included in the path.
50 *
51 * Functions List
52 * --------------
53 * - ::lyd_find_xpath()
54 * - ::lys_find_xpath()
55 *
56 * Path
57 * ====
58 *
59 * The term path is used when a simplified (subset of) XPath is expected. Path is always a valid XPath but not
60 * the other way around. In short, paths only identify a specific (set of) nodes based on their ancestors in the
61 * schema. Predicates are allowed the same as for an [instance-identifier](https://tools.ietf.org/html/rfc7950#section-9.13).
62 * Specifically, key values of a list, leaf-list value, or position of lists without keys can be used.
63 *
64 * Examples
65 * --------
66 *
67 * - get __list__ instance with __key1__ of value __1__ and __key2__ of value __2__ (this can return more __list__ instances if there are more keys than __key1__ and __key2__)
68 *
69 * /module-name:container/list[key1='1'][key2='2']
70 *
71 * - get __leaf-list__ instance with the value __val__
72 *
73 * /module-name:container/leaf-list[.='val']
74 *
75 * - get __3rd list-without-keys__ instance with no keys defined
76 *
77 * /module-name:container/list-without-keys[3]
78 *
79 * - get __aug-list__ with __aug-list-key__, which was added to __module-name__ from an augment module __augment-module__
80 *
81 * /module-name:container/container2/augment-module:aug-cont/aug-list[aug-list-key='value']
82 *
83 * Functions List
84 * --------------
85 * - ::lyd_new_path()
86 * - ::lyd_new_path2()
87 * - ::lyd_path()
Michal Vasko3e1f6552021-01-14 09:27:55 +010088 * - ::lyd_find_path()
Radek Krejcifba9c622020-10-30 08:28:54 +010089 * - ::lys_find_path()
Radek Krejci8678fa42020-08-18 16:07:28 +020090 *
91 */
92
93/**
Radek Krejci2ff0d572020-05-21 15:27:28 +020094 * @defgroup trees Trees
95 *
96 * Generic macros, functions, etc. to work with both [schema](@ref schematree) and [data](@ref datatree) trees.
97 *
98 * @{
99 */
100
101/**
Radek Krejcic4fa0292020-05-14 10:54:49 +0200102 * @brief Type (i.e. size) of the [sized array](@ref sizedarrays)'s size counter.
Radek Krejci7eb54ba2020-05-18 16:30:04 +0200103 *
Michal Vaskofd69e1d2020-07-03 11:57:17 +0200104 * To print the value via a print format, use LY_PRI_ARRAY_COUNT_TYPE specifier.
Radek Krejcic4fa0292020-05-14 10:54:49 +0200105 */
Michal Vaskofd69e1d2020-07-03 11:57:17 +0200106#define LY_ARRAY_COUNT_TYPE uint64_t
Radek Krejcic4fa0292020-05-14 10:54:49 +0200107
108/**
Radek Krejci7eb54ba2020-05-18 16:30:04 +0200109 * @brief Printing format specifier macro for LY_ARRAY_SIZE_TYPE values.
110 */
Michal Vaskofd69e1d2020-07-03 11:57:17 +0200111#define LY_PRI_ARRAY_COUNT_TYPE PRIu64
Radek Krejci7eb54ba2020-05-18 16:30:04 +0200112
113/**
Radek Krejcie7b95092019-05-15 11:03:07 +0200114 * @brief Macro selector for other LY_ARRAY_* macros, do not use directly!
115 */
116#define LY_ARRAY_SELECT(_1, _2, NAME, ...) NAME
117
118/**
119 * @brief Helper macro to go through sized-arrays with a pointer iterator.
120 *
121 * Use with opening curly bracket (`{`).
122 *
123 * @param[in] ARRAY Array to go through
124 * @param[in] TYPE Type of the records in the ARRAY
125 * @param[out] ITER Iterating pointer to the item being processed in each loop
126 */
127#define LY_ARRAY_FOR_ITER(ARRAY, TYPE, ITER) \
128 for (ITER = ARRAY; \
Michal Vaskofd69e1d2020-07-03 11:57:17 +0200129 (ARRAY) && ((void*)ITER - (void*)ARRAY)/(sizeof(TYPE)) < (*((LY_ARRAY_COUNT_TYPE*)(ARRAY) - 1)); \
Radek Krejcie7b95092019-05-15 11:03:07 +0200130 ITER = (void*)((TYPE*)ITER + 1))
131
132/**
133 * @brief Helper macro to go through sized-arrays with a numeric iterator.
134 *
135 * Use with opening curly bracket (`{`).
136 *
Radek Krejci5ee14f32020-11-05 13:16:42 +0100137 * The item on the current INDEX in the ARRAY can be accessed in a standard C way as ARRAY[INDEX].
Radek Krejcie7b95092019-05-15 11:03:07 +0200138 *
139 * @param[in] ARRAY Array to go through
Radek Krejci5ee14f32020-11-05 13:16:42 +0100140 * @param[out] INDEX Variable for the iterating index of the item being processed in each loop
Radek Krejcie7b95092019-05-15 11:03:07 +0200141 */
142#define LY_ARRAY_FOR_INDEX(ARRAY, INDEX) \
143 for (INDEX = 0; \
Radek Krejcic7d13e32020-12-09 12:32:24 +0100144 INDEX < LY_ARRAY_COUNT(ARRAY); \
Radek Krejcie7b95092019-05-15 11:03:07 +0200145 ++INDEX)
146
147/**
Michal Vaskofd69e1d2020-07-03 11:57:17 +0200148 * @brief Get the number of records in the ARRAY.
Radek Krejcie7b95092019-05-15 11:03:07 +0200149 */
Radek Krejcic7d13e32020-12-09 12:32:24 +0100150#define LY_ARRAY_COUNT(ARRAY) (ARRAY ? (*((LY_ARRAY_COUNT_TYPE*)(ARRAY) - 1)) : 0)
Radek Krejcie7b95092019-05-15 11:03:07 +0200151
152/**
153 * @brief Sized-array iterator (for-loop).
154 *
155 * Use with opening curly bracket (`{`).
156 *
157 * There are 2 variants:
158 *
159 * LY_ARRAY_FOR(ARRAY, TYPE, ITER)
160 *
161 * Where ARRAY is a sized-array to go through, TYPE is the type of the items in the ARRAY and ITER is a pointer variable
162 * providing the items of the ARRAY in the loops. This functionality is provided by LY_ARRAY_FOR_ITER macro
163 *
164 * LY_ARRAY_FOR(ARRAY, INDEX)
165 *
Michal Vaskofd69e1d2020-07-03 11:57:17 +0200166 * The ARRAY is again a sized-array to go through, the INDEX is a variable (LY_ARRAY_COUNT_TYPE) for storing iterating ARRAY's index
Radek Krejcie7b95092019-05-15 11:03:07 +0200167 * to access the items of ARRAY in the loops. This functionality is provided by LY_ARRAY_FOR_INDEX macro.
168 */
169#define LY_ARRAY_FOR(ARRAY, ...) LY_ARRAY_SELECT(__VA_ARGS__, LY_ARRAY_FOR_ITER, LY_ARRAY_FOR_INDEX)(ARRAY, __VA_ARGS__)
170
171/**
172 * @brief Macro to iterate via all sibling elements without affecting the list itself
173 *
174 * Works for all types of nodes despite it is data or schema tree, but all the
175 * parameters must be pointers to the same type.
176 *
177 * Use with opening curly bracket (`{`). All parameters must be of the same type.
178 *
179 * @param START Pointer to the starting element.
180 * @param ELEM Iterator.
181 */
182#define LY_LIST_FOR(START, ELEM) \
183 for ((ELEM) = (START); \
184 (ELEM); \
185 (ELEM) = (ELEM)->next)
186
187/**
188 * @brief Macro to iterate via all sibling elements allowing to modify the list itself (e.g. removing elements)
189 *
190 * Use with opening curly bracket (`{`). All parameters must be of the same type.
191 *
192 * @param START Pointer to the starting element.
193 * @param NEXT Temporary storage to allow removing of the current iterator content.
194 * @param ELEM Iterator.
195 */
196#define LY_LIST_FOR_SAFE(START, NEXT, ELEM) \
197 for ((ELEM) = (START); \
198 (ELEM) ? (NEXT = (ELEM)->next, 1) : 0; \
199 (ELEM) = (NEXT))
200
201/**
Michal Vasko4c583e82020-07-17 12:16:14 +0200202 * @brief Macro to iterate via all schema node data instances in data siblings.
203 *
204 * @param START Pointer to the starting sibling. Even if it is not first, all the siblings are searched.
205 * @param SCHEMA Schema node of the searched instances.
206 * @param ELEM Iterator.
207 */
208#define LYD_LIST_FOR_INST(START, SCHEMA, ELEM) \
209 for (lyd_find_sibling_val(START, SCHEMA, NULL, 0, &(ELEM)); \
210 (ELEM) && ((ELEM)->schema == (SCHEMA)); \
211 (ELEM) = (ELEM)->next)
212
213/**
214 * @brief Macro to iterate via all schema node data instances in data siblings allowing to modify the list itself.
215 *
216 * @param START Pointer to the starting sibling. Even if it is not first, all the siblings are searched.
217 * @param SCHEMA Schema node of the searched instances.
218 * @param NEXT Temporary storage to allow removing of the current iterator content.
219 * @param ELEM Iterator.
220 */
221#define LYD_LIST_FOR_INST_SAFE(START, SCHEMA, NEXT, ELEM) \
222 for (lyd_find_sibling_val(START, SCHEMA, NULL, 0, &(ELEM)); \
223 (ELEM) && ((ELEM)->schema == (SCHEMA)) ? ((NEXT) = (ELEM)->next, 1) : 0; \
224 (ELEM) = (NEXT))
225
226/**
Radek Krejcie7b95092019-05-15 11:03:07 +0200227 * @brief YANG built-in types
228 */
229typedef enum
230{
231 LY_TYPE_UNKNOWN = 0, /**< Unknown type */
232 LY_TYPE_BINARY, /**< Any binary data ([RFC 6020 sec 9.8](http://tools.ietf.org/html/rfc6020#section-9.8)) */
233 LY_TYPE_UINT8, /**< 8-bit unsigned integer ([RFC 6020 sec 9.2](http://tools.ietf.org/html/rfc6020#section-9.2)) */
234 LY_TYPE_UINT16, /**< 16-bit unsigned integer ([RFC 6020 sec 9.2](http://tools.ietf.org/html/rfc6020#section-9.2)) */
235 LY_TYPE_UINT32, /**< 32-bit unsigned integer ([RFC 6020 sec 9.2](http://tools.ietf.org/html/rfc6020#section-9.2)) */
236 LY_TYPE_UINT64, /**< 64-bit unsigned integer ([RFC 6020 sec 9.2](http://tools.ietf.org/html/rfc6020#section-9.2)) */
237 LY_TYPE_STRING, /**< Human-readable string ([RFC 6020 sec 9.4](http://tools.ietf.org/html/rfc6020#section-9.4)) */
238 LY_TYPE_BITS, /**< A set of bits or flags ([RFC 6020 sec 9.7](http://tools.ietf.org/html/rfc6020#section-9.7)) */
239 LY_TYPE_BOOL, /**< "true" or "false" ([RFC 6020 sec 9.5](http://tools.ietf.org/html/rfc6020#section-9.5)) */
240 LY_TYPE_DEC64, /**< 64-bit signed decimal number ([RFC 6020 sec 9.3](http://tools.ietf.org/html/rfc6020#section-9.3))*/
241 LY_TYPE_EMPTY, /**< A leaf that does not have any value ([RFC 6020 sec 9.11](http://tools.ietf.org/html/rfc6020#section-9.11)) */
242 LY_TYPE_ENUM, /**< Enumerated strings ([RFC 6020 sec 9.6](http://tools.ietf.org/html/rfc6020#section-9.6)) */
243 LY_TYPE_IDENT, /**< A reference to an abstract identity ([RFC 6020 sec 9.10](http://tools.ietf.org/html/rfc6020#section-9.10)) */
244 LY_TYPE_INST, /**< References a data tree node ([RFC 6020 sec 9.13](http://tools.ietf.org/html/rfc6020#section-9.13)) */
245 LY_TYPE_LEAFREF, /**< A reference to a leaf instance ([RFC 6020 sec 9.9](http://tools.ietf.org/html/rfc6020#section-9.9))*/
246 LY_TYPE_UNION, /**< Choice of member types ([RFC 6020 sec 9.12](http://tools.ietf.org/html/rfc6020#section-9.12)) */
247 LY_TYPE_INT8, /**< 8-bit signed integer ([RFC 6020 sec 9.2](http://tools.ietf.org/html/rfc6020#section-9.2)) */
248 LY_TYPE_INT16, /**< 16-bit signed integer ([RFC 6020 sec 9.2](http://tools.ietf.org/html/rfc6020#section-9.2)) */
249 LY_TYPE_INT32, /**< 32-bit signed integer ([RFC 6020 sec 9.2](http://tools.ietf.org/html/rfc6020#section-9.2)) */
Michal Vasko69730152020-10-09 16:30:07 +0200250 LY_TYPE_INT64 /**< 64-bit signed integer ([RFC 6020 sec 9.2](http://tools.ietf.org/html/rfc6020#section-9.2)) */
Radek Krejcie7b95092019-05-15 11:03:07 +0200251} LY_DATA_TYPE;
252#define LY_DATA_TYPE_COUNT 20 /**< Number of different types */
253
254/**
255 * @brief Stringified YANG built-in data types
256 */
Michal Vasko22df3f02020-08-24 13:29:22 +0200257extern const char *ly_data_type2str[LY_DATA_TYPE_COUNT];
Radek Krejcie7b95092019-05-15 11:03:07 +0200258
Radek Krejci2ff0d572020-05-21 15:27:28 +0200259/** @} trees */
Radek Krejcie7b95092019-05-15 11:03:07 +0200260
261#ifdef __cplusplus
262}
263#endif
264
265#endif /* LY_TREE_H_ */