blob: a4b295646398f00849c7b1108dd69e39c60381d5 [file] [log] [blame]
Michal Vasko5a9eb762018-03-26 11:45:33 +02001/**
2 * @file common.h
3 * @author Radek Krejci <rkrejci@cesnet.cz>
4 * @brief common internal definitions for libyang
5 *
6 * Copyright (c) 2015 - 2018 CESNET, z.s.p.o.
7 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
14
15#ifndef LY_COMMON_H_
16#define LY_COMMON_H_
17
18#include <stdint.h>
19#include <errno.h>
20#include <inttypes.h>
21
22#include "libyang.h"
23#include "hash_table.h"
24#include "resolve.h"
25
26#define UNUSED(x) @COMPILER_UNUSED_ATTR@
27
Rafael Zalamenafc543772018-10-14 16:32:53 +020028#if __STDC_VERSION__ >= 201112 && \
29 !defined __STDC_NO_THREADS__ && \
30 !defined __NetBSD__
Michal Vasko5a9eb762018-03-26 11:45:33 +020031# define THREAD_LOCAL _Thread_local
32#elif defined __GNUC__ || \
33 defined __SUNPRO_C || \
34 defined __xlC__
35# define THREAD_LOCAL __thread
36#else
37# error "Cannot define THREAD_LOCAL"
38#endif
39
40#ifndef __WORDSIZE
41# if defined __x86_64__ && !defined __ILP32__
42# define __WORDSIZE 64
43# else
44# define __WORDSIZE 32
45# endif
46#endif
47
48#ifndef __INT64_C
49# if __WORDSIZE == 64
50# define __INT64_C(c) c ## L
51# define __UINT64_C(c) c ## UL
52# else
53# define __INT64_C(c) c ## LL
54# define __UINT64_C(c) c ## ULL
55# endif
56#endif
57
Rafael Zalamena0d7142e2018-10-14 16:17:48 +020058#ifndef MAP_ANONYMOUS
59#define MAP_ANONYMOUS MAP_ANON
60#endif /* !MAP_ANONYMOUS */
61
Michal Vasko5a9eb762018-03-26 11:45:33 +020062#define LY_CHECK_GOTO(COND, GOTO) if (COND) {goto GOTO;}
63#define LY_CHECK_ERR_GOTO(COND, ERR, GOTO) if (COND) {ERR; goto GOTO;}
64#define LY_CHECK_RETURN(COND, RETVAL) if (COND) {return RETVAL;}
65#define LY_CHECK_ERR_RETURN(COND, ERR, RETVAL) if (COND) {ERR; return RETVAL;}
66
67/*
68 * If the compiler supports attribute to mark objects as hidden, mark all
69 * objects as hidden and export only objects explicitly marked to be part of
70 * the public API.
71 */
72#define API __attribute__((visibility("default")))
73
74#ifndef __USE_GNU
75/*
76 * If we don't have GNU extension, implement these function on your own
77 */
78char *get_current_dir_name(void);
79
80#endif
81
82/* how many bytes add when enlarging buffers */
83#define LY_BUF_STEP 128
84
85/* internal logging options */
86enum int_log_opts {
87 ILO_LOG = 0, /* log normally */
88 ILO_STORE, /* only store any messages, they will be processed higher on stack */
89 ILO_IGNORE, /* completely ignore messages */
90 ILO_ERR2WRN, /* change errors to warnings */
91};
92
93void ly_err_free(void *ptr);
94void ly_err_free_next(struct ly_ctx *ctx, struct ly_err_item *last_eitem);
95void ly_ilo_change(struct ly_ctx *ctx, enum int_log_opts new_ilo, enum int_log_opts *prev_ilo, struct ly_err_item **prev_last_eitem);
96void ly_ilo_restore(struct ly_ctx *ctx, enum int_log_opts prev_ilo, struct ly_err_item *prev_last_eitem, int keep_and_print);
97void ly_err_last_set_apptag(const struct ly_ctx *ctx, const char *apptag);
98extern THREAD_LOCAL enum int_log_opts log_opt;
99
100/*
101 * logger
102 */
103extern volatile uint8_t ly_log_level;
104extern volatile uint8_t ly_log_opts;
105
106void ly_log(const struct ly_ctx *ctx, LY_LOG_LEVEL level, LY_ERR no, const char *format, ...);
107
108#define LOGERR(ctx, errno, str, args...) \
109 ly_log(ctx, LY_LLERR, errno, str, ##args);
110
111#define LOGWRN(ctx, str, args...) \
112 ly_log(ctx, LY_LLWRN, 0, str, ##args);
113
114#define LOGVRB(str, args...) \
115 ly_log(NULL, LY_LLVRB, 0, str, ##args);
116
117#ifdef NDEBUG
118
119#define LOGDBG(dbg_group, str, args...)
120
121#else
122
123#define LOGDBG(dbg_group, str, args...) \
124 ly_log_dbg(dbg_group, str, ##args);
125
126void ly_log_dbg(int group, const char *format, ...);
127
128#endif
129
130#define LOGMEM(ctx) LOGERR(ctx, LY_EMEM, "Memory allocation failed (%s()).", __func__)
131
132#define LOGINT(ctx) LOGERR(ctx, LY_EINT, "Internal error (%s:%d).", __FILE__, __LINE__)
133
134#define LOGARG LOGERR(NULL, LY_EINVAL, "Invalid arguments (%s()).", __func__)
135
136typedef enum {
137 LYE_PATH = -2, /**< error path set */
138 LYE_SPEC = -1, /**< generic error */
139
140 LYE_SUCCESS = 0,
141
142 LYE_XML_MISS,
143 LYE_XML_INVAL,
144 LYE_XML_INCHAR,
145
146 LYE_EOF,
147 LYE_INSTMT,
148 LYE_INCHILDSTMT,
149 LYE_INPAR,
150 LYE_INID,
151 LYE_INDATE,
152 LYE_INARG,
153 LYE_MISSSTMT,
154 LYE_MISSCHILDSTMT,
155 LYE_MISSARG,
156 LYE_TOOMANY,
157 LYE_DUPID,
158 LYE_DUPLEAFLIST,
159 LYE_DUPLIST,
160 LYE_NOUNIQ,
161 LYE_ENUM_INVAL,
162 LYE_ENUM_INNAME,
163 LYE_ENUM_DUPVAL,
164 LYE_ENUM_DUPNAME,
165 LYE_ENUM_WS,
166 LYE_BITS_INVAL,
167 LYE_BITS_INNAME,
168 LYE_BITS_DUPVAL,
169 LYE_BITS_DUPNAME,
170 LYE_INMOD,
171 LYE_INMOD_LEN,
172 LYE_KEY_NLEAF,
173 LYE_KEY_TYPE,
174 LYE_KEY_CONFIG,
175 LYE_KEY_MISS,
176 LYE_KEY_DUP,
177 LYE_INREGEX,
178 LYE_INRESOLV,
179 LYE_INSTATUS,
180 LYE_CIRC_LEAFREFS,
181 LYE_CIRC_FEATURES,
182 LYE_CIRC_IMPORTS,
183 LYE_CIRC_INCLUDES,
184 LYE_INVER,
185 LYE_SUBMODULE,
186
187 LYE_OBSDATA,
188 LYE_OBSTYPE,
189 LYE_NORESOLV,
190 LYE_INELEM,
191 LYE_INELEM_LEN,
192 LYE_MISSELEM,
193 LYE_INVAL,
194 LYE_INMETA,
195 LYE_INATTR,
196 LYE_MISSATTR,
197 LYE_NOCONSTR,
198 LYE_INCHAR,
199 LYE_INPRED,
200 LYE_MCASEDATA,
201 LYE_NOMUST,
202 LYE_NOWHEN,
203 LYE_INORDER,
204 LYE_INWHEN,
205 LYE_NOMIN,
206 LYE_NOMAX,
207 LYE_NOREQINS,
208 LYE_NOLEAFREF,
209 LYE_NOMANDCHOICE,
210
211 LYE_XPATH_INTOK,
212 LYE_XPATH_EOF,
213 LYE_XPATH_INOP_1,
214 LYE_XPATH_INOP_2,
215 LYE_XPATH_INCTX,
216 LYE_XPATH_INMOD,
217 LYE_XPATH_INFUNC,
218 LYE_XPATH_INARGCOUNT,
219 LYE_XPATH_INARGTYPE,
220 LYE_XPATH_DUMMY,
221 LYE_XPATH_NOEND,
222
223 LYE_PATH_INCHAR,
224 LYE_PATH_INMOD,
225 LYE_PATH_MISSMOD,
226 LYE_PATH_INNODE,
227 LYE_PATH_INKEY,
228 LYE_PATH_MISSKEY,
Michal Vasko310bc582018-05-22 10:47:59 +0200229 LYE_PATH_INIDENTREF,
Michal Vasko5a9eb762018-03-26 11:45:33 +0200230 LYE_PATH_EXISTS,
231 LYE_PATH_MISSPAR,
Michal Vaskofebd13d2018-05-17 10:42:24 +0200232 LYE_PATH_PREDTOOMANY,
Michal Vasko5a9eb762018-03-26 11:45:33 +0200233} LY_ECODE;
234
235enum LY_VLOG_ELEM {
236 LY_VLOG_NONE = 0,
237 LY_VLOG_XML, /* struct lyxml_elem* */
238 LY_VLOG_LYS, /* struct lys_node* */
239 LY_VLOG_LYD, /* struct lyd_node* */
240 LY_VLOG_STR, /* const char* */
241 LY_VLOG_PREV /* use exact same previous path */
242};
243
244void ly_vlog(const struct ly_ctx *ctx, LY_ECODE code, enum LY_VLOG_ELEM elem_type, const void *elem, ...);
245#define LOGVAL(ctx, code, elem_type, elem, args...) \
246 ly_vlog(ctx, code, elem_type, elem, ##args);
247
248#define LOGPATH(ctx, elem_type, elem) \
249 ly_vlog(ctx, LYE_PATH, elem_type, elem);
250
251/**
Michal Vaskob4b31f62018-11-23 11:49:20 +0100252 * @brief Print additional validation information string.
253 *
254 * All special characters will be escaped ('%').
255 *
256 * @param[in] ctx Context to use for logging.
257 * @param[in] elem_type Identify the element at issue. Either #LY_VLOG_NONE or #LY_VLOG_PREV.
258 * @param[in] str String to print that will be escaped.
259 * @param[in] ... Always leave empty (needed for compiler to accept va_start() call).
260 */
261void ly_vlog_str(const struct ly_ctx *ctx, enum LY_VLOG_ELEM elem_type, const char *str, ...);
262
263/**
Michal Vasko5a9eb762018-03-26 11:45:33 +0200264 * @brief Build path of \p elem.
265 *
266 * @param[in] elem_type What to expect in \p elem.
267 * @param[in] elem Element to print.
268 * @param[in,out] path Resulting path printed.
269 * @param[in] schema_all_prefixes Whether to include prefixes for all the nodes (only for schema paths).
Michal Vasko185b5272018-09-13 14:26:12 +0200270 * @param[in] data_no_predicates Whether to skip generating predicates for all the nodes (only for data paths).
Michal Vasko5a9eb762018-03-26 11:45:33 +0200271 * @return 0 on success, -1 on error.
272 */
Michal Vasko185b5272018-09-13 14:26:12 +0200273int ly_vlog_build_path(enum LY_VLOG_ELEM elem_type, const void *elem, char **path, int schema_all_prefixes, int data_no_predicates);
Michal Vasko5a9eb762018-03-26 11:45:33 +0200274
275/**
276 * @brief Get module from a context based on its name and revision.
277 *
278 * @param[in] ctx Context to search in.
279 * @param[in] name Name of the module.
280 * @param[in] name_len Length of \p name, can be 0 if the name is ended with '\0'.
281 * @param[in] revision Revision of the module, can be NULL for the newest.
282 * @param[in] implemented Whether only implemented modules should be returned.
283 * @return Matching module, NULL if not found.
284 */
285const struct lys_module *ly_ctx_nget_module(const struct ly_ctx *ctx, const char *name, size_t name_len,
286 const char *revision, int implemented);
287
288/*
289 * - if \p module specified, it searches for submodules, they can be loaded only from a file or via module callback,
290 * they cannot be get from context
291 * - if \p module is not specified
292 * - if specific revision is specified, the first try is to get module from the context
293 * - if no specific revision is specified, it tries to get the newest module - first it searches for the file and
294 * then checks that the schema loaded from the same source isn't already in context. If the source wasn't
295 * previously loaded, it is parsed.
296 */
297const struct lys_module *ly_ctx_load_sub_module(struct ly_ctx *ctx, struct lys_module *module, const char *name,
298 const char *revision, int implement, struct unres_schema *unres);
299
300/**
301 * @brief Basic functionality like strpbrk(3). However, it searches string \p s
302 * backwards up to most \p s_len characters.
303 *
304 * @param[in] s String to search backwards.
305 * @param[in] accept String of characters that are searched for.
306 * @param[in] s_len Backward length of \p s.
307 *
308 * @return Pointer to the first backward occurence of a character from
309 * \p accept or \p s - \p s_len if not found.
310 */
311const char *strpbrk_backwards(const char *s, const char *accept, unsigned int s_len);
312
313char *strnchr(const char *s, int c, unsigned int len);
314
315const char *strnodetype(LYS_NODE type);
316
317/**
318 * @brief Transform a module name (JSON format prefix) to a prefix as defined
319 * in \p module imports. Its own name is transformed to its own prefix.
320 *
321 * @param[in] module Module with imports to use.
322 * @param[in] module_name Module name to transform.
323 *
324 * @return Module import prefix (do not modify, free, or lydict_remove),
325 * NULL on error.
326 */
327const char *transform_module_name2import_prefix(const struct lys_module *module, const char *module_name);
328
329/**
330 * @brief Transform expression from JSON format to XML format.
331 * Output arrays point to strings in the dictionary, but without
332 * correcting their ref_count -> do not touch them. Prefixes of
333 * the namespaces are prefixes specified by the module itself. Output
334 * parameters are optional, but either all 3 are set or none
335 * of them are. Logs directly.
336 *
337 * @param[in] module Module with imports to use.
338 * @param[in] expr JSON expression.
339 * @param[in] inst_id Whether to add prefixes to all node names (XML instance-identifier).
340 * @param[out] prefixes Array of pointers to prefixes. After use free them with free(*prefixes).
341 * Can be NULL.
342 * @param[out] namespaces Array of pointers to full namespaces. After use free them with
343 * free(*namespaces). Can be NULL.
344 * @param[out] ns_count Number of elements in both \p prefixes and \p namespaces arrays.
345 * Can be NULL.
346 *
347 * @return Transformed XML expression in the dictionary, NULL on error.
348 */
349const char *transform_json2xml(const struct lys_module *module, const char *expr, int inst_id, const char ***prefixes,
350 const char ***namespaces, uint32_t *ns_count);
351
352/**
353 * @brief Transform expression from JSON format to schema format.
354 * Prefixes of the namespaces (models) are those from the main
355 * \p module imports of the corresponding modules. Logs directly.
356 *
357 * @param[in] module Module with imports to use.
358 * @param[in] expr JSON expression.
359 *
360 * @return Transformed XML expression in the dictionary, NULL on error.
361 */
362const char *transform_json2schema(const struct lys_module *module, const char *expr);
363
364/**
365 * @brief Transform expression from XML data format (prefixes and separate NS definitions) to
366 * JSON format (prefixes are module names instead). Logs directly.
367 *
368 * @param[in] ctx libyang context to use.
369 * @param[in] expr XML expression.
370 * @param[in] xml XML element with the expression.
371 * @param[in] inst_id Whether all the node names must have a prefix (XML instance-identifier).
372 * @param[in] use_ctx_data_clb Whether to use data_clb in \p ctx if an unknown module namespace is found.
373 *
374 * @return Transformed JSON expression in the dictionary, NULL on error.
375 */
376const char *transform_xml2json(struct ly_ctx *ctx, const char *expr, struct lyxml_elem *xml, int inst_id,
377 int use_ctx_data_clb);
378
379/**
380 * @brief Transform expression from the schema format (prefixes of imports) to
381 * JSON format (prefixes are module names directly). Logs directly.
382 *
383 * @param[in] module Module (schema) with imports to search.
384 * @param[in] expr Expression from \p module.
385 *
386 * @return Transformed JSON expression in the dictionary, NULL on error.
387 */
388const char *transform_schema2json(const struct lys_module *module, const char *expr);
389
390/**
391 * @brief Same as transform_schema2json, but dumbed down, because if-feature expressions
392 * are not valid XPath expressions.
393 */
394const char *transform_iffeat_schema2json(const struct lys_module *module, const char *expr);
395
396/**
397 * @brief Transform an XPath expression in JSON node naming conventions into
398 * standard YANG XPath.
399 */
400char *transform_json2xpath(const struct lys_module *cur_module, const char *expr);
401
402/**
403 * @brief Get a new node (non-validated) validity value.
404 *
405 * @param[in] schema Schema node of the new data node.
406 *
407 * @return Validity of the new node.
408 */
409int ly_new_node_validity(const struct lys_node *schema);
410
411/**
412 * @brief Wrapper for realloc() call. The only difference is that if it fails to
413 * allocate the requested memory, the original memory is freed as well.
414 *
415 * @param[in] ptr Memory to reallocate.
416 * @param[in] size New size of the memory block.
417 *
418 * @return Pointer to the new memory, NULL on error.
419 */
420void *ly_realloc(void *ptr, size_t size);
421
422/**
423 * @brief Compare strings
424 * @param[in] s1 First string to compare
425 * @param[in] s2 Second string to compare
426 * @param[in] both_in_dictionary Flag for optimization, 1 if it is sure that \p s1 and \p s2 were stored in dictionary.
427 * This parameter is supposed to be a number (digit) known in compile time, not a variable or expression!
428 * @return 1 if both strings are the same, 0 if they differ.
429 */
430int ly_strequal_(const char *s1, const char *s2);
431#define ly_strequal0(s1, s2) ly_strequal_(s1, s2)
432#define ly_strequal1(s1, s2) (s1 == s2)
433#define ly_strequal(s1, s2, d) ly_strequal##d(s1, s2)
434
435int64_t dec_pow(uint8_t exp);
436
437int dec64cmp(int64_t num1, uint8_t dig1, int64_t num2, uint8_t dig2);
438
439#endif /* LY_COMMON_H_ */