libyang  2.0.194
libyang is YANG data modelling language parser and toolkit written (and providing API) in C.
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 "common.h"
24 #include "compat.h"
25 #include "path.h"
26 #include "plugins_internal.h" /* LY_TYPE_*_STR */
27 #include "xpath.h"
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;
54  ly_bool inherit_prefix = 0, d;
55  const char *strval;
56 
57  switch (format) {
58  case LY_VALUE_XML:
59  case LY_VALUE_SCHEMA:
61  /* everything is prefixed */
62  inherit_prefix = 0;
63  break;
64  case LY_VALUE_CANON:
65  case LY_VALUE_JSON:
66  case LY_VALUE_LYB:
67  case LY_VALUE_STR_NS:
68  /* the same prefix is inherited and skipped */
69  inherit_prefix = 1;
70  break;
71  }
72 
73  LY_ARRAY_FOR(path, u) {
74  /* new node */
75  if (!inherit_prefix || (mod != path[u].node->module)) {
76  mod = path[u].node->module;
77  ret = ly_strcat(&result, "/%s:%s", lyplg_type_get_prefix(mod, format, prefix_data), path[u].node->name);
78  } else {
79  ret = ly_strcat(&result, "/%s", path[u].node->name);
80  }
81  LY_CHECK_GOTO(ret, cleanup);
82 
83  /* node predicates */
84  LY_ARRAY_FOR(path[u].predicates, v) {
85  struct ly_path_predicate *pred = &path[u].predicates[v];
86 
87  switch (path[u].pred_type) {
88  case LY_PATH_PREDTYPE_NONE:
89  break;
90  case LY_PATH_PREDTYPE_POSITION:
91  /* position predicate */
92  ret = ly_strcat(&result, "[%" PRIu64 "]", pred->position);
93  break;
94  case LY_PATH_PREDTYPE_LIST:
95  /* key-predicate */
96  strval = pred->value.realtype->plugin->print(path[u].node->module->ctx, &pred->value, format, prefix_data,
97  &d, NULL);
98 
99  /* default quote */
100  quot = '\'';
101  if (strchr(strval, quot)) {
102  quot = '"';
103  }
104  if (inherit_prefix) {
105  /* always the same prefix as the parent */
106  ret = ly_strcat(&result, "[%s=%c%s%c]", pred->key->name, quot, strval, quot);
107  } else {
108  ret = ly_strcat(&result, "[%s:%s=%c%s%c]", lyplg_type_get_prefix(pred->key->module, format, prefix_data),
109  pred->key->name, quot, strval, quot);
110  }
111  if (d) {
112  free((char *)strval);
113  }
114  break;
115  case LY_PATH_PREDTYPE_LEAFLIST:
116  /* leaf-list-predicate */
117  strval = pred->value.realtype->plugin->print(path[u].node->module->ctx, &pred->value, format, prefix_data,
118  &d, NULL);
119 
120  /* default quote */
121  quot = '\'';
122  if (strchr(strval, quot)) {
123  quot = '"';
124  }
125  ret = ly_strcat(&result, "[.=%c%s%c]", quot, strval, quot);
126  if (d) {
127  free((char *)strval);
128  }
129  break;
130  }
131 
132  LY_CHECK_GOTO(ret, cleanup);
133  }
134  }
135 
136 cleanup:
137  if (ret) {
138  free(result);
139  } else {
140  *str = result;
141  }
142  return ret;
143 }
144 
148 static LY_ERR
149 lyplg_type_store_node_instanceid(const struct ly_ctx *ctx, const struct lysc_type *type, const void *value, size_t value_len,
150  uint32_t options, LY_VALUE_FORMAT format, void *prefix_data, uint32_t hints, const struct lysc_node *ctx_node,
151  struct lyd_value *storage, struct lys_glob_unres *unres, struct ly_err_item **err)
152 {
153  LY_ERR ret = LY_SUCCESS;
154  struct lyxp_expr *exp = NULL;
155  uint32_t prefix_opt = 0;
156  struct ly_path *path;
157  char *canon;
158 
159  /* init storage */
160  memset(storage, 0, sizeof *storage);
161  storage->realtype = type;
162 
163  /* check hints */
164  ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
165  LY_CHECK_GOTO(ret, cleanup);
166 
167  switch (format) {
168  case LY_VALUE_SCHEMA:
170  case LY_VALUE_XML:
171  prefix_opt = LY_PATH_PREFIX_MANDATORY;
172  break;
173  case LY_VALUE_CANON:
174  case LY_VALUE_LYB:
175  case LY_VALUE_JSON:
176  case LY_VALUE_STR_NS:
177  prefix_opt = LY_PATH_PREFIX_STRICT_INHERIT;
178  break;
179  }
180 
181  /* parse the value */
182  ret = ly_path_parse(ctx, ctx_node, value, value_len, 0, LY_PATH_BEGIN_ABSOLUTE, prefix_opt, LY_PATH_PRED_SIMPLE, &exp);
183  if (ret) {
184  ret = ly_err_new(err, LY_EVALID, LYVE_DATA, NULL, NULL,
185  "Invalid instance-identifier \"%.*s\" value - syntax error.", (int)value_len, (char *)value);
186  goto cleanup;
187  }
188 
189  if (options & LYPLG_TYPE_STORE_IMPLEMENT) {
190  /* implement all prefixes */
191  LY_CHECK_GOTO(ret = lys_compile_expr_implement(ctx, exp, format, prefix_data, 1, unres, NULL), cleanup);
192  }
193 
194  /* resolve it on schema tree, use JSON format instead of LYB because for this type they are equal but for some
195  * nested types (such as numbers in predicates in the path) LYB would be invalid */
196  ret = ly_path_compile(ctx, NULL, ctx_node, NULL, exp, (ctx_node && (ctx_node->flags & LYS_IS_OUTPUT)) ?
197  LY_PATH_OPER_OUTPUT : LY_PATH_OPER_INPUT, LY_PATH_TARGET_MANY, 1, (format == LY_VALUE_LYB) ?
198  LY_VALUE_JSON : format, prefix_data, &path);
199  if (ret) {
200  ret = ly_err_new(err, ret, LYVE_DATA, NULL, NULL,
201  "Invalid instance-identifier \"%.*s\" value - semantic error.", (int)value_len, (char *)value);
202  goto cleanup;
203  }
204 
205  /* store value */
206  storage->target = path;
207 
208  /* store canonical value */
209  if (format == LY_VALUE_CANON) {
210  if (options & LYPLG_TYPE_STORE_DYNAMIC) {
211  ret = lydict_insert_zc(ctx, (char *)value, &storage->_canonical);
212  options &= ~LYPLG_TYPE_STORE_DYNAMIC;
213  LY_CHECK_GOTO(ret, cleanup);
214  } else {
215  ret = lydict_insert(ctx, value, value_len, &storage->_canonical);
216  LY_CHECK_GOTO(ret, cleanup);
217  }
218  } else {
219  /* JSON format with prefix is the canonical one */
220  ret = instanceid_path2str(path, LY_VALUE_JSON, NULL, &canon);
221  LY_CHECK_GOTO(ret, cleanup);
222 
223  ret = lydict_insert_zc(ctx, canon, &storage->_canonical);
224  LY_CHECK_GOTO(ret, cleanup);
225  }
226 
227 cleanup:
228  lyxp_expr_free(ctx, exp);
229  if (options & LYPLG_TYPE_STORE_DYNAMIC) {
230  free((void *)value);
231  }
232 
233  if (ret) {
234  lyplg_type_free_instanceid(ctx, storage);
235  }
236  return ret;
237 }
238 
247  {
248  .module = "ietf-netconf-acm",
249  .revision = "2012-02-22",
250  .name = "node-instance-identifier",
251 
252  .plugin.id = "libyang 2 - node-instance-identifier, version 1",
253  .plugin.store = lyplg_type_store_node_instanceid,
254  .plugin.validate = NULL,
255  .plugin.compare = lyplg_type_compare_instanceid,
256  .plugin.sort = NULL,
257  .plugin.print = lyplg_type_print_instanceid,
258  .plugin.duplicate = lyplg_type_dup_instanceid,
259  .plugin.free = lyplg_type_free_instanceid,
260  .plugin.lyb_data_len = -1,
261  },
262  {
263  .module = "ietf-netconf-acm",
264  .revision = "2018-02-14",
265  .name = "node-instance-identifier",
266 
267  .plugin.id = "libyang 2 - node-instance-identifier, version 1",
268  .plugin.store = lyplg_type_store_node_instanceid,
269  .plugin.validate = NULL,
270  .plugin.compare = lyplg_type_compare_instanceid,
271  .plugin.sort = NULL,
272  .plugin.print = lyplg_type_print_instanceid,
273  .plugin.duplicate = lyplg_type_dup_instanceid,
274  .plugin.free = lyplg_type_free_instanceid,
275  .plugin.lyb_data_len = -1,
276  },
277  {0}
278 };
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_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:244
@ LYVE_DATA
Definition: log.h:281
@ LY_EVALID
Definition: log.h:252
@ LY_SUCCESS
Definition: log.h:245
Libyang full error structure.
Definition: log.h:289
const char * module
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.
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_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 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:328
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:244
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:351
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.
#define LYPLG_TYPE_STORE_DYNAMIC
#define LYPLG_TYPE_STORE_IMPLEMENT
LY_DATA_TYPE basetype
Definition: tree_schema.h:1536
uint16_t flags
Definition: tree_schema.h:1652
Available YANG schema tree structures representing YANG module.
Definition: tree_schema.h:2341
Compiled YANG data node.
Definition: tree_schema.h:1650
#define LYS_IS_OUTPUT
Definition: tree_schema.h:954
#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:235
#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:240
@ LY_VALUE_SCHEMA
Definition: tree.h:237
@ LY_VALUE_CANON
Definition: tree.h:236
@ LY_VALUE_XML
Definition: tree.h:239
@ LY_VALUE_STR_NS
Definition: tree.h:242
@ LY_VALUE_SCHEMA_RESOLVED
Definition: tree.h:238
@ LY_VALUE_LYB
Definition: tree.h:241
The main libyang public header.
uint8_t ly_bool
Type to indicate boolean value.
Definition: log.h:27
const struct lyplg_type_record plugins_node_instanceid[]
Plugin information for instance-identifier type implementation.
API for (user) types plugins.
const struct lysc_type * realtype
Definition: tree_data.h:564
const char * _canonical
Definition: tree_data.h:561
YANG data representation.
Definition: tree_data.h:560