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