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