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