ucl_internal.h revision 275223
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;
166275223Sbapt	unsigned priority;
167262395Sbapt	struct ucl_chunk *next;
168262395Sbapt};
169262395Sbapt
170262395Sbapt#ifdef HAVE_OPENSSL
171262395Sbaptstruct ucl_pubkey {
172262395Sbapt	EVP_PKEY *key;
173262395Sbapt	struct ucl_pubkey *next;
174262395Sbapt};
175262395Sbapt#else
176262395Sbaptstruct ucl_pubkey {
177262395Sbapt	struct ucl_pubkey *next;
178262395Sbapt};
179262395Sbapt#endif
180262395Sbapt
181262395Sbaptstruct ucl_variable {
182262395Sbapt	char *var;
183262395Sbapt	char *value;
184262395Sbapt	size_t var_len;
185262395Sbapt	size_t value_len;
186275223Sbapt	struct ucl_variable *prev, *next;
187262395Sbapt};
188262395Sbapt
189262395Sbaptstruct ucl_parser {
190262395Sbapt	enum ucl_parser_state state;
191262395Sbapt	enum ucl_parser_state prev_state;
192262395Sbapt	unsigned int recursion;
193262395Sbapt	int flags;
194262395Sbapt	ucl_object_t *top_obj;
195262395Sbapt	ucl_object_t *cur_obj;
196275223Sbapt	char *cur_file;
197262395Sbapt	struct ucl_macro *macroes;
198262395Sbapt	struct ucl_stack *stack;
199262395Sbapt	struct ucl_chunk *chunks;
200262395Sbapt	struct ucl_pubkey *keys;
201262395Sbapt	struct ucl_variable *variables;
202266636Sbapt	ucl_variable_handler var_handler;
203266636Sbapt	void *var_data;
204262395Sbapt	UT_string *err;
205262395Sbapt};
206262395Sbapt
207275223Sbaptstruct ucl_object_userdata {
208275223Sbapt	ucl_object_t obj;
209275223Sbapt	ucl_userdata_dtor dtor;
210275223Sbapt	ucl_userdata_emitter emitter;
211275223Sbapt};
212275223Sbapt
213262395Sbapt/**
214262395Sbapt * Unescape json string inplace
215262395Sbapt * @param str
216262395Sbapt */
217262395Sbaptsize_t ucl_unescape_json_string (char *str, size_t len);
218262395Sbapt
219262395Sbapt/**
220262395Sbapt * Handle include macro
221262395Sbapt * @param data include data
222262395Sbapt * @param len length of data
223262395Sbapt * @param ud user data
224262395Sbapt * @param err error ptr
225262395Sbapt * @return
226262395Sbapt */
227275223Sbaptbool ucl_include_handler (const unsigned char *data, size_t len,
228275223Sbapt		const ucl_object_t *args, void* ud);
229262395Sbapt
230275223Sbaptbool ucl_try_include_handler (const unsigned char *data, size_t len,
231275223Sbapt		const ucl_object_t *args, void* ud);
232262395Sbapt
233262395Sbapt/**
234262395Sbapt * Handle includes macro
235262395Sbapt * @param data include data
236262395Sbapt * @param len length of data
237262395Sbapt * @param ud user data
238262395Sbapt * @param err error ptr
239262395Sbapt * @return
240262395Sbapt */
241275223Sbaptbool ucl_includes_handler (const unsigned char *data, size_t len,
242275223Sbapt		const ucl_object_t *args, void* ud);
243262395Sbapt
244262395Sbaptsize_t ucl_strlcpy (char *dst, const char *src, size_t siz);
245262395Sbaptsize_t ucl_strlcpy_unsafe (char *dst, const char *src, size_t siz);
246262395Sbaptsize_t ucl_strlcpy_tolower (char *dst, const char *src, size_t siz);
247262395Sbapt
248262395Sbapt
249262395Sbapt#ifdef __GNUC__
250262395Sbaptstatic inline void
251262395Sbaptucl_create_err (UT_string **err, const char *fmt, ...)
252262395Sbapt__attribute__ (( format( printf, 2, 3) ));
253262395Sbapt#endif
254262395Sbapt
255262395Sbaptstatic inline void
256262395Sbaptucl_create_err (UT_string **err, const char *fmt, ...)
257262395Sbapt
258262395Sbapt{
259262395Sbapt	if (*err == NULL) {
260262395Sbapt		utstring_new (*err);
261262395Sbapt		va_list ap;
262262395Sbapt		va_start (ap, fmt);
263262395Sbapt		utstring_printf_va (*err, fmt, ap);
264262395Sbapt		va_end (ap);
265262395Sbapt	}
266262395Sbapt}
267262395Sbapt
268262395Sbapt/**
269262395Sbapt * Check whether a given string contains a boolean value
270262395Sbapt * @param obj object to set
271262395Sbapt * @param start start of a string
272262395Sbapt * @param len length of a string
273262395Sbapt * @return true if a string is a boolean value
274262395Sbapt */
275262395Sbaptstatic inline bool
276262395Sbaptucl_maybe_parse_boolean (ucl_object_t *obj, const unsigned char *start, size_t len)
277262395Sbapt{
278275223Sbapt	const char *p = (const char *)start;
279262395Sbapt	bool ret = false, val = false;
280262395Sbapt
281262395Sbapt	if (len == 5) {
282262395Sbapt		if ((p[0] == 'f' || p[0] == 'F') && strncasecmp (p, "false", 5) == 0) {
283262395Sbapt			ret = true;
284262395Sbapt			val = false;
285262395Sbapt		}
286262395Sbapt	}
287262395Sbapt	else if (len == 4) {
288262395Sbapt		if ((p[0] == 't' || p[0] == 'T') && strncasecmp (p, "true", 4) == 0) {
289262395Sbapt			ret = true;
290262395Sbapt			val = true;
291262395Sbapt		}
292262395Sbapt	}
293262395Sbapt	else if (len == 3) {
294262395Sbapt		if ((p[0] == 'y' || p[0] == 'Y') && strncasecmp (p, "yes", 3) == 0) {
295262395Sbapt			ret = true;
296262395Sbapt			val = true;
297262395Sbapt		}
298262395Sbapt		else if ((p[0] == 'o' || p[0] == 'O') && strncasecmp (p, "off", 3) == 0) {
299262395Sbapt			ret = true;
300262395Sbapt			val = false;
301262395Sbapt		}
302262395Sbapt	}
303262395Sbapt	else if (len == 2) {
304262395Sbapt		if ((p[0] == 'n' || p[0] == 'N') && strncasecmp (p, "no", 2) == 0) {
305262395Sbapt			ret = true;
306262395Sbapt			val = false;
307262395Sbapt		}
308262395Sbapt		else if ((p[0] == 'o' || p[0] == 'O') && strncasecmp (p, "on", 2) == 0) {
309262395Sbapt			ret = true;
310262395Sbapt			val = true;
311262395Sbapt		}
312262395Sbapt	}
313262395Sbapt
314262395Sbapt	if (ret) {
315262395Sbapt		obj->type = UCL_BOOLEAN;
316262395Sbapt		obj->value.iv = val;
317262395Sbapt	}
318262395Sbapt
319262395Sbapt	return ret;
320262395Sbapt}
321262395Sbapt
322262395Sbapt/**
323262395Sbapt * Check numeric string
324262395Sbapt * @param obj object to set if a string is numeric
325262395Sbapt * @param start start of string
326262395Sbapt * @param end end of string
327262395Sbapt * @param pos position where parsing has stopped
328262395Sbapt * @param allow_double allow parsing of floating point values
329262395Sbapt * @return 0 if string is numeric and error code (EINVAL or ERANGE) in case of conversion error
330262395Sbapt */
331262395Sbaptint ucl_maybe_parse_number (ucl_object_t *obj,
332263648Sbapt		const char *start, const char *end, const char **pos,
333263648Sbapt		bool allow_double, bool number_bytes, bool allow_time);
334262395Sbapt
335262395Sbapt
336264789Sbaptstatic inline const ucl_object_t *
337262395Sbaptucl_hash_search_obj (ucl_hash_t* hashlin, ucl_object_t *obj)
338262395Sbapt{
339264789Sbapt	return (const ucl_object_t *)ucl_hash_search (hashlin, obj->key, obj->keylen);
340262395Sbapt}
341262395Sbapt
342262395Sbaptstatic inline ucl_hash_t *
343264789Sbaptucl_hash_insert_object (ucl_hash_t *hashlin, const ucl_object_t *obj) UCL_WARN_UNUSED_RESULT;
344262395Sbapt
345262395Sbaptstatic inline ucl_hash_t *
346264789Sbaptucl_hash_insert_object (ucl_hash_t *hashlin, const ucl_object_t *obj)
347262395Sbapt{
348262395Sbapt	if (hashlin == NULL) {
349262395Sbapt		hashlin = ucl_hash_create ();
350262395Sbapt	}
351262395Sbapt	ucl_hash_insert (hashlin, obj, obj->key, obj->keylen);
352262395Sbapt
353262395Sbapt	return hashlin;
354262395Sbapt}
355262395Sbapt
356262395Sbapt/**
357268831Sbapt * Get standard emitter context for a specified emit_type
358268831Sbapt * @param emit_type type of emitter
359268831Sbapt * @return context or NULL if input is invalid
360268831Sbapt */
361268831Sbaptconst struct ucl_emitter_context *
362268831Sbaptucl_emit_get_standard_context (enum ucl_emitter emit_type);
363268831Sbapt
364268831Sbapt/**
365275223Sbapt * Serialize string as JSON string
366268831Sbapt * @param str string to emit
367268831Sbapt * @param buf target buffer
368268831Sbapt */
369268831Sbaptvoid ucl_elt_string_write_json (const char *str, size_t size,
370268831Sbapt		struct ucl_emitter_context *ctx);
371268831Sbapt
372268831Sbapt/**
373275223Sbapt * Write multiline string using `EOD` as string terminator
374275223Sbapt * @param str
375275223Sbapt * @param size
376275223Sbapt * @param ctx
377275223Sbapt */
378275223Sbaptvoid ucl_elt_string_write_multiline (const char *str, size_t size,
379275223Sbapt		struct ucl_emitter_context *ctx);
380275223Sbapt
381275223Sbapt/**
382262395Sbapt * Emit a single object to string
383262395Sbapt * @param obj
384262395Sbapt * @return
385262395Sbapt */
386264789Sbaptunsigned char * ucl_object_emit_single_json (const ucl_object_t *obj);
387262395Sbapt
388275223Sbapt/**
389275223Sbapt * Check whether a specified string is long and should be likely printed in
390275223Sbapt * multiline mode
391275223Sbapt * @param obj
392275223Sbapt * @return
393275223Sbapt */
394275223Sbaptbool ucl_maybe_long_string (const ucl_object_t *obj);
395275223Sbapt
396262395Sbapt#endif /* UCL_INTERNAL_H_ */
397