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
node_instanceid.c
Go to the documentation of this file.
1 
15 #include "plugins_types.h"
16 
17 #include <stdint.h>
18 #include <stdlib.h>
19 
20 #include "libyang.h"
21 
22 /* additional internal headers for some useful simple macros */
23 #include "compat.h"
24 #include "ly_common.h"
25 #include "path.h"
26 #include "plugins_internal.h" /* LY_TYPE_*_STR */
27 #include "xpath.h"
28 
47 static LY_ERR
48 node_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;
55  ly_bool inherit_prefix = 0, d;
56  const char *strval;
57 
58  if (!path) {
59  /* special path */
60  ret = ly_strcat(&result, "/");
61  goto cleanup;
62  }
63 
64  switch (format) {
65  case LY_VALUE_XML:
66  /* null the local module so that all the prefixes are printed */
67  mods = prefix_data;
68  local_mod = mods->objs[0];
69  mods->objs[0] = NULL;
70 
71  /* fallthrough */
72  case LY_VALUE_SCHEMA:
74  /* everything is prefixed */
75  inherit_prefix = 0;
76  break;
77  case LY_VALUE_CANON:
78  case LY_VALUE_JSON:
79  case LY_VALUE_LYB:
80  case LY_VALUE_STR_NS:
81  /* the same prefix is inherited and skipped */
82  inherit_prefix = 1;
83  break;
84  }
85 
86  LY_ARRAY_FOR(path, u) {
87  /* new node */
88  if (!inherit_prefix || (mod != path[u].node->module)) {
89  mod = path[u].node->module;
90  ret = ly_strcat(&result, "/%s:%s", lyplg_type_get_prefix(mod, format, prefix_data), path[u].node->name);
91  } else {
92  ret = ly_strcat(&result, "/%s", path[u].node->name);
93  }
94  LY_CHECK_GOTO(ret, cleanup);
95 
96  /* node predicates */
97  LY_ARRAY_FOR(path[u].predicates, v) {
98  struct ly_path_predicate *pred = &path[u].predicates[v];
99 
100  switch (pred->type) {
101  case LY_PATH_PREDTYPE_POSITION:
102  /* position predicate */
103  ret = ly_strcat(&result, "[%" PRIu64 "]", pred->position);
104  break;
105  case LY_PATH_PREDTYPE_LIST:
106  /* key-predicate */
107  strval = pred->value.realtype->plugin->print(path[u].node->module->ctx, &pred->value, format, prefix_data,
108  &d, NULL);
109 
110  /* default quote */
111  quot = '\'';
112  if (strchr(strval, quot)) {
113  quot = '"';
114  }
115  if (inherit_prefix) {
116  /* always the same prefix as the parent */
117  ret = ly_strcat(&result, "[%s=%c%s%c]", pred->key->name, quot, strval, quot);
118  } else {
119  ret = ly_strcat(&result, "[%s:%s=%c%s%c]", lyplg_type_get_prefix(pred->key->module, format, prefix_data),
120  pred->key->name, quot, strval, quot);
121  }
122  if (d) {
123  free((char *)strval);
124  }
125  break;
126  case LY_PATH_PREDTYPE_LEAFLIST:
127  /* leaf-list-predicate */
128  strval = pred->value.realtype->plugin->print(path[u].node->module->ctx, &pred->value, format, prefix_data,
129  &d, NULL);
130 
131  /* default quote */
132  quot = '\'';
133  if (strchr(strval, quot)) {
134  quot = '"';
135  }
136  ret = ly_strcat(&result, "[.=%c%s%c]", quot, strval, quot);
137  if (d) {
138  free((char *)strval);
139  }
140  break;
141  case LY_PATH_PREDTYPE_LIST_VAR:
142  /* key-predicate with a variable */
143  if (inherit_prefix) {
144  /* always the same prefix as the parent */
145  ret = ly_strcat(&result, "[%s=$%s]", pred->key->name, pred->variable);
146  } else {
147  ret = ly_strcat(&result, "[%s:%s=$%s]", lyplg_type_get_prefix(pred->key->module, format, prefix_data),
148  pred->key->name, pred->variable);
149  }
150  break;
151  }
152 
153  LY_CHECK_GOTO(ret, cleanup);
154  }
155  }
156 
157 cleanup:
158  if (local_mod) {
159  mods->objs[0] = (void *)local_mod;
160  }
161  if (ret) {
162  free(result);
163  } else {
164  *str = result;
165  }
166  return ret;
167 }
168 
172 static LY_ERR
173 lyplg_type_store_node_instanceid(const struct ly_ctx *ctx, const struct lysc_type *type, const void *value, size_t value_len,
174  uint32_t options, LY_VALUE_FORMAT format, void *prefix_data, uint32_t hints, const struct lysc_node *ctx_node,
175  struct lyd_value *storage, struct lys_glob_unres *unres, struct ly_err_item **err)
176 {
177  LY_ERR ret = LY_SUCCESS;
178  struct lyxp_expr *exp = NULL;
179  uint32_t prefix_opt = 0;
180  struct ly_path *path = NULL;
181  char *canon;
182 
183  /* init storage */
184  memset(storage, 0, sizeof *storage);
185  storage->realtype = type;
186 
187  /* check hints */
188  ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
189  LY_CHECK_GOTO(ret, cleanup);
190 
191  if ((((char *)value)[0] == '/') && (value_len == 1)) {
192  /* special path */
193  goto store;
194  }
195 
196  switch (format) {
197  case LY_VALUE_SCHEMA:
199  case LY_VALUE_XML:
200  prefix_opt = LY_PATH_PREFIX_MANDATORY;
201  break;
202  case LY_VALUE_CANON:
203  case LY_VALUE_LYB:
204  case LY_VALUE_JSON:
205  case LY_VALUE_STR_NS:
206  prefix_opt = LY_PATH_PREFIX_STRICT_INHERIT;
207  break;
208  }
209 
210  /* parse the value */
211  ret = ly_path_parse(ctx, ctx_node, value, value_len, 0, LY_PATH_BEGIN_ABSOLUTE, prefix_opt, LY_PATH_PRED_SIMPLE, &exp);
212  if (ret) {
213  ret = ly_err_new(err, LY_EVALID, LYVE_DATA, NULL, NULL,
214  "Invalid node-instance-identifier \"%.*s\" value - syntax error.", (int)value_len, (char *)value);
215  goto cleanup;
216  }
217 
218  if (options & LYPLG_TYPE_STORE_IMPLEMENT) {
219  /* implement all prefixes */
220  LY_CHECK_GOTO(ret = lys_compile_expr_implement(ctx, exp, format, prefix_data, 1, unres, NULL), cleanup);
221  }
222 
223  /* resolve it on schema tree, use JSON format instead of LYB because for this type they are equal but for some
224  * nested types (such as numbers in predicates in the path) LYB would be invalid */
225  ret = ly_path_compile(ctx, NULL, ctx_node, NULL, exp, (ctx_node && (ctx_node->flags & LYS_IS_OUTPUT)) ?
226  LY_PATH_OPER_OUTPUT : LY_PATH_OPER_INPUT, LY_PATH_TARGET_MANY, 1, (format == LY_VALUE_LYB) ?
227  LY_VALUE_JSON : format, prefix_data, &path);
228  if (ret) {
229  ret = ly_err_new(err, ret, LYVE_DATA, NULL, NULL,
230  "Invalid node-instance-identifier \"%.*s\" value - semantic error.", (int)value_len, (char *)value);
231  goto cleanup;
232  }
233 
234 store:
235  /* store value */
236  storage->target = path;
237 
238  /* store canonical value */
239  if (format == LY_VALUE_CANON) {
240  if (options & LYPLG_TYPE_STORE_DYNAMIC) {
241  ret = lydict_insert_zc(ctx, (char *)value, &storage->_canonical);
242  options &= ~LYPLG_TYPE_STORE_DYNAMIC;
243  LY_CHECK_GOTO(ret, cleanup);
244  } else {
245  ret = lydict_insert(ctx, value, value_len, &storage->_canonical);
246  LY_CHECK_GOTO(ret, cleanup);
247  }
248  } else {
249  /* JSON format with prefix is the canonical one */
250  ret = node_instanceid_path2str(path, LY_VALUE_JSON, NULL, &canon);
251  LY_CHECK_GOTO(ret, cleanup);
252 
253  ret = lydict_insert_zc(ctx, canon, &storage->_canonical);
254  LY_CHECK_GOTO(ret, cleanup);
255  }
256 
257 cleanup:
258  lyxp_expr_free(ctx, exp);
259  if (options & LYPLG_TYPE_STORE_DYNAMIC) {
260  free((void *)value);
261  }
262 
263  if (ret) {
264  lyplg_type_free_instanceid(ctx, storage);
265  }
266  return ret;
267 }
268 
272 static const void *
273 lyplg_type_print_node_instanceid(const struct ly_ctx *UNUSED(ctx), const struct lyd_value *value, LY_VALUE_FORMAT format,
274  void *prefix_data, ly_bool *dynamic, size_t *value_len)
275 {
276  char *ret;
277 
278  if ((format == LY_VALUE_CANON) || (format == LY_VALUE_JSON) || (format == LY_VALUE_LYB)) {
279  if (dynamic) {
280  *dynamic = 0;
281  }
282  if (value_len) {
283  *value_len = strlen(value->_canonical);
284  }
285  return value->_canonical;
286  }
287 
288  /* print the value in the specific format */
289  if (node_instanceid_path2str(value->target, format, prefix_data, &ret)) {
290  return NULL;
291  }
292  *dynamic = 1;
293  if (value_len) {
294  *value_len = strlen(ret);
295  }
296  return ret;
297 }
298 
307  {
308  .module = "ietf-netconf-acm",
309  .revision = "2012-02-22",
310  .name = "node-instance-identifier",
311 
312  .plugin.id = "libyang 2 - node-instance-identifier, version 1",
313  .plugin.store = lyplg_type_store_node_instanceid,
314  .plugin.validate = NULL,
315  .plugin.compare = lyplg_type_compare_instanceid,
316  .plugin.sort = lyplg_type_sort_instanceid,
317  .plugin.print = lyplg_type_print_node_instanceid,
318  .plugin.duplicate = lyplg_type_dup_instanceid,
319  .plugin.free = lyplg_type_free_instanceid,
320  .plugin.lyb_data_len = -1,
321  },
322  {
323  .module = "ietf-netconf-acm",
324  .revision = "2018-02-14",
325  .name = "node-instance-identifier",
326 
327  .plugin.id = "libyang 2 - node-instance-identifier, version 1",
328  .plugin.store = lyplg_type_store_node_instanceid,
329  .plugin.validate = NULL,
330  .plugin.compare = lyplg_type_compare_instanceid,
331  .plugin.sort = lyplg_type_sort_instanceid,
332  .plugin.print = lyplg_type_print_node_instanceid,
333  .plugin.duplicate = lyplg_type_dup_instanceid,
334  .plugin.free = lyplg_type_free_instanceid,
335  .plugin.lyb_data_len = -1,
336  },
337  {0}
338 };
struct lysc_type * realtype
Definition: tree_data.h:575
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)
uint8_t ly_bool
Type to indicate boolean value.
Definition: log.h:28
#define LYPLG_TYPE_STORE_DYNAMIC
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_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
struct lyplg_type_record plugins_node_instanceid[]
Plugin information for instance-identifier type implementation.
#define LYS_IS_OUTPUT
Definition: tree_schema.h:742
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_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
#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
uint16_t flags
Definition: tree_schema.h:1441
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.
#define LYPLG_TYPE_STORE_IMPLEMENT
LY_VALUE_FORMAT
All kinds of supported value formats and prefix mappings to modules.
Definition: tree.h:234
Definition: log.h:248
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.