ucl_internal.h revision 268831
1262395Sbapt/* Copyright (c) 2013, Vsevolod Stakhov 2262395Sbapt * All rights reserved. 3262395Sbapt * 4262395Sbapt * Redistribution and use in source and binary forms, with or without 5262395Sbapt * modification, are permitted provided that the following conditions are met: 6262395Sbapt * * Redistributions of source code must retain the above copyright 7262395Sbapt * notice, this list of conditions and the following disclaimer. 8262395Sbapt * * Redistributions in binary form must reproduce the above copyright 9262395Sbapt * notice, this list of conditions and the following disclaimer in the 10262395Sbapt * documentation and/or other materials provided with the distribution. 11262395Sbapt * 12262395Sbapt * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY 13262395Sbapt * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 14262395Sbapt * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 15262395Sbapt * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY 16262395Sbapt * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 17262395Sbapt * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 18262395Sbapt * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 19262395Sbapt * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 20262395Sbapt * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21262395Sbapt * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22262395Sbapt */ 23262395Sbapt 24262395Sbapt#ifndef UCL_INTERNAL_H_ 25262395Sbapt#define UCL_INTERNAL_H_ 26262395Sbapt 27263648Sbapt#ifdef HAVE_CONFIG_H 28263648Sbapt#include "config.h" 29263648Sbapt#else 30263648Sbapt/* Help embedded builds */ 31263648Sbapt#define HAVE_SYS_TYPES_H 32263648Sbapt#define HAVE_SYS_MMAN_H 33263648Sbapt#define HAVE_SYS_STAT_H 34263648Sbapt#define HAVE_SYS_PARAM_H 35263648Sbapt#define HAVE_LIMITS_H 36263648Sbapt#define HAVE_FCNTL_H 37263648Sbapt#define HAVE_ERRNO_H 38263648Sbapt#define HAVE_UNISTD_H 39263648Sbapt#define HAVE_CTYPE_H 40263648Sbapt#define HAVE_STDIO_H 41263648Sbapt#define HAVE_STRING_H 42263648Sbapt#define HAVE_FLOAT_H 43263648Sbapt#define HAVE_LIBGEN_H 44263648Sbapt#define HAVE_MATH_H 45263648Sbapt#define HAVE_STDBOOL_H 46263648Sbapt#define HAVE_STDINT_H 47263648Sbapt#define HAVE_STDARG_H 48264789Sbapt#ifndef _WIN32 49264789Sbapt# define HAVE_REGEX_H 50263648Sbapt#endif 51264789Sbapt#endif 52263648Sbapt 53263648Sbapt#ifdef HAVE_SYS_TYPES_H 54262395Sbapt#include <sys/types.h> 55262975Sbapt#endif 56263648Sbapt 57263648Sbapt#ifdef HAVE_SYS_MMAN_H 58263648Sbapt# ifndef _WIN32 59263648Sbapt# include <sys/mman.h> 60263648Sbapt# endif 61263648Sbapt#endif 62263648Sbapt#ifdef HAVE_SYS_STAT_H 63262395Sbapt#include <sys/stat.h> 64263648Sbapt#endif 65263648Sbapt#ifdef HAVE_SYS_PARAM_H 66262395Sbapt#include <sys/param.h> 67263648Sbapt#endif 68262395Sbapt 69263648Sbapt#ifdef HAVE_LIMITS_H 70262395Sbapt#include <limits.h> 71263648Sbapt#endif 72263648Sbapt#ifdef HAVE_FCNTL_H 73262395Sbapt#include <fcntl.h> 74263648Sbapt#endif 75263648Sbapt#ifdef HAVE_ERRNO_H 76262395Sbapt#include <errno.h> 77263648Sbapt#endif 78263648Sbapt#ifdef HAVE_UNISTD_H 79262395Sbapt#include <unistd.h> 80263648Sbapt#endif 81263648Sbapt#ifdef HAVE_CTYPE_H 82262395Sbapt#include <ctype.h> 83263648Sbapt#endif 84263648Sbapt#ifdef HAVE_STDIO_H 85263648Sbapt#include <stdio.h> 86263648Sbapt#endif 87263648Sbapt#ifdef HAVE_STRING_H 88263648Sbapt#include <string.h> 89263648Sbapt#endif 90262395Sbapt 91262395Sbapt#include "utlist.h" 92262395Sbapt#include "utstring.h" 93262395Sbapt#include "uthash.h" 94262395Sbapt#include "ucl.h" 95262395Sbapt#include "ucl_hash.h" 96262395Sbapt#include "xxhash.h" 97262395Sbapt 98262395Sbapt#ifdef HAVE_OPENSSL 99262395Sbapt#include <openssl/evp.h> 100262395Sbapt#endif 101262395Sbapt 102264789Sbapt#ifndef __DECONST 103264789Sbapt#define __DECONST(type, var) ((type)(uintptr_t)(const void *)(var)) 104264789Sbapt#endif 105264789Sbapt 106262395Sbapt/** 107262395Sbapt * @file rcl_internal.h 108262395Sbapt * Internal structures and functions of UCL library 109262395Sbapt */ 110262395Sbapt 111262395Sbapt#define UCL_MAX_RECURSION 16 112262395Sbapt#define UCL_TRASH_KEY 0 113262395Sbapt#define UCL_TRASH_VALUE 1 114262395Sbapt 115262395Sbaptenum ucl_parser_state { 116262395Sbapt UCL_STATE_INIT = 0, 117262395Sbapt UCL_STATE_OBJECT, 118262395Sbapt UCL_STATE_ARRAY, 119262395Sbapt UCL_STATE_KEY, 120262395Sbapt UCL_STATE_VALUE, 121262395Sbapt UCL_STATE_AFTER_VALUE, 122262395Sbapt UCL_STATE_ARRAY_VALUE, 123262395Sbapt UCL_STATE_SCOMMENT, 124262395Sbapt UCL_STATE_MCOMMENT, 125262395Sbapt UCL_STATE_MACRO_NAME, 126262395Sbapt UCL_STATE_MACRO, 127262395Sbapt UCL_STATE_ERROR 128262395Sbapt}; 129262395Sbapt 130262395Sbaptenum ucl_character_type { 131262395Sbapt UCL_CHARACTER_DENIED = 0, 132262395Sbapt UCL_CHARACTER_KEY = 1, 133262395Sbapt UCL_CHARACTER_KEY_START = 1 << 1, 134262395Sbapt UCL_CHARACTER_WHITESPACE = 1 << 2, 135262395Sbapt UCL_CHARACTER_WHITESPACE_UNSAFE = 1 << 3, 136262395Sbapt UCL_CHARACTER_VALUE_END = 1 << 4, 137262395Sbapt UCL_CHARACTER_VALUE_STR = 1 << 5, 138262395Sbapt UCL_CHARACTER_VALUE_DIGIT = 1 << 6, 139262395Sbapt UCL_CHARACTER_VALUE_DIGIT_START = 1 << 7, 140262395Sbapt UCL_CHARACTER_ESCAPE = 1 << 8, 141262395Sbapt UCL_CHARACTER_KEY_SEP = 1 << 9, 142262395Sbapt UCL_CHARACTER_JSON_UNSAFE = 1 << 10, 143262395Sbapt UCL_CHARACTER_UCL_UNSAFE = 1 << 11 144262395Sbapt}; 145262395Sbapt 146262395Sbaptstruct ucl_macro { 147262395Sbapt char *name; 148262395Sbapt ucl_macro_handler handler; 149262395Sbapt void* ud; 150262395Sbapt UT_hash_handle hh; 151262395Sbapt}; 152262395Sbapt 153262395Sbaptstruct ucl_stack { 154262395Sbapt ucl_object_t *obj; 155262395Sbapt struct ucl_stack *next; 156262395Sbapt int level; 157262395Sbapt}; 158262395Sbapt 159262395Sbaptstruct ucl_chunk { 160262395Sbapt const unsigned char *begin; 161262395Sbapt const unsigned char *end; 162262395Sbapt const unsigned char *pos; 163262395Sbapt size_t remain; 164262395Sbapt unsigned int line; 165262395Sbapt unsigned int column; 166262395Sbapt struct ucl_chunk *next; 167262395Sbapt}; 168262395Sbapt 169262395Sbapt#ifdef HAVE_OPENSSL 170262395Sbaptstruct ucl_pubkey { 171262395Sbapt EVP_PKEY *key; 172262395Sbapt struct ucl_pubkey *next; 173262395Sbapt}; 174262395Sbapt#else 175262395Sbaptstruct ucl_pubkey { 176262395Sbapt struct ucl_pubkey *next; 177262395Sbapt}; 178262395Sbapt#endif 179262395Sbapt 180262395Sbaptstruct ucl_variable { 181262395Sbapt char *var; 182262395Sbapt char *value; 183262395Sbapt size_t var_len; 184262395Sbapt size_t value_len; 185262395Sbapt struct ucl_variable *next; 186262395Sbapt}; 187262395Sbapt 188262395Sbaptstruct ucl_parser { 189262395Sbapt enum ucl_parser_state state; 190262395Sbapt enum ucl_parser_state prev_state; 191262395Sbapt unsigned int recursion; 192262395Sbapt int flags; 193262395Sbapt ucl_object_t *top_obj; 194262395Sbapt ucl_object_t *cur_obj; 195262395Sbapt struct ucl_macro *macroes; 196262395Sbapt struct ucl_stack *stack; 197262395Sbapt struct ucl_chunk *chunks; 198262395Sbapt struct ucl_pubkey *keys; 199262395Sbapt struct ucl_variable *variables; 200266636Sbapt ucl_variable_handler var_handler; 201266636Sbapt void *var_data; 202262395Sbapt UT_string *err; 203262395Sbapt}; 204262395Sbapt 205262395Sbapt/** 206262395Sbapt * Unescape json string inplace 207262395Sbapt * @param str 208262395Sbapt */ 209262395Sbaptsize_t ucl_unescape_json_string (char *str, size_t len); 210262395Sbapt 211262395Sbapt/** 212262395Sbapt * Handle include macro 213262395Sbapt * @param data include data 214262395Sbapt * @param len length of data 215262395Sbapt * @param ud user data 216262395Sbapt * @param err error ptr 217262395Sbapt * @return 218262395Sbapt */ 219262395Sbaptbool ucl_include_handler (const unsigned char *data, size_t len, void* ud); 220262395Sbapt 221262395Sbaptbool ucl_try_include_handler (const unsigned char *data, size_t len, void* ud); 222262395Sbapt 223262395Sbapt/** 224262395Sbapt * Handle includes macro 225262395Sbapt * @param data include data 226262395Sbapt * @param len length of data 227262395Sbapt * @param ud user data 228262395Sbapt * @param err error ptr 229262395Sbapt * @return 230262395Sbapt */ 231262395Sbaptbool ucl_includes_handler (const unsigned char *data, size_t len, void* ud); 232262395Sbapt 233262395Sbaptsize_t ucl_strlcpy (char *dst, const char *src, size_t siz); 234262395Sbaptsize_t ucl_strlcpy_unsafe (char *dst, const char *src, size_t siz); 235262395Sbaptsize_t ucl_strlcpy_tolower (char *dst, const char *src, size_t siz); 236262395Sbapt 237262395Sbapt 238262395Sbapt#ifdef __GNUC__ 239262395Sbaptstatic inline void 240262395Sbaptucl_create_err (UT_string **err, const char *fmt, ...) 241262395Sbapt__attribute__ (( format( printf, 2, 3) )); 242262395Sbapt#endif 243262395Sbapt 244262395Sbaptstatic inline void 245262395Sbaptucl_create_err (UT_string **err, const char *fmt, ...) 246262395Sbapt 247262395Sbapt{ 248262395Sbapt if (*err == NULL) { 249262395Sbapt utstring_new (*err); 250262395Sbapt va_list ap; 251262395Sbapt va_start (ap, fmt); 252262395Sbapt utstring_printf_va (*err, fmt, ap); 253262395Sbapt va_end (ap); 254262395Sbapt } 255262395Sbapt} 256262395Sbapt 257262395Sbapt/** 258262395Sbapt * Check whether a given string contains a boolean value 259262395Sbapt * @param obj object to set 260262395Sbapt * @param start start of a string 261262395Sbapt * @param len length of a string 262262395Sbapt * @return true if a string is a boolean value 263262395Sbapt */ 264262395Sbaptstatic inline bool 265262395Sbaptucl_maybe_parse_boolean (ucl_object_t *obj, const unsigned char *start, size_t len) 266262395Sbapt{ 267262395Sbapt const unsigned char *p = start; 268262395Sbapt bool ret = false, val = false; 269262395Sbapt 270262395Sbapt if (len == 5) { 271262395Sbapt if ((p[0] == 'f' || p[0] == 'F') && strncasecmp (p, "false", 5) == 0) { 272262395Sbapt ret = true; 273262395Sbapt val = false; 274262395Sbapt } 275262395Sbapt } 276262395Sbapt else if (len == 4) { 277262395Sbapt if ((p[0] == 't' || p[0] == 'T') && strncasecmp (p, "true", 4) == 0) { 278262395Sbapt ret = true; 279262395Sbapt val = true; 280262395Sbapt } 281262395Sbapt } 282262395Sbapt else if (len == 3) { 283262395Sbapt if ((p[0] == 'y' || p[0] == 'Y') && strncasecmp (p, "yes", 3) == 0) { 284262395Sbapt ret = true; 285262395Sbapt val = true; 286262395Sbapt } 287262395Sbapt else if ((p[0] == 'o' || p[0] == 'O') && strncasecmp (p, "off", 3) == 0) { 288262395Sbapt ret = true; 289262395Sbapt val = false; 290262395Sbapt } 291262395Sbapt } 292262395Sbapt else if (len == 2) { 293262395Sbapt if ((p[0] == 'n' || p[0] == 'N') && strncasecmp (p, "no", 2) == 0) { 294262395Sbapt ret = true; 295262395Sbapt val = false; 296262395Sbapt } 297262395Sbapt else if ((p[0] == 'o' || p[0] == 'O') && strncasecmp (p, "on", 2) == 0) { 298262395Sbapt ret = true; 299262395Sbapt val = true; 300262395Sbapt } 301262395Sbapt } 302262395Sbapt 303262395Sbapt if (ret) { 304262395Sbapt obj->type = UCL_BOOLEAN; 305262395Sbapt obj->value.iv = val; 306262395Sbapt } 307262395Sbapt 308262395Sbapt return ret; 309262395Sbapt} 310262395Sbapt 311262395Sbapt/** 312262395Sbapt * Check numeric string 313262395Sbapt * @param obj object to set if a string is numeric 314262395Sbapt * @param start start of string 315262395Sbapt * @param end end of string 316262395Sbapt * @param pos position where parsing has stopped 317262395Sbapt * @param allow_double allow parsing of floating point values 318262395Sbapt * @return 0 if string is numeric and error code (EINVAL or ERANGE) in case of conversion error 319262395Sbapt */ 320262395Sbaptint ucl_maybe_parse_number (ucl_object_t *obj, 321263648Sbapt const char *start, const char *end, const char **pos, 322263648Sbapt bool allow_double, bool number_bytes, bool allow_time); 323262395Sbapt 324262395Sbapt 325264789Sbaptstatic inline const ucl_object_t * 326262395Sbaptucl_hash_search_obj (ucl_hash_t* hashlin, ucl_object_t *obj) 327262395Sbapt{ 328264789Sbapt return (const ucl_object_t *)ucl_hash_search (hashlin, obj->key, obj->keylen); 329262395Sbapt} 330262395Sbapt 331262395Sbaptstatic inline ucl_hash_t * 332264789Sbaptucl_hash_insert_object (ucl_hash_t *hashlin, const ucl_object_t *obj) UCL_WARN_UNUSED_RESULT; 333262395Sbapt 334262395Sbaptstatic inline ucl_hash_t * 335264789Sbaptucl_hash_insert_object (ucl_hash_t *hashlin, const ucl_object_t *obj) 336262395Sbapt{ 337262395Sbapt if (hashlin == NULL) { 338262395Sbapt hashlin = ucl_hash_create (); 339262395Sbapt } 340262395Sbapt ucl_hash_insert (hashlin, obj, obj->key, obj->keylen); 341262395Sbapt 342262395Sbapt return hashlin; 343262395Sbapt} 344262395Sbapt 345262395Sbapt/** 346268831Sbapt * Get standard emitter context for a specified emit_type 347268831Sbapt * @param emit_type type of emitter 348268831Sbapt * @return context or NULL if input is invalid 349268831Sbapt */ 350268831Sbaptconst struct ucl_emitter_context * 351268831Sbaptucl_emit_get_standard_context (enum ucl_emitter emit_type); 352268831Sbapt 353268831Sbapt/** 354268831Sbapt * Serialise string 355268831Sbapt * @param str string to emit 356268831Sbapt * @param buf target buffer 357268831Sbapt */ 358268831Sbaptvoid ucl_elt_string_write_json (const char *str, size_t size, 359268831Sbapt struct ucl_emitter_context *ctx); 360268831Sbapt 361268831Sbapt/** 362262395Sbapt * Emit a single object to string 363262395Sbapt * @param obj 364262395Sbapt * @return 365262395Sbapt */ 366264789Sbaptunsigned char * ucl_object_emit_single_json (const ucl_object_t *obj); 367262395Sbapt 368262395Sbapt#endif /* UCL_INTERNAL_H_ */ 369