ucl_util.c revision 263648
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#include "ucl.h"
25262395Sbapt#include "ucl_internal.h"
26262395Sbapt#include "ucl_chartable.h"
27262395Sbapt
28263648Sbapt#ifdef HAVE_LIBGEN_H
29262395Sbapt#include <libgen.h> /* For dirname */
30263648Sbapt#endif
31262395Sbapt
32262395Sbapt#ifdef HAVE_OPENSSL
33262395Sbapt#include <openssl/err.h>
34262395Sbapt#include <openssl/sha.h>
35262395Sbapt#include <openssl/rsa.h>
36262395Sbapt#include <openssl/ssl.h>
37262395Sbapt#include <openssl/evp.h>
38262395Sbapt#endif
39262395Sbapt
40263648Sbapt#ifdef CURL_FOUND
41263648Sbapt#include <curl/curl.h>
42263648Sbapt#endif
43263648Sbapt#ifdef HAVE_FETCH_H
44263648Sbapt#include <fetch.h>
45263648Sbapt#endif
46263648Sbapt
47262975Sbapt#ifdef _WIN32
48262975Sbapt#include <windows.h>
49262975Sbapt
50263648Sbapt#ifndef PROT_READ
51262975Sbapt#define PROT_READ       1
52263648Sbapt#endif
53263648Sbapt#ifndef PROT_WRITE
54262975Sbapt#define PROT_WRITE      2
55263648Sbapt#endif
56263648Sbapt#ifndef PROT_READWRITE
57262975Sbapt#define PROT_READWRITE  3
58263648Sbapt#endif
59263648Sbapt#ifndef MAP_SHARED
60262975Sbapt#define MAP_SHARED      1
61263648Sbapt#endif
62263648Sbapt#ifndef MAP_PRIVATE
63262975Sbapt#define MAP_PRIVATE     2
64263648Sbapt#endif
65263648Sbapt#ifndef MAP_FAILED
66262975Sbapt#define MAP_FAILED      ((void *) -1)
67263648Sbapt#endif
68262975Sbapt
69263648Sbaptstatic void *ucl_mmap(char *addr, size_t length, int prot, int access, int fd, off_t offset)
70262975Sbapt{
71262975Sbapt	void *map = NULL;
72262975Sbapt	HANDLE handle = INVALID_HANDLE_VALUE;
73262975Sbapt
74262975Sbapt	switch (prot) {
75262975Sbapt	default:
76262975Sbapt	case PROT_READ:
77262975Sbapt		{
78262975Sbapt			handle = CreateFileMapping((HANDLE) _get_osfhandle(fd), 0, PAGE_READONLY, 0, length, 0);
79262975Sbapt			if (!handle) break;
80262975Sbapt			map = (void *) MapViewOfFile(handle, FILE_MAP_READ, 0, 0, length);
81262975Sbapt			CloseHandle(handle);
82262975Sbapt			break;
83262975Sbapt		}
84262975Sbapt	case PROT_WRITE:
85262975Sbapt		{
86262975Sbapt			handle = CreateFileMapping((HANDLE) _get_osfhandle(fd), 0, PAGE_READWRITE, 0, length, 0);
87262975Sbapt			if (!handle) break;
88262975Sbapt			map = (void *) MapViewOfFile(handle, FILE_MAP_WRITE, 0, 0, length);
89262975Sbapt			CloseHandle(handle);
90262975Sbapt			break;
91262975Sbapt		}
92262975Sbapt	case PROT_READWRITE:
93262975Sbapt		{
94262975Sbapt			handle = CreateFileMapping((HANDLE) _get_osfhandle(fd), 0, PAGE_READWRITE, 0, length, 0);
95262975Sbapt			if (!handle) break;
96262975Sbapt			map = (void *) MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, length);
97262975Sbapt			CloseHandle(handle);
98262975Sbapt			break;
99262975Sbapt		}
100262975Sbapt	}
101262975Sbapt	if (map == (void *) NULL) {
102262975Sbapt		return (void *) MAP_FAILED;
103262975Sbapt	}
104262975Sbapt	return (void *) ((char *) map + offset);
105262975Sbapt}
106262975Sbapt
107263648Sbaptstatic int ucl_munmap(void *map,size_t length)
108262975Sbapt{
109262975Sbapt	if (!UnmapViewOfFile(map)) {
110262975Sbapt		return(-1);
111262975Sbapt	}
112262975Sbapt	return(0);
113262975Sbapt}
114262975Sbapt
115263648Sbaptstatic char* ucl_realpath(const char *path, char *resolved_path) {
116262975Sbapt    char *p;
117262975Sbapt    char tmp[MAX_PATH + 1];
118262975Sbapt    strncpy(tmp, path, sizeof(tmp)-1);
119262975Sbapt    p = tmp;
120262975Sbapt    while(*p) {
121262975Sbapt        if (*p == '/') *p = '\\';
122262975Sbapt        p++;
123262975Sbapt    }
124262975Sbapt    return _fullpath(resolved_path, tmp, MAX_PATH);
125262975Sbapt}
126263648Sbapt#else
127263648Sbapt#define ucl_mmap mmap
128263648Sbapt#define ucl_munmap munmap
129263648Sbapt#define ucl_realpath realpath
130262975Sbapt#endif
131262975Sbapt
132262395Sbapt/**
133262395Sbapt * @file rcl_util.c
134262395Sbapt * Utilities for rcl parsing
135262395Sbapt */
136262395Sbapt
137262395Sbapt
138262395Sbaptstatic void
139262395Sbaptucl_object_free_internal (ucl_object_t *obj, bool allow_rec)
140262395Sbapt{
141262395Sbapt	ucl_object_t *sub, *tmp;
142262395Sbapt
143262395Sbapt	while (obj != NULL) {
144262395Sbapt		if (obj->trash_stack[UCL_TRASH_KEY] != NULL) {
145262395Sbapt			UCL_FREE (obj->hh.keylen, obj->trash_stack[UCL_TRASH_KEY]);
146262395Sbapt		}
147262395Sbapt		if (obj->trash_stack[UCL_TRASH_VALUE] != NULL) {
148262395Sbapt			UCL_FREE (obj->len, obj->trash_stack[UCL_TRASH_VALUE]);
149262395Sbapt		}
150262395Sbapt
151262395Sbapt		if (obj->type == UCL_ARRAY) {
152262395Sbapt			sub = obj->value.av;
153262395Sbapt			while (sub != NULL) {
154262395Sbapt				tmp = sub->next;
155262395Sbapt				ucl_object_free_internal (sub, false);
156262395Sbapt				sub = tmp;
157262395Sbapt			}
158262395Sbapt		}
159262395Sbapt		else if (obj->type == UCL_OBJECT) {
160262395Sbapt			if (obj->value.ov != NULL) {
161262395Sbapt				ucl_hash_destroy (obj->value.ov, (ucl_hash_free_func *)ucl_object_unref);
162262395Sbapt			}
163262395Sbapt		}
164262395Sbapt		tmp = obj->next;
165262395Sbapt		UCL_FREE (sizeof (ucl_object_t), obj);
166262395Sbapt		obj = tmp;
167262395Sbapt
168262395Sbapt		if (!allow_rec) {
169262395Sbapt			break;
170262395Sbapt		}
171262395Sbapt	}
172262395Sbapt}
173262395Sbapt
174262395Sbaptvoid
175262395Sbaptucl_object_free (ucl_object_t *obj)
176262395Sbapt{
177262395Sbapt	ucl_object_free_internal (obj, true);
178262395Sbapt}
179262395Sbapt
180262395Sbaptsize_t
181262395Sbaptucl_unescape_json_string (char *str, size_t len)
182262395Sbapt{
183262395Sbapt	char *t = str, *h = str;
184262395Sbapt	int i, uval;
185262395Sbapt
186263648Sbapt	if (len <= 1) {
187263648Sbapt		return len;
188263648Sbapt	}
189262395Sbapt	/* t is target (tortoise), h is source (hare) */
190262395Sbapt
191262395Sbapt	while (len) {
192262395Sbapt		if (*h == '\\') {
193262395Sbapt			h ++;
194262395Sbapt			switch (*h) {
195262395Sbapt			case 'n':
196262395Sbapt				*t++ = '\n';
197262395Sbapt				break;
198262395Sbapt			case 'r':
199262395Sbapt				*t++ = '\r';
200262395Sbapt				break;
201262395Sbapt			case 'b':
202262395Sbapt				*t++ = '\b';
203262395Sbapt				break;
204262395Sbapt			case 't':
205262395Sbapt				*t++ = '\t';
206262395Sbapt				break;
207262395Sbapt			case 'f':
208262395Sbapt				*t++ = '\f';
209262395Sbapt				break;
210262395Sbapt			case '\\':
211262395Sbapt				*t++ = '\\';
212262395Sbapt				break;
213262395Sbapt			case '"':
214262395Sbapt				*t++ = '"';
215262395Sbapt				break;
216262395Sbapt			case 'u':
217262395Sbapt				/* Unicode escape */
218262395Sbapt				uval = 0;
219263648Sbapt				if (len > 3) {
220263648Sbapt					for (i = 0; i < 4; i++) {
221263648Sbapt						uval <<= 4;
222263648Sbapt						if (isdigit (h[i])) {
223263648Sbapt							uval += h[i] - '0';
224263648Sbapt						}
225263648Sbapt						else if (h[i] >= 'a' && h[i] <= 'f') {
226263648Sbapt							uval += h[i] - 'a' + 10;
227263648Sbapt						}
228263648Sbapt						else if (h[i] >= 'A' && h[i] <= 'F') {
229263648Sbapt							uval += h[i] - 'A' + 10;
230263648Sbapt						}
231263648Sbapt						else {
232263648Sbapt							break;
233263648Sbapt						}
234262395Sbapt					}
235263648Sbapt					h += 3;
236263648Sbapt					len -= 3;
237263648Sbapt					/* Encode */
238263648Sbapt					if(uval < 0x80) {
239263648Sbapt						t[0] = (char)uval;
240263648Sbapt						t ++;
241262395Sbapt					}
242263648Sbapt					else if(uval < 0x800) {
243263648Sbapt						t[0] = 0xC0 + ((uval & 0x7C0) >> 6);
244263648Sbapt						t[1] = 0x80 + ((uval & 0x03F));
245263648Sbapt						t += 2;
246262395Sbapt					}
247263648Sbapt					else if(uval < 0x10000) {
248263648Sbapt						t[0] = 0xE0 + ((uval & 0xF000) >> 12);
249263648Sbapt						t[1] = 0x80 + ((uval & 0x0FC0) >> 6);
250263648Sbapt						t[2] = 0x80 + ((uval & 0x003F));
251263648Sbapt						t += 3;
252263648Sbapt					}
253263648Sbapt					else if(uval <= 0x10FFFF) {
254263648Sbapt						t[0] = 0xF0 + ((uval & 0x1C0000) >> 18);
255263648Sbapt						t[1] = 0x80 + ((uval & 0x03F000) >> 12);
256263648Sbapt						t[2] = 0x80 + ((uval & 0x000FC0) >> 6);
257263648Sbapt						t[3] = 0x80 + ((uval & 0x00003F));
258263648Sbapt						t += 4;
259263648Sbapt					}
260263648Sbapt					else {
261263648Sbapt						*t++ = '?';
262263648Sbapt					}
263262395Sbapt				}
264262395Sbapt				else {
265263648Sbapt					*t++ = 'u';
266262395Sbapt				}
267262395Sbapt				break;
268262395Sbapt			default:
269262395Sbapt				*t++ = *h;
270262395Sbapt				break;
271262395Sbapt			}
272262395Sbapt			h ++;
273262395Sbapt			len --;
274262395Sbapt		}
275262395Sbapt		else {
276262395Sbapt			*t++ = *h++;
277262395Sbapt		}
278262395Sbapt		len --;
279262395Sbapt	}
280262395Sbapt	*t = '\0';
281262395Sbapt
282262395Sbapt	return (t - str);
283262395Sbapt}
284262395Sbapt
285262975SbaptUCL_EXTERN char *
286262395Sbaptucl_copy_key_trash (ucl_object_t *obj)
287262395Sbapt{
288263648Sbapt	if (obj == NULL) {
289263648Sbapt		return NULL;
290263648Sbapt	}
291262395Sbapt	if (obj->trash_stack[UCL_TRASH_KEY] == NULL && obj->key != NULL) {
292262395Sbapt		obj->trash_stack[UCL_TRASH_KEY] = malloc (obj->keylen + 1);
293262395Sbapt		if (obj->trash_stack[UCL_TRASH_KEY] != NULL) {
294262395Sbapt			memcpy (obj->trash_stack[UCL_TRASH_KEY], obj->key, obj->keylen);
295262395Sbapt			obj->trash_stack[UCL_TRASH_KEY][obj->keylen] = '\0';
296262395Sbapt		}
297262395Sbapt		obj->key = obj->trash_stack[UCL_TRASH_KEY];
298262395Sbapt		obj->flags |= UCL_OBJECT_ALLOCATED_KEY;
299262395Sbapt	}
300262395Sbapt
301262395Sbapt	return obj->trash_stack[UCL_TRASH_KEY];
302262395Sbapt}
303262395Sbapt
304262975SbaptUCL_EXTERN char *
305262395Sbaptucl_copy_value_trash (ucl_object_t *obj)
306262395Sbapt{
307263648Sbapt	if (obj == NULL) {
308263648Sbapt		return NULL;
309263648Sbapt	}
310262395Sbapt	if (obj->trash_stack[UCL_TRASH_VALUE] == NULL) {
311262395Sbapt		if (obj->type == UCL_STRING) {
312262395Sbapt			/* Special case for strings */
313262395Sbapt			obj->trash_stack[UCL_TRASH_VALUE] = malloc (obj->len + 1);
314262395Sbapt			if (obj->trash_stack[UCL_TRASH_VALUE] != NULL) {
315262395Sbapt				memcpy (obj->trash_stack[UCL_TRASH_VALUE], obj->value.sv, obj->len);
316262395Sbapt				obj->trash_stack[UCL_TRASH_VALUE][obj->len] = '\0';
317262395Sbapt				obj->value.sv = obj->trash_stack[UCL_TRASH_VALUE];
318262395Sbapt			}
319262395Sbapt		}
320262395Sbapt		else {
321262395Sbapt			/* Just emit value in json notation */
322262395Sbapt			obj->trash_stack[UCL_TRASH_VALUE] = ucl_object_emit_single_json (obj);
323262395Sbapt			obj->len = strlen (obj->trash_stack[UCL_TRASH_VALUE]);
324262395Sbapt		}
325262395Sbapt		obj->flags |= UCL_OBJECT_ALLOCATED_VALUE;
326262395Sbapt	}
327262395Sbapt	return obj->trash_stack[UCL_TRASH_VALUE];
328262395Sbapt}
329262395Sbapt
330262975SbaptUCL_EXTERN ucl_object_t*
331262395Sbaptucl_parser_get_object (struct ucl_parser *parser)
332262395Sbapt{
333262395Sbapt	if (parser->state != UCL_STATE_ERROR && parser->top_obj != NULL) {
334262395Sbapt		return ucl_object_ref (parser->top_obj);
335262395Sbapt	}
336262395Sbapt
337262395Sbapt	return NULL;
338262395Sbapt}
339262395Sbapt
340262975SbaptUCL_EXTERN void
341262395Sbaptucl_parser_free (struct ucl_parser *parser)
342262395Sbapt{
343262395Sbapt	struct ucl_stack *stack, *stmp;
344262395Sbapt	struct ucl_macro *macro, *mtmp;
345262395Sbapt	struct ucl_chunk *chunk, *ctmp;
346262395Sbapt	struct ucl_pubkey *key, *ktmp;
347262395Sbapt	struct ucl_variable *var, *vtmp;
348262395Sbapt
349263648Sbapt	if (parser == NULL) {
350263648Sbapt		return;
351263648Sbapt	}
352263648Sbapt
353262395Sbapt	if (parser->top_obj != NULL) {
354262395Sbapt		ucl_object_unref (parser->top_obj);
355262395Sbapt	}
356262395Sbapt
357262395Sbapt	LL_FOREACH_SAFE (parser->stack, stack, stmp) {
358262395Sbapt		free (stack);
359262395Sbapt	}
360262395Sbapt	HASH_ITER (hh, parser->macroes, macro, mtmp) {
361262395Sbapt		free (macro->name);
362262395Sbapt		HASH_DEL (parser->macroes, macro);
363262395Sbapt		UCL_FREE (sizeof (struct ucl_macro), macro);
364262395Sbapt	}
365262395Sbapt	LL_FOREACH_SAFE (parser->chunks, chunk, ctmp) {
366262395Sbapt		UCL_FREE (sizeof (struct ucl_chunk), chunk);
367262395Sbapt	}
368262395Sbapt	LL_FOREACH_SAFE (parser->keys, key, ktmp) {
369262395Sbapt		UCL_FREE (sizeof (struct ucl_pubkey), key);
370262395Sbapt	}
371262395Sbapt	LL_FOREACH_SAFE (parser->variables, var, vtmp) {
372262395Sbapt		free (var->value);
373262395Sbapt		free (var->var);
374262395Sbapt		UCL_FREE (sizeof (struct ucl_variable), var);
375262395Sbapt	}
376262395Sbapt
377262395Sbapt	if (parser->err != NULL) {
378262395Sbapt		utstring_free(parser->err);
379262395Sbapt	}
380262395Sbapt
381262395Sbapt	UCL_FREE (sizeof (struct ucl_parser), parser);
382262395Sbapt}
383262395Sbapt
384262975SbaptUCL_EXTERN const char *
385262395Sbaptucl_parser_get_error(struct ucl_parser *parser)
386262395Sbapt{
387263648Sbapt	if (parser == NULL) {
388263648Sbapt		return NULL;
389263648Sbapt	}
390263648Sbapt
391262395Sbapt	if (parser->err == NULL)
392262395Sbapt		return NULL;
393262395Sbapt
394262395Sbapt	return utstring_body(parser->err);
395262395Sbapt}
396262395Sbapt
397262975SbaptUCL_EXTERN bool
398262395Sbaptucl_pubkey_add (struct ucl_parser *parser, const unsigned char *key, size_t len)
399262395Sbapt{
400262395Sbapt#ifndef HAVE_OPENSSL
401262395Sbapt	ucl_create_err (&parser->err, "cannot check signatures without openssl");
402262395Sbapt	return false;
403262395Sbapt#else
404262395Sbapt# if (OPENSSL_VERSION_NUMBER < 0x10000000L)
405262395Sbapt	ucl_create_err (&parser->err, "cannot check signatures, openssl version is unsupported");
406262395Sbapt	return EXIT_FAILURE;
407262395Sbapt# else
408262395Sbapt	struct ucl_pubkey *nkey;
409262395Sbapt	BIO *mem;
410262395Sbapt
411262395Sbapt	mem = BIO_new_mem_buf ((void *)key, len);
412262395Sbapt	nkey = UCL_ALLOC (sizeof (struct ucl_pubkey));
413263648Sbapt	if (nkey == NULL) {
414263648Sbapt		ucl_create_err (&parser->err, "cannot allocate memory for key");
415263648Sbapt		return false;
416263648Sbapt	}
417262395Sbapt	nkey->key = PEM_read_bio_PUBKEY (mem, &nkey->key, NULL, NULL);
418262395Sbapt	BIO_free (mem);
419262395Sbapt	if (nkey->key == NULL) {
420262395Sbapt		UCL_FREE (sizeof (struct ucl_pubkey), nkey);
421262395Sbapt		ucl_create_err (&parser->err, "%s",
422262395Sbapt				ERR_error_string (ERR_get_error (), NULL));
423262395Sbapt		return false;
424262395Sbapt	}
425262395Sbapt	LL_PREPEND (parser->keys, nkey);
426262395Sbapt# endif
427262395Sbapt#endif
428262395Sbapt	return true;
429262395Sbapt}
430262395Sbapt
431262395Sbapt#ifdef CURL_FOUND
432262395Sbaptstruct ucl_curl_cbdata {
433262395Sbapt	unsigned char *buf;
434262395Sbapt	size_t buflen;
435262395Sbapt};
436262395Sbapt
437262395Sbaptstatic size_t
438262395Sbaptucl_curl_write_callback (void* contents, size_t size, size_t nmemb, void* ud)
439262395Sbapt{
440262395Sbapt	struct ucl_curl_cbdata *cbdata = ud;
441262395Sbapt	size_t realsize = size * nmemb;
442262395Sbapt
443262395Sbapt	cbdata->buf = realloc (cbdata->buf, cbdata->buflen + realsize + 1);
444262395Sbapt	if (cbdata->buf == NULL) {
445262395Sbapt		return 0;
446262395Sbapt	}
447262395Sbapt
448262395Sbapt	memcpy (&(cbdata->buf[cbdata->buflen]), contents, realsize);
449262395Sbapt	cbdata->buflen += realsize;
450262395Sbapt	cbdata->buf[cbdata->buflen] = 0;
451262395Sbapt
452262395Sbapt	return realsize;
453262395Sbapt}
454262395Sbapt#endif
455262395Sbapt
456262395Sbapt/**
457262395Sbapt * Fetch a url and save results to the memory buffer
458262395Sbapt * @param url url to fetch
459262395Sbapt * @param len length of url
460262395Sbapt * @param buf target buffer
461262395Sbapt * @param buflen target length
462262395Sbapt * @return
463262395Sbapt */
464262395Sbaptstatic bool
465262395Sbaptucl_fetch_url (const unsigned char *url, unsigned char **buf, size_t *buflen,
466262395Sbapt		UT_string **err, bool must_exist)
467262395Sbapt{
468262395Sbapt
469262395Sbapt#ifdef HAVE_FETCH_H
470262395Sbapt	struct url *fetch_url;
471262395Sbapt	struct url_stat us;
472262395Sbapt	FILE *in;
473262395Sbapt
474262395Sbapt	fetch_url = fetchParseURL (url);
475262395Sbapt	if (fetch_url == NULL) {
476262395Sbapt		ucl_create_err (err, "invalid URL %s: %s",
477262395Sbapt				url, strerror (errno));
478262395Sbapt		return false;
479262395Sbapt	}
480262395Sbapt	if ((in = fetchXGet (fetch_url, &us, "")) == NULL) {
481262395Sbapt		if (!must_exist) {
482262395Sbapt			ucl_create_err (err, "cannot fetch URL %s: %s",
483262395Sbapt				url, strerror (errno));
484262395Sbapt		}
485262395Sbapt		fetchFreeURL (fetch_url);
486262395Sbapt		return false;
487262395Sbapt	}
488262395Sbapt
489262395Sbapt	*buflen = us.size;
490262395Sbapt	*buf = malloc (*buflen);
491262395Sbapt	if (*buf == NULL) {
492262395Sbapt		ucl_create_err (err, "cannot allocate buffer for URL %s: %s",
493262395Sbapt				url, strerror (errno));
494262395Sbapt		fclose (in);
495262395Sbapt		fetchFreeURL (fetch_url);
496262395Sbapt		return false;
497262395Sbapt	}
498262395Sbapt
499262395Sbapt	if (fread (*buf, *buflen, 1, in) != 1) {
500262395Sbapt		ucl_create_err (err, "cannot read URL %s: %s",
501262395Sbapt				url, strerror (errno));
502262395Sbapt		fclose (in);
503262395Sbapt		fetchFreeURL (fetch_url);
504262395Sbapt		return false;
505262395Sbapt	}
506262395Sbapt
507262395Sbapt	fetchFreeURL (fetch_url);
508262395Sbapt	return true;
509262395Sbapt#elif defined(CURL_FOUND)
510262395Sbapt	CURL *curl;
511262395Sbapt	int r;
512262395Sbapt	struct ucl_curl_cbdata cbdata;
513262395Sbapt
514262395Sbapt	curl = curl_easy_init ();
515262395Sbapt	if (curl == NULL) {
516262395Sbapt		ucl_create_err (err, "CURL interface is broken");
517262395Sbapt		return false;
518262395Sbapt	}
519262395Sbapt	if ((r = curl_easy_setopt (curl, CURLOPT_URL, url)) != CURLE_OK) {
520262395Sbapt		ucl_create_err (err, "invalid URL %s: %s",
521262395Sbapt				url, curl_easy_strerror (r));
522262395Sbapt		curl_easy_cleanup (curl);
523262395Sbapt		return false;
524262395Sbapt	}
525262395Sbapt	curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, ucl_curl_write_callback);
526262395Sbapt	cbdata.buf = *buf;
527262395Sbapt	cbdata.buflen = *buflen;
528262395Sbapt	curl_easy_setopt (curl, CURLOPT_WRITEDATA, &cbdata);
529262395Sbapt
530262395Sbapt	if ((r = curl_easy_perform (curl)) != CURLE_OK) {
531262395Sbapt		if (!must_exist) {
532262395Sbapt			ucl_create_err (err, "error fetching URL %s: %s",
533262395Sbapt				url, curl_easy_strerror (r));
534262395Sbapt		}
535262395Sbapt		curl_easy_cleanup (curl);
536262395Sbapt		if (cbdata.buf) {
537262395Sbapt			free (cbdata.buf);
538262395Sbapt		}
539262395Sbapt		return false;
540262395Sbapt	}
541262395Sbapt	*buf = cbdata.buf;
542262395Sbapt	*buflen = cbdata.buflen;
543262395Sbapt
544262395Sbapt	return true;
545262395Sbapt#else
546262395Sbapt	ucl_create_err (err, "URL support is disabled");
547262395Sbapt	return false;
548262395Sbapt#endif
549262395Sbapt}
550262395Sbapt
551262395Sbapt/**
552262395Sbapt * Fetch a file and save results to the memory buffer
553262395Sbapt * @param filename filename to fetch
554262395Sbapt * @param len length of filename
555262395Sbapt * @param buf target buffer
556262395Sbapt * @param buflen target length
557262395Sbapt * @return
558262395Sbapt */
559262395Sbaptstatic bool
560262395Sbaptucl_fetch_file (const unsigned char *filename, unsigned char **buf, size_t *buflen,
561262395Sbapt		UT_string **err, bool must_exist)
562262395Sbapt{
563262395Sbapt	int fd;
564262395Sbapt	struct stat st;
565262395Sbapt
566262395Sbapt	if (stat (filename, &st) == -1 || !S_ISREG (st.st_mode)) {
567262395Sbapt		if (must_exist) {
568262395Sbapt			ucl_create_err (err, "cannot stat file %s: %s",
569262395Sbapt					filename, strerror (errno));
570262395Sbapt		}
571262395Sbapt		return false;
572262395Sbapt	}
573262395Sbapt	if (st.st_size == 0) {
574262395Sbapt		/* Do not map empty files */
575262395Sbapt		*buf = "";
576262395Sbapt		*buflen = 0;
577262395Sbapt	}
578262395Sbapt	else {
579262395Sbapt		if ((fd = open (filename, O_RDONLY)) == -1) {
580262395Sbapt			ucl_create_err (err, "cannot open file %s: %s",
581262395Sbapt					filename, strerror (errno));
582262395Sbapt			return false;
583262395Sbapt		}
584263648Sbapt		if ((*buf = ucl_mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) {
585262395Sbapt			close (fd);
586262395Sbapt			ucl_create_err (err, "cannot mmap file %s: %s",
587262395Sbapt					filename, strerror (errno));
588262395Sbapt			return false;
589262395Sbapt		}
590262395Sbapt		*buflen = st.st_size;
591262395Sbapt		close (fd);
592262395Sbapt	}
593262395Sbapt
594262395Sbapt	return true;
595262395Sbapt}
596262395Sbapt
597262395Sbapt
598262395Sbapt#if (defined(HAVE_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10000000L)
599262395Sbaptstatic inline bool
600262395Sbaptucl_sig_check (const unsigned char *data, size_t datalen,
601262395Sbapt		const unsigned char *sig, size_t siglen, struct ucl_parser *parser)
602262395Sbapt{
603262395Sbapt	struct ucl_pubkey *key;
604262395Sbapt	char dig[EVP_MAX_MD_SIZE];
605262395Sbapt	unsigned int diglen;
606262395Sbapt	EVP_PKEY_CTX *key_ctx;
607262395Sbapt	EVP_MD_CTX *sign_ctx = NULL;
608262395Sbapt
609262395Sbapt	sign_ctx = EVP_MD_CTX_create ();
610262395Sbapt
611262395Sbapt	LL_FOREACH (parser->keys, key) {
612262395Sbapt		key_ctx = EVP_PKEY_CTX_new (key->key, NULL);
613262395Sbapt		if (key_ctx != NULL) {
614262395Sbapt			if (EVP_PKEY_verify_init (key_ctx) <= 0) {
615262395Sbapt				EVP_PKEY_CTX_free (key_ctx);
616262395Sbapt				continue;
617262395Sbapt			}
618262395Sbapt			if (EVP_PKEY_CTX_set_rsa_padding (key_ctx, RSA_PKCS1_PADDING) <= 0) {
619262395Sbapt				EVP_PKEY_CTX_free (key_ctx);
620262395Sbapt				continue;
621262395Sbapt			}
622262395Sbapt			if (EVP_PKEY_CTX_set_signature_md (key_ctx, EVP_sha256 ()) <= 0) {
623262395Sbapt				EVP_PKEY_CTX_free (key_ctx);
624262395Sbapt				continue;
625262395Sbapt			}
626262395Sbapt			EVP_DigestInit (sign_ctx, EVP_sha256 ());
627262395Sbapt			EVP_DigestUpdate (sign_ctx, data, datalen);
628262395Sbapt			EVP_DigestFinal (sign_ctx, dig, &diglen);
629262395Sbapt
630262395Sbapt			if (EVP_PKEY_verify (key_ctx, sig, siglen, dig, diglen) == 1) {
631262395Sbapt				EVP_MD_CTX_destroy (sign_ctx);
632262395Sbapt				EVP_PKEY_CTX_free (key_ctx);
633262395Sbapt				return true;
634262395Sbapt			}
635262395Sbapt
636262395Sbapt			EVP_PKEY_CTX_free (key_ctx);
637262395Sbapt		}
638262395Sbapt	}
639262395Sbapt
640262395Sbapt	EVP_MD_CTX_destroy (sign_ctx);
641262395Sbapt
642262395Sbapt	return false;
643262395Sbapt}
644262395Sbapt#endif
645262395Sbapt
646262395Sbapt/**
647262395Sbapt * Include an url to configuration
648262395Sbapt * @param data
649262395Sbapt * @param len
650262395Sbapt * @param parser
651262395Sbapt * @param err
652262395Sbapt * @return
653262395Sbapt */
654262395Sbaptstatic bool
655262395Sbaptucl_include_url (const unsigned char *data, size_t len,
656262395Sbapt		struct ucl_parser *parser, bool check_signature, bool must_exist)
657262395Sbapt{
658262395Sbapt
659262395Sbapt	bool res;
660262395Sbapt	unsigned char *buf = NULL;
661262395Sbapt	size_t buflen = 0;
662262395Sbapt	struct ucl_chunk *chunk;
663262395Sbapt	char urlbuf[PATH_MAX];
664262395Sbapt	int prev_state;
665262395Sbapt
666262395Sbapt	snprintf (urlbuf, sizeof (urlbuf), "%.*s", (int)len, data);
667262395Sbapt
668262395Sbapt	if (!ucl_fetch_url (urlbuf, &buf, &buflen, &parser->err, must_exist)) {
669262395Sbapt		return (!must_exist || false);
670262395Sbapt	}
671262395Sbapt
672262395Sbapt	if (check_signature) {
673262395Sbapt#if (defined(HAVE_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10000000L)
674262395Sbapt		unsigned char *sigbuf = NULL;
675262395Sbapt		size_t siglen = 0;
676262395Sbapt		/* We need to check signature first */
677262395Sbapt		snprintf (urlbuf, sizeof (urlbuf), "%.*s.sig", (int)len, data);
678262395Sbapt		if (!ucl_fetch_url (urlbuf, &sigbuf, &siglen, &parser->err, true)) {
679262395Sbapt			return false;
680262395Sbapt		}
681262395Sbapt		if (!ucl_sig_check (buf, buflen, sigbuf, siglen, parser)) {
682262395Sbapt			ucl_create_err (&parser->err, "cannot verify url %s: %s",
683262395Sbapt							urlbuf,
684262395Sbapt							ERR_error_string (ERR_get_error (), NULL));
685262395Sbapt			if (siglen > 0) {
686263648Sbapt				ucl_munmap (sigbuf, siglen);
687262395Sbapt			}
688262395Sbapt			return false;
689262395Sbapt		}
690262395Sbapt		if (siglen > 0) {
691263648Sbapt			ucl_munmap (sigbuf, siglen);
692262395Sbapt		}
693262395Sbapt#endif
694262395Sbapt	}
695262395Sbapt
696262395Sbapt	prev_state = parser->state;
697262395Sbapt	parser->state = UCL_STATE_INIT;
698262395Sbapt
699262395Sbapt	res = ucl_parser_add_chunk (parser, buf, buflen);
700262395Sbapt	if (res == true) {
701262395Sbapt		/* Remove chunk from the stack */
702262395Sbapt		chunk = parser->chunks;
703262395Sbapt		if (chunk != NULL) {
704262395Sbapt			parser->chunks = chunk->next;
705262395Sbapt			UCL_FREE (sizeof (struct ucl_chunk), chunk);
706262395Sbapt		}
707262395Sbapt	}
708262395Sbapt
709262395Sbapt	parser->state = prev_state;
710262395Sbapt	free (buf);
711262395Sbapt
712262395Sbapt	return res;
713262395Sbapt}
714262395Sbapt
715262395Sbapt/**
716262395Sbapt * Include a file to configuration
717262395Sbapt * @param data
718262395Sbapt * @param len
719262395Sbapt * @param parser
720262395Sbapt * @param err
721262395Sbapt * @return
722262395Sbapt */
723262395Sbaptstatic bool
724262395Sbaptucl_include_file (const unsigned char *data, size_t len,
725262395Sbapt		struct ucl_parser *parser, bool check_signature, bool must_exist)
726262395Sbapt{
727262395Sbapt	bool res;
728262395Sbapt	struct ucl_chunk *chunk;
729262395Sbapt	unsigned char *buf = NULL;
730262395Sbapt	size_t buflen;
731262395Sbapt	char filebuf[PATH_MAX], realbuf[PATH_MAX];
732262395Sbapt	int prev_state;
733262395Sbapt
734262395Sbapt	snprintf (filebuf, sizeof (filebuf), "%.*s", (int)len, data);
735263648Sbapt	if (ucl_realpath (filebuf, realbuf) == NULL) {
736262395Sbapt		if (!must_exist) {
737262395Sbapt			return true;
738262395Sbapt		}
739262395Sbapt		ucl_create_err (&parser->err, "cannot open file %s: %s",
740262395Sbapt									filebuf,
741262395Sbapt									strerror (errno));
742262395Sbapt		return false;
743262395Sbapt	}
744262395Sbapt
745262395Sbapt	if (!ucl_fetch_file (realbuf, &buf, &buflen, &parser->err, must_exist)) {
746262395Sbapt		return (!must_exist || false);
747262395Sbapt	}
748262395Sbapt
749262395Sbapt	if (check_signature) {
750262395Sbapt#if (defined(HAVE_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10000000L)
751262395Sbapt		unsigned char *sigbuf = NULL;
752262395Sbapt		size_t siglen = 0;
753262395Sbapt		/* We need to check signature first */
754262395Sbapt		snprintf (filebuf, sizeof (filebuf), "%s.sig", realbuf);
755262395Sbapt		if (!ucl_fetch_file (filebuf, &sigbuf, &siglen, &parser->err, true)) {
756262395Sbapt			return false;
757262395Sbapt		}
758262395Sbapt		if (!ucl_sig_check (buf, buflen, sigbuf, siglen, parser)) {
759262395Sbapt			ucl_create_err (&parser->err, "cannot verify file %s: %s",
760262395Sbapt							filebuf,
761262395Sbapt							ERR_error_string (ERR_get_error (), NULL));
762262395Sbapt			if (siglen > 0) {
763263648Sbapt				ucl_munmap (sigbuf, siglen);
764262395Sbapt			}
765262395Sbapt			return false;
766262395Sbapt		}
767262395Sbapt		if (siglen > 0) {
768263648Sbapt			ucl_munmap (sigbuf, siglen);
769262395Sbapt		}
770262395Sbapt#endif
771262395Sbapt	}
772262395Sbapt
773262395Sbapt	ucl_parser_set_filevars (parser, realbuf, false);
774262395Sbapt
775262395Sbapt	prev_state = parser->state;
776262395Sbapt	parser->state = UCL_STATE_INIT;
777262395Sbapt
778262395Sbapt	res = ucl_parser_add_chunk (parser, buf, buflen);
779262395Sbapt	if (res == true) {
780262395Sbapt		/* Remove chunk from the stack */
781262395Sbapt		chunk = parser->chunks;
782262395Sbapt		if (chunk != NULL) {
783262395Sbapt			parser->chunks = chunk->next;
784262395Sbapt			UCL_FREE (sizeof (struct ucl_chunk), chunk);
785262395Sbapt		}
786262395Sbapt	}
787262395Sbapt
788262395Sbapt	parser->state = prev_state;
789262395Sbapt
790262395Sbapt	if (buflen > 0) {
791263648Sbapt		ucl_munmap (buf, buflen);
792262395Sbapt	}
793262395Sbapt
794262395Sbapt	return res;
795262395Sbapt}
796262395Sbapt
797262395Sbapt/**
798262395Sbapt * Handle include macro
799262395Sbapt * @param data include data
800262395Sbapt * @param len length of data
801262395Sbapt * @param ud user data
802262395Sbapt * @param err error ptr
803262395Sbapt * @return
804262395Sbapt */
805262975SbaptUCL_EXTERN bool
806262395Sbaptucl_include_handler (const unsigned char *data, size_t len, void* ud)
807262395Sbapt{
808262395Sbapt	struct ucl_parser *parser = ud;
809262395Sbapt
810262395Sbapt	if (*data == '/' || *data == '.') {
811262395Sbapt		/* Try to load a file */
812262395Sbapt		return ucl_include_file (data, len, parser, false, true);
813262395Sbapt	}
814262395Sbapt
815262395Sbapt	return ucl_include_url (data, len, parser, false, true);
816262395Sbapt}
817262395Sbapt
818262395Sbapt/**
819262395Sbapt * Handle includes macro
820262395Sbapt * @param data include data
821262395Sbapt * @param len length of data
822262395Sbapt * @param ud user data
823262395Sbapt * @param err error ptr
824262395Sbapt * @return
825262395Sbapt */
826262975SbaptUCL_EXTERN bool
827262395Sbaptucl_includes_handler (const unsigned char *data, size_t len, void* ud)
828262395Sbapt{
829262395Sbapt	struct ucl_parser *parser = ud;
830262395Sbapt
831262395Sbapt	if (*data == '/' || *data == '.') {
832262395Sbapt		/* Try to load a file */
833262395Sbapt		return ucl_include_file (data, len, parser, true, true);
834262395Sbapt	}
835262395Sbapt
836262395Sbapt	return ucl_include_url (data, len, parser, true, true);
837262395Sbapt}
838262395Sbapt
839262395Sbapt
840262975SbaptUCL_EXTERN bool
841262395Sbaptucl_try_include_handler (const unsigned char *data, size_t len, void* ud)
842262395Sbapt{
843262395Sbapt	struct ucl_parser *parser = ud;
844262395Sbapt
845262395Sbapt	if (*data == '/' || *data == '.') {
846262395Sbapt		/* Try to load a file */
847262395Sbapt		return ucl_include_file (data, len, parser, false, false);
848262395Sbapt	}
849262395Sbapt
850262395Sbapt	return ucl_include_url (data, len, parser, false, false);
851262395Sbapt}
852262395Sbapt
853262975SbaptUCL_EXTERN bool
854262395Sbaptucl_parser_set_filevars (struct ucl_parser *parser, const char *filename, bool need_expand)
855262395Sbapt{
856262395Sbapt	char realbuf[PATH_MAX], *curdir;
857262395Sbapt
858262395Sbapt	if (filename != NULL) {
859262395Sbapt		if (need_expand) {
860263648Sbapt			if (ucl_realpath (filename, realbuf) == NULL) {
861262395Sbapt				return false;
862262395Sbapt			}
863262395Sbapt		}
864262395Sbapt		else {
865262395Sbapt			ucl_strlcpy (realbuf, filename, sizeof (realbuf));
866262395Sbapt		}
867262395Sbapt
868262395Sbapt		/* Define variables */
869262395Sbapt		ucl_parser_register_variable (parser, "FILENAME", realbuf);
870262395Sbapt		curdir = dirname (realbuf);
871262395Sbapt		ucl_parser_register_variable (parser, "CURDIR", curdir);
872262395Sbapt	}
873262395Sbapt	else {
874262395Sbapt		/* Set everything from the current dir */
875262395Sbapt		curdir = getcwd (realbuf, sizeof (realbuf));
876262395Sbapt		ucl_parser_register_variable (parser, "FILENAME", "undef");
877262395Sbapt		ucl_parser_register_variable (parser, "CURDIR", curdir);
878262395Sbapt	}
879262395Sbapt
880262395Sbapt	return true;
881262395Sbapt}
882262395Sbapt
883262975SbaptUCL_EXTERN bool
884262395Sbaptucl_parser_add_file (struct ucl_parser *parser, const char *filename)
885262395Sbapt{
886262395Sbapt	unsigned char *buf;
887262395Sbapt	size_t len;
888262395Sbapt	bool ret;
889262395Sbapt	char realbuf[PATH_MAX];
890262395Sbapt
891263648Sbapt	if (ucl_realpath (filename, realbuf) == NULL) {
892262395Sbapt		ucl_create_err (&parser->err, "cannot open file %s: %s",
893262395Sbapt				filename,
894262395Sbapt				strerror (errno));
895262395Sbapt		return false;
896262395Sbapt	}
897262395Sbapt
898262395Sbapt	if (!ucl_fetch_file (realbuf, &buf, &len, &parser->err, true)) {
899262395Sbapt		return false;
900262395Sbapt	}
901262395Sbapt
902262395Sbapt	ucl_parser_set_filevars (parser, realbuf, false);
903262395Sbapt	ret = ucl_parser_add_chunk (parser, buf, len);
904262395Sbapt
905262395Sbapt	if (len > 0) {
906263648Sbapt		ucl_munmap (buf, len);
907262395Sbapt	}
908262395Sbapt
909262395Sbapt	return ret;
910262395Sbapt}
911262395Sbapt
912262395Sbaptsize_t
913262395Sbaptucl_strlcpy (char *dst, const char *src, size_t siz)
914262395Sbapt{
915262395Sbapt	char *d = dst;
916262395Sbapt	const char *s = src;
917262395Sbapt	size_t n = siz;
918262395Sbapt
919262395Sbapt	/* Copy as many bytes as will fit */
920262395Sbapt	if (n != 0) {
921262395Sbapt		while (--n != 0) {
922262395Sbapt			if ((*d++ = *s++) == '\0') {
923262395Sbapt				break;
924262395Sbapt			}
925262395Sbapt		}
926262395Sbapt	}
927262395Sbapt
928262395Sbapt	if (n == 0 && siz != 0) {
929262395Sbapt		*d = '\0';
930262395Sbapt	}
931262395Sbapt
932262395Sbapt	return (s - src - 1);    /* count does not include NUL */
933262395Sbapt}
934262395Sbapt
935262395Sbaptsize_t
936262395Sbaptucl_strlcpy_unsafe (char *dst, const char *src, size_t siz)
937262395Sbapt{
938262395Sbapt	memcpy (dst, src, siz - 1);
939262395Sbapt	dst[siz - 1] = '\0';
940262395Sbapt
941262395Sbapt	return siz - 1;
942262395Sbapt}
943262395Sbapt
944262395Sbaptsize_t
945262395Sbaptucl_strlcpy_tolower (char *dst, const char *src, size_t siz)
946262395Sbapt{
947262395Sbapt	char *d = dst;
948262395Sbapt	const char *s = src;
949262395Sbapt	size_t n = siz;
950262395Sbapt
951262395Sbapt	/* Copy as many bytes as will fit */
952262395Sbapt	if (n != 0) {
953262395Sbapt		while (--n != 0) {
954262395Sbapt			if ((*d++ = tolower (*s++)) == '\0') {
955262395Sbapt				break;
956262395Sbapt			}
957262395Sbapt		}
958262395Sbapt	}
959262395Sbapt
960262395Sbapt	if (n == 0 && siz != 0) {
961262395Sbapt		*d = '\0';
962262395Sbapt	}
963262395Sbapt
964262395Sbapt	return (s - src);    /* count does not include NUL */
965262395Sbapt}
966262395Sbapt
967262395Sbaptucl_object_t *
968262395Sbaptucl_object_fromstring_common (const char *str, size_t len, enum ucl_string_flags flags)
969262395Sbapt{
970262395Sbapt	ucl_object_t *obj;
971262395Sbapt	const char *start, *end, *p, *pos;
972262395Sbapt	char *dst, *d;
973262395Sbapt	size_t escaped_len;
974262395Sbapt
975262395Sbapt	if (str == NULL) {
976262395Sbapt		return NULL;
977262395Sbapt	}
978262395Sbapt
979262395Sbapt	obj = ucl_object_new ();
980262395Sbapt	if (obj) {
981262395Sbapt		if (len == 0) {
982262395Sbapt			len = strlen (str);
983262395Sbapt		}
984262395Sbapt		if (flags & UCL_STRING_TRIM) {
985262395Sbapt			/* Skip leading spaces */
986262395Sbapt			for (start = str; (size_t)(start - str) < len; start ++) {
987262395Sbapt				if (!ucl_test_character (*start, UCL_CHARACTER_WHITESPACE_UNSAFE)) {
988262395Sbapt					break;
989262395Sbapt				}
990262395Sbapt			}
991262395Sbapt			/* Skip trailing spaces */
992262395Sbapt			for (end = str + len - 1; end > start; end --) {
993262395Sbapt				if (!ucl_test_character (*end, UCL_CHARACTER_WHITESPACE_UNSAFE)) {
994262395Sbapt					break;
995262395Sbapt				}
996262395Sbapt			}
997262395Sbapt			end ++;
998262395Sbapt		}
999262395Sbapt		else {
1000262395Sbapt			start = str;
1001262395Sbapt			end = str + len;
1002262395Sbapt		}
1003262395Sbapt
1004262395Sbapt		obj->type = UCL_STRING;
1005262395Sbapt		if (flags & UCL_STRING_ESCAPE) {
1006262395Sbapt			for (p = start, escaped_len = 0; p < end; p ++, escaped_len ++) {
1007262395Sbapt				if (ucl_test_character (*p, UCL_CHARACTER_JSON_UNSAFE)) {
1008262395Sbapt					escaped_len ++;
1009262395Sbapt				}
1010262395Sbapt			}
1011262395Sbapt			dst = malloc (escaped_len + 1);
1012262395Sbapt			if (dst != NULL) {
1013262395Sbapt				for (p = start, d = dst; p < end; p ++, d ++) {
1014262395Sbapt					if (ucl_test_character (*p, UCL_CHARACTER_JSON_UNSAFE)) {
1015262395Sbapt						switch (*p) {
1016262395Sbapt						case '\n':
1017262395Sbapt							*d++ = '\\';
1018262395Sbapt							*d = 'n';
1019262395Sbapt							break;
1020262395Sbapt						case '\r':
1021262395Sbapt							*d++ = '\\';
1022262395Sbapt							*d = 'r';
1023262395Sbapt							break;
1024262395Sbapt						case '\b':
1025262395Sbapt							*d++ = '\\';
1026262395Sbapt							*d = 'b';
1027262395Sbapt							break;
1028262395Sbapt						case '\t':
1029262395Sbapt							*d++ = '\\';
1030262395Sbapt							*d = 't';
1031262395Sbapt							break;
1032262395Sbapt						case '\f':
1033262395Sbapt							*d++ = '\\';
1034262395Sbapt							*d = 'f';
1035262395Sbapt							break;
1036262395Sbapt						case '\\':
1037262395Sbapt							*d++ = '\\';
1038262395Sbapt							*d = '\\';
1039262395Sbapt							break;
1040262395Sbapt						case '"':
1041262395Sbapt							*d++ = '\\';
1042262395Sbapt							*d = '"';
1043262395Sbapt							break;
1044262395Sbapt						}
1045262395Sbapt					}
1046262395Sbapt					else {
1047262395Sbapt						*d = *p;
1048262395Sbapt					}
1049262395Sbapt				}
1050262395Sbapt				*d = '\0';
1051262395Sbapt				obj->value.sv = dst;
1052262395Sbapt				obj->trash_stack[UCL_TRASH_VALUE] = dst;
1053262395Sbapt				obj->len = escaped_len;
1054262395Sbapt			}
1055262395Sbapt		}
1056262395Sbapt		else {
1057262395Sbapt			dst = malloc (end - start + 1);
1058262395Sbapt			if (dst != NULL) {
1059262395Sbapt				ucl_strlcpy_unsafe (dst, start, end - start + 1);
1060262395Sbapt				obj->value.sv = dst;
1061262395Sbapt				obj->trash_stack[UCL_TRASH_VALUE] = dst;
1062262395Sbapt				obj->len = end - start;
1063262395Sbapt			}
1064262395Sbapt		}
1065262395Sbapt		if ((flags & UCL_STRING_PARSE) && dst != NULL) {
1066262395Sbapt			/* Parse what we have */
1067262395Sbapt			if (flags & UCL_STRING_PARSE_BOOLEAN) {
1068262395Sbapt				if (!ucl_maybe_parse_boolean (obj, dst, obj->len) && (flags & UCL_STRING_PARSE_NUMBER)) {
1069262395Sbapt					ucl_maybe_parse_number (obj, dst, dst + obj->len, &pos,
1070262395Sbapt							flags & UCL_STRING_PARSE_DOUBLE,
1071263648Sbapt							flags & UCL_STRING_PARSE_BYTES,
1072263648Sbapt							flags & UCL_STRING_PARSE_TIME);
1073262395Sbapt				}
1074262395Sbapt			}
1075262395Sbapt			else {
1076262395Sbapt				ucl_maybe_parse_number (obj, dst, dst + obj->len, &pos,
1077262395Sbapt						flags & UCL_STRING_PARSE_DOUBLE,
1078263648Sbapt						flags & UCL_STRING_PARSE_BYTES,
1079263648Sbapt						flags & UCL_STRING_PARSE_TIME);
1080262395Sbapt			}
1081262395Sbapt		}
1082262395Sbapt	}
1083262395Sbapt
1084262395Sbapt	return obj;
1085262395Sbapt}
1086262395Sbapt
1087262395Sbaptstatic ucl_object_t *
1088262395Sbaptucl_object_insert_key_common (ucl_object_t *top, ucl_object_t *elt,
1089262395Sbapt		const char *key, size_t keylen, bool copy_key, bool merge, bool replace)
1090262395Sbapt{
1091262395Sbapt	ucl_object_t *found, *cur;
1092262395Sbapt	ucl_object_iter_t it = NULL;
1093262395Sbapt	const char *p;
1094262395Sbapt
1095262395Sbapt	if (elt == NULL || key == NULL) {
1096262395Sbapt		return NULL;
1097262395Sbapt	}
1098262395Sbapt
1099262395Sbapt	if (top == NULL) {
1100262395Sbapt		top = ucl_object_new ();
1101262395Sbapt		top->type = UCL_OBJECT;
1102262395Sbapt	}
1103262395Sbapt
1104262395Sbapt	if (top->type != UCL_OBJECT) {
1105262395Sbapt		/* It is possible to convert NULL type to an object */
1106262395Sbapt		if (top->type == UCL_NULL) {
1107262395Sbapt			top->type = UCL_OBJECT;
1108262395Sbapt		}
1109262395Sbapt		else {
1110262395Sbapt			/* Refuse converting of other object types */
1111262395Sbapt			return top;
1112262395Sbapt		}
1113262395Sbapt	}
1114262395Sbapt
1115262395Sbapt	if (top->value.ov == NULL) {
1116262395Sbapt		top->value.ov = ucl_hash_create ();
1117262395Sbapt	}
1118262395Sbapt
1119262395Sbapt	if (keylen == 0) {
1120262395Sbapt		keylen = strlen (key);
1121262395Sbapt	}
1122262395Sbapt
1123262395Sbapt	for (p = key; p < key + keylen; p ++) {
1124262395Sbapt		if (ucl_test_character (*p, UCL_CHARACTER_UCL_UNSAFE)) {
1125262395Sbapt			elt->flags |= UCL_OBJECT_NEED_KEY_ESCAPE;
1126262395Sbapt			break;
1127262395Sbapt		}
1128262395Sbapt	}
1129262395Sbapt
1130262395Sbapt	elt->key = key;
1131262395Sbapt	elt->keylen = keylen;
1132262395Sbapt
1133262395Sbapt	if (copy_key) {
1134262395Sbapt		ucl_copy_key_trash (elt);
1135262395Sbapt	}
1136262395Sbapt
1137262395Sbapt	found = ucl_hash_search_obj (top->value.ov, elt);
1138262395Sbapt
1139262395Sbapt	if (!found) {
1140262395Sbapt		top->value.ov = ucl_hash_insert_object (top->value.ov, elt);
1141262395Sbapt		DL_APPEND (found, elt);
1142263648Sbapt		top->len ++;
1143262395Sbapt	}
1144262395Sbapt	else {
1145262395Sbapt		if (replace) {
1146262395Sbapt			ucl_hash_delete (top->value.ov, found);
1147262395Sbapt			ucl_object_unref (found);
1148262395Sbapt			top->value.ov = ucl_hash_insert_object (top->value.ov, elt);
1149262395Sbapt			found = NULL;
1150262395Sbapt			DL_APPEND (found, elt);
1151262395Sbapt		}
1152262395Sbapt		else if (merge) {
1153262395Sbapt			if (found->type != UCL_OBJECT && elt->type == UCL_OBJECT) {
1154262395Sbapt				/* Insert old elt to new one */
1155262395Sbapt				elt = ucl_object_insert_key_common (elt, found, found->key, found->keylen, copy_key, false, false);
1156262395Sbapt				ucl_hash_delete (top->value.ov, found);
1157262395Sbapt				top->value.ov = ucl_hash_insert_object (top->value.ov, elt);
1158262395Sbapt			}
1159262395Sbapt			else if (found->type == UCL_OBJECT && elt->type != UCL_OBJECT) {
1160262395Sbapt				/* Insert new to old */
1161262395Sbapt				found = ucl_object_insert_key_common (found, elt, elt->key, elt->keylen, copy_key, false, false);
1162262395Sbapt			}
1163262395Sbapt			else if (found->type == UCL_OBJECT && elt->type == UCL_OBJECT) {
1164262395Sbapt				/* Mix two hashes */
1165262395Sbapt				while ((cur = ucl_iterate_object (elt, &it, true)) != NULL) {
1166262395Sbapt					ucl_object_ref (cur);
1167262395Sbapt					found = ucl_object_insert_key_common (found, cur, cur->key, cur->keylen, copy_key, false, false);
1168262395Sbapt				}
1169262395Sbapt				ucl_object_unref (elt);
1170262395Sbapt			}
1171262395Sbapt			else {
1172262395Sbapt				/* Just make a list of scalars */
1173262395Sbapt				DL_APPEND (found, elt);
1174262395Sbapt			}
1175262395Sbapt		}
1176262395Sbapt		else {
1177262395Sbapt			DL_APPEND (found, elt);
1178262395Sbapt		}
1179262395Sbapt	}
1180262395Sbapt
1181262395Sbapt	return top;
1182262395Sbapt}
1183262395Sbapt
1184262975Sbaptbool
1185262975Sbaptucl_object_delete_keyl(ucl_object_t *top, const char *key, size_t keylen)
1186262975Sbapt{
1187262975Sbapt	ucl_object_t *found;
1188262975Sbapt
1189263648Sbapt	if (top == NULL || key == NULL) {
1190263648Sbapt		return false;
1191263648Sbapt	}
1192263648Sbapt
1193262975Sbapt	found = ucl_object_find_keyl(top, key, keylen);
1194262975Sbapt
1195263648Sbapt	if (found == NULL) {
1196262975Sbapt		return false;
1197263648Sbapt	}
1198262975Sbapt
1199262975Sbapt	ucl_hash_delete(top->value.ov, found);
1200262975Sbapt	ucl_object_unref (found);
1201262975Sbapt	top->len --;
1202262975Sbapt
1203262975Sbapt	return true;
1204262975Sbapt}
1205262975Sbapt
1206262975Sbaptbool
1207262975Sbaptucl_object_delete_key(ucl_object_t *top, const char *key)
1208262975Sbapt{
1209262975Sbapt	return ucl_object_delete_keyl(top, key, 0);
1210262975Sbapt}
1211262975Sbapt
1212263648Sbaptucl_object_t*
1213263648Sbaptucl_object_pop_keyl (ucl_object_t *top, const char *key, size_t keylen)
1214263648Sbapt{
1215263648Sbapt	ucl_object_t *found;
1216263648Sbapt
1217263648Sbapt	if (top == NULL || key == NULL) {
1218263648Sbapt		return false;
1219263648Sbapt	}
1220263648Sbapt	found = ucl_object_find_keyl(top, key, keylen);
1221263648Sbapt
1222263648Sbapt	if (found == NULL) {
1223263648Sbapt		return NULL;
1224263648Sbapt	}
1225263648Sbapt	ucl_hash_delete(top->value.ov, found);
1226263648Sbapt	top->len --;
1227263648Sbapt
1228263648Sbapt	return found;
1229263648Sbapt}
1230263648Sbapt
1231263648Sbaptucl_object_t*
1232263648Sbaptucl_object_pop_key (ucl_object_t *top, const char *key)
1233263648Sbapt{
1234263648Sbapt	return ucl_object_pop_keyl (top, key, 0);
1235263648Sbapt}
1236263648Sbapt
1237262395Sbaptucl_object_t *
1238262395Sbaptucl_object_insert_key (ucl_object_t *top, ucl_object_t *elt,
1239262395Sbapt		const char *key, size_t keylen, bool copy_key)
1240262395Sbapt{
1241262395Sbapt	return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, false, false);
1242262395Sbapt}
1243262395Sbapt
1244262395Sbaptucl_object_t *
1245262395Sbaptucl_object_insert_key_merged (ucl_object_t *top, ucl_object_t *elt,
1246262395Sbapt		const char *key, size_t keylen, bool copy_key)
1247262395Sbapt{
1248262395Sbapt	return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, true, false);
1249262395Sbapt}
1250262395Sbapt
1251262395Sbaptucl_object_t *
1252262395Sbaptucl_object_replace_key (ucl_object_t *top, ucl_object_t *elt,
1253262395Sbapt		const char *key, size_t keylen, bool copy_key)
1254262395Sbapt{
1255262395Sbapt	return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, false, true);
1256262395Sbapt}
1257262395Sbapt
1258262395Sbaptucl_object_t *
1259262395Sbaptucl_object_find_keyl (ucl_object_t *obj, const char *key, size_t klen)
1260262395Sbapt{
1261262395Sbapt	ucl_object_t *ret, srch;
1262262395Sbapt
1263262395Sbapt	if (obj == NULL || obj->type != UCL_OBJECT || key == NULL) {
1264262395Sbapt		return NULL;
1265262395Sbapt	}
1266262395Sbapt
1267262395Sbapt	srch.key = key;
1268262395Sbapt	srch.keylen = klen;
1269262395Sbapt	ret = ucl_hash_search_obj (obj->value.ov, &srch);
1270262395Sbapt
1271262395Sbapt	return ret;
1272262395Sbapt}
1273262395Sbapt
1274262395Sbaptucl_object_t *
1275262395Sbaptucl_object_find_key (ucl_object_t *obj, const char *key)
1276262395Sbapt{
1277262395Sbapt	size_t klen;
1278262395Sbapt	ucl_object_t *ret, srch;
1279262395Sbapt
1280262395Sbapt	if (obj == NULL || obj->type != UCL_OBJECT || key == NULL) {
1281262395Sbapt		return NULL;
1282262395Sbapt	}
1283262395Sbapt
1284262395Sbapt	klen = strlen (key);
1285262395Sbapt	srch.key = key;
1286262395Sbapt	srch.keylen = klen;
1287262395Sbapt	ret = ucl_hash_search_obj (obj->value.ov, &srch);
1288262395Sbapt
1289262395Sbapt	return ret;
1290262395Sbapt}
1291262395Sbapt
1292262395Sbaptucl_object_t*
1293262395Sbaptucl_iterate_object (ucl_object_t *obj, ucl_object_iter_t *iter, bool expand_values)
1294262395Sbapt{
1295262395Sbapt	ucl_object_t *elt;
1296262395Sbapt
1297263648Sbapt	if (obj == NULL || iter == NULL) {
1298263648Sbapt		return NULL;
1299263648Sbapt	}
1300263648Sbapt
1301262395Sbapt	if (expand_values) {
1302262395Sbapt		switch (obj->type) {
1303262395Sbapt		case UCL_OBJECT:
1304262395Sbapt			return (ucl_object_t*)ucl_hash_iterate (obj->value.ov, iter);
1305262395Sbapt			break;
1306262395Sbapt		case UCL_ARRAY:
1307262395Sbapt			elt = *iter;
1308262395Sbapt			if (elt == NULL) {
1309262395Sbapt				elt = obj->value.av;
1310262395Sbapt				if (elt == NULL) {
1311262395Sbapt					return NULL;
1312262395Sbapt				}
1313262395Sbapt			}
1314262395Sbapt			else if (elt == obj->value.av) {
1315262395Sbapt				return NULL;
1316262395Sbapt			}
1317262395Sbapt			*iter = elt->next ? elt->next : obj->value.av;
1318262395Sbapt			return elt;
1319262395Sbapt		default:
1320262395Sbapt			/* Go to linear iteration */
1321262395Sbapt			break;
1322262395Sbapt		}
1323262395Sbapt	}
1324262395Sbapt	/* Treat everything as a linear list */
1325262395Sbapt	elt = *iter;
1326262395Sbapt	if (elt == NULL) {
1327262395Sbapt		elt = obj;
1328262395Sbapt		if (elt == NULL) {
1329262395Sbapt			return NULL;
1330262395Sbapt		}
1331262395Sbapt	}
1332262395Sbapt	else if (elt == obj) {
1333262395Sbapt		return NULL;
1334262395Sbapt	}
1335262395Sbapt	*iter = elt->next ? elt->next : obj;
1336262395Sbapt	return elt;
1337262395Sbapt
1338262395Sbapt	/* Not reached */
1339262395Sbapt	return NULL;
1340262395Sbapt}
1341263648Sbapt
1342263648Sbapt
1343263648Sbaptucl_object_t *
1344263648Sbaptucl_object_new (void)
1345263648Sbapt{
1346263648Sbapt	ucl_object_t *new;
1347263648Sbapt	new = malloc (sizeof (ucl_object_t));
1348263648Sbapt	if (new != NULL) {
1349263648Sbapt		memset (new, 0, sizeof (ucl_object_t));
1350263648Sbapt		new->ref = 1;
1351263648Sbapt		new->type = UCL_NULL;
1352263648Sbapt	}
1353263648Sbapt	return new;
1354263648Sbapt}
1355263648Sbapt
1356263648Sbaptucl_object_t *
1357263648Sbaptucl_object_typed_new (unsigned int type)
1358263648Sbapt{
1359263648Sbapt	ucl_object_t *new;
1360263648Sbapt	new = malloc (sizeof (ucl_object_t));
1361263648Sbapt	if (new != NULL) {
1362263648Sbapt		memset (new, 0, sizeof (ucl_object_t));
1363263648Sbapt		new->ref = 1;
1364263648Sbapt		new->type = (type <= UCL_NULL ? type : UCL_NULL);
1365263648Sbapt	}
1366263648Sbapt	return new;
1367263648Sbapt}
1368263648Sbapt
1369263648Sbaptucl_object_t*
1370263648Sbaptucl_object_fromstring (const char *str)
1371263648Sbapt{
1372263648Sbapt	return ucl_object_fromstring_common (str, 0, UCL_STRING_ESCAPE);
1373263648Sbapt}
1374263648Sbapt
1375263648Sbaptucl_object_t *
1376263648Sbaptucl_object_fromlstring (const char *str, size_t len)
1377263648Sbapt{
1378263648Sbapt	return ucl_object_fromstring_common (str, len, UCL_STRING_ESCAPE);
1379263648Sbapt}
1380263648Sbapt
1381263648Sbaptucl_object_t *
1382263648Sbaptucl_object_fromint (int64_t iv)
1383263648Sbapt{
1384263648Sbapt	ucl_object_t *obj;
1385263648Sbapt
1386263648Sbapt	obj = ucl_object_new ();
1387263648Sbapt	if (obj != NULL) {
1388263648Sbapt		obj->type = UCL_INT;
1389263648Sbapt		obj->value.iv = iv;
1390263648Sbapt	}
1391263648Sbapt
1392263648Sbapt	return obj;
1393263648Sbapt}
1394263648Sbapt
1395263648Sbaptucl_object_t *
1396263648Sbaptucl_object_fromdouble (double dv)
1397263648Sbapt{
1398263648Sbapt	ucl_object_t *obj;
1399263648Sbapt
1400263648Sbapt	obj = ucl_object_new ();
1401263648Sbapt	if (obj != NULL) {
1402263648Sbapt		obj->type = UCL_FLOAT;
1403263648Sbapt		obj->value.dv = dv;
1404263648Sbapt	}
1405263648Sbapt
1406263648Sbapt	return obj;
1407263648Sbapt}
1408263648Sbapt
1409263648Sbaptucl_object_t*
1410263648Sbaptucl_object_frombool (bool bv)
1411263648Sbapt{
1412263648Sbapt	ucl_object_t *obj;
1413263648Sbapt
1414263648Sbapt	obj = ucl_object_new ();
1415263648Sbapt	if (obj != NULL) {
1416263648Sbapt		obj->type = UCL_BOOLEAN;
1417263648Sbapt		obj->value.iv = bv;
1418263648Sbapt	}
1419263648Sbapt
1420263648Sbapt	return obj;
1421263648Sbapt}
1422263648Sbapt
1423263648Sbaptucl_object_t *
1424263648Sbaptucl_array_append (ucl_object_t *top, ucl_object_t *elt)
1425263648Sbapt{
1426263648Sbapt	ucl_object_t *head;
1427263648Sbapt
1428263648Sbapt	if (elt == NULL) {
1429263648Sbapt		return NULL;
1430263648Sbapt	}
1431263648Sbapt
1432263648Sbapt	if (top == NULL) {
1433263648Sbapt		top = ucl_object_typed_new (UCL_ARRAY);
1434263648Sbapt		top->value.av = elt;
1435263648Sbapt		elt->next = NULL;
1436263648Sbapt		elt->prev = elt;
1437263648Sbapt		top->len = 1;
1438263648Sbapt	}
1439263648Sbapt	else {
1440263648Sbapt		head = top->value.av;
1441263648Sbapt		if (head == NULL) {
1442263648Sbapt			top->value.av = elt;
1443263648Sbapt			elt->prev = elt;
1444263648Sbapt		}
1445263648Sbapt		else {
1446263648Sbapt			elt->prev = head->prev;
1447263648Sbapt			head->prev->next = elt;
1448263648Sbapt			head->prev = elt;
1449263648Sbapt		}
1450263648Sbapt		elt->next = NULL;
1451263648Sbapt		top->len ++;
1452263648Sbapt	}
1453263648Sbapt
1454263648Sbapt	return top;
1455263648Sbapt}
1456263648Sbapt
1457263648Sbaptucl_object_t *
1458263648Sbaptucl_array_prepend (ucl_object_t *top, ucl_object_t *elt)
1459263648Sbapt{
1460263648Sbapt	ucl_object_t *head;
1461263648Sbapt
1462263648Sbapt	if (elt == NULL) {
1463263648Sbapt		return NULL;
1464263648Sbapt	}
1465263648Sbapt
1466263648Sbapt	if (top == NULL) {
1467263648Sbapt		top = ucl_object_typed_new (UCL_ARRAY);
1468263648Sbapt		top->value.av = elt;
1469263648Sbapt		elt->next = NULL;
1470263648Sbapt		elt->prev = elt;
1471263648Sbapt		top->len = 1;
1472263648Sbapt	}
1473263648Sbapt	else {
1474263648Sbapt		head = top->value.av;
1475263648Sbapt		if (head == NULL) {
1476263648Sbapt			top->value.av = elt;
1477263648Sbapt			elt->prev = elt;
1478263648Sbapt		}
1479263648Sbapt		else {
1480263648Sbapt			elt->prev = head->prev;
1481263648Sbapt			head->prev = elt;
1482263648Sbapt		}
1483263648Sbapt		elt->next = head;
1484263648Sbapt		top->value.av = elt;
1485263648Sbapt		top->len ++;
1486263648Sbapt	}
1487263648Sbapt
1488263648Sbapt	return top;
1489263648Sbapt}
1490263648Sbapt
1491263648Sbaptucl_object_t *
1492263648Sbaptucl_array_delete (ucl_object_t *top, ucl_object_t *elt)
1493263648Sbapt{
1494263648Sbapt	ucl_object_t *head;
1495263648Sbapt
1496263648Sbapt	if (top == NULL || top->type != UCL_ARRAY || top->value.av == NULL) {
1497263648Sbapt		return NULL;
1498263648Sbapt	}
1499263648Sbapt	head = top->value.av;
1500263648Sbapt
1501263648Sbapt	if (elt->prev == elt) {
1502263648Sbapt		top->value.av = NULL;
1503263648Sbapt	}
1504263648Sbapt	else if (elt == head) {
1505263648Sbapt		elt->next->prev = elt->prev;
1506263648Sbapt		top->value.av = elt->next;
1507263648Sbapt	}
1508263648Sbapt	else {
1509263648Sbapt		elt->prev->next = elt->next;
1510263648Sbapt		if (elt->next) {
1511263648Sbapt			elt->next->prev = elt->prev;
1512263648Sbapt		}
1513263648Sbapt		else {
1514263648Sbapt			head->prev = elt->prev;
1515263648Sbapt		}
1516263648Sbapt	}
1517263648Sbapt	elt->next = NULL;
1518263648Sbapt	elt->prev = elt;
1519263648Sbapt	top->len --;
1520263648Sbapt
1521263648Sbapt	return elt;
1522263648Sbapt}
1523263648Sbapt
1524263648Sbaptucl_object_t *
1525263648Sbaptucl_array_head (ucl_object_t *top)
1526263648Sbapt{
1527263648Sbapt	if (top == NULL || top->type != UCL_ARRAY || top->value.av == NULL) {
1528263648Sbapt		return NULL;
1529263648Sbapt	}
1530263648Sbapt	return top->value.av;
1531263648Sbapt}
1532263648Sbapt
1533263648Sbaptucl_object_t *
1534263648Sbaptucl_array_tail (ucl_object_t *top)
1535263648Sbapt{
1536263648Sbapt	if (top == NULL || top->type != UCL_ARRAY || top->value.av == NULL) {
1537263648Sbapt		return NULL;
1538263648Sbapt	}
1539263648Sbapt	return top->value.av->prev;
1540263648Sbapt}
1541263648Sbapt
1542263648Sbaptucl_object_t *
1543263648Sbaptucl_array_pop_last (ucl_object_t *top)
1544263648Sbapt{
1545263648Sbapt	return ucl_array_delete (top, ucl_array_tail (top));
1546263648Sbapt}
1547263648Sbapt
1548263648Sbaptucl_object_t *
1549263648Sbaptucl_array_pop_first (ucl_object_t *top)
1550263648Sbapt{
1551263648Sbapt	return ucl_array_delete (top, ucl_array_head (top));
1552263648Sbapt}
1553263648Sbapt
1554263648Sbaptucl_object_t *
1555263648Sbaptucl_elt_append (ucl_object_t *head, ucl_object_t *elt)
1556263648Sbapt{
1557263648Sbapt
1558263648Sbapt	if (head == NULL) {
1559263648Sbapt		elt->next = NULL;
1560263648Sbapt		elt->prev = elt;
1561263648Sbapt		head = elt;
1562263648Sbapt	}
1563263648Sbapt	else {
1564263648Sbapt		elt->prev = head->prev;
1565263648Sbapt		head->prev->next = elt;
1566263648Sbapt		head->prev = elt;
1567263648Sbapt		elt->next = NULL;
1568263648Sbapt	}
1569263648Sbapt
1570263648Sbapt	return head;
1571263648Sbapt}
1572263648Sbapt
1573263648Sbaptbool
1574263648Sbaptucl_object_todouble_safe (ucl_object_t *obj, double *target)
1575263648Sbapt{
1576263648Sbapt	if (obj == NULL || target == NULL) {
1577263648Sbapt		return false;
1578263648Sbapt	}
1579263648Sbapt	switch (obj->type) {
1580263648Sbapt	case UCL_INT:
1581263648Sbapt		*target = obj->value.iv; /* Probaly could cause overflow */
1582263648Sbapt		break;
1583263648Sbapt	case UCL_FLOAT:
1584263648Sbapt	case UCL_TIME:
1585263648Sbapt		*target = obj->value.dv;
1586263648Sbapt		break;
1587263648Sbapt	default:
1588263648Sbapt		return false;
1589263648Sbapt	}
1590263648Sbapt
1591263648Sbapt	return true;
1592263648Sbapt}
1593263648Sbapt
1594263648Sbaptdouble
1595263648Sbaptucl_object_todouble (ucl_object_t *obj)
1596263648Sbapt{
1597263648Sbapt	double result = 0.;
1598263648Sbapt
1599263648Sbapt	ucl_object_todouble_safe (obj, &result);
1600263648Sbapt	return result;
1601263648Sbapt}
1602263648Sbapt
1603263648Sbaptbool
1604263648Sbaptucl_object_toint_safe (ucl_object_t *obj, int64_t *target)
1605263648Sbapt{
1606263648Sbapt	if (obj == NULL || target == NULL) {
1607263648Sbapt		return false;
1608263648Sbapt	}
1609263648Sbapt	switch (obj->type) {
1610263648Sbapt	case UCL_INT:
1611263648Sbapt		*target = obj->value.iv;
1612263648Sbapt		break;
1613263648Sbapt	case UCL_FLOAT:
1614263648Sbapt	case UCL_TIME:
1615263648Sbapt		*target = obj->value.dv; /* Loosing of decimal points */
1616263648Sbapt		break;
1617263648Sbapt	default:
1618263648Sbapt		return false;
1619263648Sbapt	}
1620263648Sbapt
1621263648Sbapt	return true;
1622263648Sbapt}
1623263648Sbapt
1624263648Sbaptint64_t
1625263648Sbaptucl_object_toint (ucl_object_t *obj)
1626263648Sbapt{
1627263648Sbapt	int64_t result = 0;
1628263648Sbapt
1629263648Sbapt	ucl_object_toint_safe (obj, &result);
1630263648Sbapt	return result;
1631263648Sbapt}
1632263648Sbapt
1633263648Sbaptbool
1634263648Sbaptucl_object_toboolean_safe (ucl_object_t *obj, bool *target)
1635263648Sbapt{
1636263648Sbapt	if (obj == NULL || target == NULL) {
1637263648Sbapt		return false;
1638263648Sbapt	}
1639263648Sbapt	switch (obj->type) {
1640263648Sbapt	case UCL_BOOLEAN:
1641263648Sbapt		*target = (obj->value.iv == true);
1642263648Sbapt		break;
1643263648Sbapt	default:
1644263648Sbapt		return false;
1645263648Sbapt	}
1646263648Sbapt
1647263648Sbapt	return true;
1648263648Sbapt}
1649263648Sbapt
1650263648Sbaptbool
1651263648Sbaptucl_object_toboolean (ucl_object_t *obj)
1652263648Sbapt{
1653263648Sbapt	bool result = false;
1654263648Sbapt
1655263648Sbapt	ucl_object_toboolean_safe (obj, &result);
1656263648Sbapt	return result;
1657263648Sbapt}
1658263648Sbapt
1659263648Sbaptbool
1660263648Sbaptucl_object_tostring_safe (ucl_object_t *obj, const char **target)
1661263648Sbapt{
1662263648Sbapt	if (obj == NULL || target == NULL) {
1663263648Sbapt		return false;
1664263648Sbapt	}
1665263648Sbapt
1666263648Sbapt	switch (obj->type) {
1667263648Sbapt	case UCL_STRING:
1668263648Sbapt		*target = ucl_copy_value_trash (obj);
1669263648Sbapt		break;
1670263648Sbapt	default:
1671263648Sbapt		return false;
1672263648Sbapt	}
1673263648Sbapt
1674263648Sbapt	return true;
1675263648Sbapt}
1676263648Sbapt
1677263648Sbaptconst char *
1678263648Sbaptucl_object_tostring (ucl_object_t *obj)
1679263648Sbapt{
1680263648Sbapt	const char *result = NULL;
1681263648Sbapt
1682263648Sbapt	ucl_object_tostring_safe (obj, &result);
1683263648Sbapt	return result;
1684263648Sbapt}
1685263648Sbapt
1686263648Sbaptconst char *
1687263648Sbaptucl_object_tostring_forced (ucl_object_t *obj)
1688263648Sbapt{
1689263648Sbapt	return ucl_copy_value_trash (obj);
1690263648Sbapt}
1691263648Sbapt
1692263648Sbaptbool
1693263648Sbaptucl_object_tolstring_safe (ucl_object_t *obj, const char **target, size_t *tlen)
1694263648Sbapt{
1695263648Sbapt	if (obj == NULL || target == NULL) {
1696263648Sbapt		return false;
1697263648Sbapt	}
1698263648Sbapt	switch (obj->type) {
1699263648Sbapt	case UCL_STRING:
1700263648Sbapt		*target = obj->value.sv;
1701263648Sbapt		if (tlen != NULL) {
1702263648Sbapt			*tlen = obj->len;
1703263648Sbapt		}
1704263648Sbapt		break;
1705263648Sbapt	default:
1706263648Sbapt		return false;
1707263648Sbapt	}
1708263648Sbapt
1709263648Sbapt	return true;
1710263648Sbapt}
1711263648Sbapt
1712263648Sbaptconst char *
1713263648Sbaptucl_object_tolstring (ucl_object_t *obj, size_t *tlen)
1714263648Sbapt{
1715263648Sbapt	const char *result = NULL;
1716263648Sbapt
1717263648Sbapt	ucl_object_tolstring_safe (obj, &result, tlen);
1718263648Sbapt	return result;
1719263648Sbapt}
1720263648Sbapt
1721263648Sbaptconst char *
1722263648Sbaptucl_object_key (ucl_object_t *obj)
1723263648Sbapt{
1724263648Sbapt	return ucl_copy_key_trash (obj);
1725263648Sbapt}
1726263648Sbapt
1727263648Sbaptconst char *
1728263648Sbaptucl_object_keyl (ucl_object_t *obj, size_t *len)
1729263648Sbapt{
1730263648Sbapt	if (len == NULL || obj == NULL) {
1731263648Sbapt		return NULL;
1732263648Sbapt	}
1733263648Sbapt	*len = obj->keylen;
1734263648Sbapt	return obj->key;
1735263648Sbapt}
1736263648Sbapt
1737263648Sbaptucl_object_t *
1738263648Sbaptucl_object_ref (ucl_object_t *obj)
1739263648Sbapt{
1740263648Sbapt	if (obj != NULL) {
1741263648Sbapt		obj->ref ++;
1742263648Sbapt	}
1743263648Sbapt	return obj;
1744263648Sbapt}
1745263648Sbapt
1746263648Sbaptvoid
1747263648Sbaptucl_object_unref (ucl_object_t *obj)
1748263648Sbapt{
1749263648Sbapt	if (obj != NULL && --obj->ref <= 0) {
1750263648Sbapt		ucl_object_free (obj);
1751263648Sbapt	}
1752263648Sbapt}
1753263648Sbapt
1754263648Sbaptint
1755263648Sbaptucl_object_compare (ucl_object_t *o1, ucl_object_t *o2)
1756263648Sbapt{
1757263648Sbapt	ucl_object_t *it1, *it2;
1758263648Sbapt	ucl_object_iter_t iter = NULL;
1759263648Sbapt	int ret = 0;
1760263648Sbapt
1761263648Sbapt	if (o1->type != o2->type) {
1762263648Sbapt		return (o1->type) - (o2->type);
1763263648Sbapt	}
1764263648Sbapt
1765263648Sbapt	switch (o1->type) {
1766263648Sbapt	case UCL_STRING:
1767263648Sbapt		if (o1->len == o2->len) {
1768263648Sbapt			ret = strcmp (ucl_object_tostring(o1), ucl_object_tostring(o2));
1769263648Sbapt		}
1770263648Sbapt		else {
1771263648Sbapt			ret = o1->len - o2->len;
1772263648Sbapt		}
1773263648Sbapt		break;
1774263648Sbapt	case UCL_FLOAT:
1775263648Sbapt	case UCL_INT:
1776263648Sbapt	case UCL_TIME:
1777263648Sbapt		ret = ucl_object_todouble (o1) - ucl_object_todouble (o2);
1778263648Sbapt		break;
1779263648Sbapt	case UCL_BOOLEAN:
1780263648Sbapt		ret = ucl_object_toboolean (o1) - ucl_object_toboolean (o2);
1781263648Sbapt		break;
1782263648Sbapt	case UCL_ARRAY:
1783263648Sbapt		if (o1->len == o2->len) {
1784263648Sbapt			it1 = o1->value.av;
1785263648Sbapt			it2 = o2->value.av;
1786263648Sbapt			/* Compare all elements in both arrays */
1787263648Sbapt			while (it1 != NULL && it2 != NULL) {
1788263648Sbapt				ret = ucl_object_compare (it1, it2);
1789263648Sbapt				if (ret != 0) {
1790263648Sbapt					break;
1791263648Sbapt				}
1792263648Sbapt				it1 = it1->next;
1793263648Sbapt				it2 = it2->next;
1794263648Sbapt			}
1795263648Sbapt		}
1796263648Sbapt		else {
1797263648Sbapt			ret = o1->len - o2->len;
1798263648Sbapt		}
1799263648Sbapt		break;
1800263648Sbapt	case UCL_OBJECT:
1801263648Sbapt		if (o1->len == o2->len) {
1802263648Sbapt			while ((it1 = ucl_iterate_object (o1, &iter, true)) != NULL) {
1803263648Sbapt				it2 = ucl_object_find_key (o2, ucl_object_key (it1));
1804263648Sbapt				if (it2 == NULL) {
1805263648Sbapt					ret = 1;
1806263648Sbapt					break;
1807263648Sbapt				}
1808263648Sbapt				ret = ucl_object_compare (it1, it2);
1809263648Sbapt				if (ret != 0) {
1810263648Sbapt					break;
1811263648Sbapt				}
1812263648Sbapt			}
1813263648Sbapt		}
1814263648Sbapt		else {
1815263648Sbapt			ret = o1->len - o2->len;
1816263648Sbapt		}
1817263648Sbapt		break;
1818263648Sbapt	default:
1819263648Sbapt		ret = 0;
1820263648Sbapt		break;
1821263648Sbapt	}
1822263648Sbapt
1823263648Sbapt	return ret;
1824263648Sbapt}
1825263648Sbapt
1826263648Sbaptvoid
1827263648Sbaptucl_object_array_sort (ucl_object_t *ar,
1828263648Sbapt		int (*cmp)(ucl_object_t *o1, ucl_object_t *o2))
1829263648Sbapt{
1830263648Sbapt	if (cmp == NULL || ar == NULL || ar->type != UCL_ARRAY) {
1831263648Sbapt		return;
1832263648Sbapt	}
1833263648Sbapt
1834263648Sbapt	DL_SORT (ar->value.av, cmp);
1835263648Sbapt}
1836