Radek Krejci | e7b9509 | 2019-05-15 11:03:07 +0200 | [diff] [blame] | 1 | /** |
| 2 | * @file tree.h |
| 3 | * @author Radek Krejci <rkrejci@cesnet.cz> |
| 4 | * @brief libyang geenric macros and functions to work with YANG schema or data trees. |
| 5 | * |
| 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 Vasko | ae867c7 | 2020-10-07 08:54:27 +0200 | [diff] [blame^] | 18 | #include <inttypes.h> |
Radek Krejci | 7eb54ba | 2020-05-18 16:30:04 +0200 | [diff] [blame] | 19 | |
Michal Vasko | 9f96a05 | 2020-03-10 09:41:45 +0100 | [diff] [blame] | 20 | #include "tree_data.h" |
| 21 | |
Radek Krejci | e7b9509 | 2019-05-15 11:03:07 +0200 | [diff] [blame] | 22 | #ifdef __cplusplus |
| 23 | extern "C" { |
| 24 | #endif |
| 25 | |
| 26 | /** |
Radek Krejci | 2ff0d57 | 2020-05-21 15:27:28 +0200 | [diff] [blame] | 27 | * @defgroup trees Trees |
| 28 | * |
| 29 | * Generic macros, functions, etc. to work with both [schema](@ref schematree) and [data](@ref datatree) trees. |
| 30 | * |
| 31 | * @{ |
| 32 | */ |
| 33 | |
| 34 | /** |
Radek Krejci | c4fa029 | 2020-05-14 10:54:49 +0200 | [diff] [blame] | 35 | * @brief Type (i.e. size) of the [sized array](@ref sizedarrays)'s size counter. |
Radek Krejci | 7eb54ba | 2020-05-18 16:30:04 +0200 | [diff] [blame] | 36 | * |
Michal Vasko | fd69e1d | 2020-07-03 11:57:17 +0200 | [diff] [blame] | 37 | * To print the value via a print format, use LY_PRI_ARRAY_COUNT_TYPE specifier. |
Radek Krejci | c4fa029 | 2020-05-14 10:54:49 +0200 | [diff] [blame] | 38 | */ |
Michal Vasko | fd69e1d | 2020-07-03 11:57:17 +0200 | [diff] [blame] | 39 | #define LY_ARRAY_COUNT_TYPE uint64_t |
Radek Krejci | c4fa029 | 2020-05-14 10:54:49 +0200 | [diff] [blame] | 40 | |
| 41 | /** |
Radek Krejci | 7eb54ba | 2020-05-18 16:30:04 +0200 | [diff] [blame] | 42 | * @brief Printing format specifier macro for LY_ARRAY_SIZE_TYPE values. |
| 43 | */ |
Michal Vasko | fd69e1d | 2020-07-03 11:57:17 +0200 | [diff] [blame] | 44 | #define LY_PRI_ARRAY_COUNT_TYPE PRIu64 |
Radek Krejci | 7eb54ba | 2020-05-18 16:30:04 +0200 | [diff] [blame] | 45 | |
| 46 | /** |
Radek Krejci | e7b9509 | 2019-05-15 11:03:07 +0200 | [diff] [blame] | 47 | * @brief Macro selector for other LY_ARRAY_* macros, do not use directly! |
| 48 | */ |
| 49 | #define LY_ARRAY_SELECT(_1, _2, NAME, ...) NAME |
| 50 | |
| 51 | /** |
| 52 | * @brief Helper macro to go through sized-arrays with a pointer iterator. |
| 53 | * |
| 54 | * Use with opening curly bracket (`{`). |
| 55 | * |
| 56 | * @param[in] ARRAY Array to go through |
| 57 | * @param[in] TYPE Type of the records in the ARRAY |
| 58 | * @param[out] ITER Iterating pointer to the item being processed in each loop |
| 59 | */ |
| 60 | #define LY_ARRAY_FOR_ITER(ARRAY, TYPE, ITER) \ |
| 61 | for (ITER = ARRAY; \ |
Michal Vasko | fd69e1d | 2020-07-03 11:57:17 +0200 | [diff] [blame] | 62 | (ARRAY) && ((void*)ITER - (void*)ARRAY)/(sizeof(TYPE)) < (*((LY_ARRAY_COUNT_TYPE*)(ARRAY) - 1)); \ |
Radek Krejci | e7b9509 | 2019-05-15 11:03:07 +0200 | [diff] [blame] | 63 | ITER = (void*)((TYPE*)ITER + 1)) |
| 64 | |
| 65 | /** |
| 66 | * @brief Helper macro to go through sized-arrays with a numeric iterator. |
| 67 | * |
| 68 | * Use with opening curly bracket (`{`). |
| 69 | * |
| 70 | * To access an item with the INDEX value, use always LY_ARRAY_INDEX macro! |
| 71 | * |
| 72 | * @param[in] ARRAY Array to go through |
| 73 | * @param[out] INDEX Iterating index of the item being processed in each loop |
| 74 | */ |
| 75 | #define LY_ARRAY_FOR_INDEX(ARRAY, INDEX) \ |
| 76 | for (INDEX = 0; \ |
Michal Vasko | fd69e1d | 2020-07-03 11:57:17 +0200 | [diff] [blame] | 77 | ARRAY && INDEX < (*((LY_ARRAY_COUNT_TYPE*)(ARRAY) - 1)); \ |
Radek Krejci | e7b9509 | 2019-05-15 11:03:07 +0200 | [diff] [blame] | 78 | ++INDEX) |
| 79 | |
| 80 | /** |
Michal Vasko | fd69e1d | 2020-07-03 11:57:17 +0200 | [diff] [blame] | 81 | * @brief Get the number of records in the ARRAY. |
Radek Krejci | e7b9509 | 2019-05-15 11:03:07 +0200 | [diff] [blame] | 82 | * |
| 83 | * Does not check if array exists! |
| 84 | */ |
Michal Vasko | fd69e1d | 2020-07-03 11:57:17 +0200 | [diff] [blame] | 85 | #define LY_ARRAY_COUNT(ARRAY) (*((LY_ARRAY_COUNT_TYPE*)(ARRAY) - 1)) |
Radek Krejci | e7b9509 | 2019-05-15 11:03:07 +0200 | [diff] [blame] | 86 | |
| 87 | /** |
| 88 | * @brief Sized-array iterator (for-loop). |
| 89 | * |
| 90 | * Use with opening curly bracket (`{`). |
| 91 | * |
| 92 | * There are 2 variants: |
| 93 | * |
| 94 | * LY_ARRAY_FOR(ARRAY, TYPE, ITER) |
| 95 | * |
| 96 | * 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 |
| 97 | * providing the items of the ARRAY in the loops. This functionality is provided by LY_ARRAY_FOR_ITER macro |
| 98 | * |
| 99 | * LY_ARRAY_FOR(ARRAY, INDEX) |
| 100 | * |
Michal Vasko | fd69e1d | 2020-07-03 11:57:17 +0200 | [diff] [blame] | 101 | * 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 Krejci | e7b9509 | 2019-05-15 11:03:07 +0200 | [diff] [blame] | 102 | * to access the items of ARRAY in the loops. This functionality is provided by LY_ARRAY_FOR_INDEX macro. |
| 103 | */ |
| 104 | #define LY_ARRAY_FOR(ARRAY, ...) LY_ARRAY_SELECT(__VA_ARGS__, LY_ARRAY_FOR_ITER, LY_ARRAY_FOR_INDEX)(ARRAY, __VA_ARGS__) |
| 105 | |
| 106 | /** |
| 107 | * @brief Macro to iterate via all sibling elements without affecting the list itself |
| 108 | * |
| 109 | * Works for all types of nodes despite it is data or schema tree, but all the |
| 110 | * parameters must be pointers to the same type. |
| 111 | * |
| 112 | * Use with opening curly bracket (`{`). All parameters must be of the same type. |
| 113 | * |
| 114 | * @param START Pointer to the starting element. |
| 115 | * @param ELEM Iterator. |
| 116 | */ |
| 117 | #define LY_LIST_FOR(START, ELEM) \ |
| 118 | for ((ELEM) = (START); \ |
| 119 | (ELEM); \ |
| 120 | (ELEM) = (ELEM)->next) |
| 121 | |
| 122 | /** |
| 123 | * @brief Macro to iterate via all sibling elements allowing to modify the list itself (e.g. removing elements) |
| 124 | * |
| 125 | * Use with opening curly bracket (`{`). All parameters must be of the same type. |
| 126 | * |
| 127 | * @param START Pointer to the starting element. |
| 128 | * @param NEXT Temporary storage to allow removing of the current iterator content. |
| 129 | * @param ELEM Iterator. |
| 130 | */ |
| 131 | #define LY_LIST_FOR_SAFE(START, NEXT, ELEM) \ |
| 132 | for ((ELEM) = (START); \ |
| 133 | (ELEM) ? (NEXT = (ELEM)->next, 1) : 0; \ |
| 134 | (ELEM) = (NEXT)) |
| 135 | |
| 136 | /** |
Michal Vasko | 4c583e8 | 2020-07-17 12:16:14 +0200 | [diff] [blame] | 137 | * @brief Macro to iterate via all schema node data instances in data siblings. |
| 138 | * |
| 139 | * @param START Pointer to the starting sibling. Even if it is not first, all the siblings are searched. |
| 140 | * @param SCHEMA Schema node of the searched instances. |
| 141 | * @param ELEM Iterator. |
| 142 | */ |
| 143 | #define LYD_LIST_FOR_INST(START, SCHEMA, ELEM) \ |
| 144 | for (lyd_find_sibling_val(START, SCHEMA, NULL, 0, &(ELEM)); \ |
| 145 | (ELEM) && ((ELEM)->schema == (SCHEMA)); \ |
| 146 | (ELEM) = (ELEM)->next) |
| 147 | |
| 148 | /** |
| 149 | * @brief Macro to iterate via all schema node data instances in data siblings allowing to modify the list itself. |
| 150 | * |
| 151 | * @param START Pointer to the starting sibling. Even if it is not first, all the siblings are searched. |
| 152 | * @param SCHEMA Schema node of the searched instances. |
| 153 | * @param NEXT Temporary storage to allow removing of the current iterator content. |
| 154 | * @param ELEM Iterator. |
| 155 | */ |
| 156 | #define LYD_LIST_FOR_INST_SAFE(START, SCHEMA, NEXT, ELEM) \ |
| 157 | for (lyd_find_sibling_val(START, SCHEMA, NULL, 0, &(ELEM)); \ |
| 158 | (ELEM) && ((ELEM)->schema == (SCHEMA)) ? ((NEXT) = (ELEM)->next, 1) : 0; \ |
| 159 | (ELEM) = (NEXT)) |
| 160 | |
| 161 | /** |
Radek Krejci | e7b9509 | 2019-05-15 11:03:07 +0200 | [diff] [blame] | 162 | * @brief YANG built-in types |
| 163 | */ |
| 164 | typedef enum |
| 165 | { |
| 166 | LY_TYPE_UNKNOWN = 0, /**< Unknown type */ |
| 167 | LY_TYPE_BINARY, /**< Any binary data ([RFC 6020 sec 9.8](http://tools.ietf.org/html/rfc6020#section-9.8)) */ |
| 168 | LY_TYPE_UINT8, /**< 8-bit unsigned integer ([RFC 6020 sec 9.2](http://tools.ietf.org/html/rfc6020#section-9.2)) */ |
| 169 | LY_TYPE_UINT16, /**< 16-bit unsigned integer ([RFC 6020 sec 9.2](http://tools.ietf.org/html/rfc6020#section-9.2)) */ |
| 170 | LY_TYPE_UINT32, /**< 32-bit unsigned integer ([RFC 6020 sec 9.2](http://tools.ietf.org/html/rfc6020#section-9.2)) */ |
| 171 | LY_TYPE_UINT64, /**< 64-bit unsigned integer ([RFC 6020 sec 9.2](http://tools.ietf.org/html/rfc6020#section-9.2)) */ |
| 172 | LY_TYPE_STRING, /**< Human-readable string ([RFC 6020 sec 9.4](http://tools.ietf.org/html/rfc6020#section-9.4)) */ |
| 173 | LY_TYPE_BITS, /**< A set of bits or flags ([RFC 6020 sec 9.7](http://tools.ietf.org/html/rfc6020#section-9.7)) */ |
| 174 | LY_TYPE_BOOL, /**< "true" or "false" ([RFC 6020 sec 9.5](http://tools.ietf.org/html/rfc6020#section-9.5)) */ |
| 175 | LY_TYPE_DEC64, /**< 64-bit signed decimal number ([RFC 6020 sec 9.3](http://tools.ietf.org/html/rfc6020#section-9.3))*/ |
| 176 | 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)) */ |
| 177 | LY_TYPE_ENUM, /**< Enumerated strings ([RFC 6020 sec 9.6](http://tools.ietf.org/html/rfc6020#section-9.6)) */ |
| 178 | LY_TYPE_IDENT, /**< A reference to an abstract identity ([RFC 6020 sec 9.10](http://tools.ietf.org/html/rfc6020#section-9.10)) */ |
| 179 | LY_TYPE_INST, /**< References a data tree node ([RFC 6020 sec 9.13](http://tools.ietf.org/html/rfc6020#section-9.13)) */ |
| 180 | LY_TYPE_LEAFREF, /**< A reference to a leaf instance ([RFC 6020 sec 9.9](http://tools.ietf.org/html/rfc6020#section-9.9))*/ |
| 181 | LY_TYPE_UNION, /**< Choice of member types ([RFC 6020 sec 9.12](http://tools.ietf.org/html/rfc6020#section-9.12)) */ |
| 182 | LY_TYPE_INT8, /**< 8-bit signed integer ([RFC 6020 sec 9.2](http://tools.ietf.org/html/rfc6020#section-9.2)) */ |
| 183 | LY_TYPE_INT16, /**< 16-bit signed integer ([RFC 6020 sec 9.2](http://tools.ietf.org/html/rfc6020#section-9.2)) */ |
| 184 | LY_TYPE_INT32, /**< 32-bit signed integer ([RFC 6020 sec 9.2](http://tools.ietf.org/html/rfc6020#section-9.2)) */ |
| 185 | LY_TYPE_INT64, /**< 64-bit signed integer ([RFC 6020 sec 9.2](http://tools.ietf.org/html/rfc6020#section-9.2)) */ |
| 186 | } LY_DATA_TYPE; |
| 187 | #define LY_DATA_TYPE_COUNT 20 /**< Number of different types */ |
| 188 | |
| 189 | /** |
| 190 | * @brief Stringified YANG built-in data types |
| 191 | */ |
Michal Vasko | 22df3f0 | 2020-08-24 13:29:22 +0200 | [diff] [blame] | 192 | extern const char *ly_data_type2str[LY_DATA_TYPE_COUNT]; |
Radek Krejci | e7b9509 | 2019-05-15 11:03:07 +0200 | [diff] [blame] | 193 | |
Radek Krejci | 2ff0d57 | 2020-05-21 15:27:28 +0200 | [diff] [blame] | 194 | /** @} trees */ |
Radek Krejci | e7b9509 | 2019-05-15 11:03:07 +0200 | [diff] [blame] | 195 | |
| 196 | #ifdef __cplusplus |
| 197 | } |
| 198 | #endif |
| 199 | |
| 200 | #endif /* LY_TREE_H_ */ |