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 | |
| 18 | #ifdef __cplusplus |
| 19 | extern "C" { |
| 20 | #endif |
| 21 | |
| 22 | /** |
Radek Krejci | e7b9509 | 2019-05-15 11:03:07 +0200 | [diff] [blame] | 23 | * @brief Macro selector for other LY_ARRAY_* macros, do not use directly! |
| 24 | */ |
| 25 | #define LY_ARRAY_SELECT(_1, _2, NAME, ...) NAME |
| 26 | |
| 27 | /** |
| 28 | * @brief Helper macro to go through sized-arrays with a pointer iterator. |
| 29 | * |
| 30 | * Use with opening curly bracket (`{`). |
| 31 | * |
| 32 | * @param[in] ARRAY Array to go through |
| 33 | * @param[in] TYPE Type of the records in the ARRAY |
| 34 | * @param[out] ITER Iterating pointer to the item being processed in each loop |
| 35 | */ |
| 36 | #define LY_ARRAY_FOR_ITER(ARRAY, TYPE, ITER) \ |
| 37 | for (ITER = ARRAY; \ |
| 38 | (ARRAY) && ((void*)ITER - (void*)ARRAY)/(sizeof(TYPE)) < (*((uint32_t*)(ARRAY) - 1)); \ |
| 39 | ITER = (void*)((TYPE*)ITER + 1)) |
| 40 | |
| 41 | /** |
| 42 | * @brief Helper macro to go through sized-arrays with a numeric iterator. |
| 43 | * |
| 44 | * Use with opening curly bracket (`{`). |
| 45 | * |
| 46 | * To access an item with the INDEX value, use always LY_ARRAY_INDEX macro! |
| 47 | * |
| 48 | * @param[in] ARRAY Array to go through |
| 49 | * @param[out] INDEX Iterating index of the item being processed in each loop |
| 50 | */ |
| 51 | #define LY_ARRAY_FOR_INDEX(ARRAY, INDEX) \ |
| 52 | for (INDEX = 0; \ |
| 53 | ARRAY && INDEX < (*((uint32_t*)(ARRAY) - 1)); \ |
| 54 | ++INDEX) |
| 55 | |
| 56 | /** |
| 57 | * @defgroup schematree Schema Tree |
| 58 | * @{ |
| 59 | * |
| 60 | * Data structures and functions to manipulate and access schema tree. |
| 61 | */ |
| 62 | |
| 63 | /** |
| 64 | * @brief Get a number of records in the ARRAY. |
| 65 | * |
| 66 | * Does not check if array exists! |
| 67 | */ |
| 68 | #define LY_ARRAY_SIZE(ARRAY) (*((uint32_t*)(ARRAY) - 1)) |
| 69 | |
| 70 | /** |
| 71 | * @brief Sized-array iterator (for-loop). |
| 72 | * |
| 73 | * Use with opening curly bracket (`{`). |
| 74 | * |
| 75 | * There are 2 variants: |
| 76 | * |
| 77 | * LY_ARRAY_FOR(ARRAY, TYPE, ITER) |
| 78 | * |
| 79 | * 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 |
| 80 | * providing the items of the ARRAY in the loops. This functionality is provided by LY_ARRAY_FOR_ITER macro |
| 81 | * |
| 82 | * LY_ARRAY_FOR(ARRAY, INDEX) |
| 83 | * |
| 84 | * The ARRAY is again a sized-array to go through, the INDEX is a variable (unsigned integer) for storing iterating ARRAY's index |
| 85 | * to access the items of ARRAY in the loops. This functionality is provided by LY_ARRAY_FOR_INDEX macro. |
| 86 | */ |
| 87 | #define LY_ARRAY_FOR(ARRAY, ...) LY_ARRAY_SELECT(__VA_ARGS__, LY_ARRAY_FOR_ITER, LY_ARRAY_FOR_INDEX)(ARRAY, __VA_ARGS__) |
| 88 | |
| 89 | /** |
| 90 | * @brief Macro to iterate via all sibling elements without affecting the list itself |
| 91 | * |
| 92 | * Works for all types of nodes despite it is data or schema tree, but all the |
| 93 | * parameters must be pointers to the same type. |
| 94 | * |
| 95 | * Use with opening curly bracket (`{`). All parameters must be of the same type. |
| 96 | * |
| 97 | * @param START Pointer to the starting element. |
| 98 | * @param ELEM Iterator. |
| 99 | */ |
| 100 | #define LY_LIST_FOR(START, ELEM) \ |
| 101 | for ((ELEM) = (START); \ |
| 102 | (ELEM); \ |
| 103 | (ELEM) = (ELEM)->next) |
| 104 | |
| 105 | /** |
| 106 | * @brief Macro to iterate via all sibling elements allowing to modify the list itself (e.g. removing elements) |
| 107 | * |
| 108 | * Use with opening curly bracket (`{`). All parameters must be of the same type. |
| 109 | * |
| 110 | * @param START Pointer to the starting element. |
| 111 | * @param NEXT Temporary storage to allow removing of the current iterator content. |
| 112 | * @param ELEM Iterator. |
| 113 | */ |
| 114 | #define LY_LIST_FOR_SAFE(START, NEXT, ELEM) \ |
| 115 | for ((ELEM) = (START); \ |
| 116 | (ELEM) ? (NEXT = (ELEM)->next, 1) : 0; \ |
| 117 | (ELEM) = (NEXT)) |
| 118 | |
| 119 | /** |
| 120 | * @brief YANG built-in types |
| 121 | */ |
| 122 | typedef enum |
| 123 | { |
| 124 | LY_TYPE_UNKNOWN = 0, /**< Unknown type */ |
| 125 | LY_TYPE_BINARY, /**< Any binary data ([RFC 6020 sec 9.8](http://tools.ietf.org/html/rfc6020#section-9.8)) */ |
| 126 | LY_TYPE_UINT8, /**< 8-bit unsigned integer ([RFC 6020 sec 9.2](http://tools.ietf.org/html/rfc6020#section-9.2)) */ |
| 127 | LY_TYPE_UINT16, /**< 16-bit unsigned integer ([RFC 6020 sec 9.2](http://tools.ietf.org/html/rfc6020#section-9.2)) */ |
| 128 | LY_TYPE_UINT32, /**< 32-bit unsigned integer ([RFC 6020 sec 9.2](http://tools.ietf.org/html/rfc6020#section-9.2)) */ |
| 129 | LY_TYPE_UINT64, /**< 64-bit unsigned integer ([RFC 6020 sec 9.2](http://tools.ietf.org/html/rfc6020#section-9.2)) */ |
| 130 | LY_TYPE_STRING, /**< Human-readable string ([RFC 6020 sec 9.4](http://tools.ietf.org/html/rfc6020#section-9.4)) */ |
| 131 | LY_TYPE_BITS, /**< A set of bits or flags ([RFC 6020 sec 9.7](http://tools.ietf.org/html/rfc6020#section-9.7)) */ |
| 132 | LY_TYPE_BOOL, /**< "true" or "false" ([RFC 6020 sec 9.5](http://tools.ietf.org/html/rfc6020#section-9.5)) */ |
| 133 | LY_TYPE_DEC64, /**< 64-bit signed decimal number ([RFC 6020 sec 9.3](http://tools.ietf.org/html/rfc6020#section-9.3))*/ |
| 134 | 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)) */ |
| 135 | LY_TYPE_ENUM, /**< Enumerated strings ([RFC 6020 sec 9.6](http://tools.ietf.org/html/rfc6020#section-9.6)) */ |
| 136 | LY_TYPE_IDENT, /**< A reference to an abstract identity ([RFC 6020 sec 9.10](http://tools.ietf.org/html/rfc6020#section-9.10)) */ |
| 137 | LY_TYPE_INST, /**< References a data tree node ([RFC 6020 sec 9.13](http://tools.ietf.org/html/rfc6020#section-9.13)) */ |
| 138 | LY_TYPE_LEAFREF, /**< A reference to a leaf instance ([RFC 6020 sec 9.9](http://tools.ietf.org/html/rfc6020#section-9.9))*/ |
| 139 | LY_TYPE_UNION, /**< Choice of member types ([RFC 6020 sec 9.12](http://tools.ietf.org/html/rfc6020#section-9.12)) */ |
| 140 | LY_TYPE_INT8, /**< 8-bit signed integer ([RFC 6020 sec 9.2](http://tools.ietf.org/html/rfc6020#section-9.2)) */ |
| 141 | LY_TYPE_INT16, /**< 16-bit signed integer ([RFC 6020 sec 9.2](http://tools.ietf.org/html/rfc6020#section-9.2)) */ |
| 142 | LY_TYPE_INT32, /**< 32-bit signed integer ([RFC 6020 sec 9.2](http://tools.ietf.org/html/rfc6020#section-9.2)) */ |
| 143 | LY_TYPE_INT64, /**< 64-bit signed integer ([RFC 6020 sec 9.2](http://tools.ietf.org/html/rfc6020#section-9.2)) */ |
| 144 | } LY_DATA_TYPE; |
| 145 | #define LY_DATA_TYPE_COUNT 20 /**< Number of different types */ |
| 146 | |
| 147 | /** |
| 148 | * @brief Stringified YANG built-in data types |
| 149 | */ |
| 150 | extern const char* ly_data_type2str[LY_DATA_TYPE_COUNT]; |
| 151 | |
Radek Krejci | 084289f | 2019-07-09 17:35:30 +0200 | [diff] [blame] | 152 | /** |
Radek Krejci | 13a57b6 | 2019-07-19 13:04:09 +0200 | [diff] [blame] | 153 | * @brief Callback provided by the data/schema parsers to type plugins to resolve (format-specific) mapping between prefixes used |
| 154 | * in the value strings to the YANG schemas. |
Radek Krejci | 084289f | 2019-07-09 17:35:30 +0200 | [diff] [blame] | 155 | * |
Radek Krejci | 13a57b6 | 2019-07-19 13:04:09 +0200 | [diff] [blame] | 156 | * Reverse function to ly_clb_get_prefix. |
| 157 | * |
| 158 | * XML uses XML namespaces, JSON uses schema names as prefixes, YIN/YANG uses prefixes of the imports. |
Radek Krejci | 084289f | 2019-07-09 17:35:30 +0200 | [diff] [blame] | 159 | * |
| 160 | * @param[in] ctx libyang context to find the schema. |
| 161 | * @param[in] prefix Prefix found in the value string |
| 162 | * @param[in] prefix_len Length of the @p prefix. |
| 163 | * @param[in] private Internal data needed by the callback. |
| 164 | * @return Pointer to the YANG schema identified by the provided prefix or NULL if no mapping found. |
| 165 | */ |
| 166 | typedef const struct lys_module *(*ly_clb_resolve_prefix)(struct ly_ctx *ctx, const char *prefix, size_t prefix_len, void *private); |
| 167 | |
Radek Krejci | 13a57b6 | 2019-07-19 13:04:09 +0200 | [diff] [blame] | 168 | /** |
| 169 | * @brief Callback provided by the data/schema printers to type plugins to resolve (format-specific) mapping between YANG module of a data object |
| 170 | * to prefixes used in the value strings. |
| 171 | * |
| 172 | * Reverse function to ly_clb_resolve_prefix. |
| 173 | * |
| 174 | * XML uses XML namespaces, JSON uses schema names as prefixes, YIN/YANG uses prefixes of the imports. |
| 175 | * |
| 176 | * @param[in] mod YANG module of the object. |
| 177 | * @param[in] private Internal data needed by the callback. |
| 178 | * @return String representing prefix for the object of the given YANG module @p mod. |
| 179 | */ |
| 180 | typedef const char *(*ly_clb_get_prefix)(const struct lys_module *mod, void *private); |
| 181 | |
Radek Krejci | e7b9509 | 2019-05-15 11:03:07 +0200 | [diff] [blame] | 182 | /** @} */ |
| 183 | |
| 184 | #ifdef __cplusplus |
| 185 | } |
| 186 | #endif |
| 187 | |
| 188 | #endif /* LY_TREE_H_ */ |