libyang  3.6.0
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 "compat.h"
25 #include "ly_common.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 = 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 
255 LIBYANG_API_DEF const void *
256 lyplg_type_print_instanceid(const struct ly_ctx *ctx, const struct lyd_value *value, LY_VALUE_FORMAT format,
257  void *prefix_data, ly_bool *dynamic, size_t *value_len)
258 {
259  char *ret = NULL;
260  struct ly_path *p = NULL;
261  const struct ly_path *target;
262  struct ly_err_item *err;
263 
264  if ((format == LY_VALUE_CANON) || (format == LY_VALUE_JSON) || (format == LY_VALUE_LYB)) {
265  if (dynamic) {
266  *dynamic = 0;
267  }
268  if (value_len) {
269  *value_len = strlen(value->_canonical);
270  }
271  return value->_canonical;
272  }
273 
274  if (!value->target) {
275  /* schema default value, compile it first */
276  if (lyplg_type_lypath_new(ctx, value->_canonical, strlen(value->_canonical), 0, LY_VALUE_JSON, NULL, NULL,
277  NULL, &p, &err)) {
278  if (err) {
279  ly_err_print(ctx, err);
280  ly_err_free(err);
281  }
282  goto cleanup;
283  }
284 
285  target = p;
286  } else {
287  target = value->target;
288  }
289 
290  /* print the value in the specific format */
291  if (instanceid_path2str(target, format, prefix_data, &ret)) {
292  goto cleanup;
293  }
294 
295  *dynamic = 1;
296  if (value_len) {
297  *value_len = strlen(ret);
298  }
299 
300 cleanup:
301  ly_path_free(p);
302  return ret;
303 }
304 
305 LIBYANG_API_DEF LY_ERR
306 lyplg_type_dup_instanceid(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup)
307 {
308  LY_ERR ret;
309  struct ly_err_item *err;
310 
311  memset(dup, 0, sizeof *dup);
312 
313  /* canonical value */
314  ret = lydict_insert(ctx, original->_canonical, 0, &dup->_canonical);
315  LY_CHECK_GOTO(ret, error);
316 
317  if (!original->target) {
318  /* schema default value, needs to be compiled */
319  if (lyplg_type_lypath_new(ctx, original->_canonical, strlen(original->_canonical), 0, LY_VALUE_JSON, NULL, NULL,
320  NULL, &dup->target, &err)) {
321  if (err) {
322  ly_err_print(ctx, err);
323  ly_err_free(err);
324  }
325  goto error;
326  }
327  } else {
328  /* copy path */
329  ret = ly_path_dup(ctx, original->target, &dup->target);
330  LY_CHECK_GOTO(ret, error);
331  }
332 
333  dup->realtype = original->realtype;
334  return LY_SUCCESS;
335 
336 error:
337  lyplg_type_free_instanceid(ctx, dup);
338  return ret;
339 }
340 
341 LIBYANG_API_DEF void
342 lyplg_type_free_instanceid(const struct ly_ctx *ctx, struct lyd_value *value)
343 {
344  lydict_remove(ctx, value->_canonical);
345  value->_canonical = NULL;
346  ly_path_free(value->target);
347 }
348 
357  {
358  .module = "",
359  .revision = NULL,
360  .name = LY_TYPE_INST_STR,
361 
362  .plugin.id = "libyang 2 - instance-identifier, version 1",
363  .plugin.store = lyplg_type_store_instanceid,
364  .plugin.validate = lyplg_type_validate_instanceid,
365  .plugin.compare = lyplg_type_compare_simple,
366  .plugin.sort = lyplg_type_sort_simple,
367  .plugin.print = lyplg_type_print_instanceid,
368  .plugin.duplicate = lyplg_type_dup_instanceid,
369  .plugin.free = lyplg_type_free_instanceid,
370  .plugin.lyb_data_len = -1,
371  },
372  {0}
373 };
struct lysc_type * realtype
Definition: tree_data.h:579
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:1439
memset(value->fixed_mem, 0, LYD_VALUE_FIXED_MEM_SIZE)
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:356
Generic structure for a data node.
Definition: tree_data.h:803
Definition: log.h:247
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.
uint8_t ly_bool
Type to indicate boolean value.
Definition: log.h:28
LY_ERR err
Definition: log.h:287
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 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.
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 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:342
YANG data representation.
Definition: tree_data.h:575
const char * _canonical
Definition: tree_data.h:576
Libyang full error structure.
Definition: log.h:285
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.
Definition: log.h:277
LIBYANG_API_DECL LY_ERR LIBYANG_API_DECL void ly_err_free(void *ptr)
Destructor for the error records created with ly_err_new().
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 void ly_err_print(const struct ly_ctx *ctx, const struct ly_err_item *eitem)
Print the error structure as if just generated.
Structure to hold a set of (not necessary somehow connected) objects. Usually used for lyd_node...
Definition: set.h:47
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:2131
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
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
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.
if((v1->size!=v2->size)||memcmp(v1->data, v2->data, v1->size))
Definition: binary.c:349
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. ...
Definition: instanceid.c:256
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:1305
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:306
LY_ERR
libyang&#39;s error codes returned by the libyang functions.
Definition: log.h:240
libyang context handler.