libyang 3.1.0
libyang is YANG data modelling language parser and toolkit written (and providing API) in C.
Loading...
Searching...
No Matches
instanceid.c
Go to the documentation of this file.
1
14#define _GNU_SOURCE /* strdup */
15
16#include "plugins_types.h"
17
18#include <stdint.h>
19#include <stdlib.h>
20
21#include "libyang.h"
22
23/* additional internal headers for some useful simple macros */
24#include "compat.h"
25#include "ly_common.h"
26#include "path.h"
27#include "plugins_internal.h" /* LY_TYPE_*_STR */
28
47static LY_ERR
48instanceid_path2str(const struct ly_path *path, LY_VALUE_FORMAT format, void *prefix_data, char **str)
49{
50 LY_ERR ret = LY_SUCCESS;
52 char *result = NULL, quot;
53 const struct lys_module *mod = NULL, *local_mod = NULL;
54 struct ly_set *mods = NULL;
55 ly_bool inherit_prefix = 0, d;
56 const char *strval;
57
58 switch (format) {
59 case LY_VALUE_XML:
60 /* null the local module so that all the prefixes are printed */
61 mods = prefix_data;
62 local_mod = mods->objs[0];
63 mods->objs[0] = NULL;
64
65 /* fallthrough */
66 case LY_VALUE_SCHEMA:
68 /* everything is prefixed */
69 inherit_prefix = 0;
70 break;
71 case LY_VALUE_CANON:
72 case LY_VALUE_JSON:
73 case LY_VALUE_LYB:
74 case LY_VALUE_STR_NS:
75 /* the same prefix is inherited and skipped */
76 inherit_prefix = 1;
77 break;
78 }
79
80 LY_ARRAY_FOR(path, u) {
81 /* new node */
82 if (!inherit_prefix || (mod != path[u].node->module)) {
83 mod = path[u].node->module;
84 ret = ly_strcat(&result, "/%s:%s", lyplg_type_get_prefix(mod, format, prefix_data), path[u].node->name);
85 } else {
86 ret = ly_strcat(&result, "/%s", path[u].node->name);
87 }
88 LY_CHECK_GOTO(ret, cleanup);
89
90 /* node predicates */
91 LY_ARRAY_FOR(path[u].predicates, v) {
92 struct ly_path_predicate *pred = &path[u].predicates[v];
93
94 switch (pred->type) {
95 case LY_PATH_PREDTYPE_POSITION:
96 /* position predicate */
97 ret = ly_strcat(&result, "[%" PRIu64 "]", pred->position);
98 break;
99 case LY_PATH_PREDTYPE_LIST:
100 /* key-predicate */
101 strval = pred->value.realtype->plugin->print(path[u].node->module->ctx, &pred->value, format, prefix_data,
102 &d, NULL);
103
104 /* default quote */
105 quot = '\'';
106 if (strchr(strval, quot)) {
107 quot = '"';
108 }
109 if (inherit_prefix) {
110 /* always the same prefix as the parent */
111 ret = ly_strcat(&result, "[%s=%c%s%c]", pred->key->name, quot, strval, quot);
112 } else {
113 ret = ly_strcat(&result, "[%s:%s=%c%s%c]", lyplg_type_get_prefix(pred->key->module, format, prefix_data),
114 pred->key->name, quot, strval, quot);
115 }
116 if (d) {
117 free((char *)strval);
118 }
119 break;
120 case LY_PATH_PREDTYPE_LEAFLIST:
121 /* leaf-list-predicate */
122 strval = pred->value.realtype->plugin->print(path[u].node->module->ctx, &pred->value, format, prefix_data,
123 &d, NULL);
124
125 /* default quote */
126 quot = '\'';
127 if (strchr(strval, quot)) {
128 quot = '"';
129 }
130 ret = ly_strcat(&result, "[.=%c%s%c]", quot, strval, quot);
131 if (d) {
132 free((char *)strval);
133 }
134 break;
135 case LY_PATH_PREDTYPE_LIST_VAR:
136 LOGINT(path[u].node->module->ctx);
137 ret = LY_EINT;
138 goto cleanup;
139 }
140
141 LY_CHECK_GOTO(ret, cleanup);
142 }
143 }
144
145cleanup:
146 if (local_mod) {
147 mods->objs[0] = (void *)local_mod;
148 }
149 if (ret) {
150 free(result);
151 } else {
152 *str = result;
153 }
154 return ret;
155}
156
157LIBYANG_API_DEF LY_ERR
158lyplg_type_store_instanceid(const struct ly_ctx *ctx, const struct lysc_type *type, const void *value, size_t value_len,
159 uint32_t options, LY_VALUE_FORMAT format, void *prefix_data, uint32_t hints, const struct lysc_node *ctx_node,
160 struct lyd_value *storage, struct lys_glob_unres *unres, struct ly_err_item **err)
161{
162 LY_ERR ret = LY_SUCCESS;
163 struct lysc_type_instanceid *type_inst = (struct lysc_type_instanceid *)type;
164 struct ly_path *path;
165 char *canon;
166
167 /* init storage */
168 memset(storage, 0, sizeof *storage);
169 storage->realtype = type;
170
171 /* check hints */
172 ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
173 LY_CHECK_GOTO(ret, cleanup);
174
175 /* compile instance-identifier into path */
176 if (format == LY_VALUE_LYB) {
177 /* value in LYB format is the same as in JSON format. */
178 ret = lyplg_type_lypath_new(ctx, value, value_len, options, LY_VALUE_JSON, prefix_data, ctx_node,
179 unres, &path, err);
180 } else {
181 ret = lyplg_type_lypath_new(ctx, value, value_len, options, format, prefix_data, ctx_node,
182 unres, &path, err);
183 }
184 LY_CHECK_GOTO(ret, cleanup);
185
186 /* store value */
187 storage->target = path;
188
189 /* check status */
190 ret = lyplg_type_lypath_check_status(ctx_node, path, format, prefix_data, err);
191 LY_CHECK_GOTO(ret, cleanup);
192
193 /* store canonical value */
194 if (format == LY_VALUE_CANON) {
195 if (options & LYPLG_TYPE_STORE_DYNAMIC) {
196 ret = lydict_insert_zc(ctx, (char *)value, &storage->_canonical);
197 options &= ~LYPLG_TYPE_STORE_DYNAMIC;
198 LY_CHECK_GOTO(ret, cleanup);
199 } else {
200 ret = lydict_insert(ctx, value, value_len, &storage->_canonical);
201 LY_CHECK_GOTO(ret, cleanup);
202 }
203 } else {
204 /* JSON format with prefix is the canonical one */
205 ret = instanceid_path2str(path, LY_VALUE_JSON, NULL, &canon);
206 LY_CHECK_GOTO(ret, cleanup);
207
208 ret = lydict_insert_zc(ctx, canon, &storage->_canonical);
209 LY_CHECK_GOTO(ret, cleanup);
210 }
211
212cleanup:
213 if (options & LYPLG_TYPE_STORE_DYNAMIC) {
214 free((void *)value);
215 }
216
217 if (ret) {
218 lyplg_type_free_instanceid(ctx, storage);
219 }
220 if (!ret && type_inst->require_instance) {
221 /* needs to be resolved */
222 return LY_EINCOMPLETE;
223 } else {
224 return ret;
225 }
226}
227
228LIBYANG_API_DEF LY_ERR
229lyplg_type_validate_instanceid(const struct ly_ctx *ctx, const struct lysc_type *UNUSED(type),
230 const struct lyd_node *ctx_node, const struct lyd_node *tree, struct lyd_value *storage,
231 struct ly_err_item **err)
232{
233 LY_ERR ret = LY_SUCCESS;
234 struct lysc_type_instanceid *type_inst = (struct lysc_type_instanceid *)storage->realtype;
235 const char *value;
236 char *path;
237
238 *err = NULL;
239
240 if (!type_inst->require_instance) {
241 /* redundant to resolve */
242 return LY_SUCCESS;
243 }
244
245 /* find the target in data */
246 if ((ret = ly_path_eval(storage->target, tree, NULL, NULL))) {
247 value = lyd_value_get_canonical(ctx, storage);
248 path = lyd_path(ctx_node, LYD_PATH_STD, NULL, 0);
249 return ly_err_new(err, ret, LYVE_DATA, path, strdup("instance-required"), LY_ERRMSG_NOINST, value);
250 }
251
252 return LY_SUCCESS;
253}
254
255LIBYANG_API_DEF LY_ERR
256lyplg_type_compare_instanceid(const struct ly_ctx *ctx, const struct lyd_value *val1, const struct lyd_value *val2)
257{
258 return lyplg_type_compare_simple(ctx, val1, val2);
259}
260
261LIBYANG_API_DEF int
262lyplg_type_sort_instanceid(const struct ly_ctx *ctx, const struct lyd_value *val1, const struct lyd_value *val2)
263{
264 return lyplg_type_sort_simple(ctx, val1, val2);
265}
266
267LIBYANG_API_DEF const void *
268lyplg_type_print_instanceid(const struct ly_ctx *UNUSED(ctx), const struct lyd_value *value, LY_VALUE_FORMAT format,
269 void *prefix_data, ly_bool *dynamic, size_t *value_len)
270{
271 char *ret;
272
273 if ((format == LY_VALUE_CANON) || (format == LY_VALUE_JSON) || (format == LY_VALUE_LYB)) {
274 if (dynamic) {
275 *dynamic = 0;
276 }
277 if (value_len) {
278 *value_len = strlen(value->_canonical);
279 }
280 return value->_canonical;
281 }
282
283 /* print the value in the specific format */
284 if (instanceid_path2str(value->target, format, prefix_data, &ret)) {
285 return NULL;
286 }
287 *dynamic = 1;
288 if (value_len) {
289 *value_len = strlen(ret);
290 }
291 return ret;
292}
293
294LIBYANG_API_DEF LY_ERR
295lyplg_type_dup_instanceid(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup)
296{
297 LY_ERR ret;
298
299 memset(dup, 0, sizeof *dup);
300
301 /* canonical value */
302 ret = lydict_insert(ctx, original->_canonical, 0, &dup->_canonical);
303 LY_CHECK_GOTO(ret, error);
304
305 /* copy path */
306 ret = ly_path_dup(ctx, original->target, &dup->target);
307 LY_CHECK_GOTO(ret, error);
308
309 dup->realtype = original->realtype;
310 return LY_SUCCESS;
311
312error:
314 return ret;
315}
316
317LIBYANG_API_DEF void
318lyplg_type_free_instanceid(const struct ly_ctx *ctx, struct lyd_value *value)
319{
320 lydict_remove(ctx, value->_canonical);
321 value->_canonical = NULL;
322 ly_path_free(ctx, value->target);
323}
324
333 {
334 .module = "",
335 .revision = NULL,
336 .name = LY_TYPE_INST_STR,
337
338 .plugin.id = "libyang 2 - instance-identifier, version 1",
339 .plugin.store = lyplg_type_store_instanceid,
340 .plugin.validate = lyplg_type_validate_instanceid,
341 .plugin.compare = lyplg_type_compare_instanceid,
342 .plugin.sort = lyplg_type_sort_instanceid,
343 .plugin.print = lyplg_type_print_instanceid,
344 .plugin.duplicate = lyplg_type_dup_instanceid,
345 .plugin.free = lyplg_type_free_instanceid,
346 .plugin.lyb_data_len = -1,
347 },
348 {0}
349};
libyang context handler.
LIBYANG_API_DECL LY_ERR lydict_insert(const struct ly_ctx *ctx, const char *value, size_t len, const char **str_p)
Insert string into dictionary. If the string is already present, only a reference counter is incremen...
LIBYANG_API_DECL LY_ERR lydict_remove(const struct ly_ctx *ctx, const char *value)
Remove specified string from the dictionary. It decrement reference counter for the string and if it ...
LIBYANG_API_DECL LY_ERR lydict_insert_zc(const struct ly_ctx *ctx, char *value, const char **str_p)
Insert string into dictionary - zerocopy version. If the string is already present,...
LY_ERR
libyang's error codes returned by the libyang functions.
Definition log.h:237
@ LYVE_DATA
Definition log.h:274
@ LY_EINT
Definition log.h:244
@ LY_SUCCESS
Definition log.h:238
@ LY_EINCOMPLETE
Definition log.h:247
Libyang full error structure.
Definition log.h:282
Structure to hold a set of (not necessary somehow connected) objects. Usually used for lyd_node,...
Definition set.h:47
const char *const char * revision
LIBYANG_API_DECL const char * lyplg_type_get_prefix(const struct lys_module *mod, LY_VALUE_FORMAT format, void *prefix_data)
Get format-specific prefix for a module.
LIBYANG_API_DECL LY_ERR lyplg_type_lypath_check_status(const struct lysc_node *ctx_node, const struct ly_path *path, LY_VALUE_FORMAT format, void *prefix_data, struct ly_err_item **err)
Check that the lypath instance-identifier value is allowed based on the status of the nodes.
LIBYANG_API_DECL LY_ERR lyplg_type_check_hints(uint32_t hints, const char *value, size_t value_len, LY_DATA_TYPE type, int *base, struct ly_err_item **err)
Check that the type is suitable for the parser's hints (if any) in the specified format.
LIBYANG_API_DECL LY_ERR ly_err_new(struct ly_err_item **err, LY_ERR ecode, LY_VECODE vecode, char *data_path, char *apptag, const char *err_format,...) _FORMAT_PRINTF(6
Create and fill error structure.
LIBYANG_API_DECL LY_ERR lyplg_type_lypath_new(const struct ly_ctx *ctx, const char *value, size_t value_len, uint32_t options, LY_VALUE_FORMAT format, void *prefix_data, const struct lysc_node *ctx_node, struct lys_glob_unres *unres, struct ly_path **path, struct ly_err_item **err)
Helper function to create internal schema path representation for instance-identifier value represent...
LIBYANG_API_DEF LY_ERR lyplg_type_store_instanceid(const struct ly_ctx *ctx, const struct lysc_type *type, const void *value, size_t value_len, uint32_t options, LY_VALUE_FORMAT format, void *prefix_data, uint32_t hints, const struct lysc_node *ctx_node, struct lyd_value *storage, struct lys_glob_unres *unres, struct ly_err_item **err)
Implementation of lyplg_type_store_clb for the built-in instance-identifier type.
Definition instanceid.c:158
LIBYANG_API_DEF LY_ERR lyplg_type_compare_instanceid(const struct ly_ctx *ctx, const struct lyd_value *val1, const struct lyd_value *val2)
Implementation of lyplg_type_compare_clb for the built-in instance-identifier type.
Definition instanceid.c:256
LIBYANG_API_DEF int lyplg_type_sort_instanceid(const struct ly_ctx *ctx, const struct lyd_value *val1, const struct lyd_value *val2)
Implementation of lyplg_type_sort_clb for the built-in instance-identifier type.
Definition instanceid.c:262
LIBYANG_API_DEF LY_ERR lyplg_type_dup_instanceid(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup)
Implementation of lyplg_type_dup_clb for the built-in instance-identifier type.
Definition instanceid.c:295
LIBYANG_API_DEF void lyplg_type_free_instanceid(const struct ly_ctx *ctx, struct lyd_value *value)
Implementation of lyplg_type_free_clb for the built-in instance-identifier type.
Definition instanceid.c:318
LIBYANG_API_DEF int lyplg_type_sort_simple(const struct ly_ctx *ctx, const struct lyd_value *val1, const struct lyd_value *val2)
Implementation of lyplg_type_sort_clb for a generic simple type.
LIBYANG_API_DECL LY_ERR lyplg_type_compare_simple(const struct ly_ctx *ctx, const struct lyd_value *val1, const struct lyd_value *val2)
Implementation of lyplg_type_compare_clb for a generic simple type.
#define LYPLG_TYPE_STORE_DYNAMIC
LY_DATA_TYPE basetype
Available YANG schema tree structures representing YANG module.
Compiled YANG data node.
#define LY_ARRAY_FOR(ARRAY,...)
Sized-array iterator (for-loop).
Definition tree.h:167
LY_VALUE_FORMAT
All kinds of supported value formats and prefix mappings to modules.
Definition tree.h:234
#define LY_ARRAY_COUNT_TYPE
Type (i.e. size) of the sized array's size counter.
Definition tree.h:104
@ LY_VALUE_JSON
Definition tree.h:239
@ LY_VALUE_SCHEMA
Definition tree.h:236
@ LY_VALUE_CANON
Definition tree.h:235
@ LY_VALUE_XML
Definition tree.h:238
@ LY_VALUE_STR_NS
Definition tree.h:241
@ LY_VALUE_SCHEMA_RESOLVED
Definition tree.h:237
@ LY_VALUE_LYB
Definition tree.h:240
LIBYANG_API_DEF const void * lyplg_type_print_instanceid(const struct ly_ctx *UNUSED(ctx), const struct lyd_value *value, LY_VALUE_FORMAT format, void *prefix_data, ly_bool *dynamic, size_t *value_len)
Definition instanceid.c:268
LIBYANG_API_DEF LY_ERR lyplg_type_validate_instanceid(const struct ly_ctx *ctx, const struct lysc_type *UNUSED(type), const struct lyd_node *ctx_node, const struct lyd_node *tree, struct lyd_value *storage, struct ly_err_item **err)
Definition instanceid.c:229
const struct lyplg_type_record plugins_instanceid[]
Plugin information for instance-identifier type implementation.
Definition instanceid.c:332
The main libyang public header.
uint8_t ly_bool
Type to indicate boolean value.
Definition log.h:35
API for (user) types plugins.
LIBYANG_API_DECL const char * lyd_value_get_canonical(const struct ly_ctx *ctx, const struct lyd_value *value)
Get the (canonical) value of a lyd_value.
LIBYANG_API_DECL char * lyd_path(const struct lyd_node *node, LYD_PATH_TYPE pathtype, char *buffer, size_t buflen)
Generate path of the given node in the requested format.
@ LYD_PATH_STD
Definition tree_data.h:2332
const struct lysc_type * realtype
Definition tree_data.h:575
const char * _canonical
Definition tree_data.h:572
Generic structure for a data node.
Definition tree_data.h:799
YANG data representation.
Definition tree_data.h:571