libyang  2.1.128
libyang is YANG data modelling language parser and toolkit written (and providing API) in C.
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
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 "common.h"
25 #include "compat.h"
26 #include "path.h"
27 #include "plugins_internal.h" /* LY_TYPE_*_STR */
28 
47 static LY_ERR
48 instanceid_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 
145 cleanup:
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 
157 LIBYANG_API_DEF LY_ERR
158 lyplg_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 
212 cleanup:
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 
228 LIBYANG_API_DEF LY_ERR
229 lyplg_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 = lyplg_type_print_instanceid(ctx, storage, LY_VALUE_CANON, NULL, NULL, NULL);
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 
255 LIBYANG_API_DEF LY_ERR
256 lyplg_type_compare_instanceid(const struct lyd_value *val1, const struct lyd_value *val2)
257 {
258  LY_ARRAY_COUNT_TYPE u, v;
259 
260  if (val1->realtype != val2->realtype) {
261  return LY_ENOT;
262  }
263 
264  if (val1 == val2) {
265  return LY_SUCCESS;
266  } else if (LY_ARRAY_COUNT(val1->target) != LY_ARRAY_COUNT(val2->target)) {
267  return LY_ENOT;
268  }
269 
270  LY_ARRAY_FOR(val1->target, u) {
271  struct ly_path *s1 = &val1->target[u];
272  struct ly_path *s2 = &val2->target[u];
273 
274  if ((s1->node != s2->node) || (s1->predicates && (LY_ARRAY_COUNT(s1->predicates) != LY_ARRAY_COUNT(s2->predicates)))) {
275  return LY_ENOT;
276  }
277  LY_ARRAY_FOR(s1->predicates, v) {
278  struct ly_path_predicate *pred1 = &s1->predicates[v];
279  struct ly_path_predicate *pred2 = &s2->predicates[v];
280 
281  if (pred1->type != pred2->type) {
282  return LY_ENOT;
283  }
284 
285  switch (pred1->type) {
286  case LY_PATH_PREDTYPE_POSITION:
287  /* position predicate */
288  if (pred1->position != pred2->position) {
289  return LY_ENOT;
290  }
291  break;
292  case LY_PATH_PREDTYPE_LIST:
293  /* key-predicate */
294  if ((pred1->key != pred2->key) ||
295  ((struct lysc_node_leaf *)pred1->key)->type->plugin->compare(&pred1->value, &pred2->value)) {
296  return LY_ENOT;
297  }
298  break;
299  case LY_PATH_PREDTYPE_LEAFLIST:
300  /* leaf-list predicate */
301  if (((struct lysc_node_leaflist *)s1->node)->type->plugin->compare(&pred1->value, &pred2->value)) {
302  return LY_ENOT;
303  }
304  break;
305  case LY_PATH_PREDTYPE_LIST_VAR:
306  /* key-predicate with a variable */
307  if ((pred1->key != pred2->key) || strcmp(pred1->variable, pred2->variable)) {
308  return LY_ENOT;
309  }
310  break;
311  }
312  }
313  }
314 
315  return LY_SUCCESS;
316 }
317 
318 LIBYANG_API_DEF const void *
319 lyplg_type_print_instanceid(const struct ly_ctx *UNUSED(ctx), const struct lyd_value *value, LY_VALUE_FORMAT format,
320  void *prefix_data, ly_bool *dynamic, size_t *value_len)
321 {
322  char *ret;
323 
324  if ((format == LY_VALUE_CANON) || (format == LY_VALUE_JSON) || (format == LY_VALUE_LYB)) {
325  if (dynamic) {
326  *dynamic = 0;
327  }
328  if (value_len) {
329  *value_len = strlen(value->_canonical);
330  }
331  return value->_canonical;
332  }
333 
334  /* print the value in the specific format */
335  if (instanceid_path2str(value->target, format, prefix_data, &ret)) {
336  return NULL;
337  }
338  *dynamic = 1;
339  if (value_len) {
340  *value_len = strlen(ret);
341  }
342  return ret;
343 }
344 
345 LIBYANG_API_DEF LY_ERR
346 lyplg_type_dup_instanceid(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup)
347 {
348  LY_ERR ret;
349 
350  memset(dup, 0, sizeof *dup);
351 
352  /* canonical value */
353  ret = lydict_insert(ctx, original->_canonical, 0, &dup->_canonical);
354  LY_CHECK_GOTO(ret, error);
355 
356  /* copy path */
357  ret = ly_path_dup(ctx, original->target, &dup->target);
358  LY_CHECK_GOTO(ret, error);
359 
360  dup->realtype = original->realtype;
361  return LY_SUCCESS;
362 
363 error:
364  lyplg_type_free_instanceid(ctx, dup);
365  return ret;
366 }
367 
368 LIBYANG_API_DEF void
369 lyplg_type_free_instanceid(const struct ly_ctx *ctx, struct lyd_value *value)
370 {
371  lydict_remove(ctx, value->_canonical);
372  value->_canonical = NULL;
373  ly_path_free(ctx, value->target);
374 }
375 
384  {
385  .module = "",
386  .revision = NULL,
387  .name = LY_TYPE_INST_STR,
388 
389  .plugin.id = "libyang 2 - instance-identifier, version 1",
390  .plugin.store = lyplg_type_store_instanceid,
391  .plugin.validate = lyplg_type_validate_instanceid,
392  .plugin.compare = lyplg_type_compare_instanceid,
393  .plugin.sort = NULL,
394  .plugin.print = lyplg_type_print_instanceid,
395  .plugin.duplicate = lyplg_type_dup_instanceid,
396  .plugin.free = lyplg_type_free_instanceid,
397  .plugin.lyb_data_len = -1,
398  },
399  {0}
400 };
struct lysc_type * realtype
Definition: tree_data.h:564
LIBYANG_API_DECL 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
Compiled YANG data node.
Definition: tree_schema.h:1414
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...
struct lyplg_type_record plugins_instanceid[]
Plugin information for instance-identifier type implementation.
Definition: instanceid.c:383
Generic structure for a data node.
Definition: tree_data.h:781
LIBYANG_API_DECL LY_ERR ly_err_new(struct ly_err_item **err, LY_ERR ecode, LY_VECODE vecode, char *path, char *apptag, const char *err_format,...) _FORMAT_PRINTF(6
Create and fill error structure.
uint8_t ly_bool
Type to indicate boolean value.
Definition: log.h:28
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...
#define LYPLG_TYPE_STORE_DYNAMIC
LIBYANG_API_DECL LY_ERR lyplg_type_compare_instanceid(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_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.
Definition: log.h:261
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.
The main libyang public header.
LIBYANG_API_DECL 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:369
YANG data representation.
Definition: tree_data.h:560
const char * _canonical
Definition: tree_data.h:561
Libyang full error structure.
Definition: log.h:299
Definition: log.h:291
Structure to hold a set of (not necessary somehow connected) objects. Usually used for lyd_node...
Definition: set.h:46
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(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...
Available YANG schema tree structures representing YANG module.
Definition: tree_schema.h:2108
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&#39;s hints (if any) in the specified format.
const char * module
#define LY_ARRAY_COUNT(ARRAY)
Get the number of records in the ARRAY.
Definition: tree.h:148
LIBYANG_API_DECL LY_ERR lyplg_type_validate_instanceid(const struct ly_ctx *ctx, const struct lysc_type *type, const struct lyd_node *ctx_node, const struct lyd_node *tree, struct lyd_value *storage, struct ly_err_item **err)
Implementation of lyplg_type_validate_clb for the built-in instance-identifier type.
#define LY_ARRAY_FOR(ARRAY,...)
Sized-array iterator (for-loop).
Definition: tree.h:167
#define LY_ARRAY_COUNT_TYPE
Type (i.e. size) of the sized array&#39;s size counter.
Definition: tree.h:104
Definition: log.h:268
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, only a reference counter is incremented and no memory allocation is performed. This insert function variant avoids duplication of specified value - it is inserted into the dictionary directly.
LIBYANG_API_DECL const void * lyplg_type_print_instanceid(const struct ly_ctx *ctx, const struct lyd_value *value, LY_VALUE_FORMAT format, void *prefix_data, ly_bool *dynamic, size_t *value_len)
Implementation of lyplg_type_print_clb for the built-in instance-identifier type. ...
LY_VALUE_FORMAT
All kinds of supported value formats and prefix mappings to modules.
Definition: tree.h:234
LY_DATA_TYPE basetype
Definition: tree_schema.h:1299
LY_ERR
libyang&#39;s error codes returned by the libyang functions.
Definition: log.h:254
API for (user) types plugins.
LIBYANG_API_DECL 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:346
libyang context handler.