libyang  2.0.112
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 "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  /* the same prefix is inherited and skipped */
68  inherit_prefix = 1;
69  break;
70  }
71 
72  LY_ARRAY_FOR(path, u) {
73  /* new node */
74  if (!inherit_prefix || (mod != path[u].node->module)) {
75  mod = path[u].node->module;
76  ret = ly_strcat(&result, "/%s:%s", lyplg_type_get_prefix(mod, format, prefix_data), path[u].node->name);
77  } else {
78  ret = ly_strcat(&result, "/%s", path[u].node->name);
79  }
80  LY_CHECK_GOTO(ret, cleanup);
81 
82  /* node predicates */
83  LY_ARRAY_FOR(path[u].predicates, v) {
84  struct ly_path_predicate *pred = &path[u].predicates[v];
85 
86  switch (path[u].pred_type) {
87  case LY_PATH_PREDTYPE_NONE:
88  break;
89  case LY_PATH_PREDTYPE_POSITION:
90  /* position predicate */
91  ret = ly_strcat(&result, "[%" PRIu64 "]", pred->position);
92  break;
93  case LY_PATH_PREDTYPE_LIST:
94  /* key-predicate */
95  strval = pred->value.realtype->plugin->print(path[u].node->module->ctx, &pred->value, format, prefix_data,
96  &d, NULL);
97 
98  /* default quote */
99  quot = '\'';
100  if (strchr(strval, quot)) {
101  quot = '"';
102  }
103  if (inherit_prefix) {
104  /* always the same prefix as the parent */
105  ret = ly_strcat(&result, "[%s=%c%s%c]", pred->key->name, quot, strval, quot);
106  } else {
107  ret = ly_strcat(&result, "[%s:%s=%c%s%c]", lyplg_type_get_prefix(pred->key->module, format, prefix_data),
108  pred->key->name, quot, strval, quot);
109  }
110  if (d) {
111  free((char *)strval);
112  }
113  break;
114  case LY_PATH_PREDTYPE_LEAFLIST:
115  /* leaf-list-predicate */
116  strval = pred->value.realtype->plugin->print(path[u].node->module->ctx, &pred->value, format, prefix_data,
117  &d, NULL);
118 
119  /* default quote */
120  quot = '\'';
121  if (strchr(strval, quot)) {
122  quot = '"';
123  }
124  ret = ly_strcat(&result, "[.=%c%s%c]", quot, strval, quot);
125  if (d) {
126  free((char *)strval);
127  }
128  break;
129  }
130 
131  LY_CHECK_GOTO(ret, cleanup);
132  }
133  }
134 
135 cleanup:
136  if (ret) {
137  free(result);
138  } else {
139  *str = result;
140  }
141  return ret;
142 }
143 
147 static LY_ERR
148 lyplg_type_store_node_instanceid(const struct ly_ctx *ctx, const struct lysc_type *type, const void *value, size_t value_len,
149  uint32_t options, LY_VALUE_FORMAT format, void *prefix_data, uint32_t hints, const struct lysc_node *ctx_node,
150  struct lyd_value *storage, struct lys_glob_unres *unres, struct ly_err_item **err)
151 {
152  LY_ERR ret = LY_SUCCESS;
153  struct lyxp_expr *exp = NULL;
154  uint32_t prefix_opt = 0;
155  struct ly_path *path;
156  char *canon;
157 
158  /* init storage */
159  memset(storage, 0, sizeof *storage);
160  storage->realtype = type;
161 
162  /* check hints */
163  ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
164  LY_CHECK_GOTO(ret, cleanup);
165 
166  switch (format) {
167  case LY_VALUE_SCHEMA:
169  case LY_VALUE_XML:
170  prefix_opt = LY_PATH_PREFIX_MANDATORY;
171  break;
172  case LY_VALUE_CANON:
173  case LY_VALUE_LYB:
174  case LY_VALUE_JSON:
175  prefix_opt = LY_PATH_PREFIX_STRICT_INHERIT;
176  break;
177  }
178 
179  /* parse the value */
180  ret = ly_path_parse(ctx, ctx_node, value, value_len, 0, LY_PATH_BEGIN_ABSOLUTE, prefix_opt, LY_PATH_PRED_SIMPLE, &exp);
181  if (ret) {
182  ret = ly_err_new(err, LY_EVALID, LYVE_DATA, NULL, NULL,
183  "Invalid instance-identifier \"%.*s\" value - syntax error.", (int)value_len, (char *)value);
184  goto cleanup;
185  }
186 
187  if (options & LYPLG_TYPE_STORE_IMPLEMENT) {
188  /* implement all prefixes */
189  LY_CHECK_GOTO(ret = lys_compile_expr_implement(ctx, exp, format, prefix_data, 1, unres, NULL), cleanup);
190  }
191 
192  /* resolve it on schema tree */
193  ret = ly_path_compile(ctx, NULL, ctx_node, NULL, exp, (ctx_node->flags & LYS_IS_OUTPUT) ?
194  LY_PATH_OPER_OUTPUT : LY_PATH_OPER_INPUT, LY_PATH_TARGET_MANY, 1, format, prefix_data, &path);
195  if (ret) {
196  ret = ly_err_new(err, ret, LYVE_DATA, NULL, NULL,
197  "Invalid instance-identifier \"%.*s\" value - semantic error.", (int)value_len, (char *)value);
198  goto cleanup;
199  }
200 
201  /* store value */
202  storage->target = path;
203 
204  /* store canonical value */
205  if (format == LY_VALUE_CANON) {
206  if (options & LYPLG_TYPE_STORE_DYNAMIC) {
207  ret = lydict_insert_zc(ctx, (char *)value, &storage->_canonical);
208  options &= ~LYPLG_TYPE_STORE_DYNAMIC;
209  LY_CHECK_GOTO(ret, cleanup);
210  } else {
211  ret = lydict_insert(ctx, value, value_len, &storage->_canonical);
212  LY_CHECK_GOTO(ret, cleanup);
213  }
214  } else {
215  /* JSON format with prefix is the canonical one */
216  ret = instanceid_path2str(path, LY_VALUE_JSON, NULL, &canon);
217  LY_CHECK_GOTO(ret, cleanup);
218 
219  ret = lydict_insert_zc(ctx, canon, &storage->_canonical);
220  LY_CHECK_GOTO(ret, cleanup);
221  }
222 
223 cleanup:
224  lyxp_expr_free(ctx, exp);
225  if (options & LYPLG_TYPE_STORE_DYNAMIC) {
226  free((void *)value);
227  }
228 
229  if (ret) {
230  lyplg_type_free_instanceid(ctx, storage);
231  }
232  return ret;
233 }
234 
243  {
244  .module = "ietf-netconf-acm",
245  .revision = "2012-02-22",
246  .name = "node-instance-identifier",
247 
248  .plugin.id = "libyang 2 - node-instance-identifier, version 1",
249  .plugin.store = lyplg_type_store_node_instanceid,
250  .plugin.validate = NULL,
251  .plugin.compare = lyplg_type_compare_instanceid,
252  .plugin.sort = NULL,
253  .plugin.print = lyplg_type_print_instanceid,
254  .plugin.duplicate = lyplg_type_dup_instanceid,
255  .plugin.free = lyplg_type_free_instanceid,
256  .plugin.lyb_data_len = -1,
257  },
258  {
259  .module = "ietf-netconf-acm",
260  .revision = "2018-02-14",
261  .name = "node-instance-identifier",
262 
263  .plugin.id = "libyang 2 - node-instance-identifier, version 1",
264  .plugin.store = lyplg_type_store_node_instanceid,
265  .plugin.validate = NULL,
266  .plugin.compare = lyplg_type_compare_instanceid,
267  .plugin.sort = NULL,
268  .plugin.print = lyplg_type_print_instanceid,
269  .plugin.duplicate = lyplg_type_dup_instanceid,
270  .plugin.free = lyplg_type_free_instanceid,
271  .plugin.lyb_data_len = -1,
272  },
273  {0}
274 };
struct lysc_type * realtype
Definition: tree_data.h:539
Compiled YANG data node.
Definition: tree_schema.h:1666
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:243
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.
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:350
uint8_t ly_bool
Type to indicate boolean value.
Definition: log.h:25
#define LYPLG_TYPE_STORE_DYNAMIC
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...
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.
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.
YANG data representation.
Definition: tree_data.h:535
const char * _canonical
Definition: tree_data.h:536
struct lyplg_type_record plugins_node_instanceid[]
Plugin information for instance-identifier type implementation.
#define LYS_IS_OUTPUT
Definition: tree_schema.h:970
Libyang full error structure.
Definition: log.h:291
Definition: log.h:283
Definition: log.h:254
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.
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:327
Available YANG schema tree structures representing YANG module.
Definition: tree_schema.h:2342
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:1668
#define LYPLG_TYPE_STORE_IMPLEMENT
LY_VALUE_FORMAT
All kinds of supported value formats and prefix mappings to modules.
Definition: tree.h:235
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_DATA_TYPE basetype
Definition: tree_schema.h:1552
LY_ERR
libyang&#39;s error codes returned by the libyang functions.
Definition: log.h:245
API for (user) types plugins.
libyang context handler.