libyang  2.0.7
libyang is YANG data modelling language parser and toolkit written (and providing API) in C.
xpath1.0.c
Go to the documentation of this file.
1 
15 #include "plugins_types.h"
16 
17 #include <assert.h>
18 #include <errno.h>
19 #include <stdint.h>
20 #include <stdlib.h>
21 #include <string.h>
22 
23 #include "libyang.h"
24 
25 #include "common.h"
26 #include "compat.h"
27 
28 /* internal header */
29 #include "xpath.h"
30 
44  struct lyxp_expr *exp;
45  const struct ly_ctx *ctx;
46  void *prefix_data;
48 };
49 
66 static LY_ERR
67 xpath10_print_token(const char *token, uint16_t tok_len, ly_bool is_nametest, const struct ly_ctx *resolve_ctx,
68  LY_VALUE_FORMAT resolve_format, const void *resolve_prefix_data, LY_VALUE_FORMAT get_format,
69  void *get_prefix_data, const char **prev_prefix, char **token_p, struct ly_err_item **err)
70 {
71  LY_ERR ret = LY_SUCCESS;
72  const char *str_begin, *str_next, *prefix;
73  ly_bool is_prefix;
74  uint32_t len;
75  char *str = NULL;
76  void *mem;
77  uint32_t str_len = 0;
78  const struct lys_module *mod;
79 
80  str_begin = token;
81 
82  while (!(ret = ly_value_prefix_next(str_begin, token + tok_len, &len, &is_prefix, &str_next)) && len) {
83 
84  if (is_prefix) {
85  /* resolve the module in the original format */
86  mod = lyplg_type_identity_module(resolve_ctx, NULL, str_begin, len, resolve_format, resolve_prefix_data);
87  if (!mod) {
88  ret = ly_err_new(err, LY_EVALID, LYVE_DATA, NULL, NULL, "Failed to resolve prefix \"%.*s\".", len, str_begin);
89  goto cleanup;
90  }
91 
92  /* get the prefix in the target format */
93  prefix = lyplg_type_get_prefix(mod, get_format, get_prefix_data);
94  if (!prefix) {
95  ret = ly_err_new(err, LY_EINT, LYVE_DATA, NULL, NULL, "Internal error.");
96  goto cleanup;
97  }
98 
99  /* append the prefix */
100  mem = realloc(str, str_len + strlen(prefix) + 2);
101  LY_CHECK_ERR_GOTO(!mem, ret = ly_err_new(err, LY_EMEM, LYVE_DATA, NULL, NULL, "No memory."), cleanup);
102  str = mem;
103  sprintf(str + str_len, "%s:", prefix);
104  str_len += strlen(prefix) + 1;
105 
106  if (is_nametest) {
107  /* remember prefix of a nametest */
108  *prev_prefix = prefix;
109  }
110  } else if (is_nametest && (get_format == LY_VALUE_XML) && (len == tok_len) && *prev_prefix) {
111  /* nametest without a prefix, we must add it */
112  mem = realloc(str, str_len + strlen(*prev_prefix) + 1 + len + 1);
113  LY_CHECK_ERR_GOTO(!mem, ret = ly_err_new(err, LY_EMEM, LYVE_DATA, NULL, NULL, "No memory."), cleanup);
114  str = mem;
115  sprintf(str + str_len, "%s:%.*s", *prev_prefix, len, str_begin);
116  str_len += strlen(*prev_prefix) + 1 + len;
117  } else {
118  /* just append the string */
119  mem = realloc(str, str_len + len + 1);
120  LY_CHECK_ERR_GOTO(!mem, ret = ly_err_new(err, LY_EMEM, LYVE_DATA, NULL, NULL, "No memory."), cleanup);
121  str = mem;
122  sprintf(str + str_len, "%.*s", len, str_begin);
123  str_len += len;
124  }
125 
126  str_begin = str_next;
127  }
128 
129 cleanup:
130  if (ret) {
131  free(str);
132  } else {
133  *token_p = str;
134  }
135  return ret;
136 }
137 
148 static LY_ERR
149 xpath10_print_value(const struct lyd_value_xpath10 *xp_val, LY_VALUE_FORMAT format, void *prefix_data,
150  char **str_value, struct ly_err_item **err)
151 {
152  LY_ERR ret = LY_SUCCESS;
153  char *str = NULL, *token;
154  void *mem;
155  const char *str_exp_ptr = xp_val->exp->expr, *cur_exp_ptr, *prev_prefix = NULL;
156  uint32_t str_len = 0, len;
157  uint16_t idx;
158  ly_bool is_nt;
159 
160  for (idx = 0; idx < xp_val->exp->used; ++idx) {
161  cur_exp_ptr = xp_val->exp->expr + xp_val->exp->tok_pos[idx];
162 
163  /* only these tokens may include prefixes */
164  if ((xp_val->exp->tokens[idx] == LYXP_TOKEN_NAMETEST) || (xp_val->exp->tokens[idx] == LYXP_TOKEN_LITERAL)) {
165  /* append preceding expression */
166  len = cur_exp_ptr - str_exp_ptr;
167  mem = realloc(str, str_len + len + 1);
168  LY_CHECK_ERR_GOTO(!mem, ret = ly_err_new(err, LY_EMEM, LYVE_DATA, NULL, NULL, "No memory."), cleanup);
169  str = mem;
170  sprintf(str + str_len, "%.*s", len, str_exp_ptr);
171  str_len += len;
172  str_exp_ptr = cur_exp_ptr;
173 
174  /* get the token in the target format */
175  is_nt = (xp_val->exp->tokens[idx] == LYXP_TOKEN_NAMETEST) ? 1 : 0;
176  ret = xpath10_print_token(cur_exp_ptr, xp_val->exp->tok_len[idx], is_nt, xp_val->ctx, xp_val->format,
177  xp_val->prefix_data, format, prefix_data, &prev_prefix, &token, err);
178  LY_CHECK_GOTO(ret, cleanup);
179 
180  /* append the converted token */
181  mem = realloc(str, str_len + strlen(token) + 1);
182  LY_CHECK_ERR_GOTO(!mem, free(token); ret = ly_err_new(err, LY_EMEM, LYVE_DATA, NULL, NULL, "No memory."), cleanup);
183  str = mem;
184  sprintf(str + str_len, "%s", token);
185  str_len += strlen(token);
186  str_exp_ptr += xp_val->exp->tok_len[idx];
187  free(token);
188  }
189  }
190 
191  /* append the rest of the expression */
192  if (str_exp_ptr[0]) {
193  mem = realloc(str, str_len + strlen(str_exp_ptr) + 1);
194  LY_CHECK_ERR_GOTO(!mem, ret = ly_err_new(err, LY_EMEM, LYVE_DATA, NULL, NULL, "No memory."), cleanup);
195  str = mem;
196  sprintf(str + str_len, "%s", str_exp_ptr);
197  }
198 
199 cleanup:
200  if (ret) {
201  free(str);
202  } else {
203  *str_value = str;
204  }
205  return ret;
206 }
207 
208 API LY_ERR
209 lyplg_type_store_xpath10(const struct ly_ctx *ctx, const struct lysc_type *type, const void *value, size_t value_len,
210  uint32_t options, LY_VALUE_FORMAT format, void *prefix_data, uint32_t hints,
211  const struct lysc_node *UNUSED(ctx_node), struct lyd_value *storage, struct lys_glob_unres *UNUSED(unres),
212  struct ly_err_item **err)
213 {
214  LY_ERR ret = LY_SUCCESS;
215  struct lysc_type_str *type_str = (struct lysc_type_str *)type;
216  struct lyd_value_xpath10 *val;
217  char *canon;
218 
219  /* init storage */
220  memset(storage, 0, sizeof *storage);
221  LYPLG_TYPE_VAL_INLINE_PREPARE(storage, val);
222  LY_CHECK_ERR_GOTO(!val, ret = LY_EMEM, cleanup);
223  storage->realtype = type;
224 
225  /* check hints */
226  ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
227  LY_CHECK_GOTO(ret, cleanup);
228 
229  /* length restriction of the string */
230  if (type_str->length) {
231  /* value_len is in bytes, but we need number of characters here */
232  ret = lyplg_type_validate_range(LY_TYPE_STRING, type_str->length, ly_utf8len(value, value_len), value, value_len, err);
233  LY_CHECK_GOTO(ret, cleanup);
234  }
235 
236  /* pattern restrictions */
237  ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err);
238  LY_CHECK_GOTO(ret, cleanup);
239 
240  /* store format-specific data and context for later prefix resolution */
241  ret = lyplg_type_prefix_data_new(ctx, value, value_len, format, prefix_data, &val->format, &val->prefix_data);
242  LY_CHECK_GOTO(ret, cleanup);
243  val->ctx = ctx;
244 
245  /* parse */
246  ret = lyxp_expr_parse(ctx, value, value_len, 1, &val->exp);
247  LY_CHECK_GOTO(ret, cleanup);
248 
249  /* store canonical value */
250  if ((format == LY_VALUE_CANON) || (format == LY_VALUE_JSON) || (format == LY_VALUE_LYB)) {
251  if (options & LYPLG_TYPE_STORE_DYNAMIC) {
252  ret = lydict_insert_zc(ctx, (char *)value, &storage->_canonical);
253  options &= ~LYPLG_TYPE_STORE_DYNAMIC;
254  LY_CHECK_GOTO(ret, cleanup);
255  } else {
256  ret = lydict_insert(ctx, value, value_len, &storage->_canonical);
257  LY_CHECK_GOTO(ret, cleanup);
258  }
259  } else {
260  /* JSON format with prefix is the canonical one */
261  ret = xpath10_print_value(val, LY_VALUE_JSON, NULL, &canon, err);
262  LY_CHECK_GOTO(ret, cleanup);
263 
264  ret = lydict_insert_zc(ctx, canon, &storage->_canonical);
265  LY_CHECK_GOTO(ret, cleanup);
266  }
267 
268 cleanup:
269  if (options & LYPLG_TYPE_STORE_DYNAMIC) {
270  free((void *)value);
271  }
272 
273  if (ret) {
274  lyplg_type_free_xpath10(ctx, storage);
275  }
276  return ret;
277 }
278 
279 API const void *
281  void *prefix_data, ly_bool *dynamic, size_t *value_len)
282 {
283  struct lyd_value_xpath10 *val;
284  char *ret;
285  struct ly_err_item *err = NULL;
286 
287  LYD_VALUE_GET(value, val);
288 
289  if ((format == LY_VALUE_CANON) || (format == LY_VALUE_JSON) || (format == LY_VALUE_LYB)) {
290  /* canonical */
291  if (dynamic) {
292  *dynamic = 0;
293  }
294  if (value_len) {
295  *value_len = strlen(value->_canonical);
296  }
297  return value->_canonical;
298  }
299 
300  /* print in the specific format */
301  if (xpath10_print_value(val, format, prefix_data, &ret, &err)) {
302  if (err) {
303  LOGVAL_ERRITEM(ctx, err);
304  ly_err_free(err);
305  }
306  return NULL;
307  }
308 
309  *dynamic = 1;
310  if (value_len) {
311  *value_len = strlen(ret);
312  }
313  return ret;
314 }
315 
316 API LY_ERR
317 lyplg_type_dup_xpath10(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup)
318 {
319  LY_ERR ret = LY_SUCCESS;
320  struct lyd_value_xpath10 *orig_val, *dup_val;
321 
322  /* init dup value */
323  memset(dup, 0, sizeof *dup);
324  dup->realtype = original->realtype;
325 
326  ret = lydict_insert(ctx, original->_canonical, ly_strlen(original->_canonical), &dup->_canonical);
327  LY_CHECK_GOTO(ret, cleanup);
328 
329  LYPLG_TYPE_VAL_INLINE_PREPARE(dup, dup_val);
330  LY_CHECK_ERR_GOTO(!dup_val, LOGMEM(ctx); ret = LY_EMEM, cleanup);
331  dup_val->ctx = ctx;
332 
333  LYD_VALUE_GET(original, orig_val);
334  ret = lyxp_expr_dup(ctx, orig_val->exp, &dup_val->exp);
335  LY_CHECK_GOTO(ret, cleanup);
336 
337  ret = lyplg_type_prefix_data_dup(ctx, orig_val->format, orig_val->prefix_data, &dup_val->prefix_data);
338  LY_CHECK_GOTO(ret, cleanup);
339  dup_val->format = orig_val->format;
340 
341 cleanup:
342  if (ret) {
344  }
345  return ret;
346 }
347 
348 API void
349 lyplg_type_free_xpath10(const struct ly_ctx *ctx, struct lyd_value *value)
350 {
351  struct lyd_value_xpath10 *val;
352 
353  lydict_remove(ctx, value->_canonical);
354  LYD_VALUE_GET(value, val);
355  if (val) {
356  lyxp_expr_free(ctx, val->exp);
358 
360  }
361 }
362 
370 const struct lyplg_type_record plugins_xpath10[] = {
371  {
372  .module = "ietf-yang-types",
373  .revision = "2013-07-15",
374  .name = "xpath1.0",
375 
376  .plugin.id = "libyang 2 - xpath1.0, version 1",
377  .plugin.store = lyplg_type_store_xpath10,
378  .plugin.validate = NULL,
379  .plugin.compare = lyplg_type_compare_simple,
380  .plugin.sort = NULL,
381  .plugin.print = lyplg_type_print_xpath10,
382  .plugin.duplicate = lyplg_type_dup_xpath10,
383  .plugin.free = lyplg_type_free_xpath10
384  },
385  {0}
386 };
libyang context handler.
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 ...
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 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...
LY_ERR
libyang's error codes returned by the libyang functions.
Definition: log.h:242
@ LYVE_DATA
Definition: log.h:279
@ LY_EMEM
Definition: log.h:244
@ LY_EVALID
Definition: log.h:250
@ LY_EINT
Definition: log.h:249
@ LY_SUCCESS
Definition: log.h:243
Libyang full error structure.
Definition: log.h:287
const char * module
LY_ERR lyplg_type_prefix_data_new(const struct ly_ctx *ctx, const void *value, size_t value_len, LY_VALUE_FORMAT format, const void *prefix_data, LY_VALUE_FORMAT *format_p, void **prefix_data_p)
Store used prefixes in a string into an internal libyang structure used in lyd_value.
#define LYPLG_TYPE_VAL_INLINE_PREPARE(storage, type_val)
Prepare value memory for storing a specific type value, may be allocated dynamically.
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.
const struct lys_module * lyplg_type_identity_module(const struct ly_ctx *ctx, const struct lysc_node *ctx_node, const char *prefix, size_t prefix_len, LY_VALUE_FORMAT format, const void *prefix_data)
Get the corresponding module for the identity value.
LY_ERR lyplg_type_validate_range(LY_DATA_TYPE basetype, struct lysc_range *range, int64_t value, const char *strval, size_t strval_len, struct ly_err_item **err)
Data type validator for a range/length-restricted values.
#define LYPLG_TYPE_VAL_INLINE_DESTROY(type_val)
Destroy a prepared value.
LY_ERR lyplg_type_prefix_data_dup(const struct ly_ctx *ctx, LY_VALUE_FORMAT format, const void *orig, void **dup)
Duplicate prefix data.
LY_ERR ly_err_new(struct ly_err_item **err, LY_ERR ecode, LY_VECODE vecode, char *path, char *apptag, const char *err_msg,...)
Create and fill error structure.
void ly_err_free(void *ptr)
Destructor for the error records created with ly_err_new().
void lyplg_type_prefix_data_free(LY_VALUE_FORMAT format, void *prefix_data)
Free internal prefix data.
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.
LY_ERR lyplg_type_validate_patterns(struct lysc_pattern **patterns, const char *str, size_t str_len, struct ly_err_item **err)
Data type validator for pattern-restricted string values.
LY_ERR lyplg_type_compare_simple(const struct lyd_value *val1, const struct lyd_value *val2)
Implementation of lyplg_type_compare_clb for a generic simple type.
API void lyplg_type_free_xpath10(const struct ly_ctx *ctx, struct lyd_value *value)
Implementation of lyplg_type_free_clb for the ietf-yang-types xpath1.0 type.
Definition: xpath1.0.c:349
API const void * lyplg_type_print_xpath10(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 ietf-yang-types xpath1.0 type.
Definition: xpath1.0.c:280
API LY_ERR lyplg_type_dup_xpath10(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup)
Implementation of lyplg_type_dup_clb for the ietf-yang-types xpath1.0 type.
Definition: xpath1.0.c:317
#define LYPLG_TYPE_STORE_DYNAMIC
LY_DATA_TYPE basetype
Definition: tree_schema.h:1531
struct lysc_pattern ** patterns
Definition: tree_schema.h:1558
struct lysc_range * length
Definition: tree_schema.h:1557
const char * prefix
Definition: tree_schema.h:2300
struct ly_ctx * ctx
Definition: tree_schema.h:2296
Available YANG schema tree structures representing YANG module.
Definition: tree_schema.h:2295
Compiled YANG data node.
Definition: tree_schema.h:1644
LY_VALUE_FORMAT
All kinds of supported value formats and prefix mappings to modules.
Definition: tree.h:235
@ LY_TYPE_STRING
Definition: tree.h:210
@ LY_VALUE_JSON
Definition: tree.h:240
@ LY_VALUE_CANON
Definition: tree.h:236
@ LY_VALUE_XML
Definition: tree.h:239
@ LY_VALUE_LYB
Definition: tree.h:241
The main libyang public header.
uint8_t ly_bool
Type to indicate boolean value.
Definition: log.h:25
API for (user) types plugins.
const struct lysc_type * realtype
Definition: tree_data.h:535
#define LYD_VALUE_GET(value, type_val)
Get the value in format specific to the type.
Definition: tree_data.h:573
const char * _canonical
Definition: tree_data.h:532
YANG data representation.
Definition: tree_data.h:531
#define LOGMEM(CTX)
Definition: tree_edit.h:25
struct lyxp_expr * exp
Definition: xpath1.0.c:44
API LY_ERR lyplg_type_store_xpath10(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 *UNUSED(ctx_node), struct lyd_value *storage, struct lys_glob_unres *UNUSED(unres), struct ly_err_item **err)
Definition: xpath1.0.c:209
LY_VALUE_FORMAT format
Definition: xpath1.0.c:47
const struct ly_ctx * ctx
Definition: xpath1.0.c:45
const struct lyplg_type_record plugins_xpath10[]
Plugin information for xpath1.0 type implementation.
Definition: xpath1.0.c:370
void * prefix_data
Definition: xpath1.0.c:46
Stored value structure for xpath1.0.
Definition: xpath1.0.c:43