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 27262395Sbapt#include <sys/types.h> 28263032Sbapt#ifndef _WIN32 29262395Sbapt#include <sys/mman.h> 30263032Sbapt#endif 31262395Sbapt#include <sys/stat.h> 32262395Sbapt#include <sys/param.h> 33262395Sbapt 34262395Sbapt#include <limits.h> 35262395Sbapt#include <fcntl.h> 36262395Sbapt#include <errno.h> 37262395Sbapt#include <unistd.h> 38262395Sbapt#include <ctype.h> 39262395Sbapt 40262395Sbapt#include "utlist.h" 41262395Sbapt#include "utstring.h" 42262395Sbapt#include "uthash.h" 43262395Sbapt#include "ucl.h" 44262395Sbapt#include "ucl_hash.h" 45262395Sbapt#include "xxhash.h" 46262395Sbapt 47262395Sbapt#ifdef HAVE_OPENSSL 48262395Sbapt#include <openssl/evp.h> 49262395Sbapt#endif 50262395Sbapt 51262395Sbapt/** 52262395Sbapt * @file rcl_internal.h 53262395Sbapt * Internal structures and functions of UCL library 54262395Sbapt */ 55262395Sbapt 56262395Sbapt#define UCL_MAX_RECURSION 16 57262395Sbapt#define UCL_TRASH_KEY 0 58262395Sbapt#define UCL_TRASH_VALUE 1 59262395Sbapt 60262395Sbaptenum ucl_parser_state { 61262395Sbapt UCL_STATE_INIT = 0, 62262395Sbapt UCL_STATE_OBJECT, 63262395Sbapt UCL_STATE_ARRAY, 64262395Sbapt UCL_STATE_KEY, 65262395Sbapt UCL_STATE_VALUE, 66262395Sbapt UCL_STATE_AFTER_VALUE, 67262395Sbapt UCL_STATE_ARRAY_VALUE, 68262395Sbapt UCL_STATE_SCOMMENT, 69262395Sbapt UCL_STATE_MCOMMENT, 70262395Sbapt UCL_STATE_MACRO_NAME, 71262395Sbapt UCL_STATE_MACRO, 72262395Sbapt UCL_STATE_ERROR 73262395Sbapt}; 74262395Sbapt 75262395Sbaptenum ucl_character_type { 76262395Sbapt UCL_CHARACTER_DENIED = 0, 77262395Sbapt UCL_CHARACTER_KEY = 1, 78262395Sbapt UCL_CHARACTER_KEY_START = 1 << 1, 79262395Sbapt UCL_CHARACTER_WHITESPACE = 1 << 2, 80262395Sbapt UCL_CHARACTER_WHITESPACE_UNSAFE = 1 << 3, 81262395Sbapt UCL_CHARACTER_VALUE_END = 1 << 4, 82262395Sbapt UCL_CHARACTER_VALUE_STR = 1 << 5, 83262395Sbapt UCL_CHARACTER_VALUE_DIGIT = 1 << 6, 84262395Sbapt UCL_CHARACTER_VALUE_DIGIT_START = 1 << 7, 85262395Sbapt UCL_CHARACTER_ESCAPE = 1 << 8, 86262395Sbapt UCL_CHARACTER_KEY_SEP = 1 << 9, 87262395Sbapt UCL_CHARACTER_JSON_UNSAFE = 1 << 10, 88262395Sbapt UCL_CHARACTER_UCL_UNSAFE = 1 << 11 89262395Sbapt}; 90262395Sbapt 91262395Sbaptstruct ucl_macro { 92262395Sbapt char *name; 93262395Sbapt ucl_macro_handler handler; 94262395Sbapt void* ud; 95262395Sbapt UT_hash_handle hh; 96262395Sbapt}; 97262395Sbapt 98262395Sbaptstruct ucl_stack { 99262395Sbapt ucl_object_t *obj; 100262395Sbapt struct ucl_stack *next; 101262395Sbapt int level; 102262395Sbapt}; 103262395Sbapt 104262395Sbaptstruct ucl_chunk { 105262395Sbapt const unsigned char *begin; 106262395Sbapt const unsigned char *end; 107262395Sbapt const unsigned char *pos; 108262395Sbapt size_t remain; 109262395Sbapt unsigned int line; 110262395Sbapt unsigned int column; 111262395Sbapt struct ucl_chunk *next; 112262395Sbapt}; 113262395Sbapt 114262395Sbapt#ifdef HAVE_OPENSSL 115262395Sbaptstruct ucl_pubkey { 116262395Sbapt EVP_PKEY *key; 117262395Sbapt struct ucl_pubkey *next; 118262395Sbapt}; 119262395Sbapt#else 120262395Sbaptstruct ucl_pubkey { 121262395Sbapt struct ucl_pubkey *next; 122262395Sbapt}; 123262395Sbapt#endif 124262395Sbapt 125262395Sbaptstruct ucl_variable { 126262395Sbapt char *var; 127262395Sbapt char *value; 128262395Sbapt size_t var_len; 129262395Sbapt size_t value_len; 130262395Sbapt struct ucl_variable *next; 131262395Sbapt}; 132262395Sbapt 133262395Sbaptstruct ucl_parser { 134262395Sbapt enum ucl_parser_state state; 135262395Sbapt enum ucl_parser_state prev_state; 136262395Sbapt unsigned int recursion; 137262395Sbapt int flags; 138262395Sbapt ucl_object_t *top_obj; 139262395Sbapt ucl_object_t *cur_obj; 140262395Sbapt struct ucl_macro *macroes; 141262395Sbapt struct ucl_stack *stack; 142262395Sbapt struct ucl_chunk *chunks; 143262395Sbapt struct ucl_pubkey *keys; 144262395Sbapt struct ucl_variable *variables; 145262395Sbapt UT_string *err; 146262395Sbapt}; 147262395Sbapt 148262395Sbapt/** 149262395Sbapt * Unescape json string inplace 150262395Sbapt * @param str 151262395Sbapt */ 152262395Sbaptsize_t ucl_unescape_json_string (char *str, size_t len); 153262395Sbapt 154262395Sbapt/** 155262395Sbapt * Handle include macro 156262395Sbapt * @param data include data 157262395Sbapt * @param len length of data 158262395Sbapt * @param ud user data 159262395Sbapt * @param err error ptr 160262395Sbapt * @return 161262395Sbapt */ 162262395Sbaptbool ucl_include_handler (const unsigned char *data, size_t len, void* ud); 163262395Sbapt 164262395Sbaptbool ucl_try_include_handler (const unsigned char *data, size_t len, void* ud); 165262395Sbapt 166262395Sbapt/** 167262395Sbapt * Handle includes macro 168262395Sbapt * @param data include data 169262395Sbapt * @param len length of data 170262395Sbapt * @param ud user data 171262395Sbapt * @param err error ptr 172262395Sbapt * @return 173262395Sbapt */ 174262395Sbaptbool ucl_includes_handler (const unsigned char *data, size_t len, void* ud); 175262395Sbapt 176262395Sbaptsize_t ucl_strlcpy (char *dst, const char *src, size_t siz); 177262395Sbaptsize_t ucl_strlcpy_unsafe (char *dst, const char *src, size_t siz); 178262395Sbaptsize_t ucl_strlcpy_tolower (char *dst, const char *src, size_t siz); 179262395Sbapt 180262395Sbapt 181262395Sbapt#ifdef __GNUC__ 182262395Sbaptstatic inline void 183262395Sbaptucl_create_err (UT_string **err, const char *fmt, ...) 184262395Sbapt__attribute__ (( format( printf, 2, 3) )); 185262395Sbapt#endif 186262395Sbapt 187262395Sbaptstatic inline void 188262395Sbaptucl_create_err (UT_string **err, const char *fmt, ...) 189262395Sbapt 190262395Sbapt{ 191262395Sbapt if (*err == NULL) { 192262395Sbapt utstring_new (*err); 193262395Sbapt va_list ap; 194262395Sbapt va_start (ap, fmt); 195262395Sbapt utstring_printf_va (*err, fmt, ap); 196262395Sbapt va_end (ap); 197262395Sbapt } 198262395Sbapt} 199262395Sbapt 200262395Sbapt/** 201262395Sbapt * Check whether a given string contains a boolean value 202262395Sbapt * @param obj object to set 203262395Sbapt * @param start start of a string 204262395Sbapt * @param len length of a string 205262395Sbapt * @return true if a string is a boolean value 206262395Sbapt */ 207262395Sbaptstatic inline bool 208262395Sbaptucl_maybe_parse_boolean (ucl_object_t *obj, const unsigned char *start, size_t len) 209262395Sbapt{ 210262395Sbapt const unsigned char *p = start; 211262395Sbapt bool ret = false, val = false; 212262395Sbapt 213262395Sbapt if (len == 5) { 214262395Sbapt if ((p[0] == 'f' || p[0] == 'F') && strncasecmp (p, "false", 5) == 0) { 215262395Sbapt ret = true; 216262395Sbapt val = false; 217262395Sbapt } 218262395Sbapt } 219262395Sbapt else if (len == 4) { 220262395Sbapt if ((p[0] == 't' || p[0] == 'T') && strncasecmp (p, "true", 4) == 0) { 221262395Sbapt ret = true; 222262395Sbapt val = true; 223262395Sbapt } 224262395Sbapt } 225262395Sbapt else if (len == 3) { 226262395Sbapt if ((p[0] == 'y' || p[0] == 'Y') && strncasecmp (p, "yes", 3) == 0) { 227262395Sbapt ret = true; 228262395Sbapt val = true; 229262395Sbapt } 230262395Sbapt else if ((p[0] == 'o' || p[0] == 'O') && strncasecmp (p, "off", 3) == 0) { 231262395Sbapt ret = true; 232262395Sbapt val = false; 233262395Sbapt } 234262395Sbapt } 235262395Sbapt else if (len == 2) { 236262395Sbapt if ((p[0] == 'n' || p[0] == 'N') && strncasecmp (p, "no", 2) == 0) { 237262395Sbapt ret = true; 238262395Sbapt val = false; 239262395Sbapt } 240262395Sbapt else if ((p[0] == 'o' || p[0] == 'O') && strncasecmp (p, "on", 2) == 0) { 241262395Sbapt ret = true; 242262395Sbapt val = true; 243262395Sbapt } 244262395Sbapt } 245262395Sbapt 246262395Sbapt if (ret) { 247262395Sbapt obj->type = UCL_BOOLEAN; 248262395Sbapt obj->value.iv = val; 249262395Sbapt } 250262395Sbapt 251262395Sbapt return ret; 252262395Sbapt} 253262395Sbapt 254262395Sbapt/** 255262395Sbapt * Check numeric string 256262395Sbapt * @param obj object to set if a string is numeric 257262395Sbapt * @param start start of string 258262395Sbapt * @param end end of string 259262395Sbapt * @param pos position where parsing has stopped 260262395Sbapt * @param allow_double allow parsing of floating point values 261262395Sbapt * @return 0 if string is numeric and error code (EINVAL or ERANGE) in case of conversion error 262262395Sbapt */ 263262395Sbaptint ucl_maybe_parse_number (ucl_object_t *obj, 264262395Sbapt const char *start, const char *end, const char **pos, bool allow_double, bool number_bytes); 265262395Sbapt 266262395Sbapt 267262395Sbaptstatic inline ucl_object_t * 268262395Sbaptucl_hash_search_obj (ucl_hash_t* hashlin, ucl_object_t *obj) 269262395Sbapt{ 270262395Sbapt return (ucl_object_t *)ucl_hash_search (hashlin, obj->key, obj->keylen); 271262395Sbapt} 272262395Sbapt 273262395Sbaptstatic inline ucl_hash_t * 274262395Sbaptucl_hash_insert_object (ucl_hash_t *hashlin, ucl_object_t *obj) UCL_WARN_UNUSED_RESULT; 275262395Sbapt 276262395Sbaptstatic inline ucl_hash_t * 277262395Sbaptucl_hash_insert_object (ucl_hash_t *hashlin, ucl_object_t *obj) 278262395Sbapt{ 279262395Sbapt if (hashlin == NULL) { 280262395Sbapt hashlin = ucl_hash_create (); 281262395Sbapt } 282262395Sbapt ucl_hash_insert (hashlin, obj, obj->key, obj->keylen); 283262395Sbapt 284262395Sbapt return hashlin; 285262395Sbapt} 286262395Sbapt 287262395Sbapt/** 288262395Sbapt * Emit a single object to string 289262395Sbapt * @param obj 290262395Sbapt * @return 291262395Sbapt */ 292262395Sbaptunsigned char * ucl_object_emit_single_json (ucl_object_t *obj); 293262395Sbapt 294262395Sbapt#endif /* UCL_INTERNAL_H_ */ 295