libyang  2.2.8
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 = 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 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 
261 LIBYANG_API_DEF int
262 lyplg_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 
267 LIBYANG_API_DEF const void *
268 lyplg_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 
294 LIBYANG_API_DEF LY_ERR
295 lyplg_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 
312 error:
313  lyplg_type_free_instanceid(ctx, dup);
314  return ret;
315 }
316 
317 LIBYANG_API_DEF void
318 lyplg_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 };
struct lysc_type * realtype
Definition: tree_data.h:575
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
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
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:332
Generic structure for a data node.
Definition: tree_data.h:799
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
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_DECL 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_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:318
YANG data representation.
Definition: tree_data.h:571
const char * _canonical
Definition: tree_data.h:572
Libyang full error structure.
Definition: log.h:285
Definition: log.h:277
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.
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:372
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: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:295
LY_ERR
libyang&#39;s error codes returned by the libyang functions.
Definition: log.h:240
libyang context handler.